summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs')
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_transact.c11
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsinfo.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c198
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c27
-rw-r--r--usr/src/uts/common/fs/xattr.c26
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_znode.h2
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_log.c6
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_replay.c4
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vnops.c14
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_znode.c22
-rw-r--r--usr/src/uts/common/fs/zut/zut.c9
12 files changed, 308 insertions, 20 deletions
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
index ce95e1c809..21dff73b3c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
@@ -1007,7 +1007,8 @@ smb_trans_net_workstation_getinfo(struct smb_request *sr, struct smb_xa *xa)
(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
(void) smb_mbc_encodef(&str_mb, "s", domain);
(void) smb_mbc_encodef(&xa->rep_data_mb, "bbl",
- sr->sr_cfg->skc_version.sv_major, sr->sr_cfg->skc_version.sv_minor,
+ (uint8_t)sr->sr_cfg->skc_version.sv_major,
+ (uint8_t)sr->sr_cfg->skc_version.sv_minor,
MBC_LENGTH(&str_mb));
(void) smb_mbc_encodef(&str_mb, "s", domain);
(void) smb_mbc_encodef(&xa->rep_data_mb, "l", MBC_LENGTH(&str_mb));
@@ -1070,8 +1071,8 @@ smb_trans_net_server_getinfo(struct smb_request *sr, struct smb_xa *xa)
(void) smb_mbc_encodef(&str_mb, "s",
sr->sr_cfg->skc_system_comment);
(void) smb_mbc_encodef(&xa->rep_data_mb, "16cbbll", server_name,
- sr->sr_cfg->skc_version.sv_major,
- sr->sr_cfg->skc_version.sv_minor,
+ (uint8_t)sr->sr_cfg->skc_version.sv_major,
+ (uint8_t)sr->sr_cfg->skc_version.sv_minor,
MY_SERVER_TYPE, max_data - MBC_LENGTH(&str_mb));
break;
@@ -1315,8 +1316,8 @@ smb_trans_net_server_enum2(struct smb_request *sr, struct smb_xa *xa)
(void) smb_mbc_encodef(&xa->rep_data_mb, "16c", hostname);
if (level == 1) {
(void) smb_mbc_encodef(&xa->rep_data_mb, "bbll",
- sr->sr_cfg->skc_version.sv_major,
- sr->sr_cfg->skc_version.sv_minor,
+ (uint8_t)sr->sr_cfg->skc_version.sv_major,
+ (uint8_t)sr->sr_cfg->skc_version.sv_minor,
MY_SERVER_TYPE, MBC_LENGTH(&str_mb));
(void) smb_mbc_encodef(&str_mb, "s", si->skc_system_comment);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c b/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
index eb408b34e0..519bc1ff1f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -336,6 +335,9 @@ smb_com_trans2_query_fs_information(smb_request_t *sr, smb_xa_t *xa)
if (tree->t_flags & SMB_TREE_QUOTA)
flags |= FILE_VOLUME_QUOTAS;
+ if (tree->t_flags & SMB_TREE_SPARSE)
+ flags |= FILE_SUPPORTS_SPARSE_FILES;
+
(void) smb_mbc_encodef(&xa->rep_data_mb, encode_str, sr,
flags,
MAXNAMELEN, /* max name */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c
index 1caab2937a..f214b41310 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_ioctl.c
@@ -27,8 +27,11 @@
static uint32_t smb_nt_trans_ioctl_noop(smb_request_t *, smb_xa_t *);
-static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *,
+static uint32_t smb_nt_trans_ioctl_invalid_parm(smb_request_t *, smb_xa_t *);
+static uint32_t smb_nt_trans_ioctl_set_sparse(smb_request_t *, smb_xa_t *);
+static uint32_t smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *,
smb_xa_t *);
+static uint32_t smb_nt_trans_ioctl_set_zero_data(smb_request_t *, smb_xa_t *);
/*
* This table defines the list of FSCTL values for which we'll
@@ -43,9 +46,10 @@ static struct {
uint32_t (*ioctl_func)(smb_request_t *sr, smb_xa_t *xa);
} ioctl_ret_tbl[] = {
{ FSCTL_GET_OBJECT_ID, smb_nt_trans_ioctl_invalid_parm },
- { FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_invalid_parm },
+ { FSCTL_QUERY_ALLOCATED_RANGES, smb_nt_trans_ioctl_query_alloc_ranges },
+ { FSCTL_SET_ZERO_DATA, smb_nt_trans_ioctl_set_zero_data },
{ FSCTL_SRV_ENUMERATE_SNAPSHOTS, smb_vss_ioctl_enumerate_snaps },
- { FSCTL_SET_SPARSE, smb_nt_trans_ioctl_noop },
+ { FSCTL_SET_SPARSE, smb_nt_trans_ioctl_set_sparse },
{ FSCTL_FIND_FILES_BY_SID, smb_nt_trans_ioctl_noop }
};
@@ -84,13 +88,12 @@ smb_nt_transact_ioctl(smb_request_t *sr, smb_xa_t *xa)
{
uint32_t status = NT_STATUS_NOT_SUPPORTED;
uint32_t fcode;
- unsigned short fid;
unsigned char is_fsctl;
unsigned char is_flags;
int i;
if (smb_mbc_decodef(&xa->req_setup_mb, "lwbb",
- &fcode, &fid, &is_fsctl, &is_flags) != 0) {
+ &fcode, &sr->smb_fid, &is_fsctl, &is_flags) != 0) {
smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
return (SDRC_ERROR);
}
@@ -129,3 +132,188 @@ smb_nt_trans_ioctl_invalid_parm(smb_request_t *sr, smb_xa_t *xa)
{
return (NT_STATUS_INVALID_PARAMETER);
}
+
+/*
+ * smb_nt_trans_ioctl_set_sparse
+ *
+ * There may, or may not be a data block in this request.
+ * If there IS a data block, the first byte is a boolean
+ * specifying whether to set (non zero) or clear (zero)
+ * the sparse attribute of the file.
+ * If there is no data block, this indicates a request to
+ * set the sparse attribute.
+ */
+static uint32_t
+smb_nt_trans_ioctl_set_sparse(smb_request_t *sr, smb_xa_t *xa)
+{
+ int rc = 0;
+ uint8_t set = 1;
+ smb_node_t *node;
+ smb_attr_t attr;
+
+ if (SMB_TREE_IS_READONLY(sr))
+ return (NT_STATUS_ACCESS_DENIED);
+
+ if (STYPE_ISIPC(sr->tid_tree->t_res_type))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ smbsr_lookup_file(sr);
+ if (sr->fid_ofile == NULL)
+ return (NT_STATUS_INVALID_HANDLE);
+
+ if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ node = sr->fid_ofile->f_node;
+ if (smb_node_is_dir(node)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ if (smbsr_decode_data_avail(sr)) {
+ if (smb_mbc_decodef(&xa->req_data_mb, "b", &set) != 0) {
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+ }
+
+ bzero(&attr, sizeof (smb_attr_t));
+ attr.sa_mask = SMB_AT_DOSATTR;
+ if ((rc = smb_node_getattr(sr, node, &attr)) != 0) {
+ smbsr_errno(sr, rc);
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+
+ attr.sa_mask = 0;
+ if ((set == 0) &&
+ (attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
+ attr.sa_dosattr &= ~FILE_ATTRIBUTE_SPARSE_FILE;
+ attr.sa_mask = SMB_AT_DOSATTR;
+ } else if ((set != 0) &&
+ !(attr.sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)) {
+ attr.sa_dosattr |= FILE_ATTRIBUTE_SPARSE_FILE;
+ attr.sa_mask = SMB_AT_DOSATTR;
+ }
+
+ if (attr.sa_mask != 0) {
+ rc = smb_node_setattr(sr, node, sr->user_cr, NULL, &attr);
+ if (rc != 0) {
+ smbsr_errno(sr, rc);
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+ }
+
+ smbsr_release_file(sr);
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * smb_nt_trans_ioctl_set_zero_data
+ *
+ * Check that the request is valid on the specified file.
+ * The implementation is a noop.
+ */
+/* ARGSUSED */
+static uint32_t
+smb_nt_trans_ioctl_set_zero_data(smb_request_t *sr, smb_xa_t *xa)
+{
+ smb_node_t *node;
+
+ if (SMB_TREE_IS_READONLY(sr))
+ return (NT_STATUS_ACCESS_DENIED);
+
+ if (STYPE_ISIPC(sr->tid_tree->t_res_type))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ smbsr_lookup_file(sr);
+ if (sr->fid_ofile == NULL)
+ return (NT_STATUS_INVALID_HANDLE);
+
+ if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ node = sr->fid_ofile->f_node;
+ if (smb_node_is_dir(node)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ smbsr_release_file(sr);
+ return (NT_STATUS_SUCCESS);
+}
+
+/*
+ * smb_nt_trans_ioctl_query_alloc_ranges
+ *
+ * Responds with either:
+ * - no data if the file is zero size
+ * - a single range containing the starting point and length requested
+ */
+static uint32_t
+smb_nt_trans_ioctl_query_alloc_ranges(smb_request_t *sr, smb_xa_t *xa)
+{
+ int rc;
+ uint64_t offset, len;
+ smb_node_t *node;
+ smb_attr_t attr;
+
+ if (STYPE_ISIPC(sr->tid_tree->t_res_type))
+ return (NT_STATUS_INVALID_PARAMETER);
+
+ smbsr_lookup_file(sr);
+ if (sr->fid_ofile == NULL)
+ return (NT_STATUS_INVALID_HANDLE);
+
+ if (!SMB_FTYPE_IS_DISK(sr->fid_ofile->f_ftype)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ node = sr->fid_ofile->f_node;
+ if (smb_node_is_dir(node)) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_INVALID_PARAMETER);
+ }
+
+ /* If zero size file don't return any data */
+ bzero(&attr, sizeof (smb_attr_t));
+ attr.sa_mask = SMB_AT_SIZE;
+ if ((rc = smb_node_getattr(sr, node, &attr)) != 0) {
+ smbsr_errno(sr, rc);
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+
+ if (attr.sa_vattr.va_size == 0) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_SUCCESS);
+ }
+
+ if (smb_mbc_decodef(&xa->req_data_mb, "qq", &offset, &len) != 0) {
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+
+ /*
+ * Return a single range regardless of whether the file
+ * is sparse or not.
+ */
+ if (MBC_ROOM_FOR(&xa->rep_data_mb, 16) == 0) {
+ smbsr_release_file(sr);
+ return (NT_STATUS_BUFFER_TOO_SMALL);
+ }
+
+ if (smb_mbc_encodef(&xa->rep_data_mb, "qq", offset, len) != 0) {
+ smbsr_release_file(sr);
+ return (sr->smb_error.status);
+ }
+
+ smbsr_release_file(sr);
+ return (NT_STATUS_SUCCESS);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 3b4b0b0c98..03a4e856c1 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -1107,7 +1107,8 @@ smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
} smb_mtype_t;
static smb_mtype_t smb_mtype[] = {
- { "zfs", 3, SMB_TREE_UNICODE_ON_DISK | SMB_TREE_QUOTA },
+ { "zfs", 3, SMB_TREE_UNICODE_ON_DISK |
+ SMB_TREE_QUOTA | SMB_TREE_SPARSE},
{ "ufs", 3, SMB_TREE_UNICODE_ON_DISK },
{ "nfs", 3, SMB_TREE_NFS_MOUNTED },
{ "tmpfs", 5, SMB_TREE_NO_EXPORT }
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index 41291b290f..197a3b7bc2 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/types.h>
@@ -328,6 +327,8 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
XVA_SET_REQ(&tmp_xvattr, XAT_ARCHIVE);
XVA_SET_REQ(&tmp_xvattr, XAT_CREATETIME);
XVA_SET_REQ(&tmp_xvattr, XAT_REPARSE);
+ XVA_SET_REQ(&tmp_xvattr, XAT_OFFLINE);
+ XVA_SET_REQ(&tmp_xvattr, XAT_SPARSE);
error = VOP_GETATTR(use_vp, &tmp_xvattr.xva_vattr, flags,
cr, &smb_ct);
@@ -367,6 +368,17 @@ smb_vop_getattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *ret_attr,
FILE_ATTRIBUTE_REPARSE_POINT;
}
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_OFFLINE)) &&
+ (xoap->xoa_offline)) {
+ ret_attr->sa_dosattr |= FILE_ATTRIBUTE_OFFLINE;
+ }
+
+ if ((XVA_ISSET_RTN(&tmp_xvattr, XAT_SPARSE)) &&
+ (xoap->xoa_sparse)) {
+ ret_attr->sa_dosattr |=
+ FILE_ATTRIBUTE_SPARSE_FILE;
+ }
+
ret_attr->sa_crtime = xoap->xoa_createtime;
} else {
ret_attr->sa_crtime = ret_attr->sa_vattr.va_mtime;
@@ -442,7 +454,8 @@ smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *attr,
if (attr->sa_mask & SMB_AT_DOSATTR) {
attr->sa_dosattr &=
(FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY |
- FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
+ FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_SPARSE_FILE);
}
if (unnamed_vp) {
@@ -860,6 +873,8 @@ smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr)
XVA_SET_REQ(xvattr, XAT_SYSTEM);
XVA_SET_REQ(xvattr, XAT_READONLY);
XVA_SET_REQ(xvattr, XAT_HIDDEN);
+ XVA_SET_REQ(xvattr, XAT_OFFLINE);
+ XVA_SET_REQ(xvattr, XAT_SPARSE);
/*
* smb_attr->sa_dosattr: If a given bit is not set,
@@ -879,6 +894,12 @@ smb_vop_setup_xvattr(smb_attr_t *smb_attr, xvattr_t *xvattr)
if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_HIDDEN)
xoap->xoa_hidden = 1;
+
+ if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_OFFLINE)
+ xoap->xoa_offline = 1;
+
+ if (smb_attr->sa_dosattr & FILE_ATTRIBUTE_SPARSE_FILE)
+ xoap->xoa_sparse = 1;
}
if (smb_attr->sa_mask & SMB_AT_CRTIME) {
diff --git a/usr/src/uts/common/fs/xattr.c b/usr/src/uts/common/fs/xattr.c
index 1657f25549..a1173e69f5 100644
--- a/usr/src/uts/common/fs/xattr.c
+++ b/usr/src/uts/common/fs/xattr.c
@@ -228,6 +228,12 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp,
case F_GEN:
XVA_SET_REQ(&xvattr, XAT_GEN);
break;
+ case F_OFFLINE:
+ XVA_SET_REQ(&xvattr, XAT_OFFLINE);
+ break;
+ case F_SPARSE:
+ XVA_SET_REQ(&xvattr, XAT_SPARSE);
+ break;
default:
break;
}
@@ -320,6 +326,16 @@ xattr_fill_nvlist(vnode_t *vp, xattr_view_t xattr_view, nvlist_t *nvlp,
attr_to_name(F_GEN),
xoap->xoa_generation) == 0);
}
+ if (XVA_ISSET_RTN(&xvattr, XAT_OFFLINE)) {
+ VERIFY(nvlist_add_boolean_value(nvlp,
+ attr_to_name(F_OFFLINE),
+ xoap->xoa_offline) == 0);
+ }
+ if (XVA_ISSET_RTN(&xvattr, XAT_SPARSE)) {
+ VERIFY(nvlist_add_boolean_value(nvlp,
+ attr_to_name(F_SPARSE),
+ xoap->xoa_sparse) == 0);
+ }
}
/*
* Check for optional ownersid/groupsid
@@ -697,6 +713,14 @@ xattr_file_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr,
XVA_SET_REQ(&xvattr, XAT_REPARSE);
xoap->xoa_reparse = value;
break;
+ case F_OFFLINE:
+ XVA_SET_REQ(&xvattr, XAT_OFFLINE);
+ xoap->xoa_offline = value;
+ break;
+ case F_SPARSE:
+ XVA_SET_REQ(&xvattr, XAT_SPARSE);
+ xoap->xoa_sparse = value;
+ break;
default:
break;
}
@@ -838,6 +862,8 @@ xattr_copy(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm,
XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED);
XVA_SET_REQ(&xvattr, XAT_CREATETIME);
XVA_SET_REQ(&xvattr, XAT_REPARSE);
+ XVA_SET_REQ(&xvattr, XAT_OFFLINE);
+ XVA_SET_REQ(&xvattr, XAT_SPARSE);
pdvp = gfs_file_parent(sdvp);
error = VOP_GETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct);
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
index b51287d565..3e9621a0ee 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_znode.h
@@ -60,6 +60,8 @@ extern "C" {
#define ZFS_AV_QUARANTINED 0x0000020000000000
#define ZFS_AV_MODIFIED 0x0000040000000000
#define ZFS_REPARSE 0x0000080000000000
+#define ZFS_OFFLINE 0x0000100000000000
+#define ZFS_SPARSE 0x0000200000000000
#define ZFS_ATTR_SET(zp, attr, value, pflags, tx) \
{ \
diff --git a/usr/src/uts/common/fs/zfs/zfs_log.c b/usr/src/uts/common/fs/zfs/zfs_log.c
index 70368481cc..26ab78279b 100644
--- a/usr/src/uts/common/fs/zfs/zfs_log.c
+++ b/usr/src/uts/common/fs/zfs/zfs_log.c
@@ -169,6 +169,12 @@ zfs_log_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
*attrs |= (xoap->xoa_reparse == 0) ? 0 :
XAT0_REPARSE;
+ if (XVA_ISSET_REQ(xvap, XAT_OFFLINE))
+ *attrs |= (xoap->xoa_offline == 0) ? 0 :
+ XAT0_OFFLINE;
+ if (XVA_ISSET_REQ(xvap, XAT_SPARSE))
+ *attrs |= (xoap->xoa_sparse == 0) ? 0 :
+ XAT0_SPARSE;
}
static void *
diff --git a/usr/src/uts/common/fs/zfs/zfs_replay.c b/usr/src/uts/common/fs/zfs/zfs_replay.c
index f4fb5aceb6..9fb3368569 100644
--- a/usr/src/uts/common/fs/zfs/zfs_replay.c
+++ b/usr/src/uts/common/fs/zfs/zfs_replay.c
@@ -128,6 +128,10 @@ zfs_replay_xvattr(lr_attr_t *lrattr, xvattr_t *xvap)
bcopy(scanstamp, xoap->xoa_av_scanstamp, AV_SCANSTAMP_SZ);
if (XVA_ISSET_REQ(xvap, XAT_REPARSE))
xoap->xoa_reparse = ((*attrs & XAT0_REPARSE) != 0);
+ if (XVA_ISSET_REQ(xvap, XAT_OFFLINE))
+ xoap->xoa_offline = ((*attrs & XAT0_OFFLINE) != 0);
+ if (XVA_ISSET_REQ(xvap, XAT_SPARSE))
+ xoap->xoa_sparse = ((*attrs & XAT0_SPARSE) != 0);
}
static int
diff --git a/usr/src/uts/common/fs/zfs/zfs_vnops.c b/usr/src/uts/common/fs/zfs/zfs_vnops.c
index 94234f3a25..7e3d85577a 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c
@@ -2543,6 +2543,18 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
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);
@@ -2720,6 +2732,8 @@ top:
((mask & AT_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,
diff --git a/usr/src/uts/common/fs/zfs/zfs_znode.c b/usr/src/uts/common/fs/zfs/zfs_znode.c
index 292912d382..e1e4e9e03a 100644
--- a/usr/src/uts/common/fs/zfs/zfs_znode.c
+++ b/usr/src/uts/common/fs/zfs/zfs_znode.c
@@ -1088,6 +1088,16 @@ zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
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
@@ -1564,6 +1574,8 @@ zfs_trunc(znode_t *zp, uint64_t end)
dmu_tx_t *tx;
rl_t *rl;
int error;
+ sa_bulk_attr_t bulk[2];
+ int count = 0;
/*
* We will change zp_size, lock the whole file.
@@ -1600,9 +1612,15 @@ top:
}
zp->z_size = end;
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_SIZE(zfsvfs),
+ NULL, &zp->z_size, sizeof (zp->z_size));
- VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SIZE(zp->z_zfsvfs),
- &zp->z_size, sizeof (zp->z_size), tx));
+ if (end == 0) {
+ zp->z_pflags &= ~ZFS_SPARSE;
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_FLAGS(zfsvfs),
+ NULL, &zp->z_pflags, 8);
+ }
+ VERIFY(sa_bulk_update(zp->z_sa_hdl, bulk, count, tx) == 0);
dmu_tx_commit(tx);
diff --git a/usr/src/uts/common/fs/zut/zut.c b/usr/src/uts/common/fs/zut/zut.c
index c655585968..a1c5555a39 100644
--- a/usr/src/uts/common/fs/zut/zut.c
+++ b/usr/src/uts/common/fs/zut/zut.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/conf.h>
@@ -218,6 +217,8 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr)
XVA_SET_REQ(&xv, XAT_AV_QUARANTINED);
XVA_SET_REQ(&xv, XAT_AV_MODIFIED);
XVA_SET_REQ(&xv, XAT_REPARSE);
+ XVA_SET_REQ(&xv, XAT_OFFLINE);
+ XVA_SET_REQ(&xv, XAT_SPARSE);
xv.xva_vattr.va_mask |= AT_STAT | AT_NBLOCKS | AT_BLKSIZE | AT_SIZE;
if (error = VOP_GETATTR(vp, &xv.xva_vattr, flag, cr, NULL))
@@ -266,6 +267,10 @@ zut_stat64(vnode_t *vp, struct stat64 *sb, uint64_t *xvs, int flag, cred_t *cr)
*xvs |= (1 << F_AV_MODIFIED);
if (XVA_ISSET_RTN(&xv, XAT_REPARSE) && xoap->xoa_reparse)
*xvs |= (1 << F_REPARSE);
+ if (XVA_ISSET_RTN(&xv, XAT_OFFLINE) && xoap->xoa_offline)
+ *xvs |= (1 << F_OFFLINE);
+ if (XVA_ISSET_RTN(&xv, XAT_SPARSE) && xoap->xoa_sparse)
+ *xvs |= (1 << F_SPARSE);
return (0);
}