4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, Whamcloud, Inc.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #define DEBUG_SUBSYSTEM S_LQUOTA
39 #include <linux/version.h>
40 #include <lprocfs_status.h>
42 #include <linux/seq_file.h>
43 #include <lustre_fsfilt.h>
45 #include "lquota_internal.h"
48 /* structure allocated at seq_open time and release when seq_release is called.
49 * It is passed to seq_start/stop/next/show which can thus use the same lu_env
50 * to be used with the iterator API */
51 struct lquota_procfs {
52 struct dt_object *lqp_obj;
53 struct lu_env lqp_env;
56 /* global shared environment */
57 static void *lprocfs_quota_seq_start(struct seq_file *p, loff_t *pos)
59 struct lquota_procfs *lqp = p->private;
60 const struct dt_it_ops *iops;
68 return SEQ_START_TOKEN;
71 if (lqp->lqp_obj == NULL)
72 /* accounting not enabled. */
75 /* initialize iterator */
76 iops = &lqp->lqp_obj->do_index_ops->dio_it;
77 it = iops->init(&lqp->lqp_env, lqp->lqp_obj, 0, BYPASS_CAPA);
79 CERROR("%s: failed to initialize iterator: rc = %ld\n",
80 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name,
85 /* move on to the first valid record */
86 rc = iops->load(&lqp->lqp_env, it, 0);
87 if (rc < 0) { /* Error */
91 * Iterator didn't find record with exactly the key requested.
93 * It is currently either
95 * - positioned above record with key less than
96 * requested - skip it.
97 * - or not positioned at all (is in IAM_IT_SKEWED
98 * state) - position it on the next item.
100 rc = iops->next(&lqp->lqp_env, it);
105 rc = iops->next(&lqp->lqp_env, it);
106 if (rc != 0) /* Error or reach the end */
112 iops->put(&lqp->lqp_env, it);
113 iops->fini(&lqp->lqp_env, it);
117 static void lprocfs_quota_seq_stop(struct seq_file *p, void *v)
119 struct lquota_procfs *lqp = p->private;
120 const struct dt_it_ops *iops;
123 if (lqp->lqp_obj == NULL || v == NULL || v == SEQ_START_TOKEN)
126 iops = &lqp->lqp_obj->do_index_ops->dio_it;
127 it = (struct dt_it *)v;
128 /* if something wrong happened during ->seq_show, we need to release
129 * the iterator here */
130 iops->put(&lqp->lqp_env, it);
131 iops->fini(&lqp->lqp_env, it);
134 static void *lprocfs_quota_seq_next(struct seq_file *p, void *v, loff_t *pos)
136 struct lquota_procfs *lqp = p->private;
137 const struct dt_it_ops *iops;
144 if (lqp->lqp_obj == NULL)
147 if (v == SEQ_START_TOKEN)
148 return lprocfs_quota_seq_start(p, pos);
150 iops = &lqp->lqp_obj->do_index_ops->dio_it;
151 it = (struct dt_it *)v;
153 rc = iops->next(&lqp->lqp_env, it);
158 CERROR("%s: seq_next failed: rc = %d\n",
159 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
161 /* Reach the end or error */
162 iops->put(&lqp->lqp_env, it);
163 iops->fini(&lqp->lqp_env, it);
172 * usage: { inodes: 209, bytes: 26161152 }
174 * usage: { inodes: 1, bytes: 10485760 }
176 static int lprocfs_quota_seq_show(struct seq_file *p, void *v)
178 struct lquota_procfs *lqp = p->private;
179 const struct dt_it_ops *iops;
182 struct lquota_acct_rec rec;
186 if (lqp->lqp_obj == NULL) {
187 seq_printf(p, "not supported\n");
191 if (v == SEQ_START_TOKEN) {
192 const struct lu_fid *fid = lu_object_fid(&lqp->lqp_obj->do_lu);
194 LASSERT(fid_is_acct(fid));
195 if (fid_oid(fid) == ACCT_USER_OID)
196 seq_printf(p, "user_accounting:\n");
198 seq_printf(p, "group_accounting:\n");
202 iops = &lqp->lqp_obj->do_index_ops->dio_it;
203 it = (struct dt_it *)v;
205 key = iops->key(&lqp->lqp_env, it);
207 CERROR("%s: failed to get key: rc = %ld\n",
208 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name,
213 rc = iops->rec(&lqp->lqp_env, it, (struct dt_rec *)&rec, 0);
215 CERROR("%s: failed to get rec: rc = %d\n",
216 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
220 seq_printf(p, "- %-8s %llu\n", "id:", *((__u64 *)key));
221 seq_printf(p, " %-8s { inodes: %20"LPF64"u, bytes: %20"LPF64"u }\n",
222 "usage:", rec.ispace, rec.bspace);
226 struct seq_operations lprocfs_quota_seq_sops = {
227 .start = lprocfs_quota_seq_start,
228 .stop = lprocfs_quota_seq_stop,
229 .next = lprocfs_quota_seq_next,
230 .show = lprocfs_quota_seq_show,
233 static int lprocfs_quota_seq_open(struct inode *inode, struct file *file)
235 struct proc_dir_entry *dp = PDE(inode);
236 struct seq_file *seq;
238 struct lquota_procfs *lqp;
240 /* Allocate quota procfs data. This structure will be passed to
241 * seq_start/stop/next/show via seq->private */
246 /* store pointer to object we would like to iterate over */
247 lqp->lqp_obj = (struct dt_object *)dp->data;
249 /* Initialize the common environment to be used in the seq operations */
250 rc = lu_env_init(&lqp->lqp_env, LCT_LOCAL);
252 CERROR("%s: error initializing procfs quota env: rc = %d\n",
253 lqp->lqp_obj->do_lu.lo_dev->ld_obd->obd_name, rc);
257 if (LPROCFS_ENTRY_AND_CHECK(dp)) {
262 rc = seq_open(file, &lprocfs_quota_seq_sops);
266 seq = file->private_data;
273 lu_env_fini(&lqp->lqp_env);
279 static int lprocfs_quota_seq_release(struct inode *inode, struct file *file)
281 struct seq_file *seq = file->private_data;
282 struct lquota_procfs *lqp = seq->private;
287 lu_env_fini(&lqp->lqp_env);
290 return seq_release(inode, file);
293 struct file_operations lprocfs_quota_seq_fops = {
294 .owner = THIS_MODULE,
295 .open = lprocfs_quota_seq_open,
298 .release = lprocfs_quota_seq_release,