Still awaiting feedback on this diff.

On Fri, Jul 08, 2011 at 03:13:32AM -0700, Matthew Dempsky wrote:
> I missed one flag: AT_REMOVEDIR.  This makes unlinkat() behave the
> same as rmdir(), and the diff below changes sys_rmdir() to call
> dounlinkat() using it.
> 
> Here's how to read this diff and be convinced it's correct:
> 
>   1. First read dounlinkat() by itself, and convince yourself that if
>      flag == 0, the behavior is the same as it was already.  (The new
>      control flow is a little awkward, but the semantics are the
>      same.)
> 
>   2. Next compare the resulting code with the code in sys_rmdir(), and
>      notice that if flag == AT_REMOVEDIR, then they're the same.
> 
> ok?
> 
> 
> Index: sys/fcntl.h
> ===================================================================
> RCS file: /home/mdempsky/anoncvs/cvs/src/sys/sys/fcntl.h,v
> retrieving revision 1.14
> diff -u -p -r1.14 fcntl.h
> --- sys/fcntl.h       8 Jul 2011 04:23:24 -0000       1.14
> +++ sys/fcntl.h       8 Jul 2011 10:05:05 -0000
> @@ -194,6 +194,7 @@ struct flock {
>  #define      AT_EACCESS              0x01
>  #define      AT_SYMLINK_NOFOLLOW     0x02
>  #define      AT_SYMLINK_FOLLOW       0x04
> +#define      AT_REMOVEDIR            0x08
>  #endif
>  
>  #ifndef _KERNEL
> Index: kern/vfs_syscalls.c
> ===================================================================
> RCS file: /home/mdempsky/anoncvs/cvs/src/sys/kern/vfs_syscalls.c,v
> retrieving revision 1.170
> diff -u -p -r1.170 vfs_syscalls.c
> --- kern/vfs_syscalls.c       8 Jul 2011 04:23:24 -0000       1.170
> +++ kern/vfs_syscalls.c       8 Jul 2011 10:02:06 -0000
> @@ -1484,9 +1484,8 @@ dounlinkat(struct proc *p, int fd, const
>       int error;
>       struct nameidata nd;
>  
> -     /* XXX: Support AT_REMOVEDIR. */
> -     if (flag != 0)
> -             return (ENOTSUP);
> +     if (flag & ~AT_REMOVEDIR)
> +             return (EINVAL);
>  
>       NDINITAT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
>           fd, path, p);
> @@ -1494,24 +1493,41 @@ dounlinkat(struct proc *p, int fd, const
>               return (error);
>       vp = nd.ni_vp;
>  
> +     if (flag & AT_REMOVEDIR) {
> +             if (vp->v_type != VDIR) {
> +                     error = ENOTDIR;
> +                     goto out;
> +             }
> +             /*
> +              * No rmdir "." please.
> +              */
> +             if (nd.ni_dvp == vp) {
> +                     error = EBUSY;
> +                     goto out;
> +             }
> +     }
> +
>       /*
>        * The root of a mounted filesystem cannot be deleted.
>        */
> -     if (vp->v_flag & VROOT) {
> +     if (vp->v_flag & VROOT)
> +             error = EBUSY;
> +out:
> +     if (!error) {
> +             if (flag & AT_REMOVEDIR) {
> +                     error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
> +             } else {
> +                     (void)uvm_vnp_uncache(vp);
> +                     error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
> +             }
> +     } else {
>               VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
>               if (nd.ni_dvp == vp)
>                       vrele(nd.ni_dvp);
>               else
>                       vput(nd.ni_dvp);
>               vput(vp);
> -             error = EBUSY;
> -             goto out;
>       }
> -
> -     (void)uvm_vnp_uncache(vp);
> -
> -     error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
> -out:
>       return (error);
>  }
>  
> @@ -2614,43 +2630,9 @@ sys_rmdir(struct proc *p, void *v, regis
>       struct sys_rmdir_args /* {
>               syscallarg(const char *) path;
>       } */ *uap = v;
> -     struct vnode *vp;
> -     int error;
> -     struct nameidata nd;
>  
> -     NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
> -         SCARG(uap, path), p);
> -     if ((error = namei(&nd)) != 0)
> -             return (error);
> -     vp = nd.ni_vp;
> -     if (vp->v_type != VDIR) {
> -             error = ENOTDIR;
> -             goto out;
> -     }
> -     /*
> -      * No rmdir "." please.
> -      */
> -     if (nd.ni_dvp == vp) {
> -             error = EBUSY;
> -             goto out;
> -     }
> -     /*
> -      * The root of a mounted filesystem cannot be deleted.
> -      */
> -     if (vp->v_flag & VROOT)
> -             error = EBUSY;
> -out:
> -     if (!error) {
> -             error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
> -     } else {
> -             VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
> -             if (nd.ni_dvp == vp)
> -                     vrele(nd.ni_dvp);
> -             else
> -                     vput(nd.ni_dvp);
> -             vput(vp);
> -     }
> -     return (error);
> +     return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), AT_REMOVEDIR,
> +         retval));
>  }
>  
>  /*

Reply via email to