Whamcloud - gitweb
Make obdecho return 64-bit objids so we can check 64-bit paths better.
[fs/lustre-release.git] / lustre / obdecho / echo.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  linux/fs/obdecho/echo.c
5  *
6  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
7  *
8  * This code is issued under the GNU General Public License.
9  * See the file COPYING in this distribution
10  *
11  * by Peter Braam <braam@clusterfs.com>
12  * and Andreas Dilger <adilger@clusterfs.com>
13  */
14
15 static char rcsid[] __attribute ((unused)) = "$Id: echo.c,v 1.33 2002/09/06 22:23:49 adilger Exp $";
16 #define OBDECHO_VERSION "$Revision: 1.33 $"
17
18 #define EXPORT_SYMTAB
19
20 #include <linux/version.h>
21 #include <linux/module.h>
22 #include <linux/fs.h>
23 #include <linux/stat.h>
24 #include <linux/locks.h>
25 #include <linux/ext2_fs.h>
26 #include <linux/quotaops.h>
27 #include <linux/proc_fs.h>
28 #include <linux/init.h>
29 #include <asm/unistd.h>
30
31 #define DEBUG_SUBSYSTEM S_ECHO
32
33 #include <linux/obd_support.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_echo.h>
36 #include <linux/lustre_debug.h>
37 #include <linux/lustre_dlm.h>
38
39 extern struct obd_device obd_dev[MAX_OBD_DEVICES];
40
41 static atomic_t echo_page_rws;
42 static atomic_t echo_getattrs;
43
44 #define ECHO_PROC_STAT "sys/obdecho"
45 #define ECHO_INIT_OBJID 0x1000000000000000ULL
46
47 int echo_proc_read(char *page, char **start, off_t off, int count, int *eof,
48                    void *data)
49 {
50         long long attrs = atomic_read(&echo_getattrs);
51         long long pages = atomic_read(&echo_page_rws);
52         int len;
53
54         *eof = 1;
55         if (off != 0)
56                 return (0);
57
58         len = sprintf(page, "%Ld %Ld\n", attrs, pages);
59
60         *start = page;
61         return (len);
62 }
63
64 int echo_proc_write(struct file *file, const char *ubuffer,
65                     unsigned long count, void *data)
66 {
67         /* Ignore what we've been asked to write, and just zero the counters */
68         atomic_set (&echo_page_rws, 0);
69         atomic_set (&echo_getattrs, 0);
70
71         return (count);
72 }
73
74 void echo_proc_init(void)
75 {
76         struct proc_dir_entry *entry;
77
78         entry = create_proc_entry(ECHO_PROC_STAT, S_IFREG|S_IRUGO|S_IWUSR,NULL);
79
80         if (entry == NULL) {
81                 CERROR("couldn't create proc entry %s\n", ECHO_PROC_STAT);
82                 return;
83         }
84
85         entry->data = NULL;
86         entry->read_proc = echo_proc_read;
87         entry->write_proc = echo_proc_write;
88 }
89
90 void echo_proc_fini(void)
91 {
92         remove_proc_entry(ECHO_PROC_STAT, 0);
93 }
94
95 static int echo_connect(struct lustre_handle *conn, struct obd_device *obd,
96                         uuid_t cluuid)
97 {
98         int rc;
99
100         MOD_INC_USE_COUNT;
101         rc = class_connect(conn, obd, cluuid);
102
103         if (rc)
104                 MOD_DEC_USE_COUNT;
105
106         return rc;
107 }
108
109 static int echo_disconnect(struct lustre_handle *conn)
110 {
111         int rc;
112
113         rc = class_disconnect(conn);
114         if (!rc)
115                 MOD_DEC_USE_COUNT;
116
117         return rc;
118 }
119
120 static __u64 echo_next_id(struct obd_device *obddev)
121 {
122         obd_id id;
123
124         spin_lock(&obddev->u.echo.eo_lock);
125         id = ++obddev->u.echo.eo_lastino;
126         spin_unlock(&obddev->u.echo.eo_lock);
127
128         return id;
129 }
130
131 int echo_create(struct lustre_handle *conn, struct obdo *oa,
132                 struct lov_stripe_md **ea)
133 {
134         struct obd_device *obd = class_conn2obd(conn);
135
136         if (!obd) {
137                 CERROR("invalid client %Lx\n", conn->addr);
138                 return -EINVAL;
139         }
140
141         if (!(oa->o_mode && S_IFMT)) {
142                 CERROR("filter obd: no type!\n");
143                 return -ENOENT;
144         }
145
146         if (!(oa->o_valid & OBD_MD_FLMODE)) {
147                 CERROR("invalid o_valid %08x\n", oa->o_valid);
148                 return -EINVAL;
149         }
150
151         oa->o_id = echo_next_id(obd);
152         oa->o_valid = OBD_MD_FLID;
153         atomic_inc(&obd->u.echo.eo_create);
154
155         return 0;
156 }
157
158 int echo_destroy(struct lustre_handle *conn, struct obdo *oa,
159                  struct lov_stripe_md *ea)
160 {
161         struct obd_device *obd = class_conn2obd(conn);
162
163         if (!obd) {
164                 CERROR("invalid client "LPX64"\n", conn->addr);
165                 RETURN(-EINVAL);
166         }
167
168         if (!(oa->o_valid & OBD_MD_FLID)) {
169                 CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
170                 RETURN(-EINVAL);
171         }
172
173         if (oa->o_id > obd->u.echo.eo_lastino || oa->o_id < ECHO_INIT_OBJID) {
174                 CERROR("bad destroy objid: 0x"LPX64"\n", oa->o_id);
175                 RETURN(-EINVAL);
176         }
177
178         atomic_inc(&obd->u.echo.eo_destroy);
179
180         return 0;
181 }
182
183 static int echo_getattr(struct lustre_handle *conn, struct obdo *oa,
184                         struct lov_stripe_md *md)
185 {
186         struct obd_device *obd = class_conn2obd(conn);
187         obd_id id = oa->o_id;
188
189         if (!obd) {
190                 CERROR("invalid client "LPX64"\n", conn->addr);
191                 RETURN(-EINVAL);
192         }
193
194         if (!(oa->o_valid & OBD_MD_FLID)) {
195                 CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
196                 RETURN(-EINVAL);
197         }
198
199         memcpy(oa, &obd->u.echo.oa, sizeof(*oa));
200         oa->o_id = id;
201         oa->o_valid |= OBD_MD_FLID;
202
203         atomic_inc(&echo_getattrs);
204
205         return 0;
206 }
207
208 static int echo_setattr(struct lustre_handle *conn, struct obdo *oa,
209                         struct lov_stripe_md *md)
210 {
211         struct obd_device *obd = class_conn2obd(conn);
212
213         if (!obd) {
214                 CERROR("invalid client "LPX64"\n", conn->addr);
215                 RETURN(-EINVAL);
216         }
217
218         if (!(oa->o_valid & OBD_MD_FLID)) {
219                 CERROR("obdo missing FLID valid flag: %08x\n", oa->o_valid);
220                 RETURN(-EINVAL);
221         }
222
223         memcpy(&obd->u.echo.oa, oa, sizeof(*oa));
224
225         atomic_inc(&obd->u.echo.eo_setattr);
226
227         return 0;
228 }
229
230 /* This allows us to verify that desc_private is passed unmolested */
231 #define DESC_PRIV 0x10293847
232
233 int echo_preprw(int cmd, struct lustre_handle *conn, int objcount,
234                 struct obd_ioobj *obj, int niocount, struct niobuf_remote *nb,
235                 struct niobuf_local *res, void **desc_private)
236 {
237         struct obd_device *obd;
238         struct niobuf_local *r = res;
239         int rc = 0;
240         int i;
241
242         ENTRY;
243
244         obd = class_conn2obd(conn);
245         if (!obd) {
246                 CERROR("invalid client "LPX64"\n", conn->addr);
247                 RETURN(-EINVAL);
248         }
249
250         memset(res, 0, sizeof(*res) * niocount);
251
252         CDEBUG(D_PAGE, "%s %d obdos with %d IOs\n",
253                cmd == OBD_BRW_READ ? "reading" : "writing", objcount, niocount);
254
255         *desc_private = (void *)DESC_PRIV;
256
257         for (i = 0; i < objcount; i++, obj++) {
258                 int gfp_mask = (obj->ioo_id & 1) ? GFP_HIGHUSER : GFP_KERNEL;
259                 int verify = obj->ioo_id != 0;
260                 int j;
261
262                 for (j = 0 ; j < obj->ioo_bufcnt ; j++, nb++, r++) {
263                         r->page = alloc_pages(gfp_mask, 0);
264                         if (!r->page) {
265                                 CERROR("can't get page %d/%d for id "LPU64"\n",
266                                        j, obj->ioo_bufcnt, obj->ioo_id);
267                                 GOTO(preprw_cleanup, rc = -ENOMEM);
268                         }
269                         atomic_inc(&obd->u.echo.eo_prep);
270
271                         r->offset = nb->offset;
272                         r->addr = kmap(r->page);
273                         r->len = nb->len;
274
275                         CDEBUG(D_PAGE, "$$$$ get page %p, addr %p@"LPU64"\n",
276                                r->page, r->addr, r->offset);
277
278                         if (verify && cmd == OBD_BRW_READ)
279                                 page_debug_setup(r->addr, r->len, r->offset,
280                                                  obj->ioo_id);
281                         else if (verify)
282                                 page_debug_setup(r->addr, r->len,
283                                                  0xecc0ecc0ecc0ecc0,
284                                                  0xecc0ecc0ecc0ecc0);
285                 }
286         }
287         CDEBUG(D_PAGE, "%d pages allocated after prep\n",
288                atomic_read(&obd->u.echo.eo_prep));
289
290         RETURN(0);
291
292 preprw_cleanup:
293         /* It is possible that we would rather handle errors by  allow
294          * any already-set-up pages to complete, rather than tearing them
295          * all down again.  I believe that this is what the in-kernel
296          * prep/commit operations do.
297          */
298         CERROR("cleaning up %ld pages (%d obdos)\n", (long)(r - res), objcount);
299         while (r-- > res) {
300                 kunmap(r->page);
301                 __free_pages(r->page, 0);
302                 atomic_dec(&obd->u.echo.eo_prep);
303         }
304         memset(res, 0, sizeof(*res) * niocount);
305
306         return rc;
307 }
308
309 int echo_commitrw(int cmd, struct lustre_handle *conn, int objcount,
310                   struct obd_ioobj *obj, int niocount, struct niobuf_local *res,
311                   void *desc_private)
312 {
313         struct obd_device *obd;
314         struct niobuf_local *r = res;
315         int rc = 0;
316         int i;
317         ENTRY;
318
319         obd = class_conn2obd(conn);
320         if (!obd) {
321                 CERROR("invalid client "LPX64"\n", conn->addr);
322                 RETURN(-EINVAL);
323         }
324
325         if ((cmd & OBD_BRW_RWMASK) == OBD_BRW_READ) {
326                 CDEBUG(D_PAGE, "reading %d obdos with %d IOs\n",
327                        objcount, niocount);
328         } else {
329                 CDEBUG(D_PAGE, "writing %d obdos with %d IOs\n",
330                        objcount, niocount);
331         }
332
333         if (niocount && !r) {
334                 CERROR("NULL res niobuf with niocount %d\n", niocount);
335                 RETURN(-EINVAL);
336         }
337
338         LASSERT(desc_private == (void *)DESC_PRIV);
339
340         for (i = 0; i < objcount; i++, obj++) {
341                 int verify = obj->ioo_id != 0;
342                 int j;
343
344                 for (j = 0 ; j < obj->ioo_bufcnt ; j++, r++) {
345                         struct page *page = r->page;
346                         void *addr;
347
348                         if (!page || !(addr = page_address(page)) ||
349                             !kern_addr_valid(addr)) {
350
351                                 CERROR("bad page objid "LPU64":%p, buf %d/%d\n",
352                                        obj->ioo_id, page, j, obj->ioo_bufcnt);
353                                 GOTO(commitrw_cleanup, rc = -EFAULT);
354                         }
355
356                         atomic_inc(&echo_page_rws);
357
358                         CDEBUG(D_PAGE, "$$$$ use page %p, addr %p@"LPU64"\n",
359                                r->page, addr, r->offset);
360
361                         if (verify)
362                                 page_debug_check("echo", addr, r->len,
363                                                  r->offset, obj->ioo_id);
364
365                         kunmap(page);
366                         __free_pages(page, 0);
367                         atomic_dec(&obd->u.echo.eo_prep);
368                 }
369         }
370         CDEBUG(D_PAGE, "%d pages remain after commit\n",
371                atomic_read(&obd->u.echo.eo_prep));
372         RETURN(0);
373
374 commitrw_cleanup:
375         CERROR("cleaning up %ld pages (%d obdos)\n",
376                niocount - (long)(r - res) - 1, objcount);
377         while (++r < res + niocount) {
378                 struct page *page = r->page;
379
380                 kunmap(page);
381                 __free_pages(page, 0);
382                 atomic_dec(&obd->u.echo.eo_prep);
383         }
384         return rc;
385 }
386
387 static int echo_setup(struct obd_device *obddev, obd_count len, void *buf)
388 {
389         ENTRY;
390
391         obddev->obd_namespace =
392                 ldlm_namespace_new("echo-tgt", LDLM_NAMESPACE_SERVER);
393         if (obddev->obd_namespace == NULL) {
394                 LBUG();
395                 RETURN(-ENOMEM);
396         }
397         obddev->u.echo.eo_lastino = ECHO_INIT_OBJID;
398
399         RETURN(0);
400 }
401
402 static int echo_cleanup(struct obd_device *obddev)
403 {
404         ENTRY;
405
406         ldlm_namespace_free(obddev->obd_namespace);
407         CERROR("%d prep/commitrw pages leaked\n",
408                atomic_read(&obddev->u.echo.eo_prep));
409
410         RETURN(0);
411 }
412
413 struct obd_ops echo_obd_ops = {
414         o_connect:      echo_connect,
415         o_disconnect:   echo_disconnect,
416         o_create:       echo_create,
417         o_destroy:      echo_destroy,
418         o_getattr:      echo_getattr,
419         o_setattr:      echo_setattr,
420         o_preprw:       echo_preprw,
421         o_commitrw:     echo_commitrw,
422         o_setup:        echo_setup,
423         o_cleanup:      echo_cleanup
424 };
425
426 static int __init obdecho_init(void)
427 {
428         printk(KERN_INFO "Echo OBD driver " OBDECHO_VERSION
429                " info@clusterfs.com\n");
430
431         echo_proc_init();
432
433         return class_register_type(&echo_obd_ops, OBD_ECHO_DEVICENAME);
434 }
435
436 static void __exit obdecho_exit(void)
437 {
438         echo_proc_fini();
439
440         class_unregister_type(OBD_ECHO_DEVICENAME);
441 }
442
443 MODULE_AUTHOR("Cluster Filesystems Inc. <info@clusterfs.com>");
444 MODULE_DESCRIPTION("Lustre Testing Echo OBD driver " OBDECHO_VERSION);
445 MODULE_LICENSE("GPL");
446
447 module_init(obdecho_init);
448 module_exit(obdecho_exit);