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