Whamcloud - gitweb
Branch: b1_4
[fs/lustre-release.git] / lustre / lvfs / quotactl_test.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2003 Cluster File Systems, Inc.
5  *   Author: Lai Siyao <lsy@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org/
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * A kernel module which tests the fsfilt quotactl API from the OBD setup function.
23  */
24
25 #ifndef EXPORT_SYMTAB
26 # define EXPORT_SYMTAB
27 #endif
28 #define DEBUG_SUBSYSTEM S_CLASS
29
30 #include <linux/module.h>
31 #include <linux/init.h>
32
33 #include <linux/obd_class.h>
34 #include <linux/lustre_fsfilt.h>
35 #include <linux/lustre_mds.h>
36 #include <linux/obd_ost.h>
37
38 char *test_quotafile[] = {"aquotactl.user", "aquotactl.group"};
39
40 /* Test quotaon */
41 static int quotactl_test_1(struct obd_device *obd, struct super_block *sb)
42 {
43         struct obd_quotactl oqctl;
44         int rc;
45         ENTRY;
46
47         oqctl.qc_cmd = Q_QUOTAON;
48         oqctl.qc_id = QFMT_LDISKFS;
49         oqctl.qc_type = UGQUOTA;
50         rc = fsfilt_quotactl(obd, sb, &oqctl);
51         if (rc) {
52                 CERROR("1a: quotactl Q_QUOTAON failed: %d\n", rc);
53                 RETURN(rc);
54         }
55
56         RETURN(0);
57 }
58
59 #if 0 /* set/getinfo not supported, this is for cluster-wide quotas */
60 /* Test set/getinfo */
61 static int quotactl_test_2(struct obd_device *obd, struct super_block *sb)
62 {
63         struct obd_quotactl oqctl;
64         int rc;
65         ENTRY;
66
67         oqctl.qc_cmd = Q_SETINFO;
68         oqctl.qc_type = USRQUOTA;
69         oqctl.qc_dqinfo.dqi_bgrace = 1616;
70         oqctl.qc_dqinfo.dqi_igrace = 2828;
71         oqctl.qc_dqinfo.dqi_flags = 0;
72         rc = fsfilt_quotactl(obd, sb, &oqctl);
73         if (rc) {
74                 CERROR("2a: quotactl Q_SETINFO failed: %d\n", rc);
75                 RETURN(rc);
76         }
77
78         oqctl.qc_cmd = Q_GETINFO;
79         oqctl.qc_type = USRQUOTA;
80         rc = fsfilt_quotactl(obd, sb, &oqctl);
81         if (rc) {
82                 CERROR("2b: quotactl Q_GETINFO failed: %d\n", rc);
83                 RETURN(rc);
84         }
85         if (oqctl.qc_dqinfo.dqi_bgrace != 1616 ||
86             oqctl.qc_dqinfo.dqi_igrace != 2828 ||
87             oqctl.qc_dqinfo.dqi_flags != 0) {
88                 CERROR("2c: quotactl Q_GETINFO get wrong result: %d, %d, %d\n",
89                        oqctl.qc_dqinfo.dqi_bgrace,
90                        oqctl.qc_dqinfo.dqi_igrace,
91                        oqctl.qc_dqinfo.dqi_flags);
92                 RETURN(-EINVAL);
93         }
94
95         RETURN(0);
96 }
97 #endif
98        
99 /* Test set/getquota */
100 static int quotactl_test_3(struct obd_device *obd, struct super_block *sb)
101 {
102         struct obd_quotactl oqctl;
103         int rc;
104         ENTRY;
105
106         oqctl.qc_cmd = Q_SETQUOTA;
107         oqctl.qc_type = USRQUOTA;
108         oqctl.qc_id = 500;
109         oqctl.qc_dqblk.dqb_bhardlimit = 919;
110         oqctl.qc_dqblk.dqb_bsoftlimit = 818;
111         oqctl.qc_dqblk.dqb_ihardlimit = 616;
112         oqctl.qc_dqblk.dqb_isoftlimit = 515;
113         oqctl.qc_dqblk.dqb_valid = QIF_LIMITS;
114         rc = fsfilt_quotactl(obd, sb, &oqctl);
115         if (rc) {
116                 CERROR("3a: quotactl Q_SETQUOTA failed: %d\n", rc);
117                 RETURN(rc);
118         }
119
120         oqctl.qc_cmd = Q_GETQUOTA;
121         oqctl.qc_type = USRQUOTA;
122         oqctl.qc_id = 500;
123         rc = fsfilt_quotactl(obd, sb, &oqctl);
124         if (rc) {
125                 CERROR("3b: quotactl Q_SETQUOTA failed: %d\n", rc);
126                 RETURN(rc);
127         }
128         if (oqctl.qc_dqblk.dqb_bhardlimit != 919 ||
129             oqctl.qc_dqblk.dqb_bsoftlimit != 818 ||
130             oqctl.qc_dqblk.dqb_ihardlimit != 616 ||
131             oqctl.qc_dqblk.dqb_isoftlimit != 515) {
132                 CERROR("3c: quotactl Q_GETQUOTA get wrong result:"
133                        "%llu, %llu, %llu, %llu\n",
134                        oqctl.qc_dqblk.dqb_bhardlimit,
135                        oqctl.qc_dqblk.dqb_bsoftlimit,
136                        oqctl.qc_dqblk.dqb_ihardlimit,
137                        oqctl.qc_dqblk.dqb_isoftlimit);
138                 RETURN(-EINVAL);
139         }
140
141         oqctl.qc_cmd = Q_SETQUOTA;
142         oqctl.qc_type = USRQUOTA;
143         oqctl.qc_id = 500;
144         oqctl.qc_dqblk.dqb_curspace = 717;
145         oqctl.qc_dqblk.dqb_curinodes = 414;
146         oqctl.qc_dqblk.dqb_valid = QIF_USAGE;
147         rc = fsfilt_quotactl(obd, sb, &oqctl);
148         if (rc) {
149                 CERROR("3d: quotactl Q_SETQUOTA failed: %d\n", rc);
150                 RETURN(rc);
151         }
152
153         oqctl.qc_cmd = Q_GETQUOTA;
154         oqctl.qc_type = USRQUOTA;
155         oqctl.qc_id = 500;
156         rc = fsfilt_quotactl(obd, sb, &oqctl);
157         if (rc) {
158                 CERROR("3e: quotactl Q_SETQUOTA failed: %d\n", rc);
159                 RETURN(rc);
160         }
161         if (oqctl.qc_dqblk.dqb_curspace != 717 ||
162             oqctl.qc_dqblk.dqb_curinodes != 414) {
163                 CERROR("3f: quotactl Q_GETQUOTA get wrong result: %llu, %llu\n",
164                        oqctl.qc_dqblk.dqb_curspace,
165                        oqctl.qc_dqblk.dqb_curinodes);
166                 RETURN(-EINVAL);
167         }
168
169         oqctl.qc_cmd = Q_SETQUOTA;
170         oqctl.qc_type = USRQUOTA;
171         oqctl.qc_dqblk.dqb_btime = 313;
172         oqctl.qc_dqblk.dqb_itime = 212;
173         oqctl.qc_id = 500;
174         oqctl.qc_dqblk.dqb_valid = QIF_TIMES;
175         rc = fsfilt_quotactl(obd, sb, &oqctl);
176         if (rc) {
177                 CERROR("3g: quotactl Q_SETQUOTA failed: %d\n", rc);
178                 RETURN(rc);
179         }
180
181         oqctl.qc_cmd = Q_GETQUOTA;
182         oqctl.qc_type = USRQUOTA;
183         oqctl.qc_id = 500;
184         rc = fsfilt_quotactl(obd, sb, &oqctl);
185         if (rc) {
186                 CERROR("3h: quotactl Q_SETQUOTA failed: %d\n", rc);
187                 RETURN(rc);
188         }
189         if (oqctl.qc_dqblk.dqb_btime != 313 ||
190             oqctl.qc_dqblk.dqb_itime != 212) {
191                 CERROR("3i: quotactl Q_GETQUOTA get wrong result: %llu, %llu\n",
192                        oqctl.qc_dqblk.dqb_btime,
193                        oqctl.qc_dqblk.dqb_itime);
194                 RETURN(-EINVAL);
195         }
196
197         oqctl.qc_cmd = Q_SETQUOTA;
198         oqctl.qc_type = USRQUOTA;
199         oqctl.qc_id = 500;
200         oqctl.qc_dqblk.dqb_bhardlimit = 919;
201         oqctl.qc_dqblk.dqb_bsoftlimit = 818;
202         oqctl.qc_dqblk.dqb_curspace = 717;
203         oqctl.qc_dqblk.dqb_ihardlimit = 616;
204         oqctl.qc_dqblk.dqb_isoftlimit = 515;
205         oqctl.qc_dqblk.dqb_curinodes = 414;
206         oqctl.qc_dqblk.dqb_btime = 313;
207         oqctl.qc_dqblk.dqb_itime = 212;
208         oqctl.qc_dqblk.dqb_valid = QIF_ALL;
209         rc = fsfilt_quotactl(obd, sb, &oqctl);
210         if (rc) {
211                 CERROR("3j: quotactl Q_SETQUOTA failed: %d\n", rc);
212                 RETURN(rc);
213         }
214
215         oqctl.qc_cmd = Q_GETQUOTA;
216         oqctl.qc_type = USRQUOTA;
217         oqctl.qc_id = 500;
218         rc = fsfilt_quotactl(obd, sb, &oqctl);
219         if (rc) {
220                 CERROR("3k: quotactl Q_SETQUOTA failed: %d\n", rc);
221                 RETURN(rc);
222         }
223         if (oqctl.qc_dqblk.dqb_bhardlimit != 919 ||
224             oqctl.qc_dqblk.dqb_bsoftlimit != 818 ||
225             oqctl.qc_dqblk.dqb_ihardlimit != 616 ||
226             oqctl.qc_dqblk.dqb_isoftlimit != 515 ||
227             oqctl.qc_dqblk.dqb_curspace != 717 ||
228             oqctl.qc_dqblk.dqb_curinodes != 414 ||
229             oqctl.qc_dqblk.dqb_btime != 0 ||
230             oqctl.qc_dqblk.dqb_itime != 0) {
231                 CERROR("3l: quotactl Q_GETQUOTA get wrong result:"
232                        "%llu, %llu, %llu, %llu, %llu, %llu, %llu, %llu\n",
233                        oqctl.qc_dqblk.dqb_bhardlimit,
234                        oqctl.qc_dqblk.dqb_bsoftlimit,
235                        oqctl.qc_dqblk.dqb_ihardlimit,
236                        oqctl.qc_dqblk.dqb_isoftlimit,
237                        oqctl.qc_dqblk.dqb_curspace,
238                        oqctl.qc_dqblk.dqb_curinodes,
239                        oqctl.qc_dqblk.dqb_btime,
240                        oqctl.qc_dqblk.dqb_itime);
241                 RETURN(-EINVAL);
242         }
243
244         RETURN(0);
245 }
246
247 /* Test quotaoff */
248 static int quotactl_test_4(struct obd_device *obd, struct super_block *sb)
249 {
250         struct obd_quotactl oqctl;
251         int rc;
252         ENTRY;
253
254         oqctl.qc_cmd = Q_QUOTAOFF;
255         oqctl.qc_id = 500;
256         oqctl.qc_type = UGQUOTA;
257         rc = fsfilt_quotactl(obd, sb, &oqctl);
258         if (rc) {
259                 CERROR("4a: quotactl Q_QUOTAOFF failed: %d\n", rc);
260                 RETURN(rc);
261         }
262
263         RETURN(0);
264 }
265
266 /* -------------------------------------------------------------------------
267  * Tests above, boring obd functions below
268  * ------------------------------------------------------------------------- */
269 static int quotactl_run_tests(struct obd_device *obd, struct obd_device *tgt)
270 {
271         struct super_block *sb;
272         struct obd_run_ctxt saved;
273         int rc;
274         ENTRY;
275
276         if (!strcmp(tgt->obd_type->typ_name, LUSTRE_MDS_NAME))
277                 sb = tgt->u.mds.mds_sb;
278         else if (!strcmp(tgt->obd_type->typ_name, "obdfilter"))
279                 sb = tgt->u.filter.fo_sb;
280         else {
281                 CERROR("TARGET OBD should be mds or obdfilter\n");
282                 RETURN(-EINVAL);
283         }
284
285         push_ctxt(&saved, &tgt->obd_ctxt, NULL);
286
287         rc = quotactl_test_1(tgt, sb);
288         if (rc)
289                 GOTO(cleanup, rc);
290
291 #if 0
292         rc = quotactl_test_2(tgt, sb);
293         if (rc)
294                 GOTO(cleanup, rc);
295 #endif
296
297         rc = quotactl_test_3(tgt, sb);
298         if (rc)
299                 GOTO(cleanup, rc);
300
301  cleanup:
302         quotactl_test_4(tgt, sb);
303
304         pop_ctxt(&saved, &tgt->obd_ctxt, NULL);
305
306         return rc;
307 }
308
309 static int quotactl_test_cleanup(struct obd_device *obd)
310 {
311         lprocfs_obd_cleanup(obd);
312         return 0;
313 }
314
315 static int quotactl_test_setup(struct obd_device *obd, obd_count len, void *buf)
316 {
317         struct lprocfs_static_vars lvars;
318         struct lustre_cfg *lcfg = buf;
319         struct obd_device *tgt;
320         int rc;
321         ENTRY;
322
323         if (lcfg->lcfg_bufcount < 1) {
324                 CERROR("requires a mds OBD name\n");
325                 RETURN(-EINVAL);
326         }
327
328         tgt = class_name2obd(lustre_cfg_string(lcfg, 1));
329         if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) {
330                 CERROR("target device not attached or not set up (%s)\n",
331                        lustre_cfg_string(lcfg, 1));
332                 RETURN(-EINVAL);
333         }
334
335         lprocfs_init_vars(quotactl_test, &lvars);
336         lprocfs_obd_setup(obd, lvars.obd_vars);
337
338         rc = quotactl_run_tests(obd, tgt);
339
340         quotactl_test_cleanup(obd);
341
342         RETURN(rc);
343 }
344
345 static struct obd_ops quotactl_obd_ops = {
346         .o_owner       = THIS_MODULE,
347         .o_setup       = quotactl_test_setup,
348         .o_cleanup     = quotactl_test_cleanup,
349 };
350
351 static struct lprocfs_vars lprocfs_obd_vars[] = { {0} };
352 static struct lprocfs_vars lprocfs_module_vars[] = { {0} };
353 LPROCFS_INIT_VARS(quotactl_test, lprocfs_module_vars, lprocfs_obd_vars)
354
355 static int __init quotactl_test_init(void)
356 {
357         struct lprocfs_static_vars lvars;
358
359         lprocfs_init_vars(quotactl_test, &lvars);
360         return class_register_type(&quotactl_obd_ops, lvars.module_vars,
361                                    "quotactl_test");
362 }
363
364 static void __exit quotactl_test_exit(void)
365 {
366         class_unregister_type("quotactl_test");
367 }
368
369 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
370 MODULE_DESCRIPTION("quotactl test module");
371 MODULE_LICENSE("GPL");
372
373 module_init(quotactl_test_init);
374 module_exit(quotactl_test_exit);