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;
};
/**
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(),
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)
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
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,
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 */
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))
}
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"