Author: kib
Date: Tue Dec 22 20:37:34 2015
New Revision: 292624
URL: https://svnweb.freebsd.org/changeset/base/292624

Log:
  Make it possible for the cdevsw d_close() driver method to detect last
  close and close due to revoke(2)-like operation.
  
  A new FLASTCLOSE flag indicates that this is last close.  FREVOKE is
  set for revokes, and FNONBLOCK is also set, same as is already done
  for VOP_CLOSE() call from vgonel().
  
  The flags reuse user open(2) flags which are never stored in f_flag,
  to not consume bit space in the ABI visible way.  Assert this with the
  static check.
  
  Requested and reviewed by:    bde
  Sponsored by: The FreeBSD Foundation
  MFC after:    2 weeks

Modified:
  head/sys/fs/devfs/devfs_vnops.c
  head/sys/sys/fcntl.h

Modified: head/sys/fs/devfs/devfs_vnops.c
==============================================================================
--- head/sys/fs/devfs/devfs_vnops.c     Tue Dec 22 20:36:14 2015        
(r292623)
+++ head/sys/fs/devfs/devfs_vnops.c     Tue Dec 22 20:37:34 2015        
(r292624)
@@ -557,7 +557,9 @@ devfs_access(struct vop_access_args *ap)
        return (error);
 }
 
-/* ARGSUSED */
+_Static_assert(((FMASK | FCNTLFLAGS) & (FLASTCLOSE | FREVOKE)) == 0,
+    "devfs-only flag reuse failed");
+
 static int
 devfs_close(struct vop_close_args *ap)
 {
@@ -566,7 +568,7 @@ devfs_close(struct vop_close_args *ap)
        struct proc *p;
        struct cdev *dev = vp->v_rdev;
        struct cdevsw *dsw;
-       int vp_locked, error, ref;
+       int dflags, error, ref, vp_locked;
 
        /*
         * XXX: Don't call d_close() if we were called because of
@@ -621,9 +623,11 @@ devfs_close(struct vop_close_args *ap)
        dsw = dev_refthread(dev, &ref);
        if (dsw == NULL)
                return (ENXIO);
+       dflags = 0;
        VI_LOCK(vp);
        if (vp->v_iflag & VI_DOOMED) {
                /* Forced close. */
+               dflags |= FREVOKE | FNONBLOCK;
        } else if (dsw->d_flags & D_TRACKCLOSE) {
                /* Keep device updated on status. */
        } else if (count_dev(dev) > 1) {
@@ -631,13 +635,15 @@ devfs_close(struct vop_close_args *ap)
                dev_relthread(dev, ref);
                return (0);
        }
+       if (count_dev(dev) == 1)
+               dflags |= FLASTCLOSE;
        vholdl(vp);
        VI_UNLOCK(vp);
        vp_locked = VOP_ISLOCKED(vp);
        VOP_UNLOCK(vp, 0);
        KASSERT(dev->si_refcount > 0,
            ("devfs_close() on un-referenced struct cdev *(%s)", 
devtoname(dev)));
-       error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
+       error = dsw->d_close(dev, ap->a_fflag | dflags, S_IFCHR, td);
        dev_relthread(dev, ref);
        vn_lock(vp, vp_locked | LK_RETRY);
        vdrop(vp);

Modified: head/sys/sys/fcntl.h
==============================================================================
--- head/sys/sys/fcntl.h        Tue Dec 22 20:36:14 2015        (r292623)
+++ head/sys/sys/fcntl.h        Tue Dec 22 20:37:34 2015        (r292624)
@@ -138,6 +138,11 @@ typedef    __pid_t         pid_t;
  */
 
 #ifdef _KERNEL
+
+/* Only for devfs d_close() flags. */
+#define        FLASTCLOSE      O_DIRECTORY
+#define        FREVOKE         O_VERIFY
+
 /* convert from open() flags to/from fflags; convert O_RD/WR to FREAD/FWRITE */
 #define        FFLAGS(oflags)  ((oflags) & O_EXEC ? (oflags) : (oflags) + 1)
 #define        OFLAGS(fflags)  ((fflags) & O_EXEC ? (fflags) : (fflags) - 1)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to