diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h index c33df366e73d..bdc54941e184 100644 --- a/include/sys/zfs_vnops.h +++ b/include/sys/zfs_vnops.h @@ -51,10 +51,8 @@ extern int zfs_rmdir(struct inode *dip, char *name, struct inode *cwd, extern int zfs_readdir(struct inode *ip, void *dirent, filldir_t filldir, loff_t *pos, cred_t *cr); extern int zfs_fsync(struct inode *ip, int syncflag, cred_t *cr); -extern int zfs_getattr(struct inode *ip, struct kstat *stat, int flag, - cred_t *cr); -extern int zfs_setattr(struct inode *ip, struct iattr *attr, int flag, - cred_t *cr); +extern int zfs_getattr(struct inode *ip, vattr_t *vap, int flag, cred_t *cr); +extern int zfs_setattr(struct inode *ip, vattr_t *vap, int flag, cred_t *cr); extern int zfs_rename(struct inode *sdip, char *snm, struct inode *tdip, char *tnm, cred_t *cr, int flags); extern int zfs_symlink(struct inode *dip, char *name, vattr_t *vap, diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h index 9d12a118ec31..4e0b611bd96d 100644 --- a/include/sys/zfs_znode.h +++ b/include/sys/zfs_znode.h @@ -57,8 +57,8 @@ extern "C" { #define ZFS_APPENDONLY 0x0000004000000000ull #define ZFS_NODUMP 0x0000008000000000ull #define ZFS_OPAQUE 0x0000010000000000ull -#define ZFS_AV_QUARANTINED 0x0000020000000000ull -#define ZFS_AV_MODIFIED 0x0000040000000000ull +#define ZFS_AV_QUARANTINED 0x0000020000000000ull +#define ZFS_AV_MODIFIED 0x0000040000000000ull #define ZFS_REPARSE 0x0000080000000000ull #define ZFS_OFFLINE 0x0000100000000000ull #define ZFS_SPARSE 0x0000200000000000ull @@ -69,7 +69,7 @@ extern "C" { pflags |= attr; \ else \ pflags &= ~attr; \ - VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zp->z_sb), \ + VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(ZTOZSB(zp)), \ &pflags, sizeof (pflags), tx)); \ } @@ -78,8 +78,8 @@ extern "C" { */ #define ZFS_XATTR 0x1 /* is an extended attribute */ #define ZFS_INHERIT_ACE 0x2 /* ace has inheritable ACEs */ -#define ZFS_ACL_TRIVIAL 0x4 /* files ACL is trivial */ -#define ZFS_ACL_OBJ_ACE 0x8 /* ACL has CMPLX Object ACE */ +#define ZFS_ACL_TRIVIAL 0x4 /* files ACL is trivial */ +#define ZFS_ACL_OBJ_ACE 0x8 /* ACL has CMPLX Object ACE */ #define ZFS_ACL_PROTECTED 0x10 /* ACL protected */ #define ZFS_ACL_DEFAULTED 0x20 /* ACL should be defaulted */ #define ZFS_ACL_AUTO_INHERIT 0x40 /* ACL should be inherited */ @@ -351,8 +351,7 @@ extern void zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, extern void zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, uint64_t off, uint64_t len); extern void zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, - znode_t *zp, struct iattr *attr, uint_t mask_applied, - zfs_fuid_info_t *fuidp); + znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp); extern void zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, vsecattr_t *vsecp, zfs_fuid_info_t *fuidp); extern void zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx); diff --git a/module/zfs/zfs_fuid.c b/module/zfs/zfs_fuid.c index ca03373c7a60..debb5f86d377 100644 --- a/module/zfs/zfs_fuid.c +++ b/module/zfs/zfs_fuid.c @@ -415,10 +415,10 @@ zfs_fuid_map_id(zfs_sb_t *zsb, uint64_t fuid, } return (id); #else - if(type == ZFS_OWNER || type == ZFS_ACE_USER) - return (crgetuid(cr)); - else - return (crgetgid(cr)); + /* + * The Linux port only supports POSIX IDs, use the passed id. + */ + return (fuid); #endif /* HAVE_KSID */ } diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index 5cdbb6c8d744..4d9e13d5026e 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -69,11 +69,7 @@ int zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap) { -#ifdef HAVE_XVATTR - int isxvattr = (vap->va_mask & AT_XVATTR); -#else - int isxvattr = 0; -#endif /* HAVE_XVATTR */ + int isxvattr = (vap->va_mask & ATTR_XVATTR); switch (type) { case Z_FILE: if (vsecp == NULL && !isxvattr) @@ -101,7 +97,6 @@ zfs_log_create_txtype(zil_create_t type, vsecattr_t *vsecp, vattr_t *vap) return (TX_MAX_TYPE); } -#ifdef HAVE_XVATTR /* * build up the log data necessary for logging xvattr_t * First lr_attr_t is initialized. following the lr_attr_t @@ -215,7 +210,6 @@ zfs_log_fuid_domains(zfs_fuid_info_t *fuidp, void *start) } return (start); } -#endif /* HAVE_XVATTR */ /* * zfs_log_create() is used to handle TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, @@ -244,11 +238,9 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, { itx_t *itx; lr_create_t *lr; -#ifdef HAVE_XVATTR lr_acl_create_t *lracl; xvattr_t *xvap = (xvattr_t *)vap; -#endif /* HAVE_XVATTR */ - size_t aclsize; + size_t aclsize = 0; size_t xvatsize = 0; size_t txsize; void *end; @@ -268,10 +260,8 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, fuidsz += fuidp->z_fuid_cnt * sizeof (uint64_t); } -#ifdef HAVE_XVATTR - if (vap->va_mask & AT_XVATTR) + if (vap->va_mask & ATTR_XVATTR) xvatsize = ZIL_XVAT_SIZE(xvap->xva_mapsize); -#endif /* HAVE_XVATTR */ if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR || (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR || @@ -314,8 +304,7 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, /* * Fill in xvattr info if any */ -#ifdef HAVE_XVATTR - if (vap->va_mask & AT_XVATTR) { + if (vap->va_mask & ATTR_XVATTR) { zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap); end = (caddr_t)lr + lrsize + xvatsize; } else { @@ -344,9 +333,6 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, end = zfs_log_fuid_ids(fuidp, end); end = zfs_log_fuid_domains(fuidp, end); } -#else - end = (caddr_t)lr + lrsize; -#endif /* HAVE_XVATTR */ /* * Now place file name in log record */ @@ -566,14 +552,12 @@ zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype, * zfs_log_setattr() handles TX_SETATTR transactions. */ void -zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, - struct iattr *attr, uint_t mask_applied, zfs_fuid_info_t *fuidp) +zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, + znode_t *zp, vattr_t *vap, uint_t mask_applied, zfs_fuid_info_t *fuidp) { itx_t *itx; lr_setattr_t *lr; -#ifdef HAVE_XVATTR xvattr_t *xvap = (xvattr_t *)vap; -#endif /* HAVEXVATTR */ size_t recsize = sizeof (lr_setattr_t); void *start; @@ -585,35 +569,32 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, * for lr_attr_t + xvattr mask, mapsize and create time * plus actual attribute values */ -#ifdef HAVE_XVATTR - if (attr->ia_valid & AT_XVATTR) + if (vap->va_mask & ATTR_XVATTR) recsize = sizeof (*lr) + ZIL_XVAT_SIZE(xvap->xva_mapsize); if (fuidp) recsize += fuidp->z_domain_str_sz; -#endif /* HAVE_XVATTR */ itx = zil_itx_create(txtype, recsize); lr = (lr_setattr_t *)&itx->itx_lr; lr->lr_foid = zp->z_id; lr->lr_mask = (uint64_t)mask_applied; - lr->lr_mode = (uint64_t)attr->ia_mode; - if ((mask_applied & ATTR_UID) && IS_EPHEMERAL(attr->ia_uid)) + lr->lr_mode = (uint64_t)vap->va_mode; + if ((mask_applied & ATTR_UID) && IS_EPHEMERAL(vap->va_uid)) lr->lr_uid = fuidp->z_fuid_owner; else - lr->lr_uid = (uint64_t)attr->ia_uid; + lr->lr_uid = (uint64_t)vap->va_uid; - if ((mask_applied & ATTR_GID) && IS_EPHEMERAL(attr->ia_gid)) + if ((mask_applied & ATTR_GID) && IS_EPHEMERAL(vap->va_gid)) lr->lr_gid = fuidp->z_fuid_group; else - lr->lr_gid = (uint64_t)attr->ia_gid; + lr->lr_gid = (uint64_t)vap->va_gid; - lr->lr_size = (uint64_t)attr->ia_size; - ZFS_TIME_ENCODE(&attr->ia_atime, lr->lr_atime); - ZFS_TIME_ENCODE(&attr->ia_mtime, lr->lr_mtime); + lr->lr_size = (uint64_t)vap->va_size; + ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime); + ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime); start = (lr_setattr_t *)(lr + 1); -#ifdef HAVE_XVATTR - if (attr->ia_valid & ATTR_XVATTR) { + if (vap->va_mask & ATTR_XVATTR) { zfs_log_xvattr((lr_attr_t *)start, xvap); start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize); } @@ -624,7 +605,6 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp, if (fuidp) (void) zfs_log_fuid_domains(fuidp, start); -#endif /* HAVE_XVATTR */ itx->itx_sync = (zp->z_sync_cnt != 0); zil_itx_assign(zilog, itx, tx); @@ -686,12 +666,10 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes); -#ifdef HAVE_XVATTR if (fuidp) { start = zfs_log_fuid_ids(fuidp, start); (void) zfs_log_fuid_domains(fuidp, start); } -#endif /* HAVE_XVATTR */ } itx->itx_sync = (zp->z_sync_cnt != 0); diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index f02d5add3177..a5018ee608e2 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -37,15 +37,16 @@ #include #include #include +#include #include #include -#include #include #include #include #include #include #include +#include /* * Functions to replay ZFS intent log (ZIL) records @@ -54,14 +55,17 @@ */ static void -zfs_init_iattr(struct iattr *attr, uint64_t mask, uint64_t mode, - uint64_t uid, uint64_t gid) +zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode, + uint64_t uid, uint64_t gid, uint64_t rdev, uint64_t nodeid) { - memset(attr, 0, sizeof(*attr)); - attr->ia_valid = (uint_t)mask; - attr->ia_mode = mode; - attr->ia_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; - attr->ia_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; + bzero(vap, sizeof (*vap)); + vap->va_mask = (uint_t)mask; + vap->va_type = IFTOVT(mode); + vap->va_mode = mode; + vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid; + vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid; + vap->va_rdev = rdev; + vap->va_nodeid = nodeid; } /* ARGSUSED */ @@ -71,7 +75,6 @@ zfs_replay_error(zfs_sb_t *zsb, lr_t *lr, boolean_t byteswap) return (ENOTSUP); } -#ifdef HAVE_XVATTR static void zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) { @@ -82,9 +85,9 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) void *scanstamp; int i; - xvap->xva_vattr.va_mask |= AT_XVATTR; + xvap->xva_vattr.va_mask |= ATTR_XVATTR; if ((xoap = xva_getxoptattr(xvap)) == NULL) { - xvap->xva_vattr.va_mask &= ~AT_XVATTR; /* shouldn't happen */ + xvap->xva_vattr.va_mask &= ~ATTR_XVATTR; /* shouldn't happen */ return; } @@ -132,7 +135,6 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap) if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0); } -#endif /* HAVE_XVATTR */ static int zfs_replay_domain_cnt(uint64_t uid, uint64_t gid) @@ -267,11 +269,9 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) lr_create_t *lr = (lr_create_t *)lracl; znode_t *dzp; struct inode *ip = NULL; -#ifdef HAVE_XVATTR xvattr_t xva; - vsecattr_t vsec = { 0 }; -#endif /* HAVE_XVATTR */ int vflg = 0; + vsecattr_t vsec = { 0 }; lr_attr_t *lrattr; void *aclstart; void *fuidstart; @@ -302,10 +302,9 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0) return (error); -#ifdef HAVE_XVATTR xva_init(&xva); - zfs_init_iattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID, - lr->lr_mode, lr->lr_uid, lr->lr_gid, /*lr->lr_rdev, lr->lr_foid*/); + zfs_init_vattr(&xva.xva_vattr, AT_MODE | AT_UID | AT_GID, + lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) @@ -316,7 +315,6 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) */ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); xva.xva_vattr.va_nblocks = lr->lr_gen; -#endif /* HAVE_XVATTR */ error = dmu_object_info(zsb->z_os, lr->lr_foid, NULL); if (error != ENOENT) @@ -334,11 +332,10 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) lr->lr_uid, lr->lr_gid); /*FALLTHROUGH*/ case TX_CREATE_ACL_ATTR: -#ifdef HAVE_XVATTR if (name == NULL) { lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); - xva.xva_vattr.va_mask |= AT_XVATTR; + xva.xva_vattr.va_mask |= ATTR_XVATTR; zfs_replay_xvattr(lrattr, &xva); } vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; @@ -356,8 +353,7 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) } error = zfs_create(ZTOI(dzp), name, &xva.xva_vattr, - 0, 0, &ip, kcred, vflg, NULL, &vsec); -#endif /* HAVE_XVATTR */ + 0, 0, &ip, kcred, vflg, &vsec); break; case TX_MKDIR_ACL: aclstart = (caddr_t)(lracl + 1); @@ -368,7 +364,6 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) lr->lr_uid, lr->lr_gid); /*FALLTHROUGH*/ case TX_MKDIR_ACL_ATTR: -#ifdef HAVE_XVATTR if (name == NULL) { lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); @@ -388,8 +383,7 @@ zfs_replay_create_acl(zfs_sb_t *zsb, lr_acl_create_t *lracl, boolean_t byteswap) lr->lr_uid, lr->lr_gid); } error = zfs_mkdir(ZTOI(dzp), name, &xva.xva_vattr, - &ip, kcred, NULL, vflg, &vsec); -#endif /* HAVE_XVATTR */ + &ip, kcred, vflg, &vsec); break; default: error = ENOTSUP; @@ -417,12 +411,10 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) struct inode *ip = NULL; xvattr_t xva; int vflg = 0; -#ifdef HAVE_XVATTR size_t lrsize = sizeof (lr_create_t); lr_attr_t *lrattr; - size_t xvatlen; -#endif /* HAVE_XVATTR */ void *start; + size_t xvatlen; uint64_t txtype; int error; @@ -437,10 +429,9 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0) return (error); -#ifdef HAVE_XVATTR xva_init(&xva); - zfs_init_iattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID, - lr->lr_mode, lr->lr_uid, lr->lr_gid, /*lr->lr_rdev, lr->lr_foid*/); + zfs_init_vattr(&xva.xva_vattr, AT_MODE | AT_UID | AT_GID, + lr->lr_mode, lr->lr_uid, lr->lr_gid, lr->lr_rdev, lr->lr_foid); /* * All forms of zfs create (create, mkdir, mkxattrdir, symlink) @@ -451,7 +442,6 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) */ ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_crtime); xva.xva_vattr.va_nblocks = lr->lr_gen; -#endif /* HAVE_XVATTR */ error = dmu_object_info(zsb->z_os, lr->lr_foid, NULL); if (error != ENOENT) @@ -477,7 +467,6 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) switch (txtype) { case TX_CREATE_ATTR: -#ifdef HAVE_XVATTR lrattr = (lr_attr_t *)(caddr_t)(lr + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); @@ -486,7 +475,6 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); name = (char *)start; -#endif /* HAVE_XVATTR */ /*FALLTHROUGH*/ case TX_CREATE: @@ -497,7 +485,6 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) 0, 0, &ip, kcred, vflg, NULL); break; case TX_MKDIR_ATTR: -#ifdef HAVE_XVATTR lrattr = (lr_attr_t *)(caddr_t)(lr + 1); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); @@ -506,7 +493,6 @@ zfs_replay_create(zfs_sb_t *zsb, lr_create_t *lr, boolean_t byteswap) zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); name = (char *)start; -#endif /* HAVE_XVATTR */ /*FALLTHROUGH*/ case TX_MKDIR: @@ -555,10 +541,8 @@ zfs_replay_remove(zfs_sb_t *zsb, lr_remove_t *lr, boolean_t byteswap) if ((error = zfs_zget(zsb, lr->lr_doid, &dzp)) != 0) return (error); -#ifdef HAVE_PN_UTILS if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; -#endif switch ((int)lr->lr_common.lrc_txtype) { case TX_REMOVE: @@ -582,6 +566,7 @@ zfs_replay_link(zfs_sb_t *zsb, lr_link_t *lr, boolean_t byteswap) char *name = (char *)(lr + 1); /* name follows lr_link_t */ znode_t *dzp, *zp; int error; + int vflg = 0; if (byteswap) byteswap_uint64_array(lr, sizeof (*lr)); @@ -594,10 +579,8 @@ zfs_replay_link(zfs_sb_t *zsb, lr_link_t *lr, boolean_t byteswap) return (error); } -#ifdef HAVE_PN_UTILS if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; -#endif error = zfs_link(ZTOI(dzp), ZTOI(zp), name, kcred); @@ -641,9 +624,7 @@ zfs_replay_rename(zfs_sb_t *zsb, lr_rename_t *lr, boolean_t byteswap) static int zfs_replay_write(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap) { -#if 0 char *data = (char *)(lr + 1); /* data follows lr_write_t */ -#endif znode_t *zp; int error; uint64_t eod, offset, length; @@ -690,13 +671,14 @@ zfs_replay_write(zfs_sb_t *zsb, lr_write_t *lr, boolean_t byteswap) zsb->z_replay_eof = eod; } - /* - * XXX: Use zfs_write() once uio types are removed - */ -#if 0 - error = vn_rdwr(UIO_WRITE, ZTOI(zp), data, length, offset, - UIO_SYSSPACE, 0, RLIM64_INFINITY, kcred, &resid); -#endif + error = zpl_write_common(ZTOI(zp), data, length, offset, + UIO_SYSSPACE, 0, kcred); + if (error) { + if (error < 0) + error = -error; + else + error = EIO; /* Short write */ + } iput(ZTOI(zp)); zsb->z_replay_eof = 0; /* safety */ @@ -786,53 +768,46 @@ static int zfs_replay_setattr(zfs_sb_t *zsb, lr_setattr_t *lr, boolean_t byteswap) { znode_t *zp; -#ifdef HAVE_XVATTR xvattr_t xva; -#endif /* HAVE_XATTR */ - struct iattr attr; + vattr_t *vap = &xva.xva_vattr; int error; void *start; -#ifdef HAVE_XVATTR xva_init(&xva); -#endif /* HAVE_XVATTR */ if (byteswap) { byteswap_uint64_array(lr, sizeof (*lr)); -#ifdef HAVE_XVATTR - if ((lr->lr_mask & AT_XVATTR) && + if ((lr->lr_mask & ATTR_XVATTR) && zsb->z_version >= ZPL_VERSION_INITIAL) zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); -#endif /* HAVE_XVATTR */ } if ((error = zfs_zget(zsb, lr->lr_foid, &zp)) != 0) return (error); - zfs_init_iattr(&attr, lr->lr_mask, lr->lr_mode, lr->lr_uid, lr->lr_gid); + zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, + lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); - attr.ia_size = lr->lr_size; - ZFS_TIME_DECODE(&attr.ia_atime, lr->lr_atime); - ZFS_TIME_DECODE(&attr.ia_mtime, lr->lr_mtime); + vap->va_size = lr->lr_size; + ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); + ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); /* * Fill in xvattr_t portions if necessary. */ start = (lr_setattr_t *)(lr + 1); -#ifdef HAVE_XVATTR - if (iattr->ia_mask & AT_XVATTR) { + if (vap->va_mask & ATTR_XVATTR) { zfs_replay_xvattr((lr_attr_t *)start, &xva); start = (caddr_t)start + ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); } else - xva.xva_vattr.va_mask &= ~AT_XVATTR; -#endif /* HAVE_XVATTR */ + xva.xva_vattr.va_mask &= ~ATTR_XVATTR; zsb->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); - error = zfs_setattr(ZTOI(zp), &attr, 0, kcred); + error = zfs_setattr(ZTOI(zp), vap, 0, kcred); zfs_fuid_info_free(zsb->z_fuid_replay); zsb->z_fuid_replay = NULL; diff --git a/module/zfs/zfs_sa.c b/module/zfs/zfs_sa.c index ed696490fa06..b8f208bbab30 100644 --- a/module/zfs/zfs_sa.c +++ b/module/zfs/zfs_sa.c @@ -118,7 +118,6 @@ zfs_sa_symlink(znode_t *zp, char *link, int len, dmu_tx_t *tx) } } -#ifdef HAVE_SCANSTAMP void zfs_sa_get_scanstamp(znode_t *zp, xvattr_t *xvap) { @@ -183,7 +182,6 @@ zfs_sa_set_scanstamp(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) &zp->z_pflags, sizeof (uint64_t), tx)); } } -#endif /* HAVE_SCANSTAMP */ /* * I'm not convinced we should do any of this upgrade. @@ -205,9 +203,7 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx) uint64_t uid, gid, mode, rdev, xattr, parent; uint64_t crtime[2], mtime[2], ctime[2]; zfs_acl_phys_t znode_acl; -#ifdef HAVE_SCANSTAMP char scanstamp[AV_SCANSTAMP_SZ]; -#endif /* HAVE_SCANSTAMP */ boolean_t drop_lock = B_FALSE; /* @@ -298,7 +294,6 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx) SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_XATTR(zsb), NULL, &xattr, 8); -#ifdef HAVE_SCANSTAMP /* if scanstamp then add scanstamp */ if (zp->z_pflags & ZFS_BONUS_SCANSTAMP) { @@ -308,7 +303,6 @@ zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx) NULL, scanstamp, AV_SCANSTAMP_SZ); zp->z_pflags &= ~ZFS_BONUS_SCANSTAMP; } -#endif /* HAVE_SCANSTAMP */ VERIFY(dmu_set_bonustype(db, DMU_OT_SA, tx) == 0); VERIFY(sa_replace_all_by_template_locked(hdl, sa_attrs, diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 5d6b0611cf45..2dcbfe00d655 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -1174,15 +1174,13 @@ zfs_create(struct inode *dip, char *name, vattr_t *vap, int excl, return (EILSEQ); } -#ifdef HAVE_XVATTR - if (vap->va_mask & AT_XVATTR) { + if (vap->va_mask & ATTR_XVATTR) { if ((error = secpolicy_xvattr((xvattr_t *)vap, crgetuid(cr), cr, vap->va_mode)) != 0) { ZFS_EXIT(zsb); return (error); } } -#endif /* HAVE_XVATTR */ top: *ipp = NULL; @@ -1613,15 +1611,13 @@ zfs_mkdir(struct inode *dip, char *dirname, vattr_t *vap, struct inode **ipp, if (flags & FIGNORECASE) zf |= ZCILOOK; -#ifdef HAVE_XVATTR - if (vap->va_mask & AT_XVATTR) { + if (vap->va_mask & ATTR_XVATTR) { if ((error = secpolicy_xvattr((xvattr_t *)vap, crgetuid(cr), cr, vap->va_mode)) != 0) { ZFS_EXIT(zsb); return (error); } } -#endif /* HAVE_XVATTR */ if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, vsecp, &acl_ids)) != 0) { @@ -2029,22 +2025,26 @@ EXPORT_SYMBOL(zfs_fsync); * vattr structure. * * IN: ip - inode of file. - * stat - kstat structure to fill in. + * vap - va_mask identifies requested attributes. + * If ATTR_XVATTR set, then optional attrs are requested * flags - ATTR_NOACLCHECK (CIFS server context) * cr - credentials of caller. * - * OUT: stat - filled in kstat values. + * OUT: vap - attribute values. + * + * RETURN: 0 (always succeeds) */ /* ARGSUSED */ int -zfs_getattr(struct inode *ip, struct kstat *stat, int flags, cred_t *cr) +zfs_getattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) { znode_t *zp = ITOZ(ip); zfs_sb_t *zsb = ITOZSB(ip); int error = 0; uint64_t links; uint64_t mtime[2], ctime[2]; - uint32_t blksz; + xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ + xoptattr_t *xoap = NULL; boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; sa_bulk_attr_t bulk[2]; int count = 0; @@ -2052,7 +2052,7 @@ zfs_getattr(struct inode *ip, struct kstat *stat, int flags, cred_t *cr) ZFS_ENTER(zsb); ZFS_VERIFY_ZP(zp); - zfs_fuid_map_ids(zp, cr, &stat->uid, &stat->gid); + zfs_fuid_map_ids(zp, cr, &vap->va_uid, &vap->va_gid); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, &mtime, 16); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zsb), NULL, &ctime, 16); @@ -2068,7 +2068,7 @@ zfs_getattr(struct inode *ip, struct kstat *stat, int flags, cred_t *cr) * always be allowed to read basic attributes of file. */ if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) && - (stat->uid != crgetuid(cr))) { + (vap->va_uid != crgetuid(cr))) { if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0, skipaclchk, cr))) { ZFS_EXIT(zsb); @@ -2082,33 +2082,139 @@ zfs_getattr(struct inode *ip, struct kstat *stat, int flags, cred_t *cr) */ mutex_enter(&zp->z_lock); - stat->ino = ip->i_ino; - stat->mode = zp->z_mode; - stat->uid = zp->z_uid; - stat->gid = zp->z_gid; + vap->va_type = vn_mode_to_vtype(zp->z_mode); + vap->va_mode = zp->z_mode; + vap->va_fsid = 0; + vap->va_nodeid = zp->z_id; if ((zp->z_id == zsb->z_root) && zfs_show_ctldir(zp)) links = zp->z_links + 1; else links = zp->z_links; - stat->nlink = MIN(links, ZFS_LINK_MAX); - stat->size = i_size_read(ip); - stat->rdev = ip->i_rdev; - stat->dev = ip->i_rdev; + vap->va_nlink = MIN(links, ZFS_LINK_MAX); + vap->va_size = i_size_read(ip); + vap->va_rdev = ip->i_rdev; + vap->va_seq = ip->i_generation; - ZFS_TIME_DECODE(&stat->atime, zp->z_atime); - ZFS_TIME_DECODE(&stat->mtime, mtime); - ZFS_TIME_DECODE(&stat->ctime, ctime); + /* + * Add in any requested optional attributes and the create time. + * Also set the corresponding bits in the returned attribute bitmap. + */ + if ((xoap = xva_getxoptattr(xvap)) != NULL && zsb->z_use_fuids) { + if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { + xoap->xoa_archive = + ((zp->z_pflags & ZFS_ARCHIVE) != 0); + XVA_SET_RTN(xvap, XAT_ARCHIVE); + } + + if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { + xoap->xoa_readonly = + ((zp->z_pflags & ZFS_READONLY) != 0); + XVA_SET_RTN(xvap, XAT_READONLY); + } + + if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { + xoap->xoa_system = + ((zp->z_pflags & ZFS_SYSTEM) != 0); + XVA_SET_RTN(xvap, XAT_SYSTEM); + } + + if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { + xoap->xoa_hidden = + ((zp->z_pflags & ZFS_HIDDEN) != 0); + XVA_SET_RTN(xvap, XAT_HIDDEN); + } + + if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { + xoap->xoa_nounlink = + ((zp->z_pflags & ZFS_NOUNLINK) != 0); + XVA_SET_RTN(xvap, XAT_NOUNLINK); + } + + if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { + xoap->xoa_immutable = + ((zp->z_pflags & ZFS_IMMUTABLE) != 0); + XVA_SET_RTN(xvap, XAT_IMMUTABLE); + } + + if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { + xoap->xoa_appendonly = + ((zp->z_pflags & ZFS_APPENDONLY) != 0); + XVA_SET_RTN(xvap, XAT_APPENDONLY); + } + + if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { + xoap->xoa_nodump = + ((zp->z_pflags & ZFS_NODUMP) != 0); + XVA_SET_RTN(xvap, XAT_NODUMP); + } + + if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { + xoap->xoa_opaque = + ((zp->z_pflags & ZFS_OPAQUE) != 0); + XVA_SET_RTN(xvap, XAT_OPAQUE); + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { + xoap->xoa_av_quarantined = + ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0); + XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { + xoap->xoa_av_modified = + ((zp->z_pflags & ZFS_AV_MODIFIED) != 0); + XVA_SET_RTN(xvap, XAT_AV_MODIFIED); + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) && + S_ISREG(ip->i_mode)) { + 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(zsb), + 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); + } + if (XVA_ISSET_REQ(xvap, XAT_GEN)) { + xoap->xoa_generation = zp->z_gen; + XVA_SET_RTN(xvap, XAT_GEN); + } + + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { + xoap->xoa_offline = + ((zp->z_pflags & ZFS_OFFLINE) != 0); + XVA_SET_RTN(xvap, XAT_OFFLINE); + } + + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { + xoap->xoa_sparse = + ((zp->z_pflags & ZFS_SPARSE) != 0); + XVA_SET_RTN(xvap, XAT_SPARSE); + } + } + + ZFS_TIME_DECODE(&vap->va_atime, zp->z_atime); + ZFS_TIME_DECODE(&vap->va_mtime, mtime); + ZFS_TIME_DECODE(&vap->va_ctime, ctime); mutex_exit(&zp->z_lock); - sa_object_size(zp->z_sa_hdl, &blksz, &stat->blocks); - stat->blksize = (1 << ip->i_blkbits); + sa_object_size(zp->z_sa_hdl, &vap->va_blksize, &vap->va_nblocks); if (zp->z_blksz == 0) { /* * Block size hasn't been set; suggest maximal I/O transfers. */ - stat->blksize = zsb->z_max_blksz; + vap->va_blksize = zsb->z_max_blksz; } ZFS_EXIT(zsb); @@ -2122,7 +2228,7 @@ EXPORT_SYMBOL(zfs_getattr); * * IN: ip - inode of file to be modified. * vap - new attribute values. - * If AT_XVATTR set, then optional attrs are being set + * If ATTR_XVATTR set, then optional attrs are being set * flags - ATTR_UTIME set if non-default time values provided. * - ATTR_NOACLCHECK (CIFS context only). * cr - credentials of caller. @@ -2135,14 +2241,15 @@ EXPORT_SYMBOL(zfs_getattr); */ /* ARGSUSED */ int -zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) +zfs_setattr(struct inode *ip, vattr_t *vap, int flags, cred_t *cr) { znode_t *zp = ITOZ(ip); zfs_sb_t *zsb = ITOZSB(ip); zilog_t *zilog; dmu_tx_t *tx; vattr_t oldva; - uint_t mask = attr->ia_valid; + xvattr_t tmpxvattr; + uint_t mask = vap->va_mask; uint_t saved_mask; int trim_mask = 0; uint64_t new_mode; @@ -2153,8 +2260,10 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) int need_policy = FALSE; int err, err2; zfs_fuid_info_t *fuidp = NULL; + xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */ + xoptattr_t *xoap; + zfs_acl_t *aclp; boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE; - zfs_acl_t *aclp = NULL; boolean_t fuid_dirtied = B_FALSE; sa_bulk_attr_t bulk[7], xattr_bulk[7]; int count = 0, xattr_count = 0; @@ -2171,9 +2280,11 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) * Make sure that if we have ephemeral uid/gid or xvattr specified * that file system is at proper version level */ + if (zsb->z_use_fuids == B_FALSE && - (((mask & ATTR_UID) && IS_EPHEMERAL(attr->ia_uid)) || - ((mask & ATTR_GID) && IS_EPHEMERAL(attr->ia_gid)))) { + (((mask & ATTR_UID) && IS_EPHEMERAL(vap->va_uid)) || + ((mask & ATTR_GID) && IS_EPHEMERAL(vap->va_gid)) || + (mask & ATTR_XVATTR))) { ZFS_EXIT(zsb); return (EINVAL); } @@ -2188,11 +2299,43 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) return (EINVAL); } + /* + * If this is an xvattr_t, then get a pointer to the structure of + * optional attributes. If this is NULL, then we have a vattr_t. + */ + xoap = xva_getxoptattr(xvap); + + xva_init(&tmpxvattr); + + /* + * Immutable files can only alter immutable bit and atime + */ + if ((zp->z_pflags & ZFS_IMMUTABLE) && + ((mask & (ATTR_SIZE|ATTR_UID|ATTR_GID|ATTR_MTIME|ATTR_MODE)) || + ((mask & ATTR_XVATTR) && XVA_ISSET_REQ(xvap, XAT_CREATETIME)))) { + ZFS_EXIT(zsb); + return (EPERM); + } + if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) { ZFS_EXIT(zsb); return (EPERM); } + /* + * Verify timestamps doesn't overflow 32 bits. + * ZFS can handle large timestamps, but 32bit syscalls can't + * handle times greater than 2039. This check should be removed + * once large timestamps are fully supported. + */ + if (mask & (ATTR_ATIME | ATTR_MTIME)) { + if (((mask & ATTR_ATIME) && TIMESPEC_OVERFLOW(&vap->va_atime)) || + ((mask & ATTR_MTIME) && TIMESPEC_OVERFLOW(&vap->va_mtime))) { + ZFS_EXIT(zsb); + return (EOVERFLOW); + } + } + top: attrzp = NULL; aclp = NULL; @@ -2220,20 +2363,32 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) * should be addressed in openat(). */ /* XXX - would it be OK to generate a log record here? */ - err = zfs_freesp(zp, attr->ia_size, 0, 0, FALSE); + err = zfs_freesp(zp, vap->va_size, 0, 0, FALSE); if (err) { ZFS_EXIT(zsb); return (err); } /* Careful negative Linux return code here */ - err = -vmtruncate(ip, attr->ia_size); + err = -vmtruncate(ip, vap->va_size); if (err) { ZFS_EXIT(zsb); return (err); } } + if (mask & (ATTR_ATIME|ATTR_MTIME) || + ((mask & ATTR_XVATTR) && (XVA_ISSET_REQ(xvap, XAT_HIDDEN) || + XVA_ISSET_REQ(xvap, XAT_READONLY) || + XVA_ISSET_REQ(xvap, XAT_ARCHIVE) || + XVA_ISSET_REQ(xvap, XAT_OFFLINE) || + XVA_ISSET_REQ(xvap, XAT_SPARSE) || + XVA_ISSET_REQ(xvap, XAT_CREATETIME) || + XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { + need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, + skipaclchk, cr); + } + if (mask & (ATTR_UID|ATTR_GID)) { int idmask = (mask & (ATTR_UID|ATTR_GID)); int take_owner; @@ -2245,19 +2400,18 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) */ if (!(mask & ATTR_MODE)) - attr->ia_mode = zp->z_mode; + vap->va_mode = zp->z_mode; /* * Take ownership or chgrp to group we are a member of */ - take_owner = (mask & ATTR_UID) && - (attr->ia_uid == crgetuid(cr)); + take_owner = (mask & ATTR_UID) && (vap->va_uid == crgetuid(cr)); take_group = (mask & ATTR_GID) && - zfs_groupmember(zsb, attr->ia_gid, cr); + zfs_groupmember(zsb, vap->va_gid, cr); /* - * If both AT_UID and AT_GID are set then take_owner and + * If both ATTR_UID and ATTR_GID are set then take_owner and * take_group must both be set in order to allow taking * ownership. * @@ -2274,7 +2428,7 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) /* * Remove setuid/setgid for non-privileged users */ - (void) secpolicy_setid_clear(attr, cr); + (void) secpolicy_setid_clear(vap, cr); trim_mask = (mask & (ATTR_UID|ATTR_GID)); } else { need_policy = TRUE; @@ -2287,12 +2441,94 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) mutex_enter(&zp->z_lock); oldva.va_mode = zp->z_mode; zfs_fuid_map_ids(zp, cr, &oldva.va_uid, &oldva.va_gid); + if (mask & ATTR_XVATTR) { + /* + * Update xvattr mask to include only those attributes + * that are actually changing. + * + * the bits will be restored prior to actually setting + * the attributes so the caller thinks they were set. + */ + if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { + if (xoap->xoa_appendonly != + ((zp->z_pflags & ZFS_APPENDONLY) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_APPENDONLY); + XVA_SET_REQ(&tmpxvattr, XAT_APPENDONLY); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { + if (xoap->xoa_nounlink != + ((zp->z_pflags & ZFS_NOUNLINK) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_NOUNLINK); + XVA_SET_REQ(&tmpxvattr, XAT_NOUNLINK); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { + if (xoap->xoa_immutable != + ((zp->z_pflags & ZFS_IMMUTABLE) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_IMMUTABLE); + XVA_SET_REQ(&tmpxvattr, XAT_IMMUTABLE); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { + if (xoap->xoa_nodump != + ((zp->z_pflags & ZFS_NODUMP) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_NODUMP); + XVA_SET_REQ(&tmpxvattr, XAT_NODUMP); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { + if (xoap->xoa_av_modified != + ((zp->z_pflags & ZFS_AV_MODIFIED) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_AV_MODIFIED); + XVA_SET_REQ(&tmpxvattr, XAT_AV_MODIFIED); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { + if ((!S_ISREG(ip->i_mode) && + xoap->xoa_av_quarantined) || + xoap->xoa_av_quarantined != + ((zp->z_pflags & ZFS_AV_QUARANTINED) != 0)) { + need_policy = TRUE; + } else { + XVA_CLR_REQ(xvap, XAT_AV_QUARANTINED); + XVA_SET_REQ(&tmpxvattr, XAT_AV_QUARANTINED); + } + } + + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { + mutex_exit(&zp->z_lock); + ZFS_EXIT(zsb); + return (EPERM); + } + + if (need_policy == FALSE && + (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP) || + XVA_ISSET_REQ(xvap, XAT_OPAQUE))) { + need_policy = TRUE; + } + } mutex_exit(&zp->z_lock); if (mask & ATTR_MODE) { if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { - err = secpolicy_setid_setsticky_clear(ip, attr, + err = secpolicy_setid_setsticky_clear(ip, vap, &oldva, cr); if (err) { ZFS_EXIT(zsb); @@ -2314,10 +2550,10 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) */ if (trim_mask) { - saved_mask = attr->ia_valid; - attr->ia_valid &= ~trim_mask; + saved_mask = vap->va_mask; + vap->va_mask &= ~trim_mask; } - err = secpolicy_vnode_setattr(cr, ip, attr, &oldva, flags, + err = secpolicy_vnode_setattr(cr, ip, vap, &oldva, flags, (int (*)(void *, int, cred_t *))zfs_zaccess_unix, zp); if (err) { ZFS_EXIT(zsb); @@ -2325,14 +2561,14 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) } if (trim_mask) - attr->ia_valid |= saved_mask; + vap->va_mask |= saved_mask; } /* * secpolicy_vnode_setattr, or take ownership may have * changed va_mask */ - mask = attr->ia_valid; + mask = vap->va_mask; if ((mask & (ATTR_UID | ATTR_GID))) { err = sa_lookup(zp->z_sa_hdl, SA_ZPL_XATTR(zsb), @@ -2345,7 +2581,7 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) } if (mask & ATTR_UID) { new_uid = zfs_fuid_create(zsb, - (uint64_t)attr->ia_uid, cr, ZFS_OWNER, &fuidp); + (uint64_t)vap->va_uid, cr, ZFS_OWNER, &fuidp); if (new_uid != zp->z_uid && zfs_fuid_overquota(zsb, B_FALSE, new_uid)) { if (attrzp) @@ -2356,7 +2592,7 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) } if (mask & ATTR_GID) { - new_gid = zfs_fuid_create(zsb, (uint64_t)attr->ia_gid, + new_gid = zfs_fuid_create(zsb, (uint64_t)vap->va_gid, cr, ZFS_GROUP, &fuidp); if (new_gid != zp->z_gid && zfs_fuid_overquota(zsb, B_TRUE, new_gid)) { @@ -2372,7 +2608,7 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) if (mask & ATTR_MODE) { uint64_t pmode = zp->z_mode; uint64_t acl_obj; - new_mode = (pmode & S_IFMT) | (attr->ia_mode & ~S_IFMT); + new_mode = (pmode & S_IFMT) | (vap->va_mode & ~S_IFMT); zfs_acl_chmod_setattr(zp, &aclp, new_mode); @@ -2400,7 +2636,11 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) mutex_exit(&zp->z_lock); dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); } else { - dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); + if ((mask & ATTR_XVATTR) && + XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) + dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE); + else + dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE); } if (attrzp) { @@ -2499,13 +2739,13 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) if (mask & ATTR_ATIME) { - ZFS_TIME_ENCODE(&attr->ia_atime, zp->z_atime); + ZFS_TIME_ENCODE(&vap->va_atime, zp->z_atime); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zsb), NULL, &zp->z_atime, sizeof (zp->z_atime)); } if (mask & ATTR_MTIME) { - ZFS_TIME_ENCODE(&attr->ia_mtime, mtime); + ZFS_TIME_ENCODE(&vap->va_mtime, mtime); SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zsb), NULL, mtime, sizeof (mtime)); } @@ -2536,11 +2776,43 @@ zfs_setattr(struct inode *ip, struct iattr *attr, int flags, cred_t *cr) * update from toggling bit */ + if (xoap && (mask & ATTR_XVATTR)) { + + /* + * restore trimmed off masks + * so that return masks can be set for caller. + */ + + if (XVA_ISSET_REQ(&tmpxvattr, XAT_APPENDONLY)) { + XVA_SET_REQ(xvap, XAT_APPENDONLY); + } + if (XVA_ISSET_REQ(&tmpxvattr, XAT_NOUNLINK)) { + XVA_SET_REQ(xvap, XAT_NOUNLINK); + } + if (XVA_ISSET_REQ(&tmpxvattr, XAT_IMMUTABLE)) { + XVA_SET_REQ(xvap, XAT_IMMUTABLE); + } + if (XVA_ISSET_REQ(&tmpxvattr, XAT_NODUMP)) { + XVA_SET_REQ(xvap, XAT_NODUMP); + } + if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_MODIFIED)) { + XVA_SET_REQ(xvap, XAT_AV_MODIFIED); + } + if (XVA_ISSET_REQ(&tmpxvattr, XAT_AV_QUARANTINED)) { + XVA_SET_REQ(xvap, XAT_AV_QUARANTINED); + } + + if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) + ASSERT(S_ISREG(ip->i_mode)); + + zfs_xvattr_set(zp, xvap, tx); + } + if (fuid_dirtied) zfs_fuid_sync(zsb, tx); if (mask != 0) - zfs_log_setattr(zilog, tx, TX_SETATTR, zp, attr, mask, fuidp); + zfs_log_setattr(zilog, tx, TX_SETATTR, zp, vap, mask, fuidp); mutex_exit(&zp->z_lock); if (mask & (ATTR_UID|ATTR_GID|ATTR_MODE)) @@ -4018,11 +4290,11 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, int convoff(struct inode *ip, flock64_t *lckdat, int whence, offset_t offset) { - struct kstat stat; + vattr_t vap; int error; if ((lckdat->l_whence == 2) || (whence == 2)) { - if ((error = zfs_getattr(ip, &stat, 0, CRED()) != 0)) + if ((error = zfs_getattr(ip, &vap, 0, CRED()) != 0)) return (error); } @@ -4031,7 +4303,7 @@ convoff(struct inode *ip, flock64_t *lckdat, int whence, offset_t offset) lckdat->l_start += offset; break; case 2: - lckdat->l_start += stat.size; + lckdat->l_start += vap.va_size; /* FALLTHRU */ case 0: break; @@ -4047,7 +4319,7 @@ convoff(struct inode *ip, flock64_t *lckdat, int whence, offset_t offset) lckdat->l_start -= offset; break; case 2: - lckdat->l_start -= stat.size; + lckdat->l_start -= vap.va_size; /* FALLTHRU */ case 0: break; diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c index 9aac34e31ae5..0bb9c09e57ad 100644 --- a/module/zfs/zfs_znode.c +++ b/module/zfs/zfs_znode.c @@ -701,6 +701,102 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, ZFS_OBJ_HOLD_EXIT(zsb, obj); } +/* + * zfs_xvattr_set only updates the in-core attributes + * it is assumed the caller will be doing an sa_bulk_update + * to push the changes out + */ +void +zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx) +{ + xoptattr_t *xoap; + + xoap = xva_getxoptattr(xvap); + ASSERT(xoap); + + if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) { + uint64_t times[2]; + ZFS_TIME_ENCODE(&xoap->xoa_createtime, times); + (void) sa_update(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)), + ×, sizeof (times), tx); + XVA_SET_RTN(xvap, XAT_CREATETIME); + } + if (XVA_ISSET_REQ(xvap, XAT_READONLY)) { + ZFS_ATTR_SET(zp, ZFS_READONLY, xoap->xoa_readonly, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_READONLY); + } + if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) { + ZFS_ATTR_SET(zp, ZFS_HIDDEN, xoap->xoa_hidden, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_HIDDEN); + } + if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) { + ZFS_ATTR_SET(zp, ZFS_SYSTEM, xoap->xoa_system, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_SYSTEM); + } + if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) { + ZFS_ATTR_SET(zp, ZFS_ARCHIVE, xoap->xoa_archive, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_ARCHIVE); + } + if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE)) { + ZFS_ATTR_SET(zp, ZFS_IMMUTABLE, xoap->xoa_immutable, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_IMMUTABLE); + } + if (XVA_ISSET_REQ(xvap, XAT_NOUNLINK)) { + ZFS_ATTR_SET(zp, ZFS_NOUNLINK, xoap->xoa_nounlink, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_NOUNLINK); + } + if (XVA_ISSET_REQ(xvap, XAT_APPENDONLY)) { + ZFS_ATTR_SET(zp, ZFS_APPENDONLY, xoap->xoa_appendonly, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_APPENDONLY); + } + if (XVA_ISSET_REQ(xvap, XAT_NODUMP)) { + ZFS_ATTR_SET(zp, ZFS_NODUMP, xoap->xoa_nodump, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_NODUMP); + } + if (XVA_ISSET_REQ(xvap, XAT_OPAQUE)) { + ZFS_ATTR_SET(zp, ZFS_OPAQUE, xoap->xoa_opaque, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_OPAQUE); + } + if (XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) { + ZFS_ATTR_SET(zp, ZFS_AV_QUARANTINED, + xoap->xoa_av_quarantined, zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_AV_QUARANTINED); + } + if (XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED)) { + ZFS_ATTR_SET(zp, ZFS_AV_MODIFIED, xoap->xoa_av_modified, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_AV_MODIFIED); + } + if (XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) { + zfs_sa_set_scanstamp(zp, xvap, tx); + XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP); + } + if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) { + ZFS_ATTR_SET(zp, ZFS_REPARSE, xoap->xoa_reparse, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_REPARSE); + } + if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) { + ZFS_ATTR_SET(zp, ZFS_OFFLINE, xoap->xoa_offline, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_OFFLINE); + } + if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) { + ZFS_ATTR_SET(zp, ZFS_SPARSE, xoap->xoa_sparse, + zp->z_pflags, tx); + XVA_SET_RTN(xvap, XAT_SPARSE); + } +} + int zfs_zget(zfs_sb_t *zsb, uint64_t obj_num, znode_t **zpp) { diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c index 888dc17cc45d..b7227675b554 100644 --- a/module/zfs/zpl_inode.c +++ b/module/zfs/zpl_inode.c @@ -171,10 +171,33 @@ static int zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { cred_t *cr; + vattr_t *vap; + struct inode *ip; int error; + ip = dentry->d_inode; cr = (cred_t *)get_current_cred(); - error = -zfs_getattr(dentry->d_inode, stat, 0, cr); + vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); + + error = -zfs_getattr(ip, vap, 0, cr); + if (error) + goto out; + + stat->ino = ip->i_ino; + stat->dev = 0; + stat->mode = vap->va_mode; + stat->nlink = vap->va_nlink; + stat->uid = vap->va_uid; + stat->gid = vap->va_gid; + stat->rdev = vap->va_rdev; + stat->size = vap->va_size; + stat->atime = vap->va_atime; + stat->mtime = vap->va_mtime; + stat->ctime = vap->va_ctime; + stat->blksize = vap->va_blksize; + stat->blocks = vap->va_nblocks; +out: + kmem_free(vap, sizeof(vattr_t)); put_cred(cr); ASSERT3S(error, <=, 0); @@ -182,21 +205,34 @@ zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) } static int -zpl_setattr(struct dentry *dentry, struct iattr *attr) +zpl_setattr(struct dentry *dentry, struct iattr *ia) { cred_t *cr; + vattr_t *vap; int error; - error = inode_change_ok(dentry->d_inode, attr); + error = inode_change_ok(dentry->d_inode, ia); if (error) return (error); cr = (cred_t *)get_current_cred(); - error = -zfs_setattr(dentry->d_inode, attr, 0, cr); + vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP); + vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK; + vap->va_mode = ia->ia_mode; + vap->va_uid = ia->ia_uid; + vap->va_gid = ia->ia_gid; + vap->va_size = ia->ia_size; + vap->va_atime = ia->ia_atime; + vap->va_mtime = ia->ia_mtime; + vap->va_ctime = ia->ia_ctime; + + error = -zfs_setattr(dentry->d_inode, vap, 0, cr); + + kmem_free(vap, sizeof(vattr_t)); put_cred(cr); ASSERT3S(error, <=, 0); - return (-error); + return (error); } static int