summaryrefslogtreecommitdiffstats
path: root/include/sys
diff options
context:
space:
mode:
authorNasf-Fan <[email protected]>2018-02-14 06:54:54 +0800
committerBrian Behlendorf <[email protected]>2018-02-13 14:54:54 -0800
commit9c5167d19fe02e44ba09c6d0282363c19781b19d (patch)
tree32fd87dc2f943f05f964450c0f54ea3d0d601466 /include/sys
parentc03f04708caecf9a4a4ce2134aaa6a8cabe499c9 (diff)
Project Quota on ZFS
Project quota is a new ZFS system space/object usage accounting and enforcement mechanism. Similar as user/group quota, project quota is another dimension of system quota. It bases on the new object attribute - project ID. Project ID is a numerical value to indicate to which project an object belongs. An object only can belong to one project though you (the object owner or privileged user) can change the object project ID via 'chattr -p' or 'zfs project [-s] -p' explicitly. The object also can inherit the project ID from its parent when created if the parent has the project inherit flag (that can be set via 'chattr +P' or 'zfs project -s [-p]'). By accounting the spaces/objects belong to the same project, we can know how many spaces/objects used by the project. And if we set the upper limit then we can control the spaces/objects that are consumed by such project. It is useful when multiple groups and users cooperate for the same project, or a user/group needs to participate in multiple projects. Support the following commands and functionalities: zfs set projectquota@project zfs set projectobjquota@project zfs get projectquota@project zfs get projectobjquota@project zfs get projectused@project zfs get projectobjused@project zfs projectspace zfs allow projectquota zfs allow projectobjquota zfs allow projectused zfs allow projectobjused zfs unallow projectquota zfs unallow projectobjquota zfs unallow projectused zfs unallow projectobjused chattr +/-P chattr -p project_id lsattr -p This patch also supports tree quota based on the project quota via "zfs project" commands set as following: zfs project [-d|-r] <file|directory ...> zfs project -C [-k] [-r] <file|directory ...> zfs project -c [-0] [-d|-r] [-p id] <file|directory ...> zfs project [-p id] [-r] [-s] <file|directory ...> For "df [-i] $DIR" command, if we set INHERIT (project ID) flag on the $DIR, then the proejct [obj]quota and [obj]used values for the $DIR's project ID will be shown as the total/free (avail) resource. Keep the same behavior as EXT4/XFS does. Reviewed-by: Andreas Dilger <[email protected]> Reviewed-by Ned Bass <[email protected]> Reviewed-by: Matthew Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Fan Yong <[email protected]> TEST_ZIMPORT_POOLS="zol-0.6.1 zol-0.6.2 master" Change-Id: Ib4f0544602e03fb61fd46a849d7ba51a6005693c Closes #6290
Diffstat (limited to 'include/sys')
-rw-r--r--include/sys/Makefile.am1
-rw-r--r--include/sys/dmu.h5
-rw-r--r--include/sys/dmu_objset.h28
-rw-r--r--include/sys/dnode.h6
-rw-r--r--include/sys/dsl_deleg.h4
-rw-r--r--include/sys/fs/zfs.h4
-rw-r--r--include/sys/sa.h1
-rw-r--r--include/sys/xvattr.h9
-rw-r--r--include/sys/zfs_acl.h3
-rw-r--r--include/sys/zfs_project.h83
-rw-r--r--include/sys/zfs_sa.h3
-rw-r--r--include/sys/zfs_vfsops.h14
-rw-r--r--include/sys/zfs_znode.h24
13 files changed, 163 insertions, 22 deletions
diff --git a/include/sys/Makefile.am b/include/sys/Makefile.am
index 348e6584f..8e18a8790 100644
--- a/include/sys/Makefile.am
+++ b/include/sys/Makefile.am
@@ -105,6 +105,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/zfs_delay.h \
$(top_srcdir)/include/sys/zfs_dir.h \
$(top_srcdir)/include/sys/zfs_fuid.h \
+ $(top_srcdir)/include/sys/zfs_project.h \
$(top_srcdir)/include/sys/zfs_ratelimit.h \
$(top_srcdir)/include/sys/zfs_rlock.h \
$(top_srcdir)/include/sys/zfs_sa.h \
diff --git a/include/sys/dmu.h b/include/sys/dmu.h
index 5553667c3..cf9cbaa64 100644
--- a/include/sys/dmu.h
+++ b/include/sys/dmu.h
@@ -276,9 +276,10 @@ void zfs_znode_byteswap(void *buf, size_t size);
#define DMU_USERUSED_OBJECT (-1ULL)
#define DMU_GROUPUSED_OBJECT (-2ULL)
+#define DMU_PROJECTUSED_OBJECT (-3ULL)
/*
- * Zap prefix for object accounting in DMU_{USER,GROUP}USED_OBJECT.
+ * Zap prefix for object accounting in DMU_{USER,GROUP,PROJECT}USED_OBJECT.
*/
#define DMU_OBJACCT_PREFIX "obj-"
#define DMU_OBJACCT_PREFIX_LEN 4
@@ -971,7 +972,7 @@ extern int dmu_dir_list_next(objset_t *os, int namelen, char *name,
uint64_t *idp, uint64_t *offp);
typedef int objset_used_cb_t(dmu_object_type_t bonustype,
- void *bonus, uint64_t *userp, uint64_t *groupp);
+ void *bonus, uint64_t *userp, uint64_t *groupp, uint64_t *projectp);
extern void dmu_objset_register_type(dmu_objset_type_t ost,
objset_used_cb_t *cb);
extern void dmu_objset_set_user(objset_t *os, void *user_ptr);
diff --git a/include/sys/dmu_objset.h b/include/sys/dmu_objset.h
index 7ee992f31..df9b1a73a 100644
--- a/include/sys/dmu_objset.h
+++ b/include/sys/dmu_objset.h
@@ -49,14 +49,18 @@ struct dsl_pool;
struct dsl_dataset;
struct dmu_tx;
-#define OBJSET_PHYS_SIZE 2048
-#define OBJSET_OLD_PHYS_SIZE 1024
+#define OBJSET_PHYS_SIZE_V1 1024
+#define OBJSET_PHYS_SIZE_V2 2048
+#define OBJSET_PHYS_SIZE_V3 4096
#define OBJSET_BUF_HAS_USERUSED(buf) \
- (arc_buf_size(buf) > OBJSET_OLD_PHYS_SIZE)
+ (arc_buf_size(buf) >= OBJSET_PHYS_SIZE_V2)
+#define OBJSET_BUF_HAS_PROJECTUSED(buf) \
+ (arc_buf_size(buf) >= OBJSET_PHYS_SIZE_V3)
-#define OBJSET_FLAG_USERACCOUNTING_COMPLETE (1ULL<<0)
-#define OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE (1ULL<<1)
+#define OBJSET_FLAG_USERACCOUNTING_COMPLETE (1ULL << 0)
+#define OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE (1ULL << 1)
+#define OBJSET_FLAG_PROJECTQUOTA_COMPLETE (1ULL << 2)
/* all flags are currently non-portable */
#define OBJSET_CRYPT_PORTABLE_FLAGS_MASK (0)
@@ -68,11 +72,14 @@ typedef struct objset_phys {
uint64_t os_flags;
uint8_t os_portable_mac[ZIO_OBJSET_MAC_LEN];
uint8_t os_local_mac[ZIO_OBJSET_MAC_LEN];
- char os_pad[OBJSET_PHYS_SIZE - sizeof (dnode_phys_t)*3 -
+ char os_pad0[OBJSET_PHYS_SIZE_V2 - sizeof (dnode_phys_t)*3 -
sizeof (zil_header_t) - sizeof (uint64_t)*2 -
2*ZIO_OBJSET_MAC_LEN];
dnode_phys_t os_userused_dnode;
dnode_phys_t os_groupused_dnode;
+ dnode_phys_t os_projectused_dnode;
+ char os_pad1[OBJSET_PHYS_SIZE_V3 - OBJSET_PHYS_SIZE_V2 -
+ sizeof (dnode_phys_t)];
} objset_phys_t;
typedef int (*dmu_objset_upgrade_cb_t)(objset_t *);
@@ -94,6 +101,7 @@ struct objset {
dnode_handle_t os_meta_dnode;
dnode_handle_t os_userused_dnode;
dnode_handle_t os_groupused_dnode;
+ dnode_handle_t os_projectused_dnode;
zilog_t *os_zil;
list_node_t os_evicting_node;
@@ -143,7 +151,7 @@ struct objset {
list_t os_dnodes;
list_t os_downgraded_dbufs;
- /* Protects changes to DMU_{USER,GROUP}USED_OBJECT */
+ /* Protects changes to DMU_{USER,GROUP,PROJECT}USED_OBJECT */
kmutex_t os_userused_lock;
/* stuff we store for the user */
@@ -165,6 +173,7 @@ struct objset {
#define DMU_META_DNODE(os) ((os)->os_meta_dnode.dnh_dnode)
#define DMU_USERUSED_DNODE(os) ((os)->os_userused_dnode.dnh_dnode)
#define DMU_GROUPUSED_DNODE(os) ((os)->os_groupused_dnode.dnh_dnode)
+#define DMU_PROJECTUSED_DNODE(os) ((os)->os_projectused_dnode.dnh_dnode)
#define DMU_OS_IS_L2CACHEABLE(os) \
((os)->os_secondary_cache == ZFS_CACHE_ALL || \
@@ -215,9 +224,12 @@ 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);
boolean_t dmu_objset_userobjspace_upgradable(objset_t *os);
-void dmu_objset_userobjspace_upgrade(objset_t *os);
boolean_t dmu_objset_userobjspace_present(objset_t *os);
boolean_t dmu_objset_incompatible_encryption_version(objset_t *os);
+boolean_t dmu_objset_projectquota_enabled(objset_t *os);
+boolean_t dmu_objset_projectquota_present(objset_t *os);
+boolean_t dmu_objset_projectquota_upgradable(objset_t *os);
+void dmu_objset_id_quota_upgrade(objset_t *os);
int dmu_fsname(const char *snapname, char *buf);
diff --git a/include/sys/dnode.h b/include/sys/dnode.h
index 691fd443a..9c44a2232 100644
--- a/include/sys/dnode.h
+++ b/include/sys/dnode.h
@@ -147,7 +147,7 @@ enum dnode_dirtycontext {
/* Does dnode have a SA spill blkptr in bonus? */
#define DNODE_FLAG_SPILL_BLKPTR (1 << 2)
-/* User/Group dnode accounting */
+/* User/Group/Project dnode accounting */
#define DNODE_FLAG_USEROBJUSED_ACCOUNTED (1 << 3)
#define DNODE_CRYPT_PORTABLE_FLAGS_MASK (DNODE_FLAG_SPILL_BLKPTR)
@@ -356,8 +356,8 @@ struct dnode {
/* used in syncing context */
uint64_t dn_oldused; /* old phys used bytes */
uint64_t dn_oldflags; /* old phys dn_flags */
- uint64_t dn_olduid, dn_oldgid;
- uint64_t dn_newuid, dn_newgid;
+ uint64_t dn_olduid, dn_oldgid, dn_oldprojid;
+ uint64_t dn_newuid, dn_newgid, dn_newprojid;
int dn_id_flags;
/* holds prefetch structure */
diff --git a/include/sys/dsl_deleg.h b/include/sys/dsl_deleg.h
index 153c08f93..eb95c68e8 100644
--- a/include/sys/dsl_deleg.h
+++ b/include/sys/dsl_deleg.h
@@ -63,6 +63,10 @@ extern "C" {
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
+#define ZFS_DELEG_PERM_PROJECTUSED "projectused"
+#define ZFS_DELEG_PERM_PROJECTQUOTA "projectquota"
+#define ZFS_DELEG_PERM_PROJECTOBJUSED "projectobjused"
+#define ZFS_DELEG_PERM_PROJECTOBJQUOTA "projectobjquota"
/*
* Note: the names of properties that are marked delegatable are also
diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h
index 7b86f6631..88f590276 100644
--- a/include/sys/fs/zfs.h
+++ b/include/sys/fs/zfs.h
@@ -192,6 +192,10 @@ typedef enum {
ZFS_PROP_USEROBJQUOTA,
ZFS_PROP_GROUPOBJUSED,
ZFS_PROP_GROUPOBJQUOTA,
+ ZFS_PROP_PROJECTUSED,
+ ZFS_PROP_PROJECTQUOTA,
+ ZFS_PROP_PROJECTOBJUSED,
+ ZFS_PROP_PROJECTOBJQUOTA,
ZFS_NUM_USERQUOTA_PROPS
} zfs_userquota_prop_t;
diff --git a/include/sys/sa.h b/include/sys/sa.h
index b7ed9fe38..50b906221 100644
--- a/include/sys/sa.h
+++ b/include/sys/sa.h
@@ -159,6 +159,7 @@ void sa_handle_unlock(sa_handle_t *);
#ifdef _KERNEL
int sa_lookup_uio(sa_handle_t *, sa_attr_type_t, uio_t *);
+int sa_add_projid(sa_handle_t *, dmu_tx_t *, uint64_t);
#endif
#ifdef __cplusplus
diff --git a/include/sys/xvattr.h b/include/sys/xvattr.h
index 4779b6321..1c919454d 100644
--- a/include/sys/xvattr.h
+++ b/include/sys/xvattr.h
@@ -64,6 +64,8 @@ typedef struct xoptattr {
uint64_t xoa_generation;
uint8_t xoa_offline;
uint8_t xoa_sparse;
+ uint8_t xoa_projinherit;
+ uint64_t xoa_projid;
} xoptattr_t;
/*
@@ -169,11 +171,14 @@ typedef struct xvattr {
#define XAT0_GEN 0x00004000 /* object generation number */
#define XAT0_OFFLINE 0x00008000 /* offline */
#define XAT0_SPARSE 0x00010000 /* sparse */
+#define XAT0_PROJINHERIT 0x00020000 /* Create with parent projid */
+#define XAT0_PROJID 0x00040000 /* Project ID */
#define XAT0_ALL_ATTRS (XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \
XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \
XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| XAT0_AV_MODIFIED| \
- XAT0_AV_SCANSTAMP|XAT0_REPARSE|XATO_GEN|XAT0_OFFLINE|XAT0_SPARSE)
+ XAT0_AV_SCANSTAMP|XAT0_REPARSE|XATO_GEN|XAT0_OFFLINE|XAT0_SPARSE| \
+ XAT0_PROJINHERIT | XAT0_PROJID)
/* Support for XAT_* optional attributes */
#define XVA_MASK 0xffffffff /* Used to mask off 32 bits */
@@ -210,6 +215,8 @@ typedef struct xvattr {
#define XAT_GEN ((XAT0_INDEX << XVA_SHFT) | XAT0_GEN)
#define XAT_OFFLINE ((XAT0_INDEX << XVA_SHFT) | XAT0_OFFLINE)
#define XAT_SPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_SPARSE)
+#define XAT_PROJINHERIT ((XAT0_INDEX << XVA_SHFT) | XAT0_PROJINHERIT)
+#define XAT_PROJID ((XAT0_INDEX << XVA_SHFT) | XAT0_PROJID)
/*
* The returned attribute map array (xva_rtnattrmap[]) is located past the
diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h
index 2572fee86..6d3db5041 100644
--- a/include/sys/zfs_acl.h
+++ b/include/sys/zfs_acl.h
@@ -208,7 +208,7 @@ struct zfsvfs;
int zfs_acl_ids_create(struct znode *, int, vattr_t *,
cred_t *, vsecattr_t *, zfs_acl_ids_t *);
void zfs_acl_ids_free(zfs_acl_ids_t *);
-boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *);
+boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t);
int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
int zfs_setacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
void zfs_acl_rele(void *);
@@ -237,6 +237,7 @@ void zfs_acl_xform(struct znode *, zfs_acl_t *, cred_t *);
void zfs_acl_data_locator(void **, uint32_t *, uint32_t, boolean_t, void *);
uint64_t zfs_mode_compute(uint64_t, zfs_acl_t *,
uint64_t *, uint64_t, uint64_t);
+int zfs_acl_node_read(struct znode *, boolean_t, zfs_acl_t **, boolean_t);
int zfs_acl_chown_setattr(struct znode *);
#endif
diff --git a/include/sys/zfs_project.h b/include/sys/zfs_project.h
new file mode 100644
index 000000000..52d5204a6
--- /dev/null
+++ b/include/sys/zfs_project.h
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2017, Intel Corporation. All rights reserved.
+ */
+
+#ifndef _SYS_ZFS_PROJECT_H
+#define _SYS_ZFS_PROJECT_H
+
+#ifndef _KERNEL
+#ifndef _SYS_MOUNT_H
+/* XXX: some hack to avoid include sys/mount.h */
+#define _SYS_MOUNT_H
+#endif
+#endif
+
+#include <linux/fs.h>
+
+#ifdef FS_PROJINHERIT_FL
+#define ZFS_PROJINHERIT_FL FS_PROJINHERIT_FL
+#else
+#define ZFS_PROJINHERIT_FL 0x20000000
+#endif
+
+#ifdef FS_IOC_FSGETXATTR
+typedef struct fsxattr zfsxattr_t;
+
+#define ZFS_IOC_FSGETXATTR FS_IOC_FSGETXATTR
+#define ZFS_IOC_FSSETXATTR FS_IOC_FSSETXATTR
+#else
+struct zfsxattr {
+ uint32_t fsx_xflags; /* xflags field value (get/set) */
+ uint32_t fsx_extsize; /* extsize field value (get/set) */
+ uint32_t fsx_nextents; /* nextents field value (get) */
+ uint32_t fsx_projid; /* project identifier (get/set) */
+ uint32_t fsx_cowextsize;
+ unsigned char fsx_pad[8];
+};
+typedef struct zfsxattr zfsxattr_t;
+
+#define ZFS_IOC_FSGETXATTR _IOR('X', 31, zfsxattr_t)
+#define ZFS_IOC_FSSETXATTR _IOW('X', 32, zfsxattr_t)
+#endif
+
+#define ZFS_DEFAULT_PROJID (0ULL)
+/*
+ * It is NOT ondisk project ID value. Just means either the object has
+ * no project ID or the operation does not touch project ID attribute.
+ */
+#define ZFS_INVALID_PROJID (-1ULL)
+
+static inline boolean_t
+zpl_is_valid_projid(uint32_t projid)
+{
+ /*
+ * zfsxattr::fsx_projid is 32-bits, when convert to uint64_t,
+ * the higher 32-bits will be set as zero, so cannot directly
+ * compare with ZFS_INVALID_PROJID (-1ULL)
+ */
+ if ((uint32_t)ZFS_INVALID_PROJID == projid)
+ return (B_FALSE);
+ return (B_TRUE);
+}
+
+#endif /* _SYS_ZFS_PROJECT_H */
diff --git a/include/sys/zfs_sa.h b/include/sys/zfs_sa.h
index 06c4d589a..4e6d28638 100644
--- a/include/sys/zfs_sa.h
+++ b/include/sys/zfs_sa.h
@@ -74,6 +74,7 @@ typedef enum zpl_attr {
ZPL_SCANSTAMP,
ZPL_DACL_ACES,
ZPL_DXATTR,
+ ZPL_PROJID,
ZPL_END
} zpl_attr_t;
@@ -87,6 +88,8 @@ typedef enum zpl_attr {
#define SA_UID_OFFSET 24
#define SA_GID_OFFSET 32
#define SA_PARENT_OFFSET 40
+#define SA_FLAGS_OFFSET 48
+#define SA_PROJID_OFFSET 128
extern sa_attr_reg_t zfs_attr_table[ZPL_END + 1];
extern sa_attr_reg_t zfs_legacy_attr_table[ZPL_END + 1];
diff --git a/include/sys/zfs_vfsops.h b/include/sys/zfs_vfsops.h
index 7dbdfd718..70f0cd50d 100644
--- a/include/sys/zfs_vfsops.h
+++ b/include/sys/zfs_vfsops.h
@@ -121,6 +121,8 @@ struct zfsvfs {
uint64_t z_groupquota_obj;
uint64_t z_userobjquota_obj;
uint64_t z_groupobjquota_obj;
+ uint64_t z_projectquota_obj;
+ uint64_t z_projectobjquota_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 */
@@ -195,12 +197,12 @@ extern int zfs_userspace_many(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
uint64_t *cookiep, void *vbuf, uint64_t *bufsizep);
extern int zfs_set_userquota(zfsvfs_t *zfsvfs, zfs_userquota_prop_t type,
const char *domain, uint64_t rid, uint64_t quota);
-extern boolean_t zfs_owner_overquota(zfsvfs_t *zfsvfs, struct znode *,
- boolean_t isgroup);
-extern boolean_t zfs_fuid_overquota(zfsvfs_t *zfsvfs, boolean_t isgroup,
- uint64_t fuid);
-extern boolean_t zfs_fuid_overobjquota(zfsvfs_t *zfsvfs, boolean_t isgroup,
- uint64_t fuid);
+extern boolean_t zfs_id_overblockquota(zfsvfs_t *zfsvfs, uint64_t usedobj,
+ uint64_t id);
+extern boolean_t zfs_id_overobjquota(zfsvfs_t *zfsvfs, uint64_t usedobj,
+ uint64_t id);
+extern boolean_t zfs_id_overquota(zfsvfs_t *zfsvfs, uint64_t usedobj,
+ uint64_t id);
extern int zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers);
extern int zfsvfs_create(const char *name, zfsvfs_t **zfvp);
extern int zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os);
diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h
index 6a3a3b233..311babe59 100644
--- a/include/sys/zfs_znode.h
+++ b/include/sys/zfs_znode.h
@@ -42,6 +42,7 @@
#endif
#include <sys/zfs_acl.h>
#include <sys/zil.h>
+#include <sys/zfs_project.h>
#ifdef __cplusplus
extern "C" {
@@ -66,6 +67,18 @@ extern "C" {
#define ZFS_OFFLINE 0x0000100000000000ull
#define ZFS_SPARSE 0x0000200000000000ull
+/*
+ * PROJINHERIT attribute is used to indicate that the child object under the
+ * directory which has the PROJINHERIT attribute needs to inherit its parent
+ * project ID that is used by project quota.
+ */
+#define ZFS_PROJINHERIT 0x0000400000000000ull
+
+/*
+ * PROJID attr is used internally to indicate that the object has project ID.
+ */
+#define ZFS_PROJID 0x0000800000000000ull
+
#define ZFS_ATTR_SET(zp, attr, value, pflags, tx) \
{ \
if (value) \
@@ -110,6 +123,7 @@ extern "C" {
#define SA_ZPL_ZNODE_ACL(z) z->z_attr_table[ZPL_ZNODE_ACL]
#define SA_ZPL_DXATTR(z) z->z_attr_table[ZPL_DXATTR]
#define SA_ZPL_PAD(z) z->z_attr_table[ZPL_PAD]
+#define SA_ZPL_PROJID(z) z->z_attr_table[ZPL_PROJID]
/*
* Is ID ephemeral?
@@ -128,7 +142,7 @@ extern "C" {
/*
* Special attributes for master node.
- * "userquota@" and "groupquota@" are also valid (from
+ * "userquota@", "groupquota@" and "projectquota@" are also valid (from
* zfs_userquota_prop_prefixes[]).
*/
#define ZFS_FSID "FSID"
@@ -196,6 +210,7 @@ typedef struct znode {
krwlock_t z_xattr_lock; /* xattr data lock */
nvlist_t *z_xattr_cached; /* cached xattrs */
uint64_t z_xattr_parent; /* parent obj for this xattr */
+ uint64_t z_projid; /* project ID */
list_node_t z_link_node; /* all znodes in fs link */
sa_handle_t *z_sa_hdl; /* handle to sa data */
boolean_t z_is_sa; /* are we native sa? */
@@ -212,6 +227,13 @@ typedef struct znode_hold {
refcount_t zh_refcount; /* active consumer reference count */
} znode_hold_t;
+static inline uint64_t
+zfs_inherit_projid(znode_t *dzp)
+{
+ return ((dzp->z_pflags & ZFS_PROJINHERIT) ? dzp->z_projid :
+ ZFS_DEFAULT_PROJID);
+}
+
/*
* Range locking rules
* --------------------