From 8aa8a920efd7ed8f217563df84905f972a16ad85 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Wed, 16 May 2018 10:13:13 +0800 Subject: [PATCH] LU-11017 quota: ignore quota for CAP_SYS_RESOURCE properly Currently, lustre quota will ignore this type of quota if quota id is 0 or we force to ignore. For write, we have passed CAP_SYS_RESOURCE properly, but For metadata operations this is not done. Test-Parameters: testlist=sanity-quota Change-Id: Ibcdc0e53ad125042d4889ac51a9a9ead4066c0c8 Signed-off-by: Wang Shilong Reviewed-on: https://review.whamcloud.com/32378 Tested-by: Jenkins Reviewed-by: Fan Yong Tested-by: Maloo Reviewed-by: Yingjin Qian Reviewed-by: Oleg Drokin --- lustre/include/dt_object.h | 4 +++- lustre/lod/lod_sub_object.c | 2 ++ lustre/mdd/mdd_trans.c | 9 ++++++++- lustre/osd-ldiskfs/osd_quota.c | 4 +++- lustre/osd-zfs/osd_quota.c | 4 +++- lustre/tests/sanity-quota.sh | 28 ++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lustre/include/dt_object.h b/lustre/include/dt_object.h index 2bf129e..35f1ec4 100644 --- a/lustre/include/dt_object.h +++ b/lustre/include/dt_object.h @@ -1901,7 +1901,9 @@ struct thandle { th_wait_submit:1, /* complex transaction which will track updates on all targets, * including OSTs */ - th_complex:1; + th_complex:1, + /* whether ignore quota */ + th_ignore_quota:1; }; /** diff --git a/lustre/lod/lod_sub_object.c b/lustre/lod/lod_sub_object.c index ee67616..ba97709 100644 --- a/lustre/lod/lod_sub_object.c +++ b/lustre/lod/lod_sub_object.c @@ -74,6 +74,7 @@ struct thandle *lod_sub_get_thandle(const struct lu_env *env, RETURN(th); tth = container_of(th, struct top_thandle, tt_super); + tth->tt_master_sub_thandle->th_ignore_quota = th->th_ignore_quota; /* local object must be mdt object, Note: during ost object * creation, FID is not assigned until osp_create(), @@ -103,6 +104,7 @@ struct thandle *lod_sub_get_thandle(const struct lu_env *env, sub_th = thandle_get_sub(env, th, sub_obj); if (IS_ERR(sub_th)) RETURN(sub_th); + sub_th->th_ignore_quota = th->th_ignore_quota; if (tth->tt_multiple_thandle != NULL && record_update != NULL && th->th_result == 0) diff --git a/lustre/mdd/mdd_trans.c b/lustre/mdd/mdd_trans.c index 050f397..2004bfc 100644 --- a/lustre/mdd/mdd_trans.c +++ b/lustre/mdd/mdd_trans.c @@ -48,6 +48,9 @@ struct thandle *mdd_trans_create(const struct lu_env *env, struct mdd_device *mdd) { + struct thandle *th; + struct lu_ucred *uc = lu_ucred_check(env); + /* If blocked by the write barrier, then return "-EINPROGRESS" * to the caller. Usually, such error will be forwarded to the * client, and the expected behaviour is to re-try such modify @@ -55,7 +58,11 @@ struct thandle *mdd_trans_create(const struct lu_env *env, if (unlikely(!barrier_entry(mdd->mdd_bottom))) return ERR_PTR(-EINPROGRESS); - return mdd_child_ops(mdd)->dt_trans_create(env, mdd->mdd_child); + th = mdd_child_ops(mdd)->dt_trans_create(env, mdd->mdd_child); + if (!IS_ERR(th) && uc) + th->th_ignore_quota = !!md_capable(uc, CFS_CAP_SYS_RESOURCE); + + return th; } int mdd_trans_start(const struct lu_env *env, struct mdd_device *mdd, diff --git a/lustre/osd-ldiskfs/osd_quota.c b/lustre/osd-ldiskfs/osd_quota.c index 7e15425..f0fc100 100644 --- a/lustre/osd-ldiskfs/osd_quota.c +++ b/lustre/osd-ldiskfs/osd_quota.c @@ -634,7 +634,9 @@ int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid, struct osd_thread_info *info = osd_oti_get(env); struct lquota_id_info *qi = &info->oti_qi; int rcu, rcg, rcp = 0; /* user & group & project rc */ - bool force = !!(osd_qid_declare_flags & OSD_QID_FORCE); + struct thandle *th = &oh->ot_super; + bool force = !!(osd_qid_declare_flags & OSD_QID_FORCE) || + th->th_ignore_quota; ENTRY; /* let's start with user quota */ diff --git a/lustre/osd-zfs/osd_quota.c b/lustre/osd-zfs/osd_quota.c index 8db1972..0146a7f 100644 --- a/lustre/osd-zfs/osd_quota.c +++ b/lustre/osd-zfs/osd_quota.c @@ -522,7 +522,9 @@ int osd_declare_quota(const struct lu_env *env, struct osd_device *osd, struct lquota_id_info *qi = &info->oti_qi; struct qsd_instance *qsd = osd->od_quota_slave; int rcu, rcg, rcp = 0; /* user & group & project rc */ - bool force = !!(osd_qid_declare_flags & OSD_QID_FORCE); + struct thandle *th = &oh->ot_super; + bool force = !!(osd_qid_declare_flags & OSD_QID_FORCE) || + th->th_ignore_quota; ENTRY; if (unlikely(qsd == NULL)) diff --git a/lustre/tests/sanity-quota.sh b/lustre/tests/sanity-quota.sh index 0fe27bb..be624ea 100755 --- a/lustre/tests/sanity-quota.sh +++ b/lustre/tests/sanity-quota.sh @@ -3063,6 +3063,34 @@ test_59() { } run_test 59 "lfs project dosen't crash kernel with project disabled" +test_60() { + setup_quota_test || error "setup quota failed with $?" + trap cleanup_quota_test EXIT + local testfile=$DIR/$tdir/$tfile + local limit=100 + + set_mdt_qtype "ug" || error "enable mdt quota failed" + + $LFS setquota -g $TSTUSR -b 0 -B 0 -i 0 -I $limit $DIR || + error "set quota failed" + quota_show_check a g $TSTUSR + + chown $TSTUSR.$TSTUSR $DIR/$tdir || error "chown $DIR/$tdir failed" + chmod g+s $DIR/$tdir || error "chmod g+s failed" + $RUNAS createmany -m ${testfile} $((limit-1)) || + error "create many files failed" + + $RUNAS touch $DIR/$tdir/foo && error "regular user should fail" + + # root user can overrun quota + runas -u 0 -g 0 touch $DIR/$tdir/foo || + error "root user should succeed" + + cleanup_quota_test + resetquota -u $TSTUSR +} +run_test 60 "Test quota for root with setgid" + quota_fini() { do_nodes $(comma_list $(nodes_list)) "lctl set_param debug=-quota" -- 1.8.3.1