* GPL HEADER END
*/
/*
- * Copyright (c) 2012 Intel, Inc.
+ * Copyright (c) 2012, Intel Corporation.
* Use is subject to license terms.
*
* Author: Johann Lombardi <johann.lombardi@intel.com>
* a given ID.
*/
-#ifndef EXPORT_SYMTAB
-# define EXPORT_SYMTAB
-#endif
-
#define DEBUG_SUBSYSTEM S_LQUOTA
#include <obd_class.h>
*/
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);
}
/*
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(cfs_hash_t *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(cfs_hash_t *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(cfs_hash_t *hs, struct hlist_node *hnode)
{
CERROR("Should not have any item left!\n");
}
};
/* 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);
-
+ 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 < 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, " %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 struct lprocfs_vars lprocfs_quota_qpi_vars[] = {
- { "info", lprocfs_qpi_rd_state, 0, 0},
+static struct lprocfs_seq_vars lprocfs_quota_qpi_vars[] = {
+ { .name = "info",
+ .fops = &qpi_state_fops },
{ NULL }
};
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);
/* create pool proc directory */
sprintf(qti->qti_buf, "%s-0x%x", RES_NAME(pool_type), pool_id);
- pool->qpi_proc = lprocfs_register(qti->qti_buf, qmt->qmt_proc,
- lprocfs_quota_qpi_vars, pool);
+ pool->qpi_proc = lprocfs_seq_register(qti->qti_buf, qmt->qmt_proc,
+ lprocfs_quota_qpi_vars, pool);
if (IS_ERR(pool->qpi_proc)) {
rc = PTR_ERR(pool->qpi_proc);
CERROR("%s: failed to create proc entry for pool %s (%d)\n",
}
/* 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)
/* release per-quota type site used to manage quota entries as well as
* references to global index files */
for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
+ /* release lqe storing grace time */
+ if (pool->qpi_grace_lqe[qtype] != NULL)
+ lqe_putref(pool->qpi_grace_lqe[qtype]);
+
/* release site */
if (pool->qpi_site[qtype] != NULL &&
!IS_ERR(pool->qpi_site[qtype]))
pool->qpi_qmt = NULL;
}
- LASSERT(cfs_list_empty(&pool->qpi_linkage));
+ LASSERT(list_empty(&pool->qpi_linkage));
OBD_FREE_PTR(pool);
}
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;
}
/* 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).
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;
/* 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) {
- struct dt_object *obj;
- int pool_type, pool_id;
+ 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;
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,
qmt->qmt_svname, QTYPE_NAME(qtype), rc);
RETURN(rc);
}
+
+ /* Global grace time is stored in quota settings of
+ * ID 0. */
+ qti->qti_id.qid_uid = 0;
+
+ /* look-up quota entry storing grace time */
+ lqe = lqe_locate(env, pool->qpi_site[qtype],
+ &qti->qti_id);
+ if (IS_ERR(lqe))
+ RETURN(PTR_ERR(lqe));
+ pool->qpi_grace_lqe[qtype] = lqe;
#ifdef LPROCFS
/* add procfs file to dump the global index, mostly for
* debugging purpose */
if (IS_ERR(pool))
RETURN((void *)pool);
+ if (qid->qid_uid == 0) {
+ /* caller wants to access grace time, no need to look up the
+ * entry since we keep a reference on ID 0 all the time */
+ lqe = pool->qpi_grace_lqe[qtype];
+ lqe_getref(lqe);
+ GOTO(out, lqe);
+ }
+
/* now that we have the pool, let's look-up the quota entry in the
* right quota site */
lqe = lqe_locate(env, pool->qpi_site[qtype], qid);
-
+out:
qpi_putref(env, pool);
RETURN(lqe);
}