Fix projid accounting for xattr objects
zpool upgraded with 'feature@project_quota' needs re-layout of SA's to fix the SA_ZPL_PROJID at SA_PROJID_OFFSET (128). Its necessary for the correct accounting of object usage against its projid. Old object (created before upgrade) when gets a projid assigned, its SA gets re-layout via sa_add_projid(). If object has xattr dir, SA of xattr dir also gets re-layout. But SA re-layout of xattr objects inside a xattr dir is not done. Fix zfs_setattr_dir() to re-layout SA's on xattr objects, when setting projid on old xattr object (created before upgrade). Reviewed-by: Tony Hutter <hutter2@llnl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Jitendra Patidar <jitendra.patidar@nutanix.com> Closes #16355 Closes #16356
This commit is contained in:
parent
244ea5c488
commit
d2ccc21552
|
@ -1789,24 +1789,36 @@ zfs_setattr_dir(znode_t *dzp)
|
|||
&gid, sizeof (gid));
|
||||
}
|
||||
|
||||
if (zp->z_projid != dzp->z_projid) {
|
||||
|
||||
uint64_t projid = dzp->z_projid;
|
||||
if (zp->z_projid != projid) {
|
||||
if (!(zp->z_pflags & ZFS_PROJID)) {
|
||||
zp->z_pflags |= ZFS_PROJID;
|
||||
SA_ADD_BULK_ATTR(bulk, count,
|
||||
SA_ZPL_FLAGS(zfsvfs), NULL, &zp->z_pflags,
|
||||
sizeof (zp->z_pflags));
|
||||
err = sa_add_projid(zp->z_sa_hdl, tx, projid);
|
||||
if (unlikely(err == EEXIST)) {
|
||||
err = 0;
|
||||
} else if (err != 0) {
|
||||
goto sa_add_projid_err;
|
||||
} else {
|
||||
projid = ZFS_INVALID_PROJID;
|
||||
}
|
||||
}
|
||||
|
||||
zp->z_projid = dzp->z_projid;
|
||||
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_PROJID(zfsvfs),
|
||||
NULL, &zp->z_projid, sizeof (zp->z_projid));
|
||||
if (projid != ZFS_INVALID_PROJID) {
|
||||
zp->z_projid = projid;
|
||||
SA_ADD_BULK_ATTR(bulk, count,
|
||||
SA_ZPL_PROJID(zfsvfs), NULL, &zp->z_projid,
|
||||
sizeof (zp->z_projid));
|
||||
}
|
||||
}
|
||||
|
||||
sa_add_projid_err:
|
||||
mutex_exit(&dzp->z_lock);
|
||||
|
||||
if (likely(count > 0)) {
|
||||
err = sa_bulk_update(zp->z_sa_hdl, bulk, count, tx);
|
||||
dmu_tx_commit(tx);
|
||||
} else if (projid == ZFS_INVALID_PROJID) {
|
||||
dmu_tx_commit(tx);
|
||||
} else {
|
||||
dmu_tx_abort(tx);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ log_must mkfiles $TESTDIR/fs2/tf $((RANDOM % 100 + 1))
|
|||
log_must zfs create $TESTPOOL/fs3
|
||||
log_must mkdir $TESTDIR/fs3/dir
|
||||
log_must mkfiles $TESTDIR/fs3/tf $((RANDOM % 100 + 1))
|
||||
log_must set_xattr_stdin passwd $TESTDIR/fs3/dir < /etc/passwd
|
||||
|
||||
# Make sure project quota is disabled
|
||||
zfs projectspace -o used $TESTPOOL | grep -q "USED" &&
|
||||
|
@ -109,9 +110,23 @@ log_must chattr -p 100 $TESTDIR/fs3/dir
|
|||
log_must sleep 5 # upgrade done in the background so let's wait for a while
|
||||
zfs projectspace -o used $TESTPOOL/fs3 | grep -q "USED" ||
|
||||
log_fail "project quota should be enabled for $TESTPOOL/fs3"
|
||||
dirino=$(stat -c '%i' $TESTDIR/fs3/dir)
|
||||
log_must zdb -ddddd $TESTPOOL/fs3 $dirino
|
||||
xattrdirino=$(zdb -ddddd $TESTPOOL/fs3 $dirino |grep -w "xattr" |awk '{print $2}')
|
||||
echo "xattrdirino: $xattrdirino"
|
||||
expectedcnt=1
|
||||
echo "expectedcnt: $expectedcnt"
|
||||
if [ "$xattrdirino" != "" ]; then
|
||||
expectedcnt=$(($expectedcnt + 1))
|
||||
echo "expectedcnt: $expectedcnt"
|
||||
log_must zdb -ddddd $TESTPOOL/fs3 $xattrdirino
|
||||
xattrinocnt=$(zdb -ddddd $TESTPOOL/fs3 $xattrdirino |grep -w "(type:" |wc -l)
|
||||
echo "xattrinocnt: $xattrinocnt"
|
||||
expectedcnt=$(($expectedcnt + $xattrinocnt))
|
||||
echo "expectedcnt: $expectedcnt"
|
||||
fi
|
||||
cnt=$(get_prop projectobjused@100 $TESTPOOL/fs3)
|
||||
# if 'xattr=on', then 'cnt = 2'
|
||||
[[ $cnt -ne 1 ]] && [[ $cnt -ne 2 ]] &&
|
||||
[[ $cnt -ne $expectedcnt ]] &&
|
||||
log_fail "projectquota accounting failed $cnt"
|
||||
|
||||
# All in all, after having been through this, the dataset for testpool
|
||||
|
|
Loading…
Reference in New Issue