mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 18:40:43 +03:00
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 <jinshan.xiong@intel.com> Signed-off-by: Johann Lombardi <johann.lombardi@intel.com>
This commit is contained in:
committed by
Brian Behlendorf
parent
af322debaa
commit
1de321e626
@@ -256,6 +256,12 @@ void zfs_znode_byteswap(void *buf, size_t size);
|
||||
#define DMU_USERUSED_OBJECT (-1ULL)
|
||||
#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
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
+6
-3
@@ -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 */
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user