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