X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Fqmt_pool.c;h=32171277db146b9a4795a4ac07dae39ec64725fe;hb=e760042016bb5b12f9b21568304c02711930720f;hp=c1f8b7247cb7635f178175d0cc0f3f148d4d0200;hpb=51435cfffcd6815e70fb46b0ec2edcac3327bf44;p=fs%2Flustre-release.git diff --git a/lustre/quota/qmt_pool.c b/lustre/quota/qmt_pool.c index c1f8b72..3217127 100644 --- a/lustre/quota/qmt_pool.c +++ b/lustre/quota/qmt_pool.c @@ -21,7 +21,7 @@ * GPL HEADER END */ /* - * Copyright (c) 2012 Intel, Inc. + * Copyright (c) 2012, 2016, Intel Corporation. * Use is subject to license terms. * * Author: Johann Lombardi @@ -48,10 +48,6 @@ * a given ID. */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif - #define DEBUG_SUBSYSTEM S_LQUOTA #include @@ -69,72 +65,73 @@ static void qmt_pool_free(const struct lu_env *, struct qmt_pool_info *); */ static inline void qpi_getref(struct qmt_pool_info *pool) { - cfs_atomic_inc(&pool->qpi_ref); + atomic_inc(&pool->qpi_ref); } static inline void qpi_putref(const struct lu_env *env, - struct qmt_pool_info *pool) + struct qmt_pool_info *pool) { LASSERT(atomic_read(&pool->qpi_ref) > 0); - if (cfs_atomic_dec_and_test(&pool->qpi_ref)) + if (atomic_dec_and_test(&pool->qpi_ref)) qmt_pool_free(env, pool); } static inline void qpi_putref_locked(struct qmt_pool_info *pool) { - LASSERT(cfs_atomic_read(&pool->qpi_ref) > 1); - cfs_atomic_dec(&pool->qpi_ref); + LASSERT(atomic_read(&pool->qpi_ref) > 1); + atomic_dec(&pool->qpi_ref); } /* * Hash functions for qmt_pool_info management */ -static unsigned qpi_hash_hash(cfs_hash_t *hs, const void *key, unsigned mask) +static unsigned +qpi_hash_hash(struct cfs_hash *hs, const void *key, unsigned mask) { return cfs_hash_u32_hash(*((__u32 *)key), mask); } -static void *qpi_hash_key(cfs_hlist_node_t *hnode) +static void *qpi_hash_key(struct hlist_node *hnode) { struct qmt_pool_info *pool; - pool = cfs_hlist_entry(hnode, struct qmt_pool_info, qpi_hash); + pool = hlist_entry(hnode, struct qmt_pool_info, qpi_hash); return &pool->qpi_key; } -static int qpi_hash_keycmp(const void *key, cfs_hlist_node_t *hnode) +static int qpi_hash_keycmp(const void *key, struct hlist_node *hnode) { struct qmt_pool_info *pool; - pool = cfs_hlist_entry(hnode, struct qmt_pool_info, qpi_hash); + pool = hlist_entry(hnode, struct qmt_pool_info, qpi_hash); return pool->qpi_key == *((__u32 *)key); } -static void *qpi_hash_object(cfs_hlist_node_t *hnode) +static void *qpi_hash_object(struct hlist_node *hnode) { - return cfs_hlist_entry(hnode, struct qmt_pool_info, qpi_hash); + return hlist_entry(hnode, struct qmt_pool_info, qpi_hash); } -static void qpi_hash_get(cfs_hash_t *hs, cfs_hlist_node_t *hnode) +static void qpi_hash_get(struct cfs_hash *hs, struct hlist_node *hnode) { struct qmt_pool_info *pool; - pool = cfs_hlist_entry(hnode, struct qmt_pool_info, qpi_hash); + pool = hlist_entry(hnode, struct qmt_pool_info, qpi_hash); qpi_getref(pool); } -static void qpi_hash_put_locked(cfs_hash_t *hs, cfs_hlist_node_t *hnode) +static void qpi_hash_put_locked(struct cfs_hash *hs, struct hlist_node *hnode) { struct qmt_pool_info *pool; - pool = cfs_hlist_entry(hnode, struct qmt_pool_info, qpi_hash); + pool = hlist_entry(hnode, struct qmt_pool_info, qpi_hash); qpi_putref_locked(pool); } -static void qpi_hash_exit(cfs_hash_t *hs, cfs_hlist_node_t *hnode) +static void qpi_hash_exit(struct cfs_hash *hs, struct hlist_node *hnode) { CERROR("Should not have any item left!\n"); } /* vector of hash operations */ -static cfs_hash_ops_t qpi_hash_ops = { +static struct cfs_hash_ops qpi_hash_ops = { .hs_hash = qpi_hash_hash, .hs_key = qpi_hash_key, .hs_keycmp = qpi_hash_keycmp, @@ -145,40 +142,82 @@ static cfs_hash_ops_t qpi_hash_ops = { }; /* some procfs helpers */ -static int lprocfs_qpi_rd_state(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int qpi_state_seq_show(struct seq_file *m, void *data) { - struct qmt_pool_info *pool = (struct qmt_pool_info *)data; - int type, i = 0; + struct qmt_pool_info *pool = m->private; + int type; LASSERT(pool != NULL); - i = snprintf(page, count, - "pool:\n" - " id: %u\n" - " type: %s\n" - " ref: %d\n" - " least qunit: %lu\n", - pool->qpi_key & 0x0000ffff, - RES_NAME(pool->qpi_key >> 16), - cfs_atomic_read(&pool->qpi_ref), - pool->qpi_least_qunit); - - - for (type = 0; type < MAXQUOTAS; type++) - i += snprintf(page + i, count - i, - " %s:\n" - " #slv: %d\n" - " #lqe: %d\n", - QTYPE_NAME(type), - pool->qpi_slv_nr[type], - cfs_atomic_read(&pool->qpi_site[type]->lqs_hash->hs_count)); - - return i; + seq_printf(m, "pool:\n" + " id: %u\n" + " type: %s\n" + " ref: %d\n" + " least qunit: %lu\n", + pool->qpi_key & 0x0000ffff, + RES_NAME(pool->qpi_key >> 16), + atomic_read(&pool->qpi_ref), + pool->qpi_least_qunit); + + for (type = 0; type < LL_MAXQUOTAS; type++) + seq_printf(m, " %s:\n" + " #slv: %d\n" + " #lqe: %d\n", + QTYPE_NAME(type), + pool->qpi_slv_nr[type], + atomic_read(&pool->qpi_site[type]->lqs_hash->hs_count)); + + return 0; } +LPROC_SEQ_FOPS_RO(qpi_state); + +static int qpi_soft_least_qunit_seq_show(struct seq_file *m, void *data) +{ + struct qmt_pool_info *pool = m->private; + LASSERT(pool != NULL); + + seq_printf(m, "%lu\n", pool->qpi_soft_least_qunit); + return 0; +} + +static ssize_t +qpi_soft_least_qunit_seq_write(struct file *file, const char __user *buffer, + size_t count, loff_t *off) +{ + struct qmt_pool_info *pool; + int qunit, rc; + s64 least_qunit; + + pool = ((struct seq_file *)file->private_data)->private; + LASSERT(pool != NULL); + + /* Not tuneable for inode limit */ + if (pool->qpi_key >> 16 != LQUOTA_RES_DT) + return -EINVAL; + + rc = lprocfs_str_to_s64(buffer, count, &least_qunit); + if (rc) + return rc; + + /* Miminal qpi_soft_least_qunit */ + qunit = pool->qpi_least_qunit << 2; + /* The value must be power of miminal qpi_soft_least_qunit, see + * how the qunit is adjusted in qmt_adjust_qunit(). */ + while (qunit > 0 && qunit < least_qunit) + qunit <<= 2; + if (qunit <= 0) + qunit = INT_MAX & ~3; + + pool->qpi_soft_least_qunit = qunit; + return count; +} +LPROC_SEQ_FOPS(qpi_soft_least_qunit); static struct lprocfs_vars lprocfs_quota_qpi_vars[] = { - { "info", lprocfs_qpi_rd_state, 0, 0}, + { .name = "info", + .fops = &qpi_state_fops }, + { .name = "soft_least_qunit", + .fops = &qpi_soft_least_qunit_fops }, { NULL } }; @@ -205,7 +244,7 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt, OBD_ALLOC_PTR(pool); if (pool == NULL) RETURN(-ENOMEM); - CFS_INIT_LIST_HEAD(&pool->qpi_linkage); + INIT_LIST_HEAD(&pool->qpi_linkage); /* assign key used by hash functions */ pool->qpi_key = pool_id + (pool_type << 16); @@ -216,6 +255,10 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt, /* set up least qunit size to use for this pool */ pool->qpi_least_qunit = LQUOTA_LEAST_QUNIT(pool_type); + if (pool_type == LQUOTA_RES_DT) + pool->qpi_soft_least_qunit = pool->qpi_least_qunit << 2; + else + pool->qpi_soft_least_qunit = pool->qpi_least_qunit; /* create pool proc directory */ sprintf(qti->qti_buf, "%s-0x%x", RES_NAME(pool_type), pool_id); @@ -244,7 +287,7 @@ static int qmt_pool_alloc(const struct lu_env *env, struct qmt_device *qmt, } /* add to qmt pool list */ - cfs_list_add_tail(&pool->qpi_linkage, &qmt->qmt_pool_list); + list_add_tail(&pool->qpi_linkage, &qmt->qmt_pool_list); EXIT; out: if (rc) @@ -272,7 +315,7 @@ static void qmt_pool_free(const struct lu_env *env, struct qmt_pool_info *pool) /* release per-quota type site used to manage quota entries as well as * references to global index files */ - for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + for (qtype = 0; qtype < LL_MAXQUOTAS; qtype++) { /* release lqe storing grace time */ if (pool->qpi_grace_lqe[qtype] != NULL) lqe_putref(pool->qpi_grace_lqe[qtype]); @@ -300,7 +343,7 @@ static void qmt_pool_free(const struct lu_env *env, struct qmt_pool_info *pool) pool->qpi_qmt = NULL; } - LASSERT(cfs_list_empty(&pool->qpi_linkage)); + LASSERT(list_empty(&pool->qpi_linkage)); OBD_FREE_PTR(pool); } @@ -351,27 +394,27 @@ static struct qmt_pool_info *qmt_pool_lookup(const struct lu_env *env, void qmt_pool_fini(const struct lu_env *env, struct qmt_device *qmt) { struct qmt_pool_info *pool; - cfs_list_t *pos, *n; + struct list_head *pos, *n; ENTRY; if (qmt->qmt_pool_hash == NULL) RETURN_EXIT; /* parse list of pool and destroy each element */ - cfs_list_for_each_safe(pos, n, &qmt->qmt_pool_list) { - pool = cfs_list_entry(pos, struct qmt_pool_info, - qpi_linkage); + list_for_each_safe(pos, n, &qmt->qmt_pool_list) { + pool = list_entry(pos, struct qmt_pool_info, + qpi_linkage); /* remove from hash */ cfs_hash_del(qmt->qmt_pool_hash, &pool->qpi_key, &pool->qpi_hash); /* remove from list */ - cfs_list_del_init(&pool->qpi_linkage); + list_del_init(&pool->qpi_linkage); /* release extra reference taken in qmt_pool_alloc */ qpi_putref(env, pool); } - LASSERT(cfs_list_empty(&qmt->qmt_pool_list)); + LASSERT(list_empty(&qmt->qmt_pool_list)); cfs_hash_putref(qmt->qmt_pool_hash); qmt->qmt_pool_hash = NULL; @@ -384,7 +427,7 @@ void qmt_pool_fini(const struct lu_env *env, struct qmt_device *qmt) * pool which are instantiated in this function. * * \param env - is the environment passed by the caller - * \param qmt - is the quota master target for which we have to initializa the + * \param qmt - is the quota master target for which we have to initialize the * pool configuration * * \retval - 0 on success, appropriate error on failure @@ -410,7 +453,7 @@ int qmt_pool_init(const struct lu_env *env, struct qmt_device *qmt) } /* initialize pool list */ - CFS_INIT_LIST_HEAD(&qmt->qmt_pool_list); + INIT_LIST_HEAD(&qmt->qmt_pool_list); /* Instantiate pool master for the default data and metadata pool (both * have pool ID equals to 0). @@ -443,7 +486,7 @@ static int qmt_slv_cnt(const struct lu_env *env, struct lu_fid *glb_fid, * Set up on-disk index files associated with each pool. * * \param env - is the environment passed by the caller - * \param qmt - is the quota master target for which we have to initializa the + * \param qmt - is the quota master target for which we have to initialize the * pool configuration * \param qmt_root - is the on-disk directory created for the QMT. * @@ -453,9 +496,11 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, struct dt_object *qmt_root) { struct qmt_thread_info *qti = qmt_info(env); + struct lquota_glb_rec *rec = &qti->qti_glb_rec; struct qmt_pool_info *pool; struct dt_device *dev = NULL; - cfs_list_t *pos; + dt_obj_version_t version; + struct list_head *pos; int rc = 0, qtype; ENTRY; @@ -463,13 +508,13 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, /* iterate over each pool in the hash and allocate a quota site for each * one. This involves creating a global index file on disk */ - cfs_list_for_each(pos, &qmt->qmt_pool_list) { + list_for_each(pos, &qmt->qmt_pool_list) { struct dt_object *obj; int pool_type, pool_id; struct lquota_entry *lqe; - pool = cfs_list_entry(pos, struct qmt_pool_info, - qpi_linkage); + pool = list_entry(pos, struct qmt_pool_info, + qpi_linkage); pool_id = pool->qpi_key & 0x0000ffff; pool_type = pool->qpi_key >> 16; @@ -484,7 +529,7 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, RETURN(PTR_ERR(obj)); pool->qpi_root = obj; - for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + for (qtype = 0; qtype < LL_MAXQUOTAS; qtype++) { /* Generating FID of global index in charge of storing * settings for this quota type */ lquota_generate_fid(&qti->qti_fid, pool_id, pool_type, @@ -505,6 +550,34 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, pool->qpi_glb_obj[qtype] = obj; + version = dt_version_get(env, obj); + /* set default grace time for newly created index */ + if (version == 0) { + rec->qbr_hardlimit = 0; + rec->qbr_softlimit = 0; + rec->qbr_granted = 0; + rec->qbr_time = pool_type == LQUOTA_RES_MD ? + MAX_IQ_TIME : MAX_DQ_TIME; + + rc = lquota_disk_write_glb(env, obj, 0, rec); + if (rc) { + CERROR("%s: failed to set default " + "grace time for %s type (%d)\n", + qmt->qmt_svname, + QTYPE_NAME(qtype), rc); + RETURN(rc); + } + + rc = lquota_disk_update_ver(env, dev, obj, 1); + if (rc) { + CERROR("%s: failed to set initial " + "version for %s type (%d)\n", + qmt->qmt_svname, + QTYPE_NAME(qtype), rc); + RETURN(rc); + } + } + /* create quota entry site for this quota type */ pool->qpi_site[qtype] = lquota_site_alloc(env, pool, true, qtype, @@ -541,7 +614,7 @@ int qmt_pool_prepare(const struct lu_env *env, struct qmt_device *qmt, if (IS_ERR(lqe)) RETURN(PTR_ERR(lqe)); pool->qpi_grace_lqe[qtype] = lqe; -#ifdef LPROCFS +#ifdef CONFIG_PROC_FS /* add procfs file to dump the global index, mostly for * debugging purpose */ sprintf(qti->qti_buf, "glb-%s", QTYPE_NAME(qtype)); @@ -625,7 +698,7 @@ out: * Look-up a lquota_entry in the pool hash and allocate it if not found. * * \param env - is the environment passed by the caller - * \param qmt - is the quota master target for which we have to initializa the + * \param qmt - is the quota master target for which we have to initialize the * pool configuration * \param pool_id - is the 16-bit identifier of the pool * \param pool_type - is the pool type, either LQUOTA_RES_MD or LQUOTA_RES_DT. @@ -654,7 +727,7 @@ struct lquota_entry *qmt_pool_lqe_lookup(const struct lu_env *env, * entry since we keep a reference on ID 0 all the time */ lqe = pool->qpi_grace_lqe[qtype]; lqe_getref(lqe); - GOTO(out, 0); + GOTO(out, lqe); } /* now that we have the pool, let's look-up the quota entry in the