libceph: remove 'osdtimeout' option
[linux-2.6.git] / fs / ceph / super.c
1
2 #include <linux/ceph/ceph_debug.h>
3
4 #include <linux/backing-dev.h>
5 #include <linux/ctype.h>
6 #include <linux/fs.h>
7 #include <linux/inet.h>
8 #include <linux/in6.h>
9 #include <linux/module.h>
10 #include <linux/mount.h>
11 #include <linux/parser.h>
12 #include <linux/sched.h>
13 #include <linux/seq_file.h>
14 #include <linux/slab.h>
15 #include <linux/statfs.h>
16 #include <linux/string.h>
17
18 #include "super.h"
19 #include "mds_client.h"
20
21 #include <linux/ceph/decode.h>
22 #include <linux/ceph/mon_client.h>
23 #include <linux/ceph/auth.h>
24 #include <linux/ceph/debugfs.h>
25
26 /*
27  * Ceph superblock operations
28  *
29  * Handle the basics of mounting, unmounting.
30  */
31
32 /*
33  * super ops
34  */
35 static void ceph_put_super(struct super_block *s)
36 {
37         struct ceph_fs_client *fsc = ceph_sb_to_client(s);
38
39         dout("put_super\n");
40         ceph_mdsc_close_sessions(fsc->mdsc);
41
42         /*
43          * ensure we release the bdi before put_anon_super releases
44          * the device name.
45          */
46         if (s->s_bdi == &fsc->backing_dev_info) {
47                 bdi_unregister(&fsc->backing_dev_info);
48                 s->s_bdi = NULL;
49         }
50
51         return;
52 }
53
54 static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
55 {
56         struct ceph_fs_client *fsc = ceph_inode_to_client(dentry->d_inode);
57         struct ceph_monmap *monmap = fsc->client->monc.monmap;
58         struct ceph_statfs st;
59         u64 fsid;
60         int err;
61
62         dout("statfs\n");
63         err = ceph_monc_do_statfs(&fsc->client->monc, &st);
64         if (err < 0)
65                 return err;
66
67         /* fill in kstatfs */
68         buf->f_type = CEPH_SUPER_MAGIC;  /* ?? */
69
70         /*
71          * express utilization in terms of large blocks to avoid
72          * overflow on 32-bit machines.
73          */
74         buf->f_bsize = 1 << CEPH_BLOCK_SHIFT;
75         buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10);
76         buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
77         buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10);
78
79         buf->f_files = le64_to_cpu(st.num_objects);
80         buf->f_ffree = -1;
81         buf->f_namelen = NAME_MAX;
82         buf->f_frsize = PAGE_CACHE_SIZE;
83
84         /* leave fsid little-endian, regardless of host endianness */
85         fsid = *(u64 *)(&monmap->fsid) ^ *((u64 *)&monmap->fsid + 1);
86         buf->f_fsid.val[0] = fsid & 0xffffffff;
87         buf->f_fsid.val[1] = fsid >> 32;
88
89         return 0;
90 }
91
92
93 static int ceph_sync_fs(struct super_block *sb, int wait)
94 {
95         struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
96
97         if (!wait) {
98                 dout("sync_fs (non-blocking)\n");
99                 ceph_flush_dirty_caps(fsc->mdsc);
100                 dout("sync_fs (non-blocking) done\n");
101                 return 0;
102         }
103
104         dout("sync_fs (blocking)\n");
105         ceph_osdc_sync(&fsc->client->osdc);
106         ceph_mdsc_sync(fsc->mdsc);
107         dout("sync_fs (blocking) done\n");
108         return 0;
109 }
110
111 /*
112  * mount options
113  */
114 enum {
115         Opt_wsize,
116         Opt_rsize,
117         Opt_rasize,
118         Opt_caps_wanted_delay_min,
119         Opt_caps_wanted_delay_max,
120         Opt_cap_release_safety,
121         Opt_readdir_max_entries,
122         Opt_readdir_max_bytes,
123         Opt_congestion_kb,
124         Opt_last_int,
125         /* int args above */
126         Opt_snapdirname,
127         Opt_last_string,
128         /* string args above */
129         Opt_dirstat,
130         Opt_nodirstat,
131         Opt_rbytes,
132         Opt_norbytes,
133         Opt_asyncreaddir,
134         Opt_noasyncreaddir,
135         Opt_dcache,
136         Opt_nodcache,
137         Opt_ino32,
138         Opt_noino32,
139 };
140
141 static match_table_t fsopt_tokens = {
142         {Opt_wsize, "wsize=%d"},
143         {Opt_rsize, "rsize=%d"},
144         {Opt_rasize, "rasize=%d"},
145         {Opt_caps_wanted_delay_min, "caps_wanted_delay_min=%d"},
146         {Opt_caps_wanted_delay_max, "caps_wanted_delay_max=%d"},
147         {Opt_cap_release_safety, "cap_release_safety=%d"},
148         {Opt_readdir_max_entries, "readdir_max_entries=%d"},
149         {Opt_readdir_max_bytes, "readdir_max_bytes=%d"},
150         {Opt_congestion_kb, "write_congestion_kb=%d"},
151         /* int args above */
152         {Opt_snapdirname, "snapdirname=%s"},
153         /* string args above */
154         {Opt_dirstat, "dirstat"},
155         {Opt_nodirstat, "nodirstat"},
156         {Opt_rbytes, "rbytes"},
157         {Opt_norbytes, "norbytes"},
158         {Opt_asyncreaddir, "asyncreaddir"},
159         {Opt_noasyncreaddir, "noasyncreaddir"},
160         {Opt_dcache, "dcache"},
161         {Opt_nodcache, "nodcache"},
162         {Opt_ino32, "ino32"},
163         {Opt_noino32, "noino32"},
164         {-1, NULL}
165 };
166
167 static int parse_fsopt_token(char *c, void *private)
168 {
169         struct ceph_mount_options *fsopt = private;
170         substring_t argstr[MAX_OPT_ARGS];
171         int token, intval, ret;
172
173         token = match_token((char *)c, fsopt_tokens, argstr);
174         if (token < 0)
175                 return -EINVAL;
176
177         if (token < Opt_last_int) {
178                 ret = match_int(&argstr[0], &intval);
179                 if (ret < 0) {
180                         pr_err("bad mount option arg (not int) "
181                                "at '%s'\n", c);
182                         return ret;
183                 }
184                 dout("got int token %d val %d\n", token, intval);
185         } else if (token > Opt_last_int && token < Opt_last_string) {
186                 dout("got string token %d val %s\n", token,
187                      argstr[0].from);
188         } else {
189                 dout("got token %d\n", token);
190         }
191
192         switch (token) {
193         case Opt_snapdirname:
194                 kfree(fsopt->snapdir_name);
195                 fsopt->snapdir_name = kstrndup(argstr[0].from,
196                                                argstr[0].to-argstr[0].from,
197                                                GFP_KERNEL);
198                 if (!fsopt->snapdir_name)
199                         return -ENOMEM;
200                 break;
201
202                 /* misc */
203         case Opt_wsize:
204                 fsopt->wsize = intval;
205                 break;
206         case Opt_rsize:
207                 fsopt->rsize = intval;
208                 break;
209         case Opt_rasize:
210                 fsopt->rasize = intval;
211                 break;
212         case Opt_caps_wanted_delay_min:
213                 fsopt->caps_wanted_delay_min = intval;
214                 break;
215         case Opt_caps_wanted_delay_max:
216                 fsopt->caps_wanted_delay_max = intval;
217                 break;
218         case Opt_readdir_max_entries:
219                 fsopt->max_readdir = intval;
220                 break;
221         case Opt_readdir_max_bytes:
222                 fsopt->max_readdir_bytes = intval;
223                 break;
224         case Opt_congestion_kb:
225                 fsopt->congestion_kb = intval;
226                 break;
227         case Opt_dirstat:
228                 fsopt->flags |= CEPH_MOUNT_OPT_DIRSTAT;
229                 break;
230         case Opt_nodirstat:
231                 fsopt->flags &= ~CEPH_MOUNT_OPT_DIRSTAT;
232                 break;
233         case Opt_rbytes:
234                 fsopt->flags |= CEPH_MOUNT_OPT_RBYTES;
235                 break;
236         case Opt_norbytes:
237                 fsopt->flags &= ~CEPH_MOUNT_OPT_RBYTES;
238                 break;
239         case Opt_asyncreaddir:
240                 fsopt->flags &= ~CEPH_MOUNT_OPT_NOASYNCREADDIR;
241                 break;
242         case Opt_noasyncreaddir:
243                 fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
244                 break;
245         case Opt_dcache:
246                 fsopt->flags |= CEPH_MOUNT_OPT_DCACHE;
247                 break;
248         case Opt_nodcache:
249                 fsopt->flags &= ~CEPH_MOUNT_OPT_DCACHE;
250                 break;
251         case Opt_ino32:
252                 fsopt->flags |= CEPH_MOUNT_OPT_INO32;
253                 break;
254         case Opt_noino32:
255                 fsopt->flags &= ~CEPH_MOUNT_OPT_INO32;
256                 break;
257         default:
258                 BUG_ON(token);
259         }
260         return 0;
261 }
262
263 static void destroy_mount_options(struct ceph_mount_options *args)
264 {
265         dout("destroy_mount_options %p\n", args);
266         kfree(args->snapdir_name);
267         kfree(args);
268 }
269
270 static int strcmp_null(const char *s1, const char *s2)
271 {
272         if (!s1 && !s2)
273                 return 0;
274         if (s1 && !s2)
275                 return -1;
276         if (!s1 && s2)
277                 return 1;
278         return strcmp(s1, s2);
279 }
280
281 static int compare_mount_options(struct ceph_mount_options *new_fsopt,
282                                  struct ceph_options *new_opt,
283                                  struct ceph_fs_client *fsc)
284 {
285         struct ceph_mount_options *fsopt1 = new_fsopt;
286         struct ceph_mount_options *fsopt2 = fsc->mount_options;
287         int ofs = offsetof(struct ceph_mount_options, snapdir_name);
288         int ret;
289
290         ret = memcmp(fsopt1, fsopt2, ofs);
291         if (ret)
292                 return ret;
293
294         ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
295         if (ret)
296                 return ret;
297
298         return ceph_compare_options(new_opt, fsc->client);
299 }
300
301 static int parse_mount_options(struct ceph_mount_options **pfsopt,
302                                struct ceph_options **popt,
303                                int flags, char *options,
304                                const char *dev_name,
305                                const char **path)
306 {
307         struct ceph_mount_options *fsopt;
308         const char *dev_name_end;
309         int err = -ENOMEM;
310
311         fsopt = kzalloc(sizeof(*fsopt), GFP_KERNEL);
312         if (!fsopt)
313                 return -ENOMEM;
314
315         dout("parse_mount_options %p, dev_name '%s'\n", fsopt, dev_name);
316
317         fsopt->sb_flags = flags;
318         fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
319
320         fsopt->rsize = CEPH_RSIZE_DEFAULT;
321         fsopt->rasize = CEPH_RASIZE_DEFAULT;
322         fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
323         fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
324         fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
325         fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT;
326         fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT;
327         fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT;
328         fsopt->congestion_kb = default_congestion_kb();
329
330         /* ip1[:port1][,ip2[:port2]...]:/subdir/in/fs */
331         err = -EINVAL;
332         if (!dev_name)
333                 goto out;
334         *path = strstr(dev_name, ":/");
335         if (*path == NULL) {
336                 pr_err("device name is missing path (no :/ in %s)\n",
337                                 dev_name);
338                 goto out;
339         }
340         dev_name_end = *path;
341         dout("device name '%.*s'\n", (int)(dev_name_end - dev_name), dev_name);
342
343         /* path on server */
344         *path += 2;
345         dout("server path '%s'\n", *path);
346
347         *popt = ceph_parse_options(options, dev_name, dev_name_end,
348                                  parse_fsopt_token, (void *)fsopt);
349         if (IS_ERR(*popt)) {
350                 err = PTR_ERR(*popt);
351                 goto out;
352         }
353
354         /* success */
355         *pfsopt = fsopt;
356         return 0;
357
358 out:
359         destroy_mount_options(fsopt);
360         return err;
361 }
362
363 /**
364  * ceph_show_options - Show mount options in /proc/mounts
365  * @m: seq_file to write to
366  * @root: root of that (sub)tree
367  */
368 static int ceph_show_options(struct seq_file *m, struct dentry *root)
369 {
370         struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb);
371         struct ceph_mount_options *fsopt = fsc->mount_options;
372         struct ceph_options *opt = fsc->client->options;
373
374         if (opt->flags & CEPH_OPT_FSID)
375                 seq_printf(m, ",fsid=%pU", &opt->fsid);
376         if (opt->flags & CEPH_OPT_NOSHARE)
377                 seq_puts(m, ",noshare");
378         if (opt->flags & CEPH_OPT_NOCRC)
379                 seq_puts(m, ",nocrc");
380
381         if (opt->name)
382                 seq_printf(m, ",name=%s", opt->name);
383         if (opt->key)
384                 seq_puts(m, ",secret=<hidden>");
385
386         if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
387                 seq_printf(m, ",mount_timeout=%d", opt->mount_timeout);
388         if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
389                 seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl);
390         if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
391                 seq_printf(m, ",osdkeepalivetimeout=%d",
392                            opt->osd_keepalive_timeout);
393
394         if (fsopt->flags & CEPH_MOUNT_OPT_DIRSTAT)
395                 seq_puts(m, ",dirstat");
396         if ((fsopt->flags & CEPH_MOUNT_OPT_RBYTES) == 0)
397                 seq_puts(m, ",norbytes");
398         if (fsopt->flags & CEPH_MOUNT_OPT_NOASYNCREADDIR)
399                 seq_puts(m, ",noasyncreaddir");
400         if (fsopt->flags & CEPH_MOUNT_OPT_DCACHE)
401                 seq_puts(m, ",dcache");
402         else
403                 seq_puts(m, ",nodcache");
404
405         if (fsopt->wsize)
406                 seq_printf(m, ",wsize=%d", fsopt->wsize);
407         if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
408                 seq_printf(m, ",rsize=%d", fsopt->rsize);
409         if (fsopt->rasize != CEPH_RASIZE_DEFAULT)
410                 seq_printf(m, ",rasize=%d", fsopt->rasize);
411         if (fsopt->congestion_kb != default_congestion_kb())
412                 seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
413         if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
414                 seq_printf(m, ",caps_wanted_delay_min=%d",
415                          fsopt->caps_wanted_delay_min);
416         if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
417                 seq_printf(m, ",caps_wanted_delay_max=%d",
418                            fsopt->caps_wanted_delay_max);
419         if (fsopt->cap_release_safety != CEPH_CAP_RELEASE_SAFETY_DEFAULT)
420                 seq_printf(m, ",cap_release_safety=%d",
421                            fsopt->cap_release_safety);
422         if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
423                 seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
424         if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
425                 seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
426         if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
427                 seq_printf(m, ",snapdirname=%s", fsopt->snapdir_name);
428         return 0;
429 }
430
431 /*
432  * handle any mon messages the standard library doesn't understand.
433  * return error if we don't either.
434  */
435 static int extra_mon_dispatch(struct ceph_client *client, struct ceph_msg *msg)
436 {
437         struct ceph_fs_client *fsc = client->private;
438         int type = le16_to_cpu(msg->hdr.type);
439
440         switch (type) {
441         case CEPH_MSG_MDS_MAP:
442                 ceph_mdsc_handle_map(fsc->mdsc, msg);
443                 return 0;
444
445         default:
446                 return -1;
447         }
448 }
449
450 /*
451  * create a new fs client
452  */
453 static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
454                                         struct ceph_options *opt)
455 {
456         struct ceph_fs_client *fsc;
457         const unsigned supported_features =
458                 CEPH_FEATURE_FLOCK |
459                 CEPH_FEATURE_DIRLAYOUTHASH;
460         const unsigned required_features = 0;
461         int err = -ENOMEM;
462
463         fsc = kzalloc(sizeof(*fsc), GFP_KERNEL);
464         if (!fsc)
465                 return ERR_PTR(-ENOMEM);
466
467         fsc->client = ceph_create_client(opt, fsc, supported_features,
468                                          required_features);
469         if (IS_ERR(fsc->client)) {
470                 err = PTR_ERR(fsc->client);
471                 goto fail;
472         }
473         fsc->client->extra_mon_dispatch = extra_mon_dispatch;
474         fsc->client->monc.want_mdsmap = 1;
475
476         fsc->mount_options = fsopt;
477
478         fsc->sb = NULL;
479         fsc->mount_state = CEPH_MOUNT_MOUNTING;
480
481         atomic_long_set(&fsc->writeback_count, 0);
482
483         err = bdi_init(&fsc->backing_dev_info);
484         if (err < 0)
485                 goto fail_client;
486
487         err = -ENOMEM;
488         /*
489          * The number of concurrent works can be high but they don't need
490          * to be processed in parallel, limit concurrency.
491          */
492         fsc->wb_wq = alloc_workqueue("ceph-writeback", 0, 1);
493         if (fsc->wb_wq == NULL)
494                 goto fail_bdi;
495         fsc->pg_inv_wq = alloc_workqueue("ceph-pg-invalid", 0, 1);
496         if (fsc->pg_inv_wq == NULL)
497                 goto fail_wb_wq;
498         fsc->trunc_wq = alloc_workqueue("ceph-trunc", 0, 1);
499         if (fsc->trunc_wq == NULL)
500                 goto fail_pg_inv_wq;
501
502         /* set up mempools */
503         err = -ENOMEM;
504         fsc->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
505                               fsc->mount_options->wsize >> PAGE_CACHE_SHIFT);
506         if (!fsc->wb_pagevec_pool)
507                 goto fail_trunc_wq;
508
509         /* caps */
510         fsc->min_caps = fsopt->max_readdir;
511
512         return fsc;
513
514 fail_trunc_wq:
515         destroy_workqueue(fsc->trunc_wq);
516 fail_pg_inv_wq:
517         destroy_workqueue(fsc->pg_inv_wq);
518 fail_wb_wq:
519         destroy_workqueue(fsc->wb_wq);
520 fail_bdi:
521         bdi_destroy(&fsc->backing_dev_info);
522 fail_client:
523         ceph_destroy_client(fsc->client);
524 fail:
525         kfree(fsc);
526         return ERR_PTR(err);
527 }
528
529 static void destroy_fs_client(struct ceph_fs_client *fsc)
530 {
531         dout("destroy_fs_client %p\n", fsc);
532
533         destroy_workqueue(fsc->wb_wq);
534         destroy_workqueue(fsc->pg_inv_wq);
535         destroy_workqueue(fsc->trunc_wq);
536
537         bdi_destroy(&fsc->backing_dev_info);
538
539         mempool_destroy(fsc->wb_pagevec_pool);
540
541         destroy_mount_options(fsc->mount_options);
542
543         ceph_fs_debugfs_cleanup(fsc);
544
545         ceph_destroy_client(fsc->client);
546
547         kfree(fsc);
548         dout("destroy_fs_client %p done\n", fsc);
549 }
550
551 /*
552  * caches
553  */
554 struct kmem_cache *ceph_inode_cachep;
555 struct kmem_cache *ceph_cap_cachep;
556 struct kmem_cache *ceph_dentry_cachep;
557 struct kmem_cache *ceph_file_cachep;
558
559 static void ceph_inode_init_once(void *foo)
560 {
561         struct ceph_inode_info *ci = foo;
562         inode_init_once(&ci->vfs_inode);
563 }
564
565 static int __init init_caches(void)
566 {
567         ceph_inode_cachep = kmem_cache_create("ceph_inode_info",
568                                       sizeof(struct ceph_inode_info),
569                                       __alignof__(struct ceph_inode_info),
570                                       (SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD),
571                                       ceph_inode_init_once);
572         if (ceph_inode_cachep == NULL)
573                 return -ENOMEM;
574
575         ceph_cap_cachep = KMEM_CACHE(ceph_cap,
576                                      SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
577         if (ceph_cap_cachep == NULL)
578                 goto bad_cap;
579
580         ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info,
581                                         SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
582         if (ceph_dentry_cachep == NULL)
583                 goto bad_dentry;
584
585         ceph_file_cachep = KMEM_CACHE(ceph_file_info,
586                                       SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD);
587         if (ceph_file_cachep == NULL)
588                 goto bad_file;
589
590         return 0;
591
592 bad_file:
593         kmem_cache_destroy(ceph_dentry_cachep);
594 bad_dentry:
595         kmem_cache_destroy(ceph_cap_cachep);
596 bad_cap:
597         kmem_cache_destroy(ceph_inode_cachep);
598         return -ENOMEM;
599 }
600
601 static void destroy_caches(void)
602 {
603         kmem_cache_destroy(ceph_inode_cachep);
604         kmem_cache_destroy(ceph_cap_cachep);
605         kmem_cache_destroy(ceph_dentry_cachep);
606         kmem_cache_destroy(ceph_file_cachep);
607 }
608
609
610 /*
611  * ceph_umount_begin - initiate forced umount.  Tear down down the
612  * mount, skipping steps that may hang while waiting for server(s).
613  */
614 static void ceph_umount_begin(struct super_block *sb)
615 {
616         struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
617
618         dout("ceph_umount_begin - starting forced umount\n");
619         if (!fsc)
620                 return;
621         fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
622         return;
623 }
624
625 static const struct super_operations ceph_super_ops = {
626         .alloc_inode    = ceph_alloc_inode,
627         .destroy_inode  = ceph_destroy_inode,
628         .write_inode    = ceph_write_inode,
629         .sync_fs        = ceph_sync_fs,
630         .put_super      = ceph_put_super,
631         .show_options   = ceph_show_options,
632         .statfs         = ceph_statfs,
633         .umount_begin   = ceph_umount_begin,
634 };
635
636 /*
637  * Bootstrap mount by opening the root directory.  Note the mount
638  * @started time from caller, and time out if this takes too long.
639  */
640 static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
641                                        const char *path,
642                                        unsigned long started)
643 {
644         struct ceph_mds_client *mdsc = fsc->mdsc;
645         struct ceph_mds_request *req = NULL;
646         int err;
647         struct dentry *root;
648
649         /* open dir */
650         dout("open_root_inode opening '%s'\n", path);
651         req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
652         if (IS_ERR(req))
653                 return ERR_CAST(req);
654         req->r_path1 = kstrdup(path, GFP_NOFS);
655         req->r_ino1.ino = CEPH_INO_ROOT;
656         req->r_ino1.snap = CEPH_NOSNAP;
657         req->r_started = started;
658         req->r_timeout = fsc->client->options->mount_timeout * HZ;
659         req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INODE);
660         req->r_num_caps = 2;
661         err = ceph_mdsc_do_request(mdsc, NULL, req);
662         if (err == 0) {
663                 struct inode *inode = req->r_target_inode;
664                 req->r_target_inode = NULL;
665                 dout("open_root_inode success\n");
666                 if (ceph_ino(inode) == CEPH_INO_ROOT &&
667                     fsc->sb->s_root == NULL) {
668                         root = d_make_root(inode);
669                         if (!root) {
670                                 root = ERR_PTR(-ENOMEM);
671                                 goto out;
672                         }
673                 } else {
674                         root = d_obtain_alias(inode);
675                 }
676                 ceph_init_dentry(root);
677                 dout("open_root_inode success, root dentry is %p\n", root);
678         } else {
679                 root = ERR_PTR(err);
680         }
681 out:
682         ceph_mdsc_put_request(req);
683         return root;
684 }
685
686
687
688
689 /*
690  * mount: join the ceph cluster, and open root directory.
691  */
692 static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
693                       const char *path)
694 {
695         int err;
696         unsigned long started = jiffies;  /* note the start time */
697         struct dentry *root;
698         int first = 0;   /* first vfsmount for this super_block */
699
700         dout("mount start\n");
701         mutex_lock(&fsc->client->mount_mutex);
702
703         err = __ceph_open_session(fsc->client, started);
704         if (err < 0)
705                 goto out;
706
707         dout("mount opening root\n");
708         root = open_root_dentry(fsc, "", started);
709         if (IS_ERR(root)) {
710                 err = PTR_ERR(root);
711                 goto out;
712         }
713         if (fsc->sb->s_root) {
714                 dput(root);
715         } else {
716                 fsc->sb->s_root = root;
717                 first = 1;
718
719                 err = ceph_fs_debugfs_init(fsc);
720                 if (err < 0)
721                         goto fail;
722         }
723
724         if (path[0] == 0) {
725                 dget(root);
726         } else {
727                 dout("mount opening base mountpoint\n");
728                 root = open_root_dentry(fsc, path, started);
729                 if (IS_ERR(root)) {
730                         err = PTR_ERR(root);
731                         goto fail;
732                 }
733         }
734
735         fsc->mount_state = CEPH_MOUNT_MOUNTED;
736         dout("mount success\n");
737         mutex_unlock(&fsc->client->mount_mutex);
738         return root;
739
740 out:
741         mutex_unlock(&fsc->client->mount_mutex);
742         return ERR_PTR(err);
743
744 fail:
745         if (first) {
746                 dput(fsc->sb->s_root);
747                 fsc->sb->s_root = NULL;
748         }
749         goto out;
750 }
751
752 static int ceph_set_super(struct super_block *s, void *data)
753 {
754         struct ceph_fs_client *fsc = data;
755         int ret;
756
757         dout("set_super %p data %p\n", s, data);
758
759         s->s_flags = fsc->mount_options->sb_flags;
760         s->s_maxbytes = 1ULL << 40;  /* temp value until we get mdsmap */
761
762         s->s_fs_info = fsc;
763         fsc->sb = s;
764
765         s->s_op = &ceph_super_ops;
766         s->s_export_op = &ceph_export_ops;
767
768         s->s_time_gran = 1000;  /* 1000 ns == 1 us */
769
770         ret = set_anon_super(s, NULL);  /* what is that second arg for? */
771         if (ret != 0)
772                 goto fail;
773
774         return ret;
775
776 fail:
777         s->s_fs_info = NULL;
778         fsc->sb = NULL;
779         return ret;
780 }
781
782 /*
783  * share superblock if same fs AND options
784  */
785 static int ceph_compare_super(struct super_block *sb, void *data)
786 {
787         struct ceph_fs_client *new = data;
788         struct ceph_mount_options *fsopt = new->mount_options;
789         struct ceph_options *opt = new->client->options;
790         struct ceph_fs_client *other = ceph_sb_to_client(sb);
791
792         dout("ceph_compare_super %p\n", sb);
793
794         if (compare_mount_options(fsopt, opt, other)) {
795                 dout("monitor(s)/mount options don't match\n");
796                 return 0;
797         }
798         if ((opt->flags & CEPH_OPT_FSID) &&
799             ceph_fsid_compare(&opt->fsid, &other->client->fsid)) {
800                 dout("fsid doesn't match\n");
801                 return 0;
802         }
803         if (fsopt->sb_flags != other->mount_options->sb_flags) {
804                 dout("flags differ\n");
805                 return 0;
806         }
807         return 1;
808 }
809
810 /*
811  * construct our own bdi so we can control readahead, etc.
812  */
813 static atomic_long_t bdi_seq = ATOMIC_LONG_INIT(0);
814
815 static int ceph_register_bdi(struct super_block *sb,
816                              struct ceph_fs_client *fsc)
817 {
818         int err;
819
820         /* set ra_pages based on rasize mount option? */
821         if (fsc->mount_options->rasize >= PAGE_CACHE_SIZE)
822                 fsc->backing_dev_info.ra_pages =
823                         (fsc->mount_options->rasize + PAGE_CACHE_SIZE - 1)
824                         >> PAGE_SHIFT;
825         else
826                 fsc->backing_dev_info.ra_pages =
827                         default_backing_dev_info.ra_pages;
828
829         err = bdi_register(&fsc->backing_dev_info, NULL, "ceph-%d",
830                            atomic_long_inc_return(&bdi_seq));
831         if (!err)
832                 sb->s_bdi = &fsc->backing_dev_info;
833         return err;
834 }
835
836 static struct dentry *ceph_mount(struct file_system_type *fs_type,
837                        int flags, const char *dev_name, void *data)
838 {
839         struct super_block *sb;
840         struct ceph_fs_client *fsc;
841         struct dentry *res;
842         int err;
843         int (*compare_super)(struct super_block *, void *) = ceph_compare_super;
844         const char *path = NULL;
845         struct ceph_mount_options *fsopt = NULL;
846         struct ceph_options *opt = NULL;
847
848         dout("ceph_mount\n");
849         err = parse_mount_options(&fsopt, &opt, flags, data, dev_name, &path);
850         if (err < 0) {
851                 res = ERR_PTR(err);
852                 goto out_final;
853         }
854
855         /* create client (which we may/may not use) */
856         fsc = create_fs_client(fsopt, opt);
857         if (IS_ERR(fsc)) {
858                 res = ERR_CAST(fsc);
859                 destroy_mount_options(fsopt);
860                 ceph_destroy_options(opt);
861                 goto out_final;
862         }
863
864         err = ceph_mdsc_init(fsc);
865         if (err < 0) {
866                 res = ERR_PTR(err);
867                 goto out;
868         }
869
870         if (ceph_test_opt(fsc->client, NOSHARE))
871                 compare_super = NULL;
872         sb = sget(fs_type, compare_super, ceph_set_super, fsc);
873         if (IS_ERR(sb)) {
874                 res = ERR_CAST(sb);
875                 goto out;
876         }
877
878         if (ceph_sb_to_client(sb) != fsc) {
879                 ceph_mdsc_destroy(fsc);
880                 destroy_fs_client(fsc);
881                 fsc = ceph_sb_to_client(sb);
882                 dout("get_sb got existing client %p\n", fsc);
883         } else {
884                 dout("get_sb using new client %p\n", fsc);
885                 err = ceph_register_bdi(sb, fsc);
886                 if (err < 0) {
887                         res = ERR_PTR(err);
888                         goto out_splat;
889                 }
890         }
891
892         res = ceph_real_mount(fsc, path);
893         if (IS_ERR(res))
894                 goto out_splat;
895         dout("root %p inode %p ino %llx.%llx\n", res,
896              res->d_inode, ceph_vinop(res->d_inode));
897         return res;
898
899 out_splat:
900         ceph_mdsc_close_sessions(fsc->mdsc);
901         deactivate_locked_super(sb);
902         goto out_final;
903
904 out:
905         ceph_mdsc_destroy(fsc);
906         destroy_fs_client(fsc);
907 out_final:
908         dout("ceph_mount fail %ld\n", PTR_ERR(res));
909         return res;
910 }
911
912 static void ceph_kill_sb(struct super_block *s)
913 {
914         struct ceph_fs_client *fsc = ceph_sb_to_client(s);
915         dout("kill_sb %p\n", s);
916         ceph_mdsc_pre_umount(fsc->mdsc);
917         kill_anon_super(s);    /* will call put_super after sb is r/o */
918         ceph_mdsc_destroy(fsc);
919         destroy_fs_client(fsc);
920 }
921
922 static struct file_system_type ceph_fs_type = {
923         .owner          = THIS_MODULE,
924         .name           = "ceph",
925         .mount          = ceph_mount,
926         .kill_sb        = ceph_kill_sb,
927         .fs_flags       = FS_RENAME_DOES_D_MOVE,
928 };
929
930 #define _STRINGIFY(x) #x
931 #define STRINGIFY(x) _STRINGIFY(x)
932
933 static int __init init_ceph(void)
934 {
935         int ret = init_caches();
936         if (ret)
937                 goto out;
938
939         ceph_xattr_init();
940         ret = register_filesystem(&ceph_fs_type);
941         if (ret)
942                 goto out_icache;
943
944         pr_info("loaded (mds proto %d)\n", CEPH_MDSC_PROTOCOL);
945
946         return 0;
947
948 out_icache:
949         ceph_xattr_exit();
950         destroy_caches();
951 out:
952         return ret;
953 }
954
955 static void __exit exit_ceph(void)
956 {
957         dout("exit_ceph\n");
958         unregister_filesystem(&ceph_fs_type);
959         ceph_xattr_exit();
960         destroy_caches();
961 }
962
963 module_init(init_ceph);
964 module_exit(exit_ceph);
965
966 MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
967 MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
968 MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
969 MODULE_DESCRIPTION("Ceph filesystem for Linux");
970 MODULE_LICENSE("GPL");