summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
Diffstat (limited to 'module')
-rw-r--r--module/zfs/zfs_fuid.c8
-rw-r--r--module/zfs/zfs_log.c54
-rw-r--r--module/zfs/zfs_replay.c109
-rw-r--r--module/zfs/zfs_sa.c6
-rw-r--r--module/zfs/zfs_vnops.c386
-rw-r--r--module/zfs/zfs_znode.c96
-rw-r--r--module/zfs/zpl_inode.c46
7 files changed, 528 insertions, 177 deletions
diff --git a/module/zfs/zfs_fuid.c b/module/zfs/zfs_fuid.c
index ca03373c7..debb5f86d 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 5cdbb6c8d..4d9e13d50 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 f02d5add3..a5018ee60 100644
--- a/module/zfs/zfs_replay.c
+++ b/module/zfs/zfs_replay.c
@@ -37,15 +37,16 @@
#include <sys/zfs_dir.h>
#include <sys/zfs_acl.h>
#include <sys/zfs_fuid.h>
+#include <sys/zfs_vnops.h>
#include <sys/spa.h>
#include <sys/zil.h>
-#include <sys/zfs_vnops.h>
#include <sys/byteorder.h>
#include <sys/stat.h>
#include <sys/mode.h>
#include <sys/acl.h>
#include <sys/atomic.h>
#include <sys/cred.h>
+#include <sys/zpl.h>
/*
* 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 ed696490f..b8f208bba 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 5d6b0611c..2dcbfe00d 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;
+
+ /*
+ * 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);
+ }
- ZFS_TIME_DECODE(&stat->atime, zp->z_atime);
- ZFS_TIME_DECODE(&stat->mtime, mtime);
- ZFS_TIME_DECODE(&stat->ctime, ctime);
+ 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 @@ top:
* 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 @@ top:
*/
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 @@ top:
/*
* 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 @@ top:
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 @@ top:
*/
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 @@ top:
}
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 @@ top:
}
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 @@ top:
}
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 @@ top:
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 @@ top:
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 @@ top:
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 @@ top:
* 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 9aac34e31..0bb9c09e5 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)),
+ &times, 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 888dc17cc..b7227675b 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