Author: jhb
Date: Tue Dec 19 18:20:38 2017
New Revision: 326986
URL: https://svnweb.freebsd.org/changeset/base/326986

Log:
  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

Modified:
  head/sys/fs/fdescfs/fdesc_vnops.c
  head/sys/kern/kern_descrip.c
  head/sys/sys/syscallsubr.h

Modified: head/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- head/sys/fs/fdescfs/fdesc_vnops.c   Tue Dec 19 18:12:18 2017        
(r326985)
+++ head/sys/fs/fdescfs/fdesc_vnops.c   Tue Dec 19 18:20:38 2017        
(r326986)
@@ -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,
@@ -393,6 +396,33 @@ fdesc_open(struct vop_open_args *ap)
         */
        ap->a_td->td_dupfd = VTOFDESC(vp)->fd_fd;       /* XXX */
        return (ENODEV);
+}
+
+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

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Tue Dec 19 18:12:18 2017        
(r326985)
+++ head/sys/kern/kern_descrip.c        Tue Dec 19 18:20:38 2017        
(r326986)
@@ -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;

Modified: head/sys/sys/syscallsubr.h
==============================================================================
--- head/sys/sys/syscallsubr.h  Tue Dec 19 18:12:18 2017        (r326985)
+++ head/sys/sys/syscallsubr.h  Tue Dec 19 18:20:38 2017        (r326986)
@@ -111,6 +111,7 @@ int kern_fcntl(struct thread *td, int fd, int cmd, int
 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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to