X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fquota%2Flproc_quota.c;h=cfe7b9b12f9e2890dfcf1d0351d7fb7c129fdacd;hb=dd71e74fecf45b81daa27c89c0b8065a58cac5c1;hp=581cf63149c8d6e3987a4a36a9986e9f6be9b2dd;hpb=9ddf386035767a96b54e21559f3ea0be126dc8cd;p=fs%2Flustre-release.git diff --git a/lustre/quota/lproc_quota.c b/lustre/quota/lproc_quota.c index 581cf63..cfe7b9b 100644 --- a/lustre/quota/lproc_quota.c +++ b/lustre/quota/lproc_quota.c @@ -14,24 +14,18 @@ * in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU General Public License - * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * version 2 along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA * * GPL HEADER END */ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Intel Corporation. * Use is subject to license terms. * - * Copyright (c) 2011, Whamcloud, Inc. - */ -/* - * This file is part of Lustre, http://www.lustre.org/ - * Lustre is a trademark of Sun Microsystems, Inc. + * Author: Johann Lombardi + * Author: Niu Yawei */ #define DEBUG_SUBSYSTEM S_LQUOTA @@ -40,17 +34,18 @@ #include #include #include -#include - #include "lquota_internal.h" -#ifdef LPROCFS +#ifdef CONFIG_PROC_FS /* structure allocated at seq_open time and release when seq_release is called. * It is passed to seq_start/stop/next/show which can thus use the same lu_env * to be used with the iterator API */ struct lquota_procfs { - struct dt_object *lqp_obj; - struct lu_env lqp_env; + struct dt_object *lqp_obj; + struct lu_env lqp_env; + struct dt_it *lqp_it; + __u64 lqp_cookie; + __u64 lqp_first_cookie; }; /* global shared environment */ @@ -66,27 +61,20 @@ static void *lprocfs_quota_seq_start(struct seq_file *p, loff_t *pos) if (offset == 0) return SEQ_START_TOKEN; - offset--; if (lqp->lqp_obj == NULL) /* accounting not enabled. */ return NULL; - /* initialize iterator */ - iops = &lqp->lqp_obj->do_index_ops->dio_it; - it = iops->init(&lqp->lqp_env, lqp->lqp_obj, 0, BYPASS_CAPA); - if (IS_ERR(it)) { - CERROR("%s: failed to initialize iterator: rc = %ld\n", - lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, - PTR_ERR(it)); + if (lqp->lqp_it == NULL) /* reach the end */ return NULL; - } - /* move on to the first valid record */ - rc = iops->load(&lqp->lqp_env, it, 0); - if (rc < 0) { /* Error */ - goto not_found; - } else if (rc == 0) { + offset--; + /* move on to the the last processed entry */ + iops = &lqp->lqp_obj->do_index_ops->dio_it; + it = lqp->lqp_it; + rc = iops->load(&lqp->lqp_env, it, lqp->lqp_cookie); + if (rc == 0 && offset == 0) { /* * Iterator didn't find record with exactly the key requested. * @@ -100,17 +88,25 @@ static void *lprocfs_quota_seq_start(struct seq_file *p, loff_t *pos) rc = iops->next(&lqp->lqp_env, it); if (rc != 0) goto not_found; + lqp->lqp_cookie = iops->store(&lqp->lqp_env, it); + } else if (rc <= 0) { + goto not_found; } - while (offset--) { - rc = iops->next(&lqp->lqp_env, it); - if (rc != 0) /* Error or reach the end */ - goto not_found; - } + + /* The id entry could be deleted while iteration, and above ->load() + * operation will reset cursor to the first cookie (ldiskfs), we + * need to break in such situation. */ + if (offset == 0) + lqp->lqp_first_cookie = lqp->lqp_cookie; + else if (lqp->lqp_cookie == lqp->lqp_first_cookie) + goto not_found; + return it; not_found: iops->put(&lqp->lqp_env, it); iops->fini(&lqp->lqp_env, it); + lqp->lqp_it = NULL; return NULL; } @@ -128,7 +124,6 @@ static void lprocfs_quota_seq_stop(struct seq_file *p, void *v) /* if something wrong happened during ->seq_show, we need to release * the iterator here */ iops->put(&lqp->lqp_env, it); - iops->fini(&lqp->lqp_env, it); } static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos) @@ -147,12 +142,17 @@ static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos) if (v == SEQ_START_TOKEN) return lprocfs_quota_seq_start(p, pos); + if (lqp->lqp_it == NULL) /* reach the end */ + return NULL; + iops = &lqp->lqp_obj->do_index_ops->dio_it; it = (struct dt_it *)v; rc = iops->next(&lqp->lqp_env, it); - if (rc == 0) + if (rc == 0) { + lqp->lqp_cookie = iops->store(&lqp->lqp_env, it); return it; + } if (rc < 0) CERROR("%s: seq_next failed: rc = %d\n", @@ -161,26 +161,44 @@ static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos) /* Reach the end or error */ iops->put(&lqp->lqp_env, it); iops->fini(&lqp->lqp_env, it); + lqp->lqp_it = NULL; return NULL; } +static inline const char *oid2name(__u32 oid) +{ + switch (oid) { + case ACCT_USER_OID: + return "usr_accounting"; + case ACCT_GROUP_OID: + return "grp_accounting"; + case ACCT_PROJECT_OID: + return "prj_accounting"; + break; + default: + return "unknown_accounting"; + } +} + /* * Output example: * - * user_accounting: + * usr_accounting: * - id: 0 - * usage: { inodes: 209, bytes: 26161152 } + * usage: { inodes: 209, kbytes: 2616 } * - id: 840000038 - * usage: { inodes: 1, bytes: 10485760 } + * usage: { inodes: 1, kbytes: 1048 } */ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) { - struct lquota_procfs *lqp = p->private; - const struct dt_it_ops *iops; - struct dt_it *it; - struct dt_key *key; - struct lquota_acct_rec rec; - int rc; + struct lquota_procfs *lqp = p->private; + struct lquota_thread_info *qti = lquota_info(&lqp->lqp_env); + const struct dt_it_ops *iops; + struct dt_it *it; + struct dt_key *key; + struct dt_rec *rec = (struct dt_rec *)&qti->qti_rec; + const struct lu_fid *fid; + int rc; LASSERT(lqp); if (lqp->lqp_obj == NULL) { @@ -188,14 +206,26 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) return 0; } - if (v == SEQ_START_TOKEN) { - const struct lu_fid *fid = lu_object_fid(&lqp->lqp_obj->do_lu); + fid = lu_object_fid(&lqp->lqp_obj->do_lu); - LASSERT(fid_is_acct(fid)); - if (fid_oid(fid) == ACCT_USER_OID) - seq_printf(p, "user_accounting:\n"); - else - seq_printf(p, "group_accounting:\n"); + if (v == SEQ_START_TOKEN) { + if (fid_is_acct(fid)) { + seq_printf(p, "%s:\n", oid2name(fid_oid(fid))); + } else if (fid_seq(fid) == FID_SEQ_QUOTA_GLB) { + int rtype, qtype; + + rc = lquota_extract_fid(fid, &rtype, &qtype); + if (rc) + return rc; + + seq_printf(p, "global_pool%d_%s_%s\n", 0, + RES_NAME(rtype), qtype_name(qtype)); + } else if (fid_seq(fid) == FID_SEQ_LOCAL_NAME) { + /* global index copy object */ + seq_printf(p, "global_index_copy:\n"); + } else { + return -ENOTSUPP; + } return 0; } @@ -210,7 +240,7 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) return PTR_ERR(key); } - rc = iops->rec(&lqp->lqp_env, it, (struct dt_rec *)&rec, 0); + rc = iops->rec(&lqp->lqp_env, it, rec, 0); if (rc) { CERROR("%s: failed to get rec: rc = %d\n", lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc); @@ -218,8 +248,18 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v) } seq_printf(p, "- %-8s %llu\n", "id:", *((__u64 *)key)); - seq_printf(p, " %-8s { inodes: %20"LPF64"u, bytes: %20"LPF64"u }\n", - "usage:", rec.ispace, rec.bspace); + if (fid_is_acct(fid)) + seq_printf(p, " %-8s { inodes: %20llu, kbytes: %20llu }\n", "usage:", + ((struct lquota_acct_rec *)rec)->ispace, + toqb(((struct lquota_acct_rec *)rec)->bspace)); + else if (fid_seq(fid) == FID_SEQ_QUOTA_GLB || + fid_seq(fid) == FID_SEQ_LOCAL_NAME) + seq_printf(p, " %-8s { hard: %20llu, soft: %20llu, granted: %20llu, time: %20llu }\n", + "limits:", + ((struct lquota_glb_rec *)rec)->qbr_hardlimit, + ((struct lquota_glb_rec *)rec)->qbr_softlimit, + ((struct lquota_glb_rec *)rec)->qbr_granted, + ((struct lquota_glb_rec *)rec)->qbr_time); return 0; } @@ -232,10 +272,11 @@ struct seq_operations lprocfs_quota_seq_sops = { static int lprocfs_quota_seq_open(struct inode *inode, struct file *file) { - struct proc_dir_entry *dp = PDE(inode); struct seq_file *seq; int rc; struct lquota_procfs *lqp; + const struct dt_it_ops *iops; + struct dt_it *it; /* Allocate quota procfs data. This structure will be passed to * seq_start/stop/next/show via seq->private */ @@ -244,31 +285,53 @@ static int lprocfs_quota_seq_open(struct inode *inode, struct file *file) return -ENOMEM; /* store pointer to object we would like to iterate over */ - lqp->lqp_obj = (struct dt_object *)dp->data; + lqp->lqp_obj = (struct dt_object *)PDE_DATA(inode); /* Initialize the common environment to be used in the seq operations */ rc = lu_env_init(&lqp->lqp_env, LCT_LOCAL); if (rc) { + char *obd_name = "quota"; + + if (lqp->lqp_obj != NULL) + obd_name = lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name; + CERROR("%s: error initializing procfs quota env: rc = %d\n", - lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc); + obd_name, rc); goto out_lqp; } - if (LPROCFS_ENTRY_AND_CHECK(dp)) { - rc = -ENOENT; + rc = LPROCFS_ENTRY_CHECK(inode); + if (rc < 0) goto out_env; - } rc = seq_open(file, &lprocfs_quota_seq_sops); if (rc) - goto out_lprocfs; + goto out_env; + if (!lqp->lqp_obj) { + lqp->lqp_it = NULL; + goto out_seq; + } + + /* initialize iterator */ + iops = &lqp->lqp_obj->do_index_ops->dio_it; + it = iops->init(&lqp->lqp_env, lqp->lqp_obj, 0); + if (IS_ERR(it)) { + rc = PTR_ERR(it); + CERROR("%s: failed to initialize iterator: rc = %ld\n", + lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, + PTR_ERR(it)); + seq_release(inode, file); + goto out_env; + } + lqp->lqp_it = it; + lqp->lqp_cookie = 0; + +out_seq: seq = file->private_data; seq->private = lqp; return 0; -out_lprocfs: - LPROCFS_EXIT(); out_env: lu_env_fini(&lqp->lqp_env); out_lqp: @@ -280,10 +343,13 @@ static int lprocfs_quota_seq_release(struct inode *inode, struct file *file) { struct seq_file *seq = file->private_data; struct lquota_procfs *lqp = seq->private; - - LPROCFS_EXIT(); + const struct dt_it_ops *iops; LASSERT(lqp); + if (lqp->lqp_it != NULL) { + iops = &lqp->lqp_obj->do_index_ops->dio_it; + iops->fini(&lqp->lqp_env, lqp->lqp_it); + } lu_env_fini(&lqp->lqp_env); OBD_FREE_PTR(lqp); @@ -297,4 +363,4 @@ struct file_operations lprocfs_quota_seq_fops = { .llseek = seq_lseek, .release = lprocfs_quota_seq_release, }; -#endif /* LPROCFS */ +#endif /* CONFIG_PROC_FS */