Whamcloud - gitweb
LU-8955 nodemap: add SELinux policy info to nodemap
[fs/lustre-release.git] / lustre / quota / lproc_quota.c
index 9c65526..a9a3b0b 100644 (file)
@@ -21,7 +21,7 @@
  * GPL HEADER END
  */
 /*
- * Copyright (c) 2012 Intel, Inc.
+ * Copyright (c) 2011, 2017, Intel Corporation.
  * Use is subject to license terms.
  *
  * Author: Johann Lombardi <johann.lombardi@intel.com>
 #include <lprocfs_status.h>
 #include <obd.h>
 #include <linux/seq_file.h>
-#include <lustre_fsfilt.h>
-
 #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 */
@@ -60,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.
                 *
@@ -94,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;
 }
 
@@ -122,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)
@@ -141,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",
@@ -155,9 +161,25 @@ 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:
  *
@@ -188,10 +210,7 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v)
 
        if (v == SEQ_START_TOKEN) {
                if (fid_is_acct(fid)) {
-                       if (fid_oid(fid) == ACCT_USER_OID)
-                               seq_printf(p, "usr_accounting:\n");
-                       else
-                               seq_printf(p, "grp_accounting:\n");
+                       seq_printf(p, "%s:\n", oid2name(fid_oid(fid)));
                } else if (fid_seq(fid) == FID_SEQ_QUOTA_GLB) {
                        int     poolid, rtype, qtype;
 
@@ -200,7 +219,10 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v)
                                return rc;
 
                        seq_printf(p, "global_pool%d_%s_%s\n", poolid,
-                                  RES_NAME(rtype), QTYPE_NAME(qtype));
+                                  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;
                }
@@ -227,13 +249,12 @@ static int lprocfs_quota_seq_show(struct seq_file *p, void *v)
 
        seq_printf(p, "- %-8s %llu\n", "id:", *((__u64 *)key));
        if (fid_is_acct(fid))
-               seq_printf(p, "  %-8s { inodes: %20"LPF64"u, kbytes: %20"LPF64
-                          "u }\n", "usage:",
+               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)
-               seq_printf(p, "  %-8s { hard: %20"LPF64"u, soft: %20"LPF64
-                          "u, granted: %20"LPF64"u, time: %20"LPF64"u }\n",
+       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,
@@ -251,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 */
@@ -263,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:
@@ -299,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);
 
@@ -316,4 +363,4 @@ struct file_operations lprocfs_quota_seq_fops = {
        .llseek         = seq_lseek,
        .release        = lprocfs_quota_seq_release,
 };
-#endif  /* LPROCFS */
+#endif /* CONFIG_PROC_FS */