xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_sa.c (revision 12620:12fcd99a642d)
111935SMark.Shellenbaum@Sun.COM /*
211935SMark.Shellenbaum@Sun.COM  * CDDL HEADER START
311935SMark.Shellenbaum@Sun.COM  *
411935SMark.Shellenbaum@Sun.COM  * The contents of this file are subject to the terms of the
511935SMark.Shellenbaum@Sun.COM  * Common Development and Distribution License (the "License").
611935SMark.Shellenbaum@Sun.COM  * You may not use this file except in compliance with the License.
711935SMark.Shellenbaum@Sun.COM  *
811935SMark.Shellenbaum@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911935SMark.Shellenbaum@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011935SMark.Shellenbaum@Sun.COM  * See the License for the specific language governing permissions
1111935SMark.Shellenbaum@Sun.COM  * and limitations under the License.
1211935SMark.Shellenbaum@Sun.COM  *
1311935SMark.Shellenbaum@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411935SMark.Shellenbaum@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511935SMark.Shellenbaum@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611935SMark.Shellenbaum@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711935SMark.Shellenbaum@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811935SMark.Shellenbaum@Sun.COM  *
1911935SMark.Shellenbaum@Sun.COM  * CDDL HEADER END
2011935SMark.Shellenbaum@Sun.COM  */
2111935SMark.Shellenbaum@Sun.COM /*
2212050SMark.Shellenbaum@Sun.COM  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2311935SMark.Shellenbaum@Sun.COM  */
2411935SMark.Shellenbaum@Sun.COM 
2511935SMark.Shellenbaum@Sun.COM #include <sys/types.h>
2611935SMark.Shellenbaum@Sun.COM #include <sys/param.h>
2711935SMark.Shellenbaum@Sun.COM #include <sys/vnode.h>
2811935SMark.Shellenbaum@Sun.COM #include <sys/sa.h>
2911935SMark.Shellenbaum@Sun.COM #include <sys/zfs_acl.h>
3011935SMark.Shellenbaum@Sun.COM #include <sys/zfs_sa.h>
3111935SMark.Shellenbaum@Sun.COM 
3211935SMark.Shellenbaum@Sun.COM /*
3311935SMark.Shellenbaum@Sun.COM  * ZPL attribute registration table.
3411935SMark.Shellenbaum@Sun.COM  * Order of attributes doesn't matter
3511935SMark.Shellenbaum@Sun.COM  * a unique value will be assigned for each
3611935SMark.Shellenbaum@Sun.COM  * attribute that is file system specific
3711935SMark.Shellenbaum@Sun.COM  *
3811935SMark.Shellenbaum@Sun.COM  * This is just the set of ZPL attributes that this
3911935SMark.Shellenbaum@Sun.COM  * version of ZFS deals with natively.  The file system
4011935SMark.Shellenbaum@Sun.COM  * could have other attributes stored in files, but they will be
4111935SMark.Shellenbaum@Sun.COM  * ignored.  The SA framework will preserve them, just that
4211935SMark.Shellenbaum@Sun.COM  * this version of ZFS won't change or delete them.
4311935SMark.Shellenbaum@Sun.COM  */
4411935SMark.Shellenbaum@Sun.COM 
4511935SMark.Shellenbaum@Sun.COM sa_attr_reg_t zfs_attr_table[ZPL_END+1] = {
4611935SMark.Shellenbaum@Sun.COM 	{"ZPL_ATIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 0},
4711935SMark.Shellenbaum@Sun.COM 	{"ZPL_MTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 1},
4811935SMark.Shellenbaum@Sun.COM 	{"ZPL_CTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 2},
4911935SMark.Shellenbaum@Sun.COM 	{"ZPL_CRTIME", sizeof (uint64_t) * 2, SA_UINT64_ARRAY, 3},
5011935SMark.Shellenbaum@Sun.COM 	{"ZPL_GEN", sizeof (uint64_t), SA_UINT64_ARRAY, 4},
5111935SMark.Shellenbaum@Sun.COM 	{"ZPL_MODE", sizeof (uint64_t), SA_UINT64_ARRAY, 5},
5211935SMark.Shellenbaum@Sun.COM 	{"ZPL_SIZE", sizeof (uint64_t), SA_UINT64_ARRAY, 6},
5311935SMark.Shellenbaum@Sun.COM 	{"ZPL_PARENT", sizeof (uint64_t), SA_UINT64_ARRAY, 7},
5411935SMark.Shellenbaum@Sun.COM 	{"ZPL_LINKS", sizeof (uint64_t), SA_UINT64_ARRAY, 8},
5511935SMark.Shellenbaum@Sun.COM 	{"ZPL_XATTR", sizeof (uint64_t), SA_UINT64_ARRAY, 9},
5611935SMark.Shellenbaum@Sun.COM 	{"ZPL_RDEV", sizeof (uint64_t), SA_UINT64_ARRAY, 10},
5711935SMark.Shellenbaum@Sun.COM 	{"ZPL_FLAGS", sizeof (uint64_t), SA_UINT64_ARRAY, 11},
5811935SMark.Shellenbaum@Sun.COM 	{"ZPL_UID", sizeof (uint64_t), SA_UINT64_ARRAY, 12},
5911935SMark.Shellenbaum@Sun.COM 	{"ZPL_GID", sizeof (uint64_t), SA_UINT64_ARRAY, 13},
6011935SMark.Shellenbaum@Sun.COM 	{"ZPL_PAD", sizeof (uint64_t) * 4, SA_UINT64_ARRAY, 14},
6111935SMark.Shellenbaum@Sun.COM 	{"ZPL_ZNODE_ACL", 88, SA_UINT8_ARRAY, 15},
6211935SMark.Shellenbaum@Sun.COM 	{"ZPL_DACL_COUNT", sizeof (uint64_t), SA_UINT64_ARRAY, 0},
6311935SMark.Shellenbaum@Sun.COM 	{"ZPL_SYMLINK", 0, SA_UINT8_ARRAY, 0},
6411935SMark.Shellenbaum@Sun.COM 	{"ZPL_SCANSTAMP", 32, SA_UINT8_ARRAY, 0},
6511935SMark.Shellenbaum@Sun.COM 	{"ZPL_DACL_ACES", 0, SA_ACL, 0},
6611935SMark.Shellenbaum@Sun.COM 	{NULL, 0, 0, 0}
6711935SMark.Shellenbaum@Sun.COM };
6811935SMark.Shellenbaum@Sun.COM 
6911935SMark.Shellenbaum@Sun.COM #ifdef _KERNEL
7011935SMark.Shellenbaum@Sun.COM 
7111935SMark.Shellenbaum@Sun.COM int
zfs_sa_readlink(znode_t * zp,uio_t * uio)7211935SMark.Shellenbaum@Sun.COM zfs_sa_readlink(znode_t *zp, uio_t *uio)
7311935SMark.Shellenbaum@Sun.COM {
7411935SMark.Shellenbaum@Sun.COM 	dmu_buf_t *db = sa_get_db(zp->z_sa_hdl);
7511935SMark.Shellenbaum@Sun.COM 	size_t bufsz;
7611935SMark.Shellenbaum@Sun.COM 	int error;
7711935SMark.Shellenbaum@Sun.COM 
7811935SMark.Shellenbaum@Sun.COM 	bufsz = zp->z_size;
7911952SMark.Shellenbaum@Sun.COM 	if (bufsz + ZFS_OLD_ZNODE_PHYS_SIZE <= db->db_size) {
8011935SMark.Shellenbaum@Sun.COM 		error = uiomove((caddr_t)db->db_data +
8111935SMark.Shellenbaum@Sun.COM 		    ZFS_OLD_ZNODE_PHYS_SIZE,
8211935SMark.Shellenbaum@Sun.COM 		    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
8311935SMark.Shellenbaum@Sun.COM 	} else {
8411935SMark.Shellenbaum@Sun.COM 		dmu_buf_t *dbp;
8511935SMark.Shellenbaum@Sun.COM 		if ((error = dmu_buf_hold(zp->z_zfsvfs->z_os, zp->z_id,
8612285SJeff.Bonwick@Sun.COM 		    0, FTAG, &dbp, DMU_READ_NO_PREFETCH)) == 0) {
8711935SMark.Shellenbaum@Sun.COM 			error = uiomove(dbp->db_data,
8811935SMark.Shellenbaum@Sun.COM 			    MIN((size_t)bufsz, uio->uio_resid), UIO_READ, uio);
8911935SMark.Shellenbaum@Sun.COM 			dmu_buf_rele(dbp, FTAG);
9011935SMark.Shellenbaum@Sun.COM 		}
9111935SMark.Shellenbaum@Sun.COM 	}
9211935SMark.Shellenbaum@Sun.COM 	return (error);
9311935SMark.Shellenbaum@Sun.COM }
9411935SMark.Shellenbaum@Sun.COM 
9511935SMark.Shellenbaum@Sun.COM void
zfs_sa_symlink(znode_t * zp,char * link,int len,dmu_tx_t * tx)9611935SMark.Shellenbaum@Sun.COM zfs_sa_symlink(znode_t *zp, char *link, int len, dmu_tx_t *tx)
9711935SMark.Shellenbaum@Sun.COM {
9811935SMark.Shellenbaum@Sun.COM 	dmu_buf_t *db = sa_get_db(zp->z_sa_hdl);
9911935SMark.Shellenbaum@Sun.COM 
10011935SMark.Shellenbaum@Sun.COM 	if (ZFS_OLD_ZNODE_PHYS_SIZE + len <= dmu_bonus_max()) {
10111935SMark.Shellenbaum@Sun.COM 		VERIFY(dmu_set_bonus(db,
10211935SMark.Shellenbaum@Sun.COM 		    len + ZFS_OLD_ZNODE_PHYS_SIZE, tx) == 0);
10311935SMark.Shellenbaum@Sun.COM 		if (len) {
10411935SMark.Shellenbaum@Sun.COM 			bcopy(link, (caddr_t)db->db_data +
10511935SMark.Shellenbaum@Sun.COM 			    ZFS_OLD_ZNODE_PHYS_SIZE, len);
10611935SMark.Shellenbaum@Sun.COM 		}
10711935SMark.Shellenbaum@Sun.COM 	} else {
10811935SMark.Shellenbaum@Sun.COM 		dmu_buf_t *dbp;
10911935SMark.Shellenbaum@Sun.COM 
11011935SMark.Shellenbaum@Sun.COM 		zfs_grow_blocksize(zp, len, tx);
11111935SMark.Shellenbaum@Sun.COM 		VERIFY(0 == dmu_buf_hold(zp->z_zfsvfs->z_os,
11212285SJeff.Bonwick@Sun.COM 		    zp->z_id, 0, FTAG, &dbp, DMU_READ_NO_PREFETCH));
11311935SMark.Shellenbaum@Sun.COM 
11411935SMark.Shellenbaum@Sun.COM 		dmu_buf_will_dirty(dbp, tx);
11511935SMark.Shellenbaum@Sun.COM 
11611935SMark.Shellenbaum@Sun.COM 		ASSERT3U(len, <=, dbp->db_size);
11711935SMark.Shellenbaum@Sun.COM 		bcopy(link, dbp->db_data, len);
11811935SMark.Shellenbaum@Sun.COM 		dmu_buf_rele(dbp, FTAG);
11911935SMark.Shellenbaum@Sun.COM 	}
12011935SMark.Shellenbaum@Sun.COM }
12111935SMark.Shellenbaum@Sun.COM 
12211935SMark.Shellenbaum@Sun.COM void
zfs_sa_get_scanstamp(znode_t * zp,xvattr_t * xvap)12311935SMark.Shellenbaum@Sun.COM zfs_sa_get_scanstamp(znode_t *zp, xvattr_t *xvap)
12411935SMark.Shellenbaum@Sun.COM {
12511935SMark.Shellenbaum@Sun.COM 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
12611935SMark.Shellenbaum@Sun.COM 	xoptattr_t *xoap;
12711935SMark.Shellenbaum@Sun.COM 
128*12620SMark.Shellenbaum@Oracle.COM 	ASSERT(MUTEX_HELD(&zp->z_lock));
12911935SMark.Shellenbaum@Sun.COM 	VERIFY((xoap = xva_getxoptattr(xvap)) != NULL);
13011935SMark.Shellenbaum@Sun.COM 	if (zp->z_is_sa) {
13111935SMark.Shellenbaum@Sun.COM 		if (sa_lookup(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs),
13211935SMark.Shellenbaum@Sun.COM 		    &xoap->xoa_av_scanstamp,
13311935SMark.Shellenbaum@Sun.COM 		    sizeof (xoap->xoa_av_scanstamp)) != 0)
13411935SMark.Shellenbaum@Sun.COM 			return;
13511935SMark.Shellenbaum@Sun.COM 	} else {
13611935SMark.Shellenbaum@Sun.COM 		dmu_object_info_t doi;
13711935SMark.Shellenbaum@Sun.COM 		dmu_buf_t *db = sa_get_db(zp->z_sa_hdl);
13811935SMark.Shellenbaum@Sun.COM 		int len;
13911935SMark.Shellenbaum@Sun.COM 
14011935SMark.Shellenbaum@Sun.COM 		if (!(zp->z_pflags & ZFS_BONUS_SCANSTAMP))
14111935SMark.Shellenbaum@Sun.COM 			return;
14211935SMark.Shellenbaum@Sun.COM 
14311935SMark.Shellenbaum@Sun.COM 		sa_object_info(zp->z_sa_hdl, &doi);
14411935SMark.Shellenbaum@Sun.COM 		len = sizeof (xoap->xoa_av_scanstamp) +
14511935SMark.Shellenbaum@Sun.COM 		    ZFS_OLD_ZNODE_PHYS_SIZE;
14611935SMark.Shellenbaum@Sun.COM 
14711935SMark.Shellenbaum@Sun.COM 		if (len <= doi.doi_bonus_size) {
14811935SMark.Shellenbaum@Sun.COM 			(void) memcpy(xoap->xoa_av_scanstamp,
14911935SMark.Shellenbaum@Sun.COM 			    (caddr_t)db->db_data + ZFS_OLD_ZNODE_PHYS_SIZE,
15011935SMark.Shellenbaum@Sun.COM 			    sizeof (xoap->xoa_av_scanstamp));
15111935SMark.Shellenbaum@Sun.COM 		}
15211935SMark.Shellenbaum@Sun.COM 	}
15311935SMark.Shellenbaum@Sun.COM 	XVA_SET_RTN(xvap, XAT_AV_SCANSTAMP);
15411935SMark.Shellenbaum@Sun.COM }
15511935SMark.Shellenbaum@Sun.COM 
15611935SMark.Shellenbaum@Sun.COM void
zfs_sa_set_scanstamp(znode_t * zp,xvattr_t * xvap,dmu_tx_t * tx)15711935SMark.Shellenbaum@Sun.COM zfs_sa_set_scanstamp(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
15811935SMark.Shellenbaum@Sun.COM {
15911935SMark.Shellenbaum@Sun.COM 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
16011935SMark.Shellenbaum@Sun.COM 	xoptattr_t *xoap;
16111935SMark.Shellenbaum@Sun.COM 
162*12620SMark.Shellenbaum@Oracle.COM 	ASSERT(MUTEX_HELD(&zp->z_lock));
16311935SMark.Shellenbaum@Sun.COM 	VERIFY((xoap = xva_getxoptattr(xvap)) != NULL);
16411935SMark.Shellenbaum@Sun.COM 	if (zp->z_is_sa)
16511935SMark.Shellenbaum@Sun.COM 		VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_SCANSTAMP(zfsvfs),
16611935SMark.Shellenbaum@Sun.COM 		    &xoap->xoa_av_scanstamp,
16711935SMark.Shellenbaum@Sun.COM 		    sizeof (xoap->xoa_av_scanstamp), tx));
16811935SMark.Shellenbaum@Sun.COM 	else {
16911935SMark.Shellenbaum@Sun.COM 		dmu_object_info_t doi;
17011935SMark.Shellenbaum@Sun.COM 		dmu_buf_t *db = sa_get_db(zp->z_sa_hdl);
17111935SMark.Shellenbaum@Sun.COM 		int len;
17211935SMark.Shellenbaum@Sun.COM 
17311935SMark.Shellenbaum@Sun.COM 		sa_object_info(zp->z_sa_hdl, &doi);
17411935SMark.Shellenbaum@Sun.COM 		len = sizeof (xoap->xoa_av_scanstamp) +
17511935SMark.Shellenbaum@Sun.COM 		    ZFS_OLD_ZNODE_PHYS_SIZE;
17611935SMark.Shellenbaum@Sun.COM 		if (len > doi.doi_bonus_size)
17711935SMark.Shellenbaum@Sun.COM 			VERIFY(dmu_set_bonus(db, len, tx) == 0);
17811935SMark.Shellenbaum@Sun.COM 		(void) memcpy((caddr_t)db->db_data + ZFS_OLD_ZNODE_PHYS_SIZE,
17911935SMark.Shellenbaum@Sun.COM 		    xoap->xoa_av_scanstamp, sizeof (xoap->xoa_av_scanstamp));
18011935SMark.Shellenbaum@Sun.COM 
18111935SMark.Shellenbaum@Sun.COM 		zp->z_pflags |= ZFS_BONUS_SCANSTAMP;
18211935SMark.Shellenbaum@Sun.COM 		VERIFY(0 == sa_update(zp->z_sa_hdl, SA_ZPL_FLAGS(zfsvfs),
18311935SMark.Shellenbaum@Sun.COM 		    &zp->z_pflags, sizeof (uint64_t), tx));
18411935SMark.Shellenbaum@Sun.COM 	}
18511935SMark.Shellenbaum@Sun.COM }
18611935SMark.Shellenbaum@Sun.COM 
18711935SMark.Shellenbaum@Sun.COM /*
18811935SMark.Shellenbaum@Sun.COM  * I'm not convinced we should do any of this upgrade.
18911935SMark.Shellenbaum@Sun.COM  * since the SA code can read both old/new znode formats
19011935SMark.Shellenbaum@Sun.COM  * with probably little to know performance difference.
19111935SMark.Shellenbaum@Sun.COM  *
19211935SMark.Shellenbaum@Sun.COM  * All new files will be created with the new format.
19311935SMark.Shellenbaum@Sun.COM  */
19411935SMark.Shellenbaum@Sun.COM 
19511935SMark.Shellenbaum@Sun.COM void
zfs_sa_upgrade(sa_handle_t * hdl,dmu_tx_t * tx)19611935SMark.Shellenbaum@Sun.COM zfs_sa_upgrade(sa_handle_t *hdl, dmu_tx_t *tx)
19711935SMark.Shellenbaum@Sun.COM {
19811935SMark.Shellenbaum@Sun.COM 	dmu_buf_t *db = sa_get_db(hdl);
19911935SMark.Shellenbaum@Sun.COM 	znode_t *zp = sa_get_userdata(hdl);
20011935SMark.Shellenbaum@Sun.COM 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
20111935SMark.Shellenbaum@Sun.COM 	sa_bulk_attr_t bulk[20];
20211935SMark.Shellenbaum@Sun.COM 	int count = 0;
20311935SMark.Shellenbaum@Sun.COM 	sa_bulk_attr_t sa_attrs[20] = { 0 };
20411935SMark.Shellenbaum@Sun.COM 	zfs_acl_locator_cb_t locate = { 0 };
20511935SMark.Shellenbaum@Sun.COM 	uint64_t uid, gid, mode, rdev, xattr, parent;
20611935SMark.Shellenbaum@Sun.COM 	uint64_t crtime[2], mtime[2], ctime[2];
20711935SMark.Shellenbaum@Sun.COM 	zfs_acl_phys_t znode_acl;
20811935SMark.Shellenbaum@Sun.COM 	char scanstamp[AV_SCANSTAMP_SZ];
209*12620SMark.Shellenbaum@Oracle.COM 	boolean_t drop_lock = B_FALSE;
21011935SMark.Shellenbaum@Sun.COM 
21111935SMark.Shellenbaum@Sun.COM 	/*
21211935SMark.Shellenbaum@Sun.COM 	 * No upgrade if ACL isn't cached
21311935SMark.Shellenbaum@Sun.COM 	 * since we won't know which locks are held
21411935SMark.Shellenbaum@Sun.COM 	 * and ready the ACL would require special "locked"
21511935SMark.Shellenbaum@Sun.COM 	 * interfaces that would be messy
21611935SMark.Shellenbaum@Sun.COM 	 */
21712178SMark.Shellenbaum@Sun.COM 	if (zp->z_acl_cached == NULL || ZTOV(zp)->v_type == VLNK)
21811935SMark.Shellenbaum@Sun.COM 		return;
21911935SMark.Shellenbaum@Sun.COM 
220*12620SMark.Shellenbaum@Oracle.COM 	/*
221*12620SMark.Shellenbaum@Oracle.COM 	 * If the z_lock is held and we aren't the owner
222*12620SMark.Shellenbaum@Oracle.COM 	 * the just return since we don't want to deadlock
223*12620SMark.Shellenbaum@Oracle.COM 	 * trying to update the status of z_is_sa.  This
224*12620SMark.Shellenbaum@Oracle.COM 	 * file can then be upgraded at a later time.
225*12620SMark.Shellenbaum@Oracle.COM 	 *
226*12620SMark.Shellenbaum@Oracle.COM 	 * Otherwise, we know we are doing the
227*12620SMark.Shellenbaum@Oracle.COM 	 * sa_update() that caused us to enter this function.
228*12620SMark.Shellenbaum@Oracle.COM 	 */
229*12620SMark.Shellenbaum@Oracle.COM 	if (mutex_owner(&zp->z_lock) != curthread) {
230*12620SMark.Shellenbaum@Oracle.COM 		if (mutex_tryenter(&zp->z_lock) == 0)
231*12620SMark.Shellenbaum@Oracle.COM 			return;
232*12620SMark.Shellenbaum@Oracle.COM 		else
233*12620SMark.Shellenbaum@Oracle.COM 			drop_lock = B_TRUE;
234*12620SMark.Shellenbaum@Oracle.COM 	}
235*12620SMark.Shellenbaum@Oracle.COM 
23611935SMark.Shellenbaum@Sun.COM 	/* First do a bulk query of the attributes that aren't cached */
23711935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
23811935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
23911935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CRTIME(zfsvfs), NULL, &crtime, 16);
24011935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
24111935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PARENT(zfsvfs), NULL, &parent, 8);
24211935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_XATTR(zfsvfs), NULL, &xattr, 8);
24311935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_RDEV(zfsvfs), NULL, &rdev, 8);
24411935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_UID(zfsvfs), NULL, &uid, 8);
24511935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_GID(zfsvfs), NULL, &gid, 8);
24611935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ZNODE_ACL(zfsvfs), NULL,
24711935SMark.Shellenbaum@Sun.COM 	    &znode_acl, 88);
24811935SMark.Shellenbaum@Sun.COM 
24911935SMark.Shellenbaum@Sun.COM 	if (sa_bulk_lookup_locked(hdl, bulk, count) != 0)
250*12620SMark.Shellenbaum@Oracle.COM 		goto done;
25111935SMark.Shellenbaum@Sun.COM 
25211935SMark.Shellenbaum@Sun.COM 
25311935SMark.Shellenbaum@Sun.COM 	/*
25411935SMark.Shellenbaum@Sun.COM 	 * While the order here doesn't matter its best to try and organize
25511935SMark.Shellenbaum@Sun.COM 	 * it is such a way to pick up an already existing layout number
25611935SMark.Shellenbaum@Sun.COM 	 */
25711935SMark.Shellenbaum@Sun.COM 	count = 0;
25811935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MODE(zfsvfs), NULL, &mode, 8);
25911935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SIZE(zfsvfs), NULL,
26011935SMark.Shellenbaum@Sun.COM 	    &zp->z_size, 8);
26111935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GEN(zfsvfs),
26211935SMark.Shellenbaum@Sun.COM 	    NULL, &zp->z_gen, 8);
26311935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_UID(zfsvfs), NULL, &uid, 8);
26411935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_GID(zfsvfs), NULL, &gid, 8);
26511935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_PARENT(zfsvfs),
26611935SMark.Shellenbaum@Sun.COM 	    NULL, &parent, 8);
26711935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_FLAGS(zfsvfs), NULL,
26811935SMark.Shellenbaum@Sun.COM 	    &zp->z_pflags, 8);
26911935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_ATIME(zfsvfs), NULL,
27011935SMark.Shellenbaum@Sun.COM 	    zp->z_atime, 16);
27111935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_MTIME(zfsvfs), NULL,
27211935SMark.Shellenbaum@Sun.COM 	    &mtime, 16);
27311935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CTIME(zfsvfs), NULL,
27411935SMark.Shellenbaum@Sun.COM 	    &ctime, 16);
27511935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_CRTIME(zfsvfs), NULL,
27611935SMark.Shellenbaum@Sun.COM 	    &crtime, 16);
27711935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_LINKS(zfsvfs), NULL,
27811935SMark.Shellenbaum@Sun.COM 	    &zp->z_links, 8);
27911935SMark.Shellenbaum@Sun.COM 	if (zp->z_vnode->v_type == VBLK || zp->z_vnode->v_type == VCHR)
28011935SMark.Shellenbaum@Sun.COM 		SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_RDEV(zfsvfs), NULL,
28111935SMark.Shellenbaum@Sun.COM 		    &rdev, 8);
28211935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_COUNT(zfsvfs), NULL,
28311935SMark.Shellenbaum@Sun.COM 	    &zp->z_acl_cached->z_acl_count, 8);
28411935SMark.Shellenbaum@Sun.COM 
28511935SMark.Shellenbaum@Sun.COM 	if (zp->z_acl_cached->z_version < ZFS_ACL_VERSION_FUID)
28611935SMark.Shellenbaum@Sun.COM 		zfs_acl_xform(zp, zp->z_acl_cached, CRED());
28711935SMark.Shellenbaum@Sun.COM 
28811935SMark.Shellenbaum@Sun.COM 	locate.cb_aclp = zp->z_acl_cached;
28911935SMark.Shellenbaum@Sun.COM 	SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_DACL_ACES(zfsvfs),
29011935SMark.Shellenbaum@Sun.COM 	    zfs_acl_data_locator, &locate, zp->z_acl_cached->z_acl_bytes);
291*12620SMark.Shellenbaum@Oracle.COM 
29211935SMark.Shellenbaum@Sun.COM 	if (xattr)
293*12620SMark.Shellenbaum@Oracle.COM 		SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_XATTR(zfsvfs),
294*12620SMark.Shellenbaum@Oracle.COM 		    NULL, &xattr, 8);
29511935SMark.Shellenbaum@Sun.COM 
29611935SMark.Shellenbaum@Sun.COM 	/* if scanstamp then add scanstamp */
29711935SMark.Shellenbaum@Sun.COM 
29811935SMark.Shellenbaum@Sun.COM 	if (zp->z_pflags & ZFS_BONUS_SCANSTAMP) {
29911935SMark.Shellenbaum@Sun.COM 		bcopy((caddr_t)db->db_data + ZFS_OLD_ZNODE_PHYS_SIZE,
30011935SMark.Shellenbaum@Sun.COM 		    scanstamp, AV_SCANSTAMP_SZ);
30111935SMark.Shellenbaum@Sun.COM 		SA_ADD_BULK_ATTR(sa_attrs, count, SA_ZPL_SCANSTAMP(zfsvfs),
30211935SMark.Shellenbaum@Sun.COM 		    NULL, scanstamp, AV_SCANSTAMP_SZ);
30311935SMark.Shellenbaum@Sun.COM 		zp->z_pflags &= ~ZFS_BONUS_SCANSTAMP;
30411935SMark.Shellenbaum@Sun.COM 	}
30511935SMark.Shellenbaum@Sun.COM 
30611935SMark.Shellenbaum@Sun.COM 	VERIFY(dmu_set_bonustype(db, DMU_OT_SA, tx) == 0);
30711935SMark.Shellenbaum@Sun.COM 	VERIFY(sa_replace_all_by_template_locked(hdl, sa_attrs,
30811935SMark.Shellenbaum@Sun.COM 	    count, tx) == 0);
30911935SMark.Shellenbaum@Sun.COM 	if (znode_acl.z_acl_extern_obj)
31011935SMark.Shellenbaum@Sun.COM 		VERIFY(0 == dmu_object_free(zfsvfs->z_os,
31111935SMark.Shellenbaum@Sun.COM 		    znode_acl.z_acl_extern_obj, tx));
31211935SMark.Shellenbaum@Sun.COM 
31311935SMark.Shellenbaum@Sun.COM 	zp->z_is_sa = B_TRUE;
314*12620SMark.Shellenbaum@Oracle.COM done:
315*12620SMark.Shellenbaum@Oracle.COM 	if (drop_lock)
316*12620SMark.Shellenbaum@Oracle.COM 		mutex_exit(&zp->z_lock);
31711935SMark.Shellenbaum@Sun.COM }
31811935SMark.Shellenbaum@Sun.COM 
31911935SMark.Shellenbaum@Sun.COM void
zfs_sa_upgrade_txholds(dmu_tx_t * tx,znode_t * zp)32011935SMark.Shellenbaum@Sun.COM zfs_sa_upgrade_txholds(dmu_tx_t *tx, znode_t *zp)
32111935SMark.Shellenbaum@Sun.COM {
32211935SMark.Shellenbaum@Sun.COM 	if (!zp->z_zfsvfs->z_use_sa || zp->z_is_sa)
32311935SMark.Shellenbaum@Sun.COM 		return;
32411935SMark.Shellenbaum@Sun.COM 
32511935SMark.Shellenbaum@Sun.COM 
32611935SMark.Shellenbaum@Sun.COM 	dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_TRUE);
32711935SMark.Shellenbaum@Sun.COM 
328*12620SMark.Shellenbaum@Oracle.COM 	if (zfs_external_acl(zp)) {
329*12620SMark.Shellenbaum@Oracle.COM 		dmu_tx_hold_free(tx, zfs_external_acl(zp), 0,
33011935SMark.Shellenbaum@Sun.COM 		    DMU_OBJECT_END);
33111935SMark.Shellenbaum@Sun.COM 	}
33211935SMark.Shellenbaum@Sun.COM }
33311935SMark.Shellenbaum@Sun.COM 
33411935SMark.Shellenbaum@Sun.COM #endif
335