diff options
author | Ryan Moeller <[email protected]> | 2019-12-11 15:12:08 -0500 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2019-12-11 12:12:08 -0800 |
commit | 957c7aa23c3000cfdff5d5b1c1341ea773e60afa (patch) | |
tree | bf497380441b8cbd7d17e85bee3fb196bb03e8e5 /module/os/linux/zfs | |
parent | 4bc721965ff272ad59c6e8a130a544e1e2c01b34 (diff) |
Relocate common quota functions to shared code
The quota functions are common to all implementations and can be
moved to common code. As a simplification they were moved to the
Linux platform code in the initial refactoring.
Reviewed-by: Jorgen Lundman <[email protected]>
Reviewed-by: Igor Kozhukhov <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Ryan Moeller <[email protected]>
Closes #9710
Diffstat (limited to 'module/os/linux/zfs')
-rw-r--r-- | module/os/linux/zfs/zfs_acl.c | 1 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_vfsops.c | 458 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_vnops.c | 1 |
3 files changed, 5 insertions, 455 deletions
diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c index ab813cf26..794c99551 100644 --- a/module/os/linux/zfs/zfs_acl.c +++ b/module/os/linux/zfs/zfs_acl.c @@ -42,6 +42,7 @@ #include <sys/zfs_fuid.h> #include <sys/zfs_acl.h> #include <sys/zfs_dir.h> +#include <sys/zfs_quota.h> #include <sys/zfs_vfsops.h> #include <sys/dmu.h> #include <sys/dnode.h> diff --git a/module/os/linux/zfs/zfs_vfsops.c b/module/os/linux/zfs/zfs_vfsops.c index 02e37f964..dba52baeb 100644 --- a/module/os/linux/zfs/zfs_vfsops.c +++ b/module/os/linux/zfs/zfs_vfsops.c @@ -52,6 +52,7 @@ #include <sys/zfs_ioctl.h> #include <sys/zfs_ctldir.h> #include <sys/zfs_fuid.h> +#include <sys/zfs_quota.h> #include <sys/sunddi.h> #include <sys/dmu_objset.h> #include <sys/spa_boot.h> @@ -608,454 +609,6 @@ zfs_get_temporary_prop(dsl_dataset_t *ds, zfs_prop_t zfs_prop, uint64_t *val, return (0); } -static int -zfs_space_delta_cb(dmu_object_type_t bonustype, void *data, - uint64_t *userp, uint64_t *groupp, uint64_t *projectp) -{ - sa_hdr_phys_t sa; - sa_hdr_phys_t *sap = data; - uint64_t flags; - int hdrsize; - boolean_t swap = B_FALSE; - - /* - * Is it a valid type of object to track? - */ - if (bonustype != DMU_OT_ZNODE && bonustype != DMU_OT_SA) - return (SET_ERROR(ENOENT)); - - /* - * If we have a NULL data pointer - * then assume the id's aren't changing and - * return EEXIST to the dmu to let it know to - * use the same ids - */ - if (data == NULL) - return (SET_ERROR(EEXIST)); - - if (bonustype == DMU_OT_ZNODE) { - znode_phys_t *znp = data; - *userp = znp->zp_uid; - *groupp = znp->zp_gid; - *projectp = ZFS_DEFAULT_PROJID; - return (0); - } - - if (sap->sa_magic == 0) { - /* - * This should only happen for newly created files - * that haven't had the znode data filled in yet. - */ - *userp = 0; - *groupp = 0; - *projectp = ZFS_DEFAULT_PROJID; - return (0); - } - - sa = *sap; - if (sa.sa_magic == BSWAP_32(SA_MAGIC)) { - sa.sa_magic = SA_MAGIC; - sa.sa_layout_info = BSWAP_16(sa.sa_layout_info); - swap = B_TRUE; - } else { - VERIFY3U(sa.sa_magic, ==, SA_MAGIC); - } - - hdrsize = sa_hdrsize(&sa); - VERIFY3U(hdrsize, >=, sizeof (sa_hdr_phys_t)); - - *userp = *((uint64_t *)((uintptr_t)data + hdrsize + SA_UID_OFFSET)); - *groupp = *((uint64_t *)((uintptr_t)data + hdrsize + SA_GID_OFFSET)); - flags = *((uint64_t *)((uintptr_t)data + hdrsize + SA_FLAGS_OFFSET)); - if (swap) - flags = BSWAP_64(flags); - - if (flags & ZFS_PROJID) - *projectp = *((uint64_t *)((uintptr_t)data + hdrsize + - SA_PROJID_OFFSET)); - else - *projectp = ZFS_DEFAULT_PROJID; - - if (swap) { - *userp = BSWAP_64(*userp); - *groupp = BSWAP_64(*groupp); - *projectp = BSWAP_64(*projectp); - } - return (0); -} - -static void -fuidstr_to_sid(zfsvfs_t *zfsvfs, const char *fuidstr, - char *domainbuf, int buflen, uid_t *ridp) -{ - uint64_t fuid; - const char *domain; - - fuid = zfs_strtonum(fuidstr, NULL); - - domain = zfs_fuid_find_by_idx(zfsvfs, FUID_INDEX(fuid)); - if (domain) - (void) strlcpy(domainbuf, domain, buflen); - else - domainbuf[0] = '\0'; - *ridp = FUID_RID(fuid); -} - -static uint64_t -zfs_userquota_prop_to_obj(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type) -{ - switch (type) { - case ZFS_PROP_USERUSED: - case ZFS_PROP_USEROBJUSED: - return (DMU_USERUSED_OBJECT); - case ZFS_PROP_GROUPUSED: - case ZFS_PROP_GROUPOBJUSED: - return (DMU_GROUPUSED_OBJECT); - case ZFS_PROP_PROJECTUSED: - case ZFS_PROP_PROJECTOBJUSED: - return (DMU_PROJECTUSED_OBJECT); - case ZFS_PROP_USERQUOTA: - return (zfsvfs->z_userquota_obj); - case ZFS_PROP_GROUPQUOTA: - return (zfsvfs->z_groupquota_obj); - case ZFS_PROP_USEROBJQUOTA: - return (zfsvfs->z_userobjquota_obj); - case ZFS_PROP_GROUPOBJQUOTA: - return (zfsvfs->z_groupobjquota_obj); - case ZFS_PROP_PROJECTQUOTA: - return (zfsvfs->z_projectquota_obj); - case ZFS_PROP_PROJECTOBJQUOTA: - return (zfsvfs->z_projectobjquota_obj); - default: - return (ZFS_NO_OBJECT); - } -} - -int -zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, - uint64_t *cookiep, void *vbuf, uint64_t *bufsizep) -{ - int error; - zap_cursor_t zc; - zap_attribute_t za; - zfs_useracct_t *buf = vbuf; - uint64_t obj; - int offset = 0; - - if (!dmu_objset_userspace_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - - if ((type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED || - type == ZFS_PROP_PROJECTOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED) && - !dmu_objset_projectquota_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - - if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || - type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED || - type == ZFS_PROP_PROJECTOBJQUOTA) && - !dmu_objset_userobjspace_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - - obj = zfs_userquota_prop_to_obj(zfsvfs, type); - if (obj == ZFS_NO_OBJECT) { - *bufsizep = 0; - return (0); - } - - if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || - type == ZFS_PROP_PROJECTOBJUSED) - offset = DMU_OBJACCT_PREFIX_LEN; - - for (zap_cursor_init_serialized(&zc, zfsvfs->z_os, obj, *cookiep); - (error = zap_cursor_retrieve(&zc, &za)) == 0; - zap_cursor_advance(&zc)) { - if ((uintptr_t)buf - (uintptr_t)vbuf + sizeof (zfs_useracct_t) > - *bufsizep) - break; - - /* - * skip object quota (with zap name prefix DMU_OBJACCT_PREFIX) - * when dealing with block quota and vice versa. - */ - if ((offset > 0) != (strncmp(za.za_name, DMU_OBJACCT_PREFIX, - DMU_OBJACCT_PREFIX_LEN) == 0)) - continue; - - fuidstr_to_sid(zfsvfs, za.za_name + offset, - buf->zu_domain, sizeof (buf->zu_domain), &buf->zu_rid); - - buf->zu_space = za.za_first_integer; - buf++; - } - if (error == ENOENT) - error = 0; - - ASSERT3U((uintptr_t)buf - (uintptr_t)vbuf, <=, *bufsizep); - *bufsizep = (uintptr_t)buf - (uintptr_t)vbuf; - *cookiep = zap_cursor_serialize(&zc); - zap_cursor_fini(&zc); - return (error); -} - -/* - * buf must be big enough (eg, 32 bytes) - */ -static int -id_to_fuidstr(zfsvfs_t *zfsvfs, const char *domain, uid_t rid, - char *buf, boolean_t addok) -{ - uint64_t fuid; - int domainid = 0; - - if (domain && domain[0]) { - domainid = zfs_fuid_find_by_domain(zfsvfs, domain, NULL, addok); - if (domainid == -1) - return (SET_ERROR(ENOENT)); - } - fuid = FUID_ENCODE(domainid, rid); - (void) sprintf(buf, "%llx", (longlong_t)fuid); - return (0); -} - -int -zfs_userspace_one(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, - const char *domain, uint64_t rid, uint64_t *valp) -{ - char buf[20 + DMU_OBJACCT_PREFIX_LEN]; - int offset = 0; - int err; - uint64_t obj; - - *valp = 0; - - if (!dmu_objset_userspace_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - - if ((type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || - type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED || - type == ZFS_PROP_PROJECTOBJQUOTA) && - !dmu_objset_userobjspace_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - - if (type == ZFS_PROP_PROJECTQUOTA || type == ZFS_PROP_PROJECTUSED || - type == ZFS_PROP_PROJECTOBJQUOTA || - type == ZFS_PROP_PROJECTOBJUSED) { - if (!dmu_objset_projectquota_present(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - if (!zpl_is_valid_projid(rid)) - return (SET_ERROR(EINVAL)); - } - - obj = zfs_userquota_prop_to_obj(zfsvfs, type); - if (obj == ZFS_NO_OBJECT) - return (0); - - if (type == ZFS_PROP_USEROBJUSED || type == ZFS_PROP_GROUPOBJUSED || - type == ZFS_PROP_PROJECTOBJUSED) { - strlcpy(buf, DMU_OBJACCT_PREFIX, DMU_OBJACCT_PREFIX_LEN + 1); - offset = DMU_OBJACCT_PREFIX_LEN; - } - - err = id_to_fuidstr(zfsvfs, domain, rid, buf + offset, B_FALSE); - if (err) - return (err); - - err = zap_lookup(zfsvfs->z_os, obj, buf, 8, 1, valp); - if (err == ENOENT) - err = 0; - return (err); -} - -int -zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type, - const char *domain, uint64_t rid, uint64_t quota) -{ - char buf[32]; - int err; - dmu_tx_t *tx; - uint64_t *objp; - boolean_t fuid_dirtied; - - if (zfsvfs->z_version < ZPL_VERSION_USERSPACE) - return (SET_ERROR(ENOTSUP)); - - switch (type) { - case ZFS_PROP_USERQUOTA: - objp = &zfsvfs->z_userquota_obj; - break; - case ZFS_PROP_GROUPQUOTA: - objp = &zfsvfs->z_groupquota_obj; - break; - case ZFS_PROP_USEROBJQUOTA: - objp = &zfsvfs->z_userobjquota_obj; - break; - case ZFS_PROP_GROUPOBJQUOTA: - objp = &zfsvfs->z_groupobjquota_obj; - break; - case ZFS_PROP_PROJECTQUOTA: - if (!dmu_objset_projectquota_enabled(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - if (!zpl_is_valid_projid(rid)) - return (SET_ERROR(EINVAL)); - - objp = &zfsvfs->z_projectquota_obj; - break; - case ZFS_PROP_PROJECTOBJQUOTA: - if (!dmu_objset_projectquota_enabled(zfsvfs->z_os)) - return (SET_ERROR(ENOTSUP)); - if (!zpl_is_valid_projid(rid)) - return (SET_ERROR(EINVAL)); - - objp = &zfsvfs->z_projectobjquota_obj; - break; - default: - return (SET_ERROR(EINVAL)); - } - - err = id_to_fuidstr(zfsvfs, domain, rid, buf, B_TRUE); - if (err) - return (err); - fuid_dirtied = zfsvfs->z_fuid_dirty; - - tx = dmu_tx_create(zfsvfs->z_os); - dmu_tx_hold_zap(tx, *objp ? *objp : DMU_NEW_OBJECT, B_TRUE, NULL); - if (*objp == 0) { - dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, B_TRUE, - zfs_userquota_prop_prefixes[type]); - } - if (fuid_dirtied) - zfs_fuid_txhold(zfsvfs, tx); - err = dmu_tx_assign(tx, TXG_WAIT); - if (err) { - dmu_tx_abort(tx); - return (err); - } - - mutex_enter(&zfsvfs->z_lock); - if (*objp == 0) { - *objp = zap_create(zfsvfs->z_os, DMU_OT_USERGROUP_QUOTA, - DMU_OT_NONE, 0, tx); - VERIFY(0 == zap_add(zfsvfs->z_os, MASTER_NODE_OBJ, - zfs_userquota_prop_prefixes[type], 8, 1, objp, tx)); - } - mutex_exit(&zfsvfs->z_lock); - - if (quota == 0) { - err = zap_remove(zfsvfs->z_os, *objp, buf, tx); - if (err == ENOENT) - err = 0; - } else { - err = zap_update(zfsvfs->z_os, *objp, buf, 8, 1, "a, tx); - } - ASSERT(err == 0); - if (fuid_dirtied) - zfs_fuid_sync(zfsvfs, tx); - dmu_tx_commit(tx); - return (err); -} - -boolean_t -zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) -{ - char buf[20 + DMU_OBJACCT_PREFIX_LEN]; - uint64_t used, quota, quotaobj; - int err; - - if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) { - if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) { - dsl_pool_config_enter( - dmu_objset_pool(zfsvfs->z_os), FTAG); - dmu_objset_id_quota_upgrade(zfsvfs->z_os); - dsl_pool_config_exit( - dmu_objset_pool(zfsvfs->z_os), FTAG); - } - return (B_FALSE); - } - - if (usedobj == DMU_PROJECTUSED_OBJECT) { - if (!dmu_objset_projectquota_present(zfsvfs->z_os)) { - if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) { - dsl_pool_config_enter( - dmu_objset_pool(zfsvfs->z_os), FTAG); - dmu_objset_id_quota_upgrade(zfsvfs->z_os); - dsl_pool_config_exit( - dmu_objset_pool(zfsvfs->z_os), FTAG); - } - return (B_FALSE); - } - quotaobj = zfsvfs->z_projectobjquota_obj; - } else if (usedobj == DMU_USERUSED_OBJECT) { - quotaobj = zfsvfs->z_userobjquota_obj; - } else if (usedobj == DMU_GROUPUSED_OBJECT) { - quotaobj = zfsvfs->z_groupobjquota_obj; - } else { - return (B_FALSE); - } - if (quotaobj == 0 || zfsvfs->z_replay) - return (B_FALSE); - - (void) sprintf(buf, "%llx", (longlong_t)id); - err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); - if (err != 0) - return (B_FALSE); - - (void) sprintf(buf, DMU_OBJACCT_PREFIX "%llx", (longlong_t)id); - err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); - if (err != 0) - return (B_FALSE); - return (used >= quota); -} - -boolean_t -zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) -{ - char buf[20]; - uint64_t used, quota, quotaobj; - int err; - - if (usedobj == DMU_PROJECTUSED_OBJECT) { - if (!dmu_objset_projectquota_present(zfsvfs->z_os)) { - if (dmu_objset_projectquota_upgradable(zfsvfs->z_os)) { - dsl_pool_config_enter( - dmu_objset_pool(zfsvfs->z_os), FTAG); - dmu_objset_id_quota_upgrade(zfsvfs->z_os); - dsl_pool_config_exit( - dmu_objset_pool(zfsvfs->z_os), FTAG); - } - return (B_FALSE); - } - quotaobj = zfsvfs->z_projectquota_obj; - } else if (usedobj == DMU_USERUSED_OBJECT) { - quotaobj = zfsvfs->z_userquota_obj; - } else if (usedobj == DMU_GROUPUSED_OBJECT) { - quotaobj = zfsvfs->z_groupquota_obj; - } else { - return (B_FALSE); - } - if (quotaobj == 0 || zfsvfs->z_replay) - return (B_FALSE); - - (void) sprintf(buf, "%llx", (longlong_t)id); - err = zap_lookup(zfsvfs->z_os, quotaobj, buf, 8, 1, "a); - if (err != 0) - return (B_FALSE); - - err = zap_lookup(zfsvfs->z_os, usedobj, buf, 8, 1, &used); - if (err != 0) - return (B_FALSE); - return (used >= quota); -} - -boolean_t -zfs_id_overquota(zfsvfs_t *zfsvfs, uint64_t usedobj, uint64_t id) -{ - return (zfs_id_overblockquota(zfsvfs, usedobj, id) || - zfs_id_overobjquota(zfsvfs, usedobj, id)); -} - /* * Associate this zfsvfs with the given objset, which must be owned. * This will cache a bunch of on-disk state from the objset in the @@ -1454,7 +1007,8 @@ zfs_statfs_project(zfsvfs_t *zfsvfs, znode_t *zp, struct kstatfs *statp, int err; strlcpy(buf, DMU_OBJACCT_PREFIX, DMU_OBJACCT_PREFIX_LEN + 1); - err = id_to_fuidstr(zfsvfs, NULL, zp->z_projid, buf + offset, B_FALSE); + err = zfs_id_to_fuidstr(zfsvfs, NULL, zp->z_projid, buf + offset, + B_FALSE); if (err) return (err); @@ -2575,12 +2129,6 @@ zfs_fini(void) #if defined(_KERNEL) EXPORT_SYMBOL(zfs_suspend_fs); EXPORT_SYMBOL(zfs_resume_fs); -EXPORT_SYMBOL(zfs_userspace_one); -EXPORT_SYMBOL(zfs_userspace_many); -EXPORT_SYMBOL(zfs_set_userquota); -EXPORT_SYMBOL(zfs_id_overblockquota); -EXPORT_SYMBOL(zfs_id_overobjquota); -EXPORT_SYMBOL(zfs_id_overquota); EXPORT_SYMBOL(zfs_set_version); EXPORT_SYMBOL(zfsvfs_create); EXPORT_SYMBOL(zfsvfs_free); diff --git a/module/os/linux/zfs/zfs_vnops.c b/module/os/linux/zfs/zfs_vnops.c index b5e1a63ad..b1fa89167 100644 --- a/module/os/linux/zfs/zfs_vnops.c +++ b/module/os/linux/zfs/zfs_vnops.c @@ -61,6 +61,7 @@ #include <sys/sid.h> #include <sys/zfs_ctldir.h> #include <sys/zfs_fuid.h> +#include <sys/zfs_quota.h> #include <sys/zfs_sa.h> #include <sys/zfs_vnops.h> #include <sys/zfs_rlock.h> |