Whamcloud - gitweb
Update <linux/malloc.h> to <linux/slab.h>.
[fs/lustre-release.git] / lustre / obdfs / super.c
1 /*
2  * OBDFS Super operations
3  *
4  * Copryright (C) 1996 Peter J. Braam <braam@stelias.com>
5  * Copryright (C) 1999 Stelias Computing Inc. <braam@stelias.com>
6  * Copryright (C) 1999 Seagate Technology Inc.
7  * Copryright (C) 2001 Mountain View Data, Inc.
8  *
9  */
10
11 #define EXPORT_SYMTAB
12
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/mm.h>
17 #include <linux/string.h>
18 #include <linux/stat.h>
19 #include <linux/errno.h>
20 #include <linux/locks.h>
21 #include <linux/unistd.h>
22
23 #include <asm/system.h>
24 #include <asm/uaccess.h>
25
26 #include <linux/fs.h>
27 #include <linux/stat.h>
28 #include <asm/uaccess.h>
29 #include <linux/vmalloc.h>
30 #include <asm/segment.h>
31
32 #include <linux/obd_support.h>
33 #include <linux/obd_class.h>
34 #include <linux/obdfs.h>
35
36 struct list_head obdfs_super_list;
37 struct address_space_operations obdfs_aops;
38 struct super_operations obdfs_super_operations;
39 long obdfs_cache_count = 0;
40 long obdfs_mutex_start = 0;
41 long obd_memory = 0;
42
43 static char *obdfs_read_opt(const char *opt, char *data)
44 {
45         char *value;
46         char *retval;
47
48         CDEBUG(D_INFO, "option: %s, data %s\n", opt, data);
49         if ( strncmp(opt, data, strlen(opt)) )
50                 return NULL;
51
52         if ( (value = strchr(data, '=')) == NULL )
53                 return NULL;
54
55         value++;
56         OBD_ALLOC(retval, char *, strlen(value) + 1);
57         if ( !retval ) {
58                 printk(KERN_ALERT __FUNCTION__ ": out of memory!\n");
59                 return NULL;
60         }
61         
62         memcpy(retval, value, strlen(value)+1);
63         CDEBUG(D_PSDEV, "Assigned option: %s, value %s\n", opt, retval);
64         return retval;
65 }
66
67 static void obdfs_options(char *options, char **dev, char **vers)
68 {
69         char *this_char;
70
71         if (!options)
72                 return;
73
74         for (this_char = strtok (options, ",");
75              this_char != NULL;
76              this_char = strtok (NULL, ",")) {
77                 CDEBUG(D_INFO, "this_char %s\n", this_char);
78                 if ( (!*dev && (*dev = obdfs_read_opt("device", this_char)))||
79                      (!*vers && (*vers = obdfs_read_opt("version", this_char))) )
80                         continue;
81                 
82         }
83 }
84
85 static int obdfs_getdev(char *devpath, int *dev)
86 {
87         struct dentry *dentry;
88         kdev_t devno;
89         struct nameidata nd;
90         int error = 0; 
91
92         ENTRY;
93         if (path_init(devpath, LOOKUP_POSITIVE, &nd))
94                 error = path_walk(devpath, &nd);
95         if (error)
96                 return error;
97
98         dentry = nd.dentry;
99         if (!S_ISCHR(dentry->d_inode->i_mode))
100                 return -ENODEV;
101
102         devno = dentry->d_inode->i_rdev;
103         if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) 
104                 return -ENODEV;
105         
106         if ( MINOR(devno) >= MAX_OBD_DEVICES ) 
107                 return -ENODEV;
108
109         *dev = devno;
110         return 0;
111 }
112
113
114 static struct super_block * obdfs_read_super(struct super_block *sb, 
115                                             void *data, int silent)
116 {
117         struct inode *root = 0; 
118         struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)(&sb->u.generic_sbp);
119         struct obd_device *obddev;
120         char *device = NULL;
121         char *version = NULL;
122         int devno;
123         int err;
124         unsigned long blocksize;
125         unsigned long blocksize_bits;
126         unsigned long root_ino;
127         int scratch;
128         
129
130         ENTRY;
131         MOD_INC_USE_COUNT; 
132         
133         memset(sbi, 0, sizeof(*sbi));
134         
135         CDEBUG(D_INFO, "\n"); 
136         obdfs_options(data, &device, &version);
137         if ( !device ) {
138                 printk(__FUNCTION__ ": no device\n");
139                 EXIT;
140                 goto ERR;
141         }
142
143         CDEBUG(D_INFO, "\n"); 
144         if ( (err = obdfs_getdev(device, &devno)) ) {
145                 printk("Cannot get devno of %s, error %d\n", device, err);
146                 EXIT;
147                 goto ERR;;
148         }
149
150         CDEBUG(D_INFO, "\n"); 
151         if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) {
152                 printk(__FUNCTION__ ": wrong major number %d!\n", MAJOR(devno));
153                 EXIT;
154                 goto ERR;
155         }
156                 
157         CDEBUG(D_INFO, "\n"); 
158         if ( MINOR(devno) >= MAX_OBD_DEVICES ) {
159                 printk(__FUNCTION__ ": minor of %s too high (%d)\n",
160                        device, MINOR(devno));
161                 EXIT;
162                 goto ERR;
163         } 
164
165         CDEBUG(D_INFO, "\n"); 
166         obddev = &obd_dev[MINOR(devno)];
167
168         CDEBUG(D_INFO, "\n"); 
169         if ( ! (obddev->obd_flags & OBD_ATTACHED) || 
170              ! (obddev->obd_flags & OBD_SET_UP) ){
171                 printk("device %s not attached or not set up (%d)\n", 
172                        device, MINOR(devno));
173                 EXIT;
174                 goto ERR;;
175         } 
176
177         CDEBUG(D_INFO, "\n"); 
178         sbi->osi_obd = obddev;
179         sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops;
180         
181         sbi->osi_conn.oc_dev = obddev;
182         err = sbi->osi_ops->o_connect(&sbi->osi_conn);
183         if ( err ) {
184                 printk("OBDFS: cannot connect to %s\n", device);
185                 EXIT;
186                 goto ERR;
187         }
188
189         CDEBUG(D_INFO, "\n"); 
190         /* list of dirty inodes, and a mutex to hold while modifying it */
191         INIT_LIST_HEAD(&sbi->osi_inodes);
192         sema_init(&sbi->osi_list_mutex, 1);
193
194         CDEBUG(D_INFO, "\n"); 
195         sbi->osi_super = sb;
196
197         CDEBUG(D_INFO, "\n"); 
198         err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize"),
199                                        "blocksize", &scratch,
200                                        (void *)&blocksize);
201         if ( err ) {
202                 printk("getinfo call to drive failed (blocksize)\n");
203                 EXIT;
204                 goto ERR;
205         }
206
207         CDEBUG(D_INFO, "\n"); 
208         err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize_bits"),
209                                        "blocksize_bits", &scratch,
210                                        (void *)&blocksize_bits);
211         if ( err ) {
212                 printk("getinfo call to drive failed (blocksize_bits)\n");
213                 EXIT;
214                 goto ERR;
215         }
216
217         CDEBUG(D_INFO, "\n"); 
218         err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("root_ino"), 
219                                        "root_ino", &scratch, (void *)&root_ino);
220         if ( err ) {
221                 printk("getinfo call to drive failed (root_ino)\n");
222                 EXIT;
223                 goto ERR;
224         }
225         
226         CDEBUG(D_INFO, "\n"); 
227         sb->s_blocksize = blocksize;
228         sb->s_blocksize_bits = (unsigned char)blocksize_bits;
229         sb->s_magic = OBDFS_SUPER_MAGIC;
230         sb->s_op = &obdfs_super_operations;
231
232         /* XXX how to get "sb->s_flags |= MS_RDONLY" here for snapshots? */
233
234         /* make root inode */
235         CDEBUG(D_INFO, "\n"); 
236         root = iget(sb, root_ino);
237         if (!root || is_bad_inode(root)) {
238             printk("OBDFS: bad iget for root\n");
239             sb->s_dev = 0;
240             err = -ENOENT;
241             EXIT;
242             goto ERR;
243         } 
244         
245         CDEBUG(D_INFO, "obdfs_read_super: sbdev %d, rootino: %ld, dev %s, "
246                "minor: %d, blocksize: %ld, blocksize bits %ld\n", 
247                sb->s_dev, root->i_ino, device, MINOR(devno), 
248                blocksize, blocksize_bits);
249         sb->s_root = d_alloc_root(root);
250         list_add(&sbi->osi_list, &obdfs_super_list);
251         OBD_FREE(device, strlen(device) + 1);
252         if (version)
253                 OBD_FREE(version, strlen(version) + 1);
254         EXIT;  
255         return sb;
256
257 ERR:
258         MOD_DEC_USE_COUNT;
259         if (device)
260                 OBD_FREE(device, strlen(device) + 1);
261         if (version)
262                 OBD_FREE(version, strlen(version) + 1);
263         if (sbi) {
264                 sbi->osi_super = NULL;
265         }
266         if (root) {
267                 iput(root);
268         }
269         sb->s_dev = 0;
270         return NULL;
271 } /* obdfs_read_super */
272
273
274 static void obdfs_put_super(struct super_block *sb)
275 {
276         struct obdfs_sb_info *sbi;
277
278         ENTRY;
279         sb->s_dev = 0;
280         
281         sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp;
282         obdfs_flush_reqs(&sbi->osi_inodes, ~0UL);
283
284         OPS(sb,disconnect)(ID(sb));
285         list_del(&sbi->osi_list);
286         memset(sbi, 0, sizeof(*sbi));
287         
288         printk(KERN_INFO "OBDFS: Bye bye.\n");
289
290         MOD_DEC_USE_COUNT;
291         EXIT;
292 } /* obdfs_put_super */
293
294
295 /* all filling in of inodes postponed until lookup */
296 static void obdfs_read_inode(struct inode *inode)
297 {
298         struct obdo *oa;
299         ENTRY;
300         oa = obdo_fromid(IID(inode), inode->i_ino,
301                          OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS);
302         if ( IS_ERR(oa) ) {
303                 printk(__FUNCTION__ ": obdo_fromid failed\n");
304                 EXIT;
305                 return /* PTR_ERR(oa) */;
306         }
307
308         ODEBUG(oa);
309         obdfs_to_inode(inode, oa);
310         INIT_LIST_HEAD(obdfs_iplist(inode)); /* list of dirty pages on inode */
311         INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */
312
313         obdo_free(oa);
314         /* OIDEBUG(inode); */
315
316         if (S_ISREG(inode->i_mode)) {
317                 inode->i_op = &obdfs_file_inode_operations;
318                 inode->i_fop = &obdfs_file_operations;
319                 inode->i_mapping->a_ops = &obdfs_aops;
320                 EXIT;
321         } else if (S_ISDIR(inode->i_mode)) {
322                 inode->i_op = &obdfs_dir_inode_operations;
323                 inode->i_fop = &obdfs_dir_operations; 
324                 EXIT;
325         } else if (S_ISLNK(inode->i_mode)) {
326                 if (inode->i_blocks) { 
327                         inode->i_op = &obdfs_symlink_inode_operations;
328                         inode->i_mapping->a_ops = &obdfs_aops;
329                 }else {
330                         inode->i_op = &obdfs_fast_symlink_inode_operations;
331                 }
332                 EXIT;
333         } else {
334                 init_special_inode(inode, inode->i_mode,
335                                    ((int *)obdfs_i2info(inode)->oi_inline)[0]);
336         }
337
338         return;
339 }
340
341 static void obdfs_write_inode(struct inode *inode, int wait) 
342 {
343         struct obdo *oa;
344         int err;
345         
346         ENTRY;
347         if (IOPS(inode, setattr) == NULL) {
348                 printk(KERN_ERR __FUNCTION__ ": no setattr method!\n");
349                 EXIT;
350                 return;
351         }
352         oa = obdo_alloc();
353         if ( !oa ) {
354                 printk(__FUNCTION__ ": obdo_alloc failed\n");
355                 EXIT;
356                 return;
357         }
358
359         oa->o_valid = OBD_MD_FLNOTOBD;
360         obdfs_from_inode(oa, inode);
361         err = IOPS(inode, setattr)(IID(inode), oa);
362
363         if ( err )
364                 printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err);
365
366         EXIT;
367         obdo_free(oa);
368 } /* obdfs_write_inode */
369
370
371 /* This routine is called from iput() (for each unlink on the inode).
372  * We can't put this call into delete_inode() since that is called only
373  * when i_count == 0, and we need to keep a reference on the inode while
374  * it is in the page cache, which means i_count > 0.  Catch 22.
375  */
376 static void obdfs_put_inode(struct inode *inode)
377 {
378         ENTRY;
379         if (inode->i_nlink) {
380                 EXIT;
381                 return;
382         }
383
384         obdfs_dequeue_pages(inode);
385         EXIT;
386 } /* obdfs_put_inode */
387
388
389 static void obdfs_delete_inode(struct inode *inode)
390 {
391         struct obdo *oa;
392         int err;
393
394         ENTRY;
395         if (IOPS(inode, destroy) == NULL) {
396                 printk(KERN_ERR __FUNCTION__ ": no destroy method!\n");
397                 EXIT;
398                 return;
399         }
400
401         oa = obdo_alloc();
402         if ( !oa ) {
403                 printk(__FUNCTION__ ": obdo_alloc failed\n");
404                 EXIT;
405                 return;
406         }
407         oa->o_valid = OBD_MD_FLNOTOBD;
408         obdfs_from_inode(oa, inode);
409
410         ODEBUG(oa);
411         err = IOPS(inode, destroy)(IID(inode), oa);
412         obdo_free(oa);
413         clear_inode(inode);
414         if (err) {
415                 printk(__FUNCTION__ ": obd_destroy fails (%d)\n", err);
416                 EXIT;
417                 return;
418         }
419
420         EXIT;
421 } /* obdfs_delete_inode */
422
423
424 int obdfs_notify_change(struct dentry *de, struct iattr *attr)
425 {
426         struct inode *inode = de->d_inode;
427         struct obdo *oa;
428         int err;
429
430         ENTRY;
431         if (IOPS(inode, setattr) == NULL) {
432                 printk(KERN_ERR __FUNCTION__ ": no setattr method!\n");
433                 EXIT;
434                 return -EIO;
435         }
436         oa = obdo_alloc();
437         if ( !oa ) {
438                 printk(__FUNCTION__ ": obdo_alloc failed\n");
439                 return -ENOMEM;
440         }
441
442         oa->o_id = inode->i_ino;
443         obdo_from_iattr(oa, attr);
444         err = IOPS(inode, setattr)(IID(inode), oa);
445
446         if ( err )
447                 printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err);
448
449         EXIT;
450         obdo_free(oa);
451         return err;
452 } /* obdfs_notify_change */
453
454
455 static int obdfs_statfs(struct super_block *sb, struct statfs *buf)
456 {
457         struct statfs tmp;
458         int bufsize = sizeof(*buf);
459         int err;
460
461         ENTRY;
462
463         err = OPS(sb,statfs)(ID(sb), &tmp);
464         if ( err ) { 
465                 printk(__FUNCTION__ ": obd_statfs fails (%d)\n", err);
466                 return err;
467         }
468         copy_to_user(buf, &tmp, (bufsize<sizeof(tmp)) ? bufsize : sizeof(tmp));
469
470         EXIT;
471
472         return err; 
473 }
474
475 /* exported operations */
476 struct super_operations obdfs_super_operations =
477 {
478         read_inode: obdfs_read_inode,
479         write_inode: obdfs_write_inode,
480         put_inode: obdfs_put_inode,
481         delete_inode: obdfs_delete_inode,
482         put_super: obdfs_put_super,
483         statfs: obdfs_statfs
484 };
485
486 struct file_system_type obdfs_fs_type = {
487    "obdfs", 0, obdfs_read_super, NULL
488 };
489
490 int init_obdfs(void)
491 {
492         int err;
493
494         printk(KERN_INFO "OBDFS v0.1, braam@stelias.com\n");
495
496         obdfs_sysctl_init();
497
498         INIT_LIST_HEAD(&obdfs_super_list);
499         err = obdfs_init_pgrqcache();
500         if (err)
501                 return err;
502
503         obdfs_flushd_init();
504         return register_filesystem(&obdfs_fs_type);
505 }
506
507 struct address_space_operations obdfs_aops = {
508         readpage: obdfs_readpage,
509         writepage: obdfs_writepage,
510         sync_page: block_sync_page,
511         prepare_write: obdfs_prepare_write, 
512         commit_write: obdfs_commit_write,
513         bmap: NULL
514 };
515
516
517 #ifdef MODULE
518 int init_module(void)
519 {
520         return init_obdfs();
521 }
522
523 void cleanup_module(void)
524 {
525         ENTRY;
526
527         obdfs_flushd_cleanup();
528         obdfs_sysctl_clean();
529         obdfs_cleanup_pgrqcache();
530         unregister_filesystem(&obdfs_fs_type);
531         CDEBUG(D_MALLOC, "OBDFS mem used %ld\n", obd_memory);
532         EXIT;
533 }
534
535 #endif