diff options
author | Jinshan Xiong <[email protected]> | 2016-10-04 11:46:10 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-10-07 09:45:13 -0700 |
commit | 1de321e6260f5b83eb943b6ce2166a3879f42df4 (patch) | |
tree | 5af1627e1f4b9efc0bf67eff965d480e6d603396 /include | |
parent | af322debaa11b22c4fe7b6bc8941e562694eabb2 (diff) |
Add support for user/group dnode accounting & quota
This patch tracks dnode usage for each user/group in the
DMU_USER/GROUPUSED_OBJECT ZAPs. ZAP entries dedicated to dnode
accounting have the key prefixed with "obj-" followed by the UID/GID
in string format (as done for the block accounting).
A new SPA feature has been added for dnode accounting as well as
a new ZPL version. The SPA feature must be enabled in the pool
before upgrading the zfs filesystem. During the zfs version upgrade,
a "quotacheck" will be executed by marking all dnode as dirty.
ZoL-bug-id: https://github.com/zfsonlinux/zfs/issues/3500
Signed-off-by: Jinshan Xiong <[email protected]>
Signed-off-by: Johann Lombardi <[email protected]>
Diffstat (limited to 'include')
-rw-r--r-- | include/sys/dmu.h | 6 | ||||
-rw-r--r-- | include/sys/dmu_objset.h | 21 | ||||
-rw-r--r-- | include/sys/dnode.h | 9 | ||||
-rw-r--r-- | include/sys/dsl_deleg.h | 4 | ||||
-rw-r--r-- | include/sys/fs/zfs.h | 4 | ||||
-rw-r--r-- | include/sys/spa_impl.h | 2 | ||||
-rw-r--r-- | include/sys/zfs_vfsops.h | 4 | ||||
-rw-r--r-- | include/zfeature_common.h | 1 | ||||
-rw-r--r-- | include/zfs_deleg.h | 4 |
9 files changed, 52 insertions, 3 deletions
diff --git a/include/sys/dmu.h b/include/sys/dmu.h index b67acb52c..ec89e9018 100644 --- a/include/sys/dmu.h +++ b/include/sys/dmu.h @@ -257,6 +257,12 @@ void zfs_znode_byteswap(void *buf, size_t size); #define DMU_GROUPUSED_OBJECT (-2ULL) /* + * Zap prefix for object accounting in DMU_{USER,GROUP}USED_OBJECT. + */ +#define DMU_OBJACCT_PREFIX "obj-" +#define DMU_OBJACCT_PREFIX_LEN 4 + +/* * artificial blkids for bonus buffer and spill blocks */ #define DMU_BONUS_BLKID (-1ULL) diff --git a/include/sys/dmu_objset.h b/include/sys/dmu_objset.h index 1674897c2..68fb5cffb 100644 --- a/include/sys/dmu_objset.h +++ b/include/sys/dmu_objset.h @@ -56,6 +56,7 @@ struct dmu_tx; (arc_buf_size(buf) > OBJSET_OLD_PHYS_SIZE) #define OBJSET_FLAG_USERACCOUNTING_COMPLETE (1ULL<<0) +#define OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE (1ULL<<1) typedef struct objset_phys { dnode_phys_t os_meta_dnode; @@ -68,6 +69,8 @@ typedef struct objset_phys { dnode_phys_t os_groupused_dnode; } objset_phys_t; +typedef int (*dmu_objset_upgrade_cb_t)(objset_t *); + struct objset { /* Immutable: */ struct dsl_dataset *os_dsl_dataset; @@ -125,6 +128,13 @@ struct objset { kmutex_t os_user_ptr_lock; void *os_user_ptr; sa_os_t *os_sa; + + /* kernel thread to upgrade this dataset */ + kmutex_t os_upgrade_lock; + taskqid_t os_upgrade_id; + dmu_objset_upgrade_cb_t os_upgrade_cb; + boolean_t os_upgrade_exit; + int os_upgrade_status; }; #define DMU_META_OBJSET 0 @@ -173,6 +183,17 @@ void dmu_objset_userquota_get_ids(dnode_t *dn, boolean_t before, dmu_tx_t *tx); boolean_t dmu_objset_userused_enabled(objset_t *os); int dmu_objset_userspace_upgrade(objset_t *os); boolean_t dmu_objset_userspace_present(objset_t *os); +boolean_t dmu_objset_userobjused_enabled(objset_t *os); +void dmu_objset_userobjspace_upgrade(objset_t *os); +boolean_t dmu_objset_userobjspace_present(objset_t *os); + +static inline boolean_t dmu_objset_userobjspace_upgradable(objset_t *os) +{ + return (dmu_objset_type(os) == DMU_OST_ZFS && + dmu_objset_userobjused_enabled(os) && + !dmu_objset_userobjspace_present(os)); +} + int dmu_fsname(const char *snapname, char *buf); void dmu_objset_evict_done(objset_t *os); diff --git a/include/sys/dnode.h b/include/sys/dnode.h index fe36e5989..fe4cd3e4b 100644 --- a/include/sys/dnode.h +++ b/include/sys/dnode.h @@ -126,11 +126,14 @@ enum dnode_dirtycontext { }; /* Is dn_used in bytes? if not, it's in multiples of SPA_MINBLOCKSIZE */ -#define DNODE_FLAG_USED_BYTES (1<<0) -#define DNODE_FLAG_USERUSED_ACCOUNTED (1<<1) +#define DNODE_FLAG_USED_BYTES (1 << 0) +#define DNODE_FLAG_USERUSED_ACCOUNTED (1 << 1) /* Does dnode have a SA spill blkptr in bonus? */ -#define DNODE_FLAG_SPILL_BLKPTR (1<<2) +#define DNODE_FLAG_SPILL_BLKPTR (1 << 2) + +/* User/Group dnode accounting */ +#define DNODE_FLAG_USEROBJUSED_ACCOUNTED (1 << 3) typedef struct dnode_phys { uint8_t dn_type; /* dmu_object_type_t */ diff --git a/include/sys/dsl_deleg.h b/include/sys/dsl_deleg.h index 59e8e0555..d399d1da9 100644 --- a/include/sys/dsl_deleg.h +++ b/include/sys/dsl_deleg.h @@ -51,8 +51,12 @@ extern "C" { #define ZFS_DELEG_PERM_VSCAN "vscan" #define ZFS_DELEG_PERM_USERQUOTA "userquota" #define ZFS_DELEG_PERM_GROUPQUOTA "groupquota" +#define ZFS_DELEG_PERM_USEROBJQUOTA "userobjquota" +#define ZFS_DELEG_PERM_GROUPOBJQUOTA "groupobjquota" #define ZFS_DELEG_PERM_USERUSED "userused" #define ZFS_DELEG_PERM_GROUPUSED "groupused" +#define ZFS_DELEG_PERM_USEROBJUSED "userobjused" +#define ZFS_DELEG_PERM_GROUPOBJUSED "groupobjused" #define ZFS_DELEG_PERM_HOLD "hold" #define ZFS_DELEG_PERM_RELEASE "release" #define ZFS_DELEG_PERM_DIFF "diff" diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 9d3008934..5c93f53de 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -171,6 +171,10 @@ typedef enum { ZFS_PROP_USERQUOTA, ZFS_PROP_GROUPUSED, ZFS_PROP_GROUPQUOTA, + ZFS_PROP_USEROBJUSED, + ZFS_PROP_USEROBJQUOTA, + ZFS_PROP_GROUPOBJUSED, + ZFS_PROP_GROUPOBJQUOTA, ZFS_NUM_USERQUOTA_PROPS } zfs_userquota_prop_t; diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h index 7b9e1ee0c..cb1d16ad5 100644 --- a/include/sys/spa_impl.h +++ b/include/sys/spa_impl.h @@ -277,6 +277,8 @@ struct spa { */ spa_config_lock_t spa_config_lock[SCL_LOCKS]; /* config changes */ refcount_t spa_refcount; /* number of opens */ + + taskq_t *spa_upgrade_taskq; /* taskq for upgrade jobs */ }; extern char *spa_config_path; diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h index efaefdacc..b59ace5b1 100644 --- a/include/sys/zfs_vfsops.h +++ b/include/sys/zfs_vfsops.h @@ -110,6 +110,8 @@ typedef struct zfs_sb { kmutex_t z_lock; uint64_t z_userquota_obj; uint64_t z_groupquota_obj; + uint64_t z_userobjquota_obj; + uint64_t z_groupobjquota_obj; uint64_t z_replay_eof; /* New end of file - replay only */ sa_attr_type_t *z_attr_table; /* SA attr mapping->id */ uint64_t z_hold_size; /* znode hold array size */ @@ -190,6 +192,8 @@ extern boolean_t zfs_owner_overquota(zfs_sb_t *zsb, struct znode *, boolean_t isgroup); extern boolean_t zfs_fuid_overquota(zfs_sb_t *zsb, boolean_t isgroup, uint64_t fuid); +extern boolean_t zfs_fuid_overobjquota(zfs_sb_t *zsb, boolean_t isgroup, + uint64_t fuid); extern int zfs_set_version(zfs_sb_t *zsb, uint64_t newvers); extern int zfs_get_zplprop(objset_t *os, zfs_prop_t prop, uint64_t *value); diff --git a/include/zfeature_common.h b/include/zfeature_common.h index f05480181..acf76381b 100644 --- a/include/zfeature_common.h +++ b/include/zfeature_common.h @@ -54,6 +54,7 @@ typedef enum spa_feature { SPA_FEATURE_SHA512, SPA_FEATURE_SKEIN, SPA_FEATURE_EDONR, + SPA_FEATURE_USEROBJ_ACCOUNTING, SPA_FEATURES } spa_feature_t; diff --git a/include/zfs_deleg.h b/include/zfs_deleg.h index 16133c59f..95db9921f 100644 --- a/include/zfs_deleg.h +++ b/include/zfs_deleg.h @@ -63,6 +63,10 @@ typedef enum { ZFS_DELEG_NOTE_GROUPQUOTA, ZFS_DELEG_NOTE_USERUSED, ZFS_DELEG_NOTE_GROUPUSED, + ZFS_DELEG_NOTE_USEROBJQUOTA, + ZFS_DELEG_NOTE_GROUPOBJQUOTA, + ZFS_DELEG_NOTE_USEROBJUSED, + ZFS_DELEG_NOTE_GROUPOBJUSED, ZFS_DELEG_NOTE_HOLD, ZFS_DELEG_NOTE_RELEASE, ZFS_DELEG_NOTE_DIFF, |