From 2e92c57d71384d50f06baf5b6591d2809c8288b2 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Fri, 7 Apr 2017 09:09:18 +0800 Subject: [PATCH] LU-4017 quota: add project inherit attributes Add @LUSTRE_PROJINHERIT_FL inode flag which means creating new objects parents projid, it is disabled in default, unless setting explictly. It is kept same inteface as Ext4/XFS, you could use following ioctl directly: chattr +P Agent inode for DNE should ignore project ID, patch also remove some unnecessary lustre_set_wire_obdo() call for attr fetching/updates, which mixed la flags and obdo flags. Change-Id: I573b71c5bd7b0089172025c30c6824562444d57d Signed-off-by: Wang Shilong Reviewed-on: https://review.whamcloud.com/26463 Reviewed-by: Andreas Dilger Reviewed-by: Niu Yawei Reviewed-by: Li Xi Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustre_idl.h | 11 +++++++++-- lustre/mdd/mdd_dir.c | 30 ++++++++++++++++++++++++++++++ lustre/osd-ldiskfs/osd_handler.c | 29 ++++++++++++++++++++++++++++- lustre/target/out_handler.c | 1 - lustre/target/out_lib.c | 2 -- lustre/target/update_records.c | 2 -- 6 files changed, 67 insertions(+), 8 deletions(-) diff --git a/lustre/include/lustre/lustre_idl.h b/lustre/include/lustre/lustre_idl.h index 89b632c..dc1e37c 100644 --- a/lustre/include/lustre/lustre_idl.h +++ b/lustre/include/lustre/lustre_idl.h @@ -1621,6 +1621,7 @@ enum { LUSTRE_TOPDIR_FL = 0x00020000, /* Top of directory hierarchies*/ LUSTRE_DIRECTIO_FL = 0x00100000, /* Use direct i/o */ LUSTRE_INLINE_DATA_FL = 0x10000000, /* Inode has inline data. */ + LUSTRE_PROJINHERIT_FL = 0x20000000, /* Create with parents projid */ /* These flags will not be identical to any EXT4_*_FL counterparts, * and only reserved for lustre purpose. Note: these flags might @@ -1634,6 +1635,10 @@ enum { LUSTRE_LMA_FL_MASKS = LUSTRE_ORPHAN_FL, }; +#ifndef FS_XFLAG_PROJINHERIT +#define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */ +#endif + #ifdef __KERNEL__ /* Convert wire LUSTRE_*_FL to corresponding client local VFS S_* values * for the client inode i_flags. The LUSTRE_*_FL are the Lustre wire @@ -1649,7 +1654,8 @@ static inline int ll_ext_to_inode_flags(int flags) #if defined(S_DIRSYNC) ((flags & LUSTRE_DIRSYNC_FL) ? S_DIRSYNC : 0) | #endif - ((flags & LUSTRE_IMMUTABLE_FL) ? S_IMMUTABLE : 0)); + ((flags & LUSTRE_IMMUTABLE_FL) ? S_IMMUTABLE : 0) | + ((flags & LUSTRE_PROJINHERIT_FL) ? FS_XFLAG_PROJINHERIT : 0)); } static inline int ll_inode_to_ext_flags(int iflags) @@ -1660,7 +1666,8 @@ static inline int ll_inode_to_ext_flags(int iflags) #if defined(S_DIRSYNC) ((iflags & S_DIRSYNC) ? LUSTRE_DIRSYNC_FL : 0) | #endif - ((iflags & S_IMMUTABLE) ? LUSTRE_IMMUTABLE_FL : 0)); + ((iflags & S_IMMUTABLE) ? LUSTRE_IMMUTABLE_FL : 0) | + ((iflags & FS_XFLAG_PROJINHERIT) ? LUSTRE_PROJINHERIT_FL : 0)); } #endif diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index b37c795..07fe079 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -1285,6 +1285,15 @@ static int mdd_link(const struct lu_env *env, struct md_object *tgt_obj, if (rc != 0) RETURN(rc); + /* + * If we are using project inheritance, we only allow hard link + * creation in our tree when the project IDs are the same; + * otherwise the tree quota mechanism could be circumvented. + */ + if ((tattr->la_flags & LUSTRE_PROJINHERIT_FL) && + (tattr->la_projid != cattr->la_projid)) + RETURN(-EXDEV); + handle = mdd_trans_create(env, mdd); if (IS_ERR(handle)) GOTO(out_pending, rc = PTR_ERR(handle)); @@ -1942,6 +1951,16 @@ static int mdd_create_sanity_check(const struct lu_env *env, } } + /* Inherit project ID from parent directory */ + if (pattr->la_flags & LUSTRE_PROJINHERIT_FL) { + cattr->la_projid = pattr->la_projid; + if (S_ISDIR(cattr->la_mode)) { + cattr->la_flags |= LUSTRE_PROJINHERIT_FL; + cattr->la_valid |= LA_FLAGS; + } + cattr->la_valid |= LA_PROJID; + } + rc = mdd_name_check(m, lname); if (rc < 0) RETURN(rc); @@ -2581,6 +2600,17 @@ static int mdd_rename_sanity_check(const struct lu_env *env, * before mdd_rename and enable MDS_PERM_BYPASS. */ LASSERT(sobj); + /* + * If we are using project inheritance, we only allow renames + * into our tree when the project IDs are the same; otherwise + * tree quota mechanism would be circumvented. + */ + if (((tpattr->la_flags & LUSTRE_PROJINHERIT_FL) && + tpattr->la_projid != cattr->la_projid) || + ((pattr->la_flags & LUSTRE_PROJINHERIT_FL) && + (pattr->la_projid != tpattr->la_projid))) + RETURN(-EXDEV); + rc = mdd_may_delete(env, src_pobj, pattr, sobj, cattr, NULL, 1, 0); if (rc) RETURN(rc); diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index dd682f5..2876e6e 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -2382,6 +2382,13 @@ static void osd_inode_getattr(const struct lu_env *env, attr->la_rdev = inode->i_rdev; attr->la_blksize = 1 << inode->i_blkbits; attr->la_blkbits = inode->i_blkbits; + /* + * Ext4 did not transfer inherit flags from raw inode + * to inode flags, and ext4 internally test raw inode + * @i_flags directly. Instead of patching ext4, we do it here. + */ + if (LDISKFS_I(inode)->i_flags & LUSTRE_PROJINHERIT_FL) + attr->la_flags |= LUSTRE_PROJINHERIT_FL; } static int osd_attr_get(const struct lu_env *env, @@ -2586,6 +2593,13 @@ static int osd_inode_setattr(const struct lu_env *env, /* always keep S_NOCMTIME */ inode->i_flags = ll_ext_to_inode_flags(attr->la_flags) | S_NOCMTIME; + /* + * Ext4 did not transfer inherit flags from + * @inode->i_flags to raw inode i_flags when writing + * flags, we do it explictly here. + */ + if (attr->la_flags & LUSTRE_PROJINHERIT_FL) + LDISKFS_I(inode)->i_flags |= LUSTRE_PROJINHERIT_FL; } return 0; } @@ -2617,7 +2631,7 @@ static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr) } #ifdef HAVE_PROJECT_QUOTA - /* Handle project id Transfer here properly */ + /* Handle project id transfer here properly */ if (attr->la_valid & LA_PROJID && attr->la_projid != i_projid_read(inode)) { rc = __ldiskfs_ioctl_setproject(inode, attr->la_projid); @@ -3456,6 +3470,19 @@ static struct inode *osd_create_local_agent_inode(const struct lu_env *env, ldiskfs_set_inode_state(local, LDISKFS_STATE_LUSTRE_NOSCRUB); unlock_new_inode(local); + /* Agent inode should not have project ID*/ +#ifdef HAVE_PROJECT_QUOTA + if (LDISKFS_I(pobj->oo_inode)->i_flags & LUSTRE_PROJINHERIT_FL) { + rc = __ldiskfs_ioctl_setproject(local, 0); + if (rc) { + CERROR("%s: quota transfer failed: rc = %d. Is project " + "quota enforcement enabled on the ldiskfs " + "filesystem?\n", local->i_sb->s_id, rc); + RETURN(ERR_PTR(rc)); + } + } + +#endif /* Set special LMA flag for local agent inode */ rc = osd_ea_fid_set(info, local, fid, 0, LMAI_AGENT); if (rc != 0) { diff --git a/lustre/target/out_handler.c b/lustre/target/out_handler.c index 221ea37..6ad753e 100644 --- a/lustre/target/out_handler.c +++ b/lustre/target/out_handler.c @@ -224,7 +224,6 @@ static int out_attr_get(struct tgt_session_info *tsi) obdo->o_valid = 0; obdo_from_la(obdo, la, la->la_valid); - lustre_set_wire_obdo(NULL, obdo, obdo); out_unlock: dt_read_unlock(env, obj); diff --git a/lustre/target/out_lib.c b/lustre/target/out_lib.c index e71484d..55b47c6 100644 --- a/lustre/target/out_lib.c +++ b/lustre/target/out_lib.c @@ -215,7 +215,6 @@ int out_create_pack(const struct lu_env *env, struct object_update *update, obdo->o_valid = 0; obdo_from_la(obdo, attr, attr->la_valid); - lustre_set_wire_obdo(NULL, obdo, obdo); if (parent_fid != NULL) { struct lu_fid *tmp; @@ -267,7 +266,6 @@ int out_attr_set_pack(const struct lu_env *env, struct object_update *update, obdo->o_valid = 0; obdo_from_la(obdo, attr, attr->la_valid); - lustre_set_wire_obdo(NULL, obdo, obdo); RETURN(0); } diff --git a/lustre/target/update_records.c b/lustre/target/update_records.c index ab1932d..5510bf2 100644 --- a/lustre/target/update_records.c +++ b/lustre/target/update_records.c @@ -348,7 +348,6 @@ int update_records_create_pack(const struct lu_env *env, obdo = &update_env_info(env)->uti_obdo; obdo->o_valid = 0; obdo_from_la(obdo, attr, attr->la_valid); - lustre_set_wire_obdo(NULL, obdo, obdo); bufs[buf_count] = obdo; sizes[buf_count] = sizeof(*obdo); buf_count++; @@ -422,7 +421,6 @@ int update_records_attr_set_pack(const struct lu_env *env, obdo->o_valid = 0; obdo_from_la(obdo, attr, attr->la_valid); - lustre_set_wire_obdo(NULL, obdo, obdo); return update_records_update_pack(env, fid, OUT_ATTR_SET, ops, op_count, max_ops_size, params, param_count, max_param_size, 1, -- 1.8.3.1