aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2017-12-19 18:20:38 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2017-12-19 18:20:38 +0000
commitdd688800e1ce85d375190252a245d9b83695575e (patch)
treef156f6efac61a01a2cbfe35769164857ede68d57
parent78fcf2de930af71c827151dac2dbd72e976e7c7d (diff)
downloadsrc-dd688800e1ce85d375190252a245d9b83695575e.tar.gz
src-dd688800e1ce85d375190252a245d9b83695575e.zip
Add a custom VOP_PATHCONF method for fdescfs.
The method handles NAME_MAX and LINK_MAX explicitly. For all other pathconf variables, the method passes the request down to the underlying file descriptor. This requires splitting a kern_fpathconf() syscallsubr routine out of sys_fpathconf(). Also, to avoid lock order reversals with vnode locks, the fdescfs vnode is unlocked around the call to kern_fpathconf(), but with the usecount of the vnode bumped. MFC after: 1 month Sponsored by: Chelsio Communications
Notes
Notes: svn path=/head/; revision=326986
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c32
-rw-r--r--sys/kern/kern_descrip.c15
-rw-r--r--sys/sys/syscallsubr.h1
3 files changed, 43 insertions, 5 deletions
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index c6d0dfbfb060..59ea8d92bfb3 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -55,6 +55,8 @@
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/stat.h>
+#include <sys/syscallsubr.h>
+#include <sys/unistd.h>
#include <sys/vnode.h>
#include <fs/fdescfs/fdesc.h>
@@ -70,6 +72,7 @@ struct mtx fdesc_hashmtx;
static vop_getattr_t fdesc_getattr;
static vop_lookup_t fdesc_lookup;
static vop_open_t fdesc_open;
+static vop_pathconf_t fdesc_pathconf;
static vop_readdir_t fdesc_readdir;
static vop_readlink_t fdesc_readlink;
static vop_reclaim_t fdesc_reclaim;
@@ -82,7 +85,7 @@ static struct vop_vector fdesc_vnodeops = {
.vop_getattr = fdesc_getattr,
.vop_lookup = fdesc_lookup,
.vop_open = fdesc_open,
- .vop_pathconf = vop_stdpathconf,
+ .vop_pathconf = fdesc_pathconf,
.vop_readdir = fdesc_readdir,
.vop_readlink = fdesc_readlink,
.vop_reclaim = fdesc_reclaim,
@@ -396,6 +399,33 @@ fdesc_open(struct vop_open_args *ap)
}
static int
+fdesc_pathconf(struct vop_pathconf_args *ap)
+{
+ struct vnode *vp = ap->a_vp;
+ int error;
+
+ switch (ap->a_name) {
+ case _PC_NAME_MAX:
+ *ap->a_retval = NAME_MAX;
+ return (0);
+ case _PC_LINK_MAX:
+ if (VTOFDESC(vp)->fd_type == Froot)
+ *ap->a_retval = 2;
+ else
+ *ap->a_retval = 1;
+ return (0);
+ default:
+ vref(vp);
+ VOP_UNLOCK(vp, 0);
+ error = kern_fpathconf(curthread, VTOFDESC(vp)->fd_fd,
+ ap->a_name);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ vunref(vp);
+ return (error);
+ }
+}
+
+static int
fdesc_getattr(struct vop_getattr_args *ap)
{
struct vnode *vp = ap->a_vp;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 67253fa4050e..c1100b7c8fdf 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1418,26 +1418,33 @@ struct fpathconf_args {
int
sys_fpathconf(struct thread *td, struct fpathconf_args *uap)
{
+
+ return (kern_fpathconf(td, uap->fd, uap->name));
+}
+
+int
+kern_fpathconf(struct thread *td, int fd, int name)
+{
struct file *fp;
struct vnode *vp;
cap_rights_t rights;
int error;
- error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp);
if (error != 0)
return (error);
- if (uap->name == _PC_ASYNC_IO) {
+ if (name == _PC_ASYNC_IO) {
td->td_retval[0] = _POSIX_ASYNCHRONOUS_IO;
goto out;
}
vp = fp->f_vnode;
if (vp != NULL) {
vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_PATHCONF(vp, uap->name, td->td_retval);
+ error = VOP_PATHCONF(vp, name, td->td_retval);
VOP_UNLOCK(vp, 0);
} else if (fp->f_type == DTYPE_PIPE || fp->f_type == DTYPE_SOCKET) {
- if (uap->name != _PC_PIPE_BUF) {
+ if (name != _PC_PIPE_BUF) {
error = EINVAL;
} else {
td->td_retval[0] = PIPE_BUF;
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index c97b27f1193a..d95b2dd7d4bf 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -111,6 +111,7 @@ int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);
int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg);
int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf);
int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
+int kern_fpathconf(struct thread *td, int fd, int name);
int kern_fstat(struct thread *td, int fd, struct stat *sbp);
int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
int kern_fsync(struct thread *td, int fd, bool fullsync);