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