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