Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / lustre / quota / quotacheck_test.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see [sun.com URL with a
20  * copy of GPLv2].
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/quota/quotacheck_test.c
37  *
38  * Author: Lai Siyao <lsy@clusterfs.com>
39  */
40
41 #ifndef EXPORT_SYMTAB
42 # define EXPORT_SYMTAB
43 #endif
44 #define DEBUG_SUBSYSTEM S_CLASS
45
46 #include <linux/module.h>
47 #include <linux/init.h>
48 #include <linux/fs.h>
49 #include <linux/jbd.h>
50 #include <linux/slab.h>
51 #include <linux/pagemap.h>
52 #include <linux/quotaops.h>
53 #include <linux/ext3_fs.h>
54 #include <linux/ext3_jbd.h>
55 #include <linux/version.h>
56 #include <linux/bitops.h>
57
58 #include <obd_class.h>
59 #include <lustre_fsfilt.h>
60 #include <lustre_mds.h>
61 #include <obd_ost.h>
62
63 char *test_quotafile[] = {"aquotacheck.user", "aquotacheck.group"};
64
65 static inline struct ext3_group_desc *
66 get_group_desc(struct super_block *sb, int group)
67 {
68         unsigned long desc_block, desc;
69         struct ext3_group_desc *gdp;
70
71         desc_block = group / EXT3_DESC_PER_BLOCK(sb);
72         desc = group % EXT3_DESC_PER_BLOCK(sb);
73         gdp = (struct ext3_group_desc *)
74               EXT3_SB(sb)->s_group_desc[desc_block]->b_data;
75
76         return gdp + desc;
77 }
78
79 static inline struct buffer_head *
80 read_inode_bitmap(struct super_block *sb, unsigned long group)
81 {
82         struct ext3_group_desc *desc;
83         struct buffer_head *bh;
84
85         desc = get_group_desc(sb, group);
86         bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
87
88         return bh;
89 }
90
91 static inline struct inode *ext3_iget_inuse(struct super_block *sb,
92                                      struct buffer_head *bitmap_bh,
93                                      int index, unsigned long ino)
94 {
95         struct inode *inode = NULL;
96
97         if (ext3_test_bit(index, bitmap_bh->b_data)) {
98                 CERROR("i: %d, ino: %lu\n", index, ino);
99                 ll_sleep(1);
100                 inode = iget(sb, ino);
101         }
102
103         return inode;
104 }
105
106 static void print_inode(struct inode *inode)
107 {
108         loff_t size = 0;
109
110         if (S_ISDIR(inode->i_mode) ||
111             S_ISREG(inode->i_mode) ||
112             S_ISLNK(inode->i_mode))
113                 size = inode_get_bytes(inode);
114
115          CERROR("%lu: uid: %u, size: %llu, blocks: %llu, real size: %llu\n",
116                 inode->i_ino, inode->i_uid, i_size_read(inode),
117                 (unsigned long long)inode->i_blocks, size);
118 }
119
120 /* Test quotaon */
121 static int quotacheck_test_1(struct obd_device *obd, struct super_block *sb)
122 {
123         struct ext3_sb_info *sbi = EXT3_SB(sb);
124         struct buffer_head *bitmap_bh = NULL;
125         struct inode *inode;
126         unsigned long ino;
127         int i, group;
128         ENTRY;
129
130         for (group = 0; group < sbi->s_groups_count; group++) {
131                 ino = group * sbi->s_inodes_per_group + 1;
132                 brelse(bitmap_bh);
133                 bitmap_bh = read_inode_bitmap(sb, group);
134
135                 if (group == 0)
136                         CERROR("groups_count: %lu, inodes_per_group: %lu, first_ino: %u, inodes_count: %u\n",
137                                sbi->s_groups_count, sbi->s_inodes_per_group,
138                                sbi->s_first_ino, le32_to_cpu(sbi->s_es->s_inodes_count));
139
140                 for (i = 0; i < sbi->s_inodes_per_group; i++, ino++) {
141                         if (ino < sbi->s_first_ino)
142                                 continue;
143                         if (ino > le32_to_cpu(sbi->s_es->s_inodes_count)) {
144                                 CERROR("bad inode number: %lu > s_inodes_count\n", ino);
145                                 brelse(bitmap_bh);
146                                 RETURN(-E2BIG);
147                         }
148                         inode = ext3_iget_inuse(sb, bitmap_bh, i, ino);
149                         if (inode)
150                                 print_inode(inode);
151                         iput(inode);
152                 }
153         }
154         brelse(bitmap_bh);
155
156         RETURN(0);
157 }
158
159 /* -------------------------------------------------------------------------
160  * Tests above, boring obd functions below
161  * ------------------------------------------------------------------------- */
162 static int quotacheck_run_tests(struct obd_device *obd, struct obd_device *tgt)
163 {
164         int rc;
165         ENTRY;
166
167         if (strcmp(tgt->obd_type->typ_name, LUSTRE_MDS_NAME) &&
168             !strcmp(tgt->obd_type->typ_name, "obdfilter")) {
169                 CERROR("TARGET OBD should be mds or ost\n");
170                 RETURN(-EINVAL);
171         }
172
173         rc = quotacheck_test_1(tgt, tgt->u.obt.obt_sb);
174
175         return rc;
176 }
177
178 #ifdef LPROCFS
179 static struct lprocfs_vars lprocfs_quotacheck_test_obd_vars[] = { {0} };
180 static struct lprocfs_vars lprocfs_quotacheck_test_module_vars[] = { {0} };
181
182 void lprocfs_quotacheck_test_init_vars(struct lprocfs_static_vars *lvars)
183 {
184     lvars->module_vars  = lprocfs_quotacheck_test_module_vars;
185     lvars->obd_vars     = lprocfs_quotacheck_test_obd_vars;
186 }
187 #endif
188
189 static int quotacheck_test_cleanup(struct obd_device *obd)
190 {
191         lprocfs_obd_cleanup(obd);
192         return 0;
193 }
194
195 static int quotacheck_test_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
196 {
197         struct lprocfs_static_vars lvars = { 0 };
198         struct obd_device *tgt;
199         int rc;
200         ENTRY;
201
202         if (lcfg->lcfg_bufcount < 1) {
203                 CERROR("requires a mds OBD name\n");
204                 RETURN(-EINVAL);
205         }
206
207         tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
208         if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
209                 CERROR("target device not attached or not set up (%s)\n",
210                        lustre_cfg_string(lcfg, 1));
211                 RETURN(-EINVAL);
212         }
213
214         rc = quotacheck_run_tests(obd, tgt);
215         if (rc)
216                 quotacheck_test_cleanup(obd);
217
218         lprocfs_quotacheck_test_init_vars(&lvars);
219         lprocfs_obd_setup(obd, lvars.obd_vars);
220
221         RETURN(rc);
222 }
223
224 static struct obd_ops quotacheck_obd_ops = {
225         .o_owner       = THIS_MODULE,
226         .o_setup       = quotacheck_test_setup,
227         .o_cleanup     = quotacheck_test_cleanup,
228 };
229
230 static int __init quotacheck_test_init(void)
231 {
232         struct lprocfs_static_vars lvars = { 0 };
233
234         lprocfs_quotacheck_test_init_vars(&lvars);
235         return class_register_type(&quotacheck_obd_ops, NULL, lvars.module_vars,
236                                    "quotacheck_test", NULL);
237 }
238
239 static void __exit quotacheck_test_exit(void)
240 {
241         class_unregister_type("quotacheck_test");
242 }
243
244 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
245 MODULE_DESCRIPTION("quotacheck test module");
246 MODULE_LICENSE("GPL");
247
248 module_init(quotacheck_test_init);
249 module_exit(quotacheck_test_exit);