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