X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Fqmt_internal.h;h=a3ab56f5f8a1935560107d7fc414f367b2b207e7;hb=2a620f07e23b3b044f429f049bcc5ffa96f6d844;hp=d83ff830e2fb869b0059c841f898d7cb78eb3a5c;hpb=08aa217ce49aba1ded52e0f7adb8a607035123fd;p=fs%2Flustre-release.git diff --git a/lustre/quota/qmt_internal.h b/lustre/quota/qmt_internal.h index d83ff83..a3ab56f 100644 --- a/lustre/quota/qmt_internal.h +++ b/lustre/quota/qmt_internal.h @@ -21,15 +21,15 @@ * GPL HEADER END */ /* - * Copyright (c) 2012, Intel Corporation. + * Copyright (c) 2012, 2017, Intel Corporation. * Use is subject to license terms. */ -#include "lquota_internal.h" - #ifndef _QMT_INTERNAL_H #define _QMT_INTERNAL_H +#include "lquota_internal.h" + /* * The Quota Master Target Device. * The qmt is responsible for: @@ -65,19 +65,21 @@ struct qmt_device { * Once we support quota on non-default pools, then more pools will * be added to this hash table and pool master setup would have to be * handled via configuration logs */ - cfs_hash_t *qmt_pool_hash; + struct cfs_hash *qmt_pool_hash; /* List of pools managed by this master target */ - cfs_list_t qmt_pool_list; + struct list_head qmt_pool_list; + /* rw spinlock to protect pool list */ + rwlock_t qmt_pool_lock; /* procfs root directory for this qmt */ - cfs_proc_dir_entry_t *qmt_proc; + struct proc_dir_entry *qmt_proc; /* dedicated thread in charge of space rebalancing */ struct ptlrpc_thread qmt_reba_thread; /* list of lqe entry which need space rebalancing */ - cfs_list_t qmt_reba_list; + struct list_head qmt_reba_list; /* lock protecting rebalancing list */ spinlock_t qmt_reba_lock; @@ -86,29 +88,24 @@ struct qmt_device { }; +#define QPI_MAXNAME (LOV_MAXPOOLNAME + 1) + /* * Per-pool quota information. * The qmt creates one such structure for each pool - * with quota enforced. All the structures are kept in a hash which is used to - * determine whether or not quota is enforced for a given pool. - * We currently only support the default data pool and default metadata pool - * with the pool_id 0. + * with quota enforced. All the structures are kept in a list. + * We currently only support the default data pool and default metadata pool. */ struct qmt_pool_info { - /* link to qmt's pool hash */ - cfs_hlist_node_t qpi_hash; - /* chained list of all pools managed by the same qmt */ - cfs_list_t qpi_linkage; + struct list_head qpi_linkage; - /* Pool key composed of pool_id | (pool_type << 16) - * Only pool ID 0 is supported for now and the pool type is either - * QUOTA_RES_MD or QUOTA_RES_DT. - * immutable after creation. */ - __u32 qpi_key; + /* Could be LQUOTA_RES_MD or LQUOTA_RES_DT */ + int qpi_rtype; + char qpi_name[QPI_MAXNAME]; /* track users of this pool instance */ - cfs_atomic_t qpi_ref; + atomic_t qpi_ref; /* back pointer to master target * immutable after creation. */ @@ -116,21 +113,21 @@ struct qmt_pool_info { /* pointer to dt object associated with global indexes for both user * and group quota */ - struct dt_object *qpi_glb_obj[MAXQUOTAS]; + struct dt_object *qpi_glb_obj[LL_MAXQUOTAS]; /* A pool supports two different quota types: user and group quota. * Each quota type has its own global index and lquota_entry hash table. */ - struct lquota_site *qpi_site[MAXQUOTAS]; + struct lquota_site *qpi_site[LL_MAXQUOTAS]; /* number of slaves registered for each quota types */ - int qpi_slv_nr[MAXQUOTAS]; + int qpi_slv_nr[LL_MAXQUOTAS]; /* reference on lqe (ID 0) storing grace time. */ - struct lquota_entry *qpi_grace_lqe[MAXQUOTAS]; + struct lquota_entry *qpi_grace_lqe[LL_MAXQUOTAS]; /* procfs root directory for this pool */ - cfs_proc_dir_entry_t *qpi_proc; + struct proc_dir_entry *qpi_proc; /* pool directory where all indexes related to this pool instance are * stored */ @@ -139,6 +136,22 @@ struct qmt_pool_info { /* Global quota parameters which apply to all quota type */ /* the least value of qunit */ unsigned long qpi_least_qunit; + + /* Least value of qunit when soft limit is exceeded. + * + * When soft limit is exceeded, qunit will be shrinked to least_qunit + * (1M for block limit), that results in significant write performance + * drop since the client will turn to sync write from now on. + * + * To retain the write performance in an acceptable level, we choose + * to sacrifice grace time accuracy a bit and use a larger least_qunit + * when soft limit is exceeded. It's (qpi_least_qunit * 4) by default, + * and user may enlarge it via procfs to get even better performance + * (with the cost of losing more grace time accuracy). + * + * See qmt_calc_softlimit(). + */ + unsigned long qpi_soft_least_qunit; }; /* @@ -189,15 +202,7 @@ extern struct lu_context_key qmt_thread_key; static inline struct qmt_thread_info *qmt_info(const struct lu_env *env) { - struct qmt_thread_info *info; - - info = lu_context_key_get(&env->le_ctx, &qmt_thread_key); - if (info == NULL) { - lu_env_refill((struct lu_env *)env); - info = lu_context_key_get(&env->le_ctx, &qmt_thread_key); - } - LASSERT(info); - return info; + return lu_env_info(env, &qmt_thread_key); } /* helper routine to convert a lu_device into a qmt_device */ @@ -248,21 +253,40 @@ static inline void qmt_restore(struct lquota_entry *lqe, (slv) -= (cnt); \ } while (0) -/* helper routine returning true when the id has run out of quota space, which - * means that it has either: - * - reached hardlimit - * OR - * - reached softlimit and grace time expired already */ -static inline bool qmt_space_exhausted(struct lquota_entry *lqe, __u64 now) +/* helper routine returning true when reached hardlimit */ +static inline bool qmt_hard_exhausted(struct lquota_entry *lqe) { if (lqe->lqe_hardlimit != 0 && lqe->lqe_granted >= lqe->lqe_hardlimit) return true; + return false; +} + +/* helper routine returning true when reached softlimit */ +static inline bool qmt_soft_exhausted(struct lquota_entry *lqe, __u64 now) +{ if (lqe->lqe_softlimit != 0 && lqe->lqe_granted > lqe->lqe_softlimit && lqe->lqe_gracetime != 0 && now >= lqe->lqe_gracetime) return true; return false; } +/* helper routine returning true when the id has run out of quota space: + * - reached hardlimit + * OR + * - reached softlimit and grace time expired already */ +static inline bool qmt_space_exhausted(struct lquota_entry *lqe, __u64 now) +{ + return (qmt_hard_exhausted(lqe) || qmt_soft_exhausted(lqe, now)); +} + +/* helper routine clearing the default quota setting */ +static inline void qmt_lqe_clear_default(struct lquota_entry *lqe) +{ + lqe->lqe_is_default = false; + lqe->lqe_gracetime &= ~((__u64)LQUOTA_FLAG_DEFAULT << + LQUOTA_GRACE_BITS); +} + /* number of seconds to wait for slaves to release quota space after * rebalancing */ #define QMT_REBA_TIMEOUT 2 @@ -276,10 +300,12 @@ int qmt_pool_new_conn(const struct lu_env *, struct qmt_device *, struct lu_fid *, struct lu_fid *, __u64 *, struct obd_uuid *); struct lquota_entry *qmt_pool_lqe_lookup(const struct lu_env *, - struct qmt_device *, int, int, int, + struct qmt_device *, int, int, union lquota_id *); /* qmt_entry.c */ extern struct lquota_entry_operations qmt_lqe_ops; +int qmt_lqe_set_default(const struct lu_env *env, struct qmt_pool_info *pool, + struct lquota_entry *lqe, bool create_record); struct thandle *qmt_trans_start_with_slv(const struct lu_env *, struct lquota_entry *, struct dt_object *, @@ -300,6 +326,9 @@ void qmt_revalidate(const struct lu_env *, struct lquota_entry *); __u64 qmt_alloc_expand(struct lquota_entry *, __u64, __u64); /* qmt_handler.c */ +int qmt_set_with_lqe(const struct lu_env *env, struct qmt_device *qmt, + struct lquota_entry *lqe, __u64 hard, __u64 soft, + __u64 time, __u32 valid, bool is_default, bool is_updated); int qmt_dqacq0(const struct lu_env *, struct lquota_entry *, struct qmt_device *, struct obd_uuid *, __u32, __u64, __u64, struct quota_body *);