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