linux/fs/orangefs/super.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * (C) 2001 Clemson University and The University of Chicago
   4 *
   5 * See COPYING in top-level directory.
   6 */
   7
   8#include "protocol.h"
   9#include "orangefs-kernel.h"
  10#include "orangefs-bufmap.h"
  11
  12#include <linux/parser.h>
  13#include <linux/hashtable.h>
  14
  15/* a cache for orangefs-inode objects (i.e. orangefs inode private data) */
  16static struct kmem_cache *orangefs_inode_cache;
  17
  18/* list for storing orangefs specific superblocks in use */
  19LIST_HEAD(orangefs_superblocks);
  20
  21DEFINE_SPINLOCK(orangefs_superblocks_lock);
  22
  23enum {
  24        Opt_intr,
  25        Opt_acl,
  26        Opt_local_lock,
  27
  28        Opt_err
  29};
  30
  31static const match_table_t tokens = {
  32        { Opt_acl,              "acl" },
  33        { Opt_intr,             "intr" },
  34        { Opt_local_lock,       "local_lock" },
  35        { Opt_err,      NULL }
  36};
  37
  38uint64_t orangefs_features;
  39
  40static int orangefs_show_options(struct seq_file *m, struct dentry *root)
  41{
  42        struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(root->d_sb);
  43
  44        if (root->d_sb->s_flags & SB_POSIXACL)
  45                seq_puts(m, ",acl");
  46        if (orangefs_sb->flags & ORANGEFS_OPT_INTR)
  47                seq_puts(m, ",intr");
  48        if (orangefs_sb->flags & ORANGEFS_OPT_LOCAL_LOCK)
  49                seq_puts(m, ",local_lock");
  50        return 0;
  51}
  52
  53static int parse_mount_options(struct super_block *sb, char *options,
  54                int silent)
  55{
  56        struct orangefs_sb_info_s *orangefs_sb = ORANGEFS_SB(sb);
  57        substring_t args[MAX_OPT_ARGS];
  58        char *p;
  59
  60        /*
  61         * Force any potential flags that might be set from the mount
  62         * to zero, ie, initialize to unset.
  63         */
  64        sb->s_flags &= ~SB_POSIXACL;
  65        orangefs_sb->flags &= ~ORANGEFS_OPT_INTR;
  66        orangefs_sb->flags &= ~ORANGEFS_OPT_LOCAL_LOCK;
  67
  68        while ((p = strsep(&options, ",")) != NULL) {
  69                int token;
  70
  71                if (!*p)
  72                        continue;
  73
  74                token = match_token(p, tokens, args);
  75                switch (token) {
  76                case Opt_acl:
  77                        sb->s_flags |= SB_POSIXACL;
  78                        break;
  79                case Opt_intr:
  80                        orangefs_sb->flags |= ORANGEFS_OPT_INTR;
  81                        break;
  82                case Opt_local_lock:
  83                        orangefs_sb->flags |= ORANGEFS_OPT_LOCAL_LOCK;
  84                        break;
  85                default:
  86                        goto fail;
  87                }
  88        }
  89
  90        return 0;
  91fail:
  92        if (!silent)
  93                gossip_err("Error: mount option [%s] is not supported.\n", p);
  94        return -EINVAL;
  95}
  96
  97static void orangefs_inode_cache_ctor(void *req)
  98{
  99        struct orangefs_inode_s *orangefs_inode = req;
 100
 101        inode_init_once(&orangefs_inode->vfs_inode);
 102        init_rwsem(&orangefs_inode->xattr_sem);
 103}
 104
 105static struct inode *orangefs_alloc_inode(struct super_block *sb)
 106{
 107        struct orangefs_inode_s *orangefs_inode;
 108
 109        orangefs_inode = kmem_cache_alloc(orangefs_inode_cache, GFP_KERNEL);
 110        if (!orangefs_inode)
 111                return NULL;
 112
 113        /*
 114         * We want to clear everything except for rw_semaphore and the
 115         * vfs_inode.
 116         */
 117        memset(&orangefs_inode->refn.khandle, 0, 16);
 118        orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL;
 119        orangefs_inode->last_failed_block_index_read = 0;
 120        memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target));
 121
 122        gossip_debug(GOSSIP_SUPER_DEBUG,
 123                     "orangefs_alloc_inode: allocated %p\n",
 124                     &orangefs_inode->vfs_inode);
 125        return &orangefs_inode->vfs_inode;
 126}
 127
 128static void orangefs_free_inode(struct inode *inode)
 129{
 130        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 131        struct orangefs_cached_xattr *cx;
 132        struct hlist_node *tmp;
 133        int i;
 134
 135        hash_for_each_safe(orangefs_inode->xattr_cache, i, tmp, cx, node) {
 136                hlist_del(&cx->node);
 137                kfree(cx);
 138        }
 139
 140        kmem_cache_free(orangefs_inode_cache, orangefs_inode);
 141}
 142
 143static void orangefs_destroy_inode(struct inode *inode)
 144{
 145        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 146
 147        gossip_debug(GOSSIP_SUPER_DEBUG,
 148                        "%s: deallocated %p destroying inode %pU\n",
 149                        __func__, orangefs_inode, get_khandle_from_ino(inode));
 150}
 151
 152static int orangefs_write_inode(struct inode *inode,
 153                                struct writeback_control *wbc)
 154{
 155        gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_write_inode\n");
 156        return orangefs_inode_setattr(inode);
 157}
 158
 159/*
 160 * NOTE: information filled in here is typically reflected in the
 161 * output of the system command 'df'
 162*/
 163static int orangefs_statfs(struct dentry *dentry, struct kstatfs *buf)
 164{
 165        int ret = -ENOMEM;
 166        struct orangefs_kernel_op_s *new_op = NULL;
 167        int flags = 0;
 168        struct super_block *sb = NULL;
 169
 170        sb = dentry->d_sb;
 171
 172        gossip_debug(GOSSIP_SUPER_DEBUG,
 173                        "%s: called on sb %p (fs_id is %d)\n",
 174                        __func__,
 175                        sb,
 176                        (int)(ORANGEFS_SB(sb)->fs_id));
 177
 178        new_op = op_alloc(ORANGEFS_VFS_OP_STATFS);
 179        if (!new_op)
 180                return ret;
 181        new_op->upcall.req.statfs.fs_id = ORANGEFS_SB(sb)->fs_id;
 182
 183        if (ORANGEFS_SB(sb)->flags & ORANGEFS_OPT_INTR)
 184                flags = ORANGEFS_OP_INTERRUPTIBLE;
 185
 186        ret = service_operation(new_op, "orangefs_statfs", flags);
 187
 188        if (new_op->downcall.status < 0)
 189                goto out_op_release;
 190
 191        gossip_debug(GOSSIP_SUPER_DEBUG,
 192                     "%s: got %ld blocks available | "
 193                     "%ld blocks total | %ld block size | "
 194                     "%ld files total | %ld files avail\n",
 195                     __func__,
 196                     (long)new_op->downcall.resp.statfs.blocks_avail,
 197                     (long)new_op->downcall.resp.statfs.blocks_total,
 198                     (long)new_op->downcall.resp.statfs.block_size,
 199                     (long)new_op->downcall.resp.statfs.files_total,
 200                     (long)new_op->downcall.resp.statfs.files_avail);
 201
 202        buf->f_type = sb->s_magic;
 203        memcpy(&buf->f_fsid, &ORANGEFS_SB(sb)->fs_id, sizeof(buf->f_fsid));
 204        buf->f_bsize = new_op->downcall.resp.statfs.block_size;
 205        buf->f_namelen = ORANGEFS_NAME_MAX;
 206
 207        buf->f_blocks = (sector_t) new_op->downcall.resp.statfs.blocks_total;
 208        buf->f_bfree = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
 209        buf->f_bavail = (sector_t) new_op->downcall.resp.statfs.blocks_avail;
 210        buf->f_files = (sector_t) new_op->downcall.resp.statfs.files_total;
 211        buf->f_ffree = (sector_t) new_op->downcall.resp.statfs.files_avail;
 212        buf->f_frsize = 0;
 213
 214out_op_release:
 215        op_release(new_op);
 216        gossip_debug(GOSSIP_SUPER_DEBUG, "%s: returning %d\n", __func__, ret);
 217        return ret;
 218}
 219
 220/*
 221 * Remount as initiated by VFS layer.  We just need to reparse the mount
 222 * options, no need to signal pvfs2-client-core about it.
 223 */
 224static int orangefs_remount_fs(struct super_block *sb, int *flags, char *data)
 225{
 226        gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount_fs: called\n");
 227        return parse_mount_options(sb, data, 1);
 228}
 229
 230/*
 231 * Remount as initiated by pvfs2-client-core on restart.  This is used to
 232 * repopulate mount information left from previous pvfs2-client-core.
 233 *
 234 * the idea here is that given a valid superblock, we're
 235 * re-initializing the user space client with the initial mount
 236 * information specified when the super block was first initialized.
 237 * this is very different than the first initialization/creation of a
 238 * superblock.  we use the special service_priority_operation to make
 239 * sure that the mount gets ahead of any other pending operation that
 240 * is waiting for servicing.  this means that the pvfs2-client won't
 241 * fail to start several times for all other pending operations before
 242 * the client regains all of the mount information from us.
 243 * NOTE: this function assumes that the request_mutex is already acquired!
 244 */
 245int orangefs_remount(struct orangefs_sb_info_s *orangefs_sb)
 246{
 247        struct orangefs_kernel_op_s *new_op;
 248        int ret = -EINVAL;
 249
 250        gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount: called\n");
 251
 252        new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
 253        if (!new_op)
 254                return -ENOMEM;
 255        strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
 256                orangefs_sb->devname,
 257                ORANGEFS_MAX_SERVER_ADDR_LEN);
 258
 259        gossip_debug(GOSSIP_SUPER_DEBUG,
 260                     "Attempting ORANGEFS Remount via host %s\n",
 261                     new_op->upcall.req.fs_mount.orangefs_config_server);
 262
 263        /*
 264         * we assume that the calling function has already acquired the
 265         * request_mutex to prevent other operations from bypassing
 266         * this one
 267         */
 268        ret = service_operation(new_op, "orangefs_remount",
 269                ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
 270        gossip_debug(GOSSIP_SUPER_DEBUG,
 271                     "orangefs_remount: mount got return value of %d\n",
 272                     ret);
 273        if (ret == 0) {
 274                /*
 275                 * store the id assigned to this sb -- it's just a
 276                 * short-lived mapping that the system interface uses
 277                 * to map this superblock to a particular mount entry
 278                 */
 279                orangefs_sb->id = new_op->downcall.resp.fs_mount.id;
 280                orangefs_sb->mount_pending = 0;
 281        }
 282
 283        op_release(new_op);
 284
 285        if (orangefs_userspace_version >= 20906) {
 286                new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
 287                if (!new_op)
 288                        return -ENOMEM;
 289                new_op->upcall.req.features.features = 0;
 290                ret = service_operation(new_op, "orangefs_features",
 291                    ORANGEFS_OP_PRIORITY | ORANGEFS_OP_NO_MUTEX);
 292                if (!ret)
 293                        orangefs_features =
 294                            new_op->downcall.resp.features.features;
 295                else
 296                        orangefs_features = 0;
 297                op_release(new_op);
 298        } else {
 299                orangefs_features = 0;
 300        }
 301
 302        return ret;
 303}
 304
 305int fsid_key_table_initialize(void)
 306{
 307        return 0;
 308}
 309
 310void fsid_key_table_finalize(void)
 311{
 312}
 313
 314static const struct super_operations orangefs_s_ops = {
 315        .alloc_inode = orangefs_alloc_inode,
 316        .free_inode = orangefs_free_inode,
 317        .destroy_inode = orangefs_destroy_inode,
 318        .write_inode = orangefs_write_inode,
 319        .drop_inode = generic_delete_inode,
 320        .statfs = orangefs_statfs,
 321        .remount_fs = orangefs_remount_fs,
 322        .show_options = orangefs_show_options,
 323};
 324
 325static struct dentry *orangefs_fh_to_dentry(struct super_block *sb,
 326                                  struct fid *fid,
 327                                  int fh_len,
 328                                  int fh_type)
 329{
 330        struct orangefs_object_kref refn;
 331
 332        if (fh_len < 5 || fh_type > 2)
 333                return NULL;
 334
 335        ORANGEFS_khandle_from(&(refn.khandle), fid->raw, 16);
 336        refn.fs_id = (u32) fid->raw[4];
 337        gossip_debug(GOSSIP_SUPER_DEBUG,
 338                     "fh_to_dentry: handle %pU, fs_id %d\n",
 339                     &refn.khandle,
 340                     refn.fs_id);
 341
 342        return d_obtain_alias(orangefs_iget(sb, &refn));
 343}
 344
 345static int orangefs_encode_fh(struct inode *inode,
 346                    __u32 *fh,
 347                    int *max_len,
 348                    struct inode *parent)
 349{
 350        int len = parent ? 10 : 5;
 351        int type = 1;
 352        struct orangefs_object_kref refn;
 353
 354        if (*max_len < len) {
 355                gossip_err("fh buffer is too small for encoding\n");
 356                *max_len = len;
 357                type = 255;
 358                goto out;
 359        }
 360
 361        refn = ORANGEFS_I(inode)->refn;
 362        ORANGEFS_khandle_to(&refn.khandle, fh, 16);
 363        fh[4] = refn.fs_id;
 364
 365        gossip_debug(GOSSIP_SUPER_DEBUG,
 366                     "Encoding fh: handle %pU, fsid %u\n",
 367                     &refn.khandle,
 368                     refn.fs_id);
 369
 370
 371        if (parent) {
 372                refn = ORANGEFS_I(parent)->refn;
 373                ORANGEFS_khandle_to(&refn.khandle, (char *) fh + 20, 16);
 374                fh[9] = refn.fs_id;
 375
 376                type = 2;
 377                gossip_debug(GOSSIP_SUPER_DEBUG,
 378                             "Encoding parent: handle %pU, fsid %u\n",
 379                             &refn.khandle,
 380                             refn.fs_id);
 381        }
 382        *max_len = len;
 383
 384out:
 385        return type;
 386}
 387
 388static const struct export_operations orangefs_export_ops = {
 389        .encode_fh = orangefs_encode_fh,
 390        .fh_to_dentry = orangefs_fh_to_dentry,
 391};
 392
 393static int orangefs_unmount(int id, __s32 fs_id, const char *devname)
 394{
 395        struct orangefs_kernel_op_s *op;
 396        int r;
 397        op = op_alloc(ORANGEFS_VFS_OP_FS_UMOUNT);
 398        if (!op)
 399                return -ENOMEM;
 400        op->upcall.req.fs_umount.id = id;
 401        op->upcall.req.fs_umount.fs_id = fs_id;
 402        strncpy(op->upcall.req.fs_umount.orangefs_config_server,
 403            devname, ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
 404        r = service_operation(op, "orangefs_fs_umount", 0);
 405        /* Not much to do about an error here. */
 406        if (r)
 407                gossip_err("orangefs_unmount: service_operation %d\n", r);
 408        op_release(op);
 409        return r;
 410}
 411
 412static int orangefs_fill_sb(struct super_block *sb,
 413                struct orangefs_fs_mount_response *fs_mount,
 414                void *data, int silent)
 415{
 416        int ret;
 417        struct inode *root;
 418        struct dentry *root_dentry;
 419        struct orangefs_object_kref root_object;
 420
 421        ORANGEFS_SB(sb)->sb = sb;
 422
 423        ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle;
 424        ORANGEFS_SB(sb)->fs_id = fs_mount->fs_id;
 425        ORANGEFS_SB(sb)->id = fs_mount->id;
 426
 427        if (data) {
 428                ret = parse_mount_options(sb, data, silent);
 429                if (ret)
 430                        return ret;
 431        }
 432
 433        /* Hang the xattr handlers off the superblock */
 434        sb->s_xattr = orangefs_xattr_handlers;
 435        sb->s_magic = ORANGEFS_SUPER_MAGIC;
 436        sb->s_op = &orangefs_s_ops;
 437        sb->s_d_op = &orangefs_dentry_operations;
 438
 439        sb->s_blocksize = PAGE_SIZE;
 440        sb->s_blocksize_bits = PAGE_SHIFT;
 441        sb->s_maxbytes = MAX_LFS_FILESIZE;
 442
 443        ret = super_setup_bdi(sb);
 444        if (ret)
 445                return ret;
 446
 447        root_object.khandle = ORANGEFS_SB(sb)->root_khandle;
 448        root_object.fs_id = ORANGEFS_SB(sb)->fs_id;
 449        gossip_debug(GOSSIP_SUPER_DEBUG,
 450                     "get inode %pU, fsid %d\n",
 451                     &root_object.khandle,
 452                     root_object.fs_id);
 453
 454        root = orangefs_iget(sb, &root_object);
 455        if (IS_ERR(root))
 456                return PTR_ERR(root);
 457
 458        gossip_debug(GOSSIP_SUPER_DEBUG,
 459                     "Allocated root inode [%p] with mode %x\n",
 460                     root,
 461                     root->i_mode);
 462
 463        /* allocates and places root dentry in dcache */
 464        root_dentry = d_make_root(root);
 465        if (!root_dentry)
 466                return -ENOMEM;
 467
 468        sb->s_export_op = &orangefs_export_ops;
 469        sb->s_root = root_dentry;
 470        return 0;
 471}
 472
 473struct dentry *orangefs_mount(struct file_system_type *fst,
 474                           int flags,
 475                           const char *devname,
 476                           void *data)
 477{
 478        int ret = -EINVAL;
 479        struct super_block *sb = ERR_PTR(-EINVAL);
 480        struct orangefs_kernel_op_s *new_op;
 481        struct dentry *d = ERR_PTR(-EINVAL);
 482
 483        gossip_debug(GOSSIP_SUPER_DEBUG,
 484                     "orangefs_mount: called with devname %s\n",
 485                     devname);
 486
 487        if (!devname) {
 488                gossip_err("ERROR: device name not specified.\n");
 489                return ERR_PTR(-EINVAL);
 490        }
 491
 492        new_op = op_alloc(ORANGEFS_VFS_OP_FS_MOUNT);
 493        if (!new_op)
 494                return ERR_PTR(-ENOMEM);
 495
 496        strncpy(new_op->upcall.req.fs_mount.orangefs_config_server,
 497                devname,
 498                ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
 499
 500        gossip_debug(GOSSIP_SUPER_DEBUG,
 501                     "Attempting ORANGEFS Mount via host %s\n",
 502                     new_op->upcall.req.fs_mount.orangefs_config_server);
 503
 504        ret = service_operation(new_op, "orangefs_mount", 0);
 505        gossip_debug(GOSSIP_SUPER_DEBUG,
 506                     "orangefs_mount: mount got return value of %d\n", ret);
 507        if (ret)
 508                goto free_op;
 509
 510        if (new_op->downcall.resp.fs_mount.fs_id == ORANGEFS_FS_ID_NULL) {
 511                gossip_err("ERROR: Retrieved null fs_id\n");
 512                ret = -EINVAL;
 513                goto free_op;
 514        }
 515
 516        sb = sget(fst, NULL, set_anon_super, flags, NULL);
 517
 518        if (IS_ERR(sb)) {
 519                d = ERR_CAST(sb);
 520                orangefs_unmount(new_op->downcall.resp.fs_mount.id,
 521                    new_op->downcall.resp.fs_mount.fs_id, devname);
 522                goto free_op;
 523        }
 524
 525        /* alloc and init our private orangefs sb info */
 526        sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
 527        if (!ORANGEFS_SB(sb)) {
 528                d = ERR_PTR(-ENOMEM);
 529                goto free_op;
 530        }
 531
 532        ret = orangefs_fill_sb(sb,
 533              &new_op->downcall.resp.fs_mount, data,
 534              flags & SB_SILENT ? 1 : 0);
 535
 536        if (ret) {
 537                d = ERR_PTR(ret);
 538                goto free_sb_and_op;
 539        }
 540
 541        /*
 542         * on successful mount, store the devname and data
 543         * used
 544         */
 545        strncpy(ORANGEFS_SB(sb)->devname,
 546                devname,
 547                ORANGEFS_MAX_SERVER_ADDR_LEN - 1);
 548
 549        /* mount_pending must be cleared */
 550        ORANGEFS_SB(sb)->mount_pending = 0;
 551
 552        /*
 553         * finally, add this sb to our list of known orangefs
 554         * sb's
 555         */
 556        gossip_debug(GOSSIP_SUPER_DEBUG,
 557                     "Adding SB %p to orangefs superblocks\n",
 558                     ORANGEFS_SB(sb));
 559        spin_lock(&orangefs_superblocks_lock);
 560        list_add_tail(&ORANGEFS_SB(sb)->list, &orangefs_superblocks);
 561        spin_unlock(&orangefs_superblocks_lock);
 562        op_release(new_op);
 563
 564        /* Must be removed from the list now. */
 565        ORANGEFS_SB(sb)->no_list = 0;
 566
 567        if (orangefs_userspace_version >= 20906) {
 568                new_op = op_alloc(ORANGEFS_VFS_OP_FEATURES);
 569                if (!new_op)
 570                        return ERR_PTR(-ENOMEM);
 571                new_op->upcall.req.features.features = 0;
 572                ret = service_operation(new_op, "orangefs_features", 0);
 573                orangefs_features = new_op->downcall.resp.features.features;
 574                op_release(new_op);
 575        } else {
 576                orangefs_features = 0;
 577        }
 578
 579        return dget(sb->s_root);
 580
 581free_sb_and_op:
 582        /* Will call orangefs_kill_sb with sb not in list. */
 583        ORANGEFS_SB(sb)->no_list = 1;
 584        /* ORANGEFS_VFS_OP_FS_UMOUNT is done by orangefs_kill_sb. */
 585        deactivate_locked_super(sb);
 586free_op:
 587        gossip_err("orangefs_mount: mount request failed with %d\n", ret);
 588        if (ret == -EINVAL) {
 589                gossip_err("Ensure that all orangefs-servers have the same FS configuration files\n");
 590                gossip_err("Look at pvfs2-client-core log file (typically /tmp/pvfs2-client.log) for more details\n");
 591        }
 592
 593        op_release(new_op);
 594
 595        return d;
 596}
 597
 598void orangefs_kill_sb(struct super_block *sb)
 599{
 600        int r;
 601        gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_kill_sb: called\n");
 602
 603        /* provided sb cleanup */
 604        kill_anon_super(sb);
 605
 606        if (!ORANGEFS_SB(sb)) {
 607                mutex_lock(&orangefs_request_mutex);
 608                mutex_unlock(&orangefs_request_mutex);
 609                return;
 610        }
 611        /*
 612         * issue the unmount to userspace to tell it to remove the
 613         * dynamic mount info it has for this superblock
 614         */
 615        r = orangefs_unmount(ORANGEFS_SB(sb)->id, ORANGEFS_SB(sb)->fs_id,
 616            ORANGEFS_SB(sb)->devname);
 617        if (!r)
 618                ORANGEFS_SB(sb)->mount_pending = 1;
 619
 620        if (!ORANGEFS_SB(sb)->no_list) {
 621                /* remove the sb from our list of orangefs specific sb's */
 622                spin_lock(&orangefs_superblocks_lock);
 623                /* not list_del_init */
 624                __list_del_entry(&ORANGEFS_SB(sb)->list);
 625                ORANGEFS_SB(sb)->list.prev = NULL;
 626                spin_unlock(&orangefs_superblocks_lock);
 627        }
 628
 629        /*
 630         * make sure that ORANGEFS_DEV_REMOUNT_ALL loop that might've seen us
 631         * gets completed before we free the dang thing.
 632         */
 633        mutex_lock(&orangefs_request_mutex);
 634        mutex_unlock(&orangefs_request_mutex);
 635
 636        /* free the orangefs superblock private data */
 637        kfree(ORANGEFS_SB(sb));
 638}
 639
 640int orangefs_inode_cache_initialize(void)
 641{
 642        orangefs_inode_cache = kmem_cache_create_usercopy(
 643                                        "orangefs_inode_cache",
 644                                        sizeof(struct orangefs_inode_s),
 645                                        0,
 646                                        ORANGEFS_CACHE_CREATE_FLAGS,
 647                                        offsetof(struct orangefs_inode_s,
 648                                                link_target),
 649                                        sizeof_field(struct orangefs_inode_s,
 650                                                link_target),
 651                                        orangefs_inode_cache_ctor);
 652
 653        if (!orangefs_inode_cache) {
 654                gossip_err("Cannot create orangefs_inode_cache\n");
 655                return -ENOMEM;
 656        }
 657        return 0;
 658}
 659
 660int orangefs_inode_cache_finalize(void)
 661{
 662        kmem_cache_destroy(orangefs_inode_cache);
 663        return 0;
 664}
 665