Author: asomers
Date: Thu Feb  9 21:30:53 2017
New Revision: 313483
URL: https://svnweb.freebsd.org/changeset/base/313483

Log:
  Fix setting birthtime in ZFS
  
  sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
        * In zfs_freebsd_setattr, if the caller wants to set the birthtime,
          set the bits that zfs_settattr expects
  
        * In zfs_setattr, if XAT_CREATETIME is set, set xoa_createtime,
          expected by zfs_xvattr_set.  The two levels of indirection seem
          excessive, but it minimizes diffs vs OpenZFS.
  
        * In zfs_setattr, check for overflow of va_birthtime (from delphij)
  
        * Remove red herring in zfs_getattr
  
  sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
        * Un-booby-trap some macros
  
  New tests are under review at https://github.com/pjd/pjdfstest/pull/6
  
  Reviewed by:  avg
  MFC after:    3 weeks
  Sponsored by: Spectra Logic Corp
  Differential Revision:        https://reviews.freebsd.org/D9353

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Thu Feb 
 9 21:29:18 2017        (r313482)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c     Thu Feb 
 9 21:30:53 2017        (r313483)
@@ -2786,15 +2786,6 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, i
                        zfs_sa_get_scanstamp(zp, xvap);
                }
 
-               if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
-                       uint64_t times[2];
-
-                       (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs),
-                           times, sizeof (times));
-                       ZFS_TIME_DECODE(&xoap->xoa_createtime, times);
-                       XVA_SET_RTN(xvap, XAT_CREATETIME);
-               }
-
                if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
                        xoap->xoa_reparse = ((zp->z_pflags & ZFS_REPARSE) != 0);
                        XVA_SET_RTN(xvap, XAT_REPARSE);
@@ -2956,6 +2947,11 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i
                        return (SET_ERROR(EOVERFLOW));
                }
        }
+       if (xoap && (mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME) &&
+           TIMESPEC_OVERFLOW(&vap->va_birthtime)) {
+               ZFS_EXIT(zfsvfs);
+               return (SET_ERROR(EOVERFLOW));
+       }
 
        attrzp = NULL;
        aclp = NULL;
@@ -3400,6 +3396,8 @@ zfs_setattr(vnode_t *vp, vattr_t *vap, i
 
        if (xoap && (mask & AT_XVATTR)) {
 
+               if (XVA_ISSET_REQ(xvap, XAT_CREATETIME))
+                       xoap->xoa_createtime = vap->va_birthtime;
                /*
                 * restore trimmed off masks
                 * so that return masks can be set for caller.
@@ -5251,6 +5249,10 @@ zfs_freebsd_setattr(ap)
                    xvap.xva_xoptattrs.xoa_sparse);
 #undef FLAG_CHANGE
        }
+       if (vap->va_birthtime.tv_sec != VNOVAL) {
+               xvap.xva_vattr.va_mask |= AT_XVATTR;
+               XVA_SET_REQ(&xvap, XAT_CREATETIME);
+       }
        return (zfs_setattr(vp, (vattr_t *)&xvap, 0, cred, NULL));
 }
 

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h    Thu Feb  9 
21:29:18 2017        (r313482)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/vnode.h    Thu Feb  9 
21:30:53 2017        (r313483)
@@ -268,27 +268,30 @@ typedef struct xvattr {
  * XVA_SET_REQ() sets an attribute bit in the proper element in the bitmap
  * of requested attributes (xva_reqattrmap[]).
  */
-#define        XVA_SET_REQ(xvap, attr)                                 \
+#define        XVA_SET_REQ(xvap, attr) {                               \
        ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR);          \
        ASSERT((xvap)->xva_magic == XVA_MAGIC);                 \
-       (xvap)->xva_reqattrmap[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr)
+       (xvap)->xva_reqattrmap[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr); \
+}
 /*
  * XVA_CLR_REQ() clears an attribute bit in the proper element in the bitmap
  * of requested attributes (xva_reqattrmap[]).
  */
-#define        XVA_CLR_REQ(xvap, attr)                                 \
+#define        XVA_CLR_REQ(xvap, attr) {                               \
        ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR);          \
        ASSERT((xvap)->xva_magic == XVA_MAGIC);                 \
-       (xvap)->xva_reqattrmap[XVA_INDEX(attr)] &= ~XVA_ATTRBIT(attr)
+       (xvap)->xva_reqattrmap[XVA_INDEX(attr)] &= ~XVA_ATTRBIT(attr); \
+}
 
 /*
  * XVA_SET_RTN() sets an attribute bit in the proper element in the bitmap
  * of returned attributes (xva_rtnattrmap[]).
  */
-#define        XVA_SET_RTN(xvap, attr)                                 \
+#define        XVA_SET_RTN(xvap, attr) {                               \
        ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR);          \
        ASSERT((xvap)->xva_magic == XVA_MAGIC);                 \
-       (XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr)
+       (XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr); \
+}
 
 /*
  * XVA_ISSET_REQ() checks the requested attribute bitmap (xva_reqattrmap[])
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to