static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct mtd_info *mtd) { struct super_block *sb; struct jffs2_sb_info *c; int ret; c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); memset(c, 0, sizeof(*c)); c->mtd = mtd; sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); if (IS_ERR(sb)) goto out_put; if (sb->s_root) { /* New mountpoint for JFFS2 which is already mounted */ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name)); goto out_put; } D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", mtd->index, mtd->name)); /* Initialize JFFS2 superblock locks, the further initialization will be * done later */ init_MUTEX(&c->alloc_sem); init_MUTEX(&c->erase_free_sem); init_waitqueue_head(&c->erase_wait); init_waitqueue_head(&c->inocache_wq); spin_lock_init(&c->erase_completion_lock); spin_lock_init(&c->inocache_lock); sb->s_op = &jffs2_super_operations; sb->s_flags = flags | MS_NOATIME; ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0); if (ret) { /* Failure case... */ up_write(&sb->s_umount); deactivate_super(sb); return ERR_PTR(ret); } sb->s_flags |= MS_ACTIVE; return sb; out_put: kfree(c); put_mtd_device(mtd); return sb; }
void cifs_sb_deactive(struct super_block *sb) { struct cifs_sb_info *server = CIFS_SB(sb); if (atomic_dec_and_test(&server->active)) deactivate_super(sb); }
int zfsctl_lookup_objset(struct super_block *sb, uint64_t objsetid, zfs_sb_t **zsbp) { zfs_sb_t *zsb = sb->s_fs_info; struct super_block *sbp; zfs_snapentry_t *sep; uint64_t id; int error; ASSERT(zsb->z_ctldir != NULL); mutex_enter(&zsb->z_ctldir_lock); /* * Verify that the snapshot is mounted. */ sep = avl_first(&zsb->z_ctldir_snaps); while (sep != NULL) { error = dmu_snapshot_lookup(zsb->z_os, sep->se_name, &id); if (error) goto out; if (id == objsetid) break; sep = AVL_NEXT(&zsb->z_ctldir_snaps, sep); } if (sep != NULL) { /* * Lookup the mounted root rather than the covered mount * point. This may fail if the snapshot has just been * unmounted by an unrelated user space process. This * race cannot occur to an expired mount point because * we hold the zsb->z_ctldir_lock to prevent the race. */ sbp = zpl_sget(&zpl_fs_type, zfsctl_test_super, zfsctl_set_super, 0, &id); if (IS_ERR(sbp)) { error = -PTR_ERR(sbp); } else { *zsbp = sbp->s_fs_info; deactivate_super(sbp); } } else { error = EINVAL; } out: mutex_exit(&zsb->z_ctldir_lock); ASSERT3S(error, >=, 0); return (error); }
static int proc_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { int err; struct super_block *sb; struct pid_namespace *ns; struct proc_inode *ei; if (proc_mnt) { /* Seed the root directory with a pid so it doesn't need * to be special in base.c. I would do this earlier but * the only task alive when /proc is mounted the first time * is the init_task and it doesn't have any pids. */ ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode); if (!ei->pid) ei->pid = find_get_pid(1); } if (flags & MS_KERNMOUNT) ns = (struct pid_namespace *)data; else ns = current->nsproxy->pid_ns; sb = sget(fs_type, proc_test_super, proc_set_super, ns); if (IS_ERR(sb)) return PTR_ERR(sb); if (!sb->s_root) { sb->s_flags = flags; err = proc_fill_super(sb); if (err) { up_write(&sb->s_umount); deactivate_super(sb); return err; } ei = PROC_I(sb->s_root->d_inode); if (!ei->pid) { rcu_read_lock(); ei->pid = get_pid(find_pid_ns(1, ns)); rcu_read_unlock(); } sb->s_flags |= MS_ACTIVE; ns->proc_mnt = mnt; } return simple_set_mnt(mnt, sb); }
static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct mtd_info *mtd) { struct super_block *sb; struct jffs2_sb_info *c; int ret; c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); memset(c, 0, sizeof(*c)); c->mtd = mtd; sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); if (IS_ERR(sb)) goto out_put; if (sb->s_root) { /* New mountpoint for JFFS2 which is already mounted */ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name)); goto out_put; } D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", mtd->index, mtd->name)); sb->s_op = &jffs2_super_operations; ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0); if (ret) { /* Failure case... */ up_write(&sb->s_umount); deactivate_super(sb); return ERR_PTR(ret); } sb->s_flags |= MS_ACTIVE; return sb; out_put: kfree(c); put_mtd_device(mtd); return sb; }
/* * get a superblock on an MTD-backed filesystem */ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct mtd_info *mtd, int (*fill_super)(struct super_block *, void *, int), struct vfsmount *mnt) { struct super_block *sb; int ret; sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd); if (IS_ERR(sb)) goto out_error; if (sb->s_root) goto already_mounted; /* fresh new superblock */ DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n", mtd->index, mtd->name); sb->s_flags = flags; ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret < 0) { up_write(&sb->s_umount); deactivate_super(sb); return ret; } /* go */ sb->s_flags |= MS_ACTIVE; return simple_set_mnt(mnt, sb); /* new mountpoint for an already mounted superblock */ already_mounted: DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name); ret = simple_set_mnt(mnt, sb); goto out_put; out_error: ret = PTR_ERR(sb); out_put: put_mtd_device(mtd); return ret; }
static struct super_block * perfctr_get_sb_pseudo(struct file_system_type *fs_type, char *name, struct super_operations *ops, unsigned long magic) { struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); static struct super_operations default_ops = {.statfs = simple_statfs}; struct dentry *dentry; struct inode *root; struct qstr d_name = {.name = name, .len = strlen(name)}; if (IS_ERR(s)) return s; s->s_flags = MS_NOUSER; s->s_maxbytes = ~0ULL; s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = magic; s->s_op = ops ? ops : &default_ops; root = new_inode(s); if (!root) goto Enomem; root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; root->i_uid = root->i_gid = 0; root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; dentry = d_alloc(NULL, &d_name); if (!dentry) { iput(root); goto Enomem; } dentry->d_sb = s; dentry->d_parent = dentry; d_instantiate(dentry, root); s->s_root = dentry; s->s_flags |= MS_ACTIVE; return s; Enomem: up_write(&s->s_umount); deactivate_super(s); return ERR_PTR(-ENOMEM); }
static struct super_block * cifs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { int rc; struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); if (IS_ERR(sb)) return sb; sb->s_flags = flags; rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0); if (rc) { up_write(&sb->s_umount); deactivate_super(sb); return ERR_PTR(rc); } sb->s_flags |= MS_ACTIVE; return sb; }
/** * put_fs_context - Dispose of a superblock configuration context. * @fc: The context to dispose of. */ void put_fs_context(struct fs_context *fc) { struct super_block *sb; if (fc->root) { sb = fc->root->d_sb; dput(fc->root); fc->root = NULL; deactivate_super(sb); } if (fc->need_free && fc->ops && fc->ops->free) fc->ops->free(fc); security_free_mnt_opts(&fc->security); put_net(fc->net_ns); put_user_ns(fc->user_ns); put_cred(fc->cred); kfree(fc->subtype); put_fc_log(fc); put_filesystem(fc->fs_type); kfree(fc->source); kfree(fc); }
static int v9fs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { struct super_block *sb = NULL; struct inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; struct p9_stat *st = NULL; int mode = S_IRWXUGO | S_ISVTX; uid_t uid = current->fsuid; gid_t gid = current->fsgid; struct p9_fid *fid; int retval = 0; P9_DPRINTK(P9_DEBUG_VFS, " \n"); st = NULL; v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); fid = NULL; kfree(v9ses); v9ses = NULL; goto error; } st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); goto error; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto error; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto error; } inode->i_uid = uid; inode->i_gid = gid; root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; goto error; } sb->s_root = root; root->d_inode->i_ino = v9fs_qid2ino(&st->qid); v9fs_stat2inode(st, root->d_inode, sb); v9fs_fid_add(root, fid); kfree(st); return simple_set_mnt(mnt, sb); error: kfree(st); if (fid) p9_client_clunk(fid); if (v9ses) { v9fs_session_close(v9ses); kfree(v9ses); } if (sb) { up_write(&sb->s_umount); deactivate_super(sb); } return retval; }
static int dazukofs_fill_super(struct super_block *sb, void *data, int silent) { struct dazukofs_sb_info *sbi; struct dentry *root; static const struct qstr name = { .name = "/", .len = 1 }; struct dazukofs_dentry_info *di; sbi = kmem_cache_zalloc(dazukofs_sb_info_cachep, GFP_KERNEL); if (!sbi) return -ENOMEM; sb->s_op = &dazukofs_sops; root = d_alloc(NULL, &name); if (!root) { kmem_cache_free(dazukofs_sb_info_cachep, sbi); return -ENOMEM; } sb->s_root = root; sb->s_root->d_op = &dazukofs_dops; sb->s_root->d_sb = sb; sb->s_root->d_parent = sb->s_root; di = kmem_cache_zalloc(dazukofs_dentry_info_cachep, GFP_KERNEL); if (!di) { kmem_cache_free(dazukofs_sb_info_cachep, sbi); dput(sb->s_root); return -ENOMEM; } set_dentry_private(sb->s_root, di); set_sb_private(sb, sbi); return 0; } static int dazukofs_read_super(struct super_block *sb, const char *dev_name) { struct nameidata nd; struct dentry *lower_root; struct vfsmount *lower_mnt; int err; memset(&nd, 0, sizeof(struct nameidata)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd.path); #else err = path_lookup(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); #endif if (err) return err; lower_root = dget(nd.path.dentry); lower_mnt = mntget(nd.path.mnt); if (IS_ERR(lower_root)) { err = PTR_ERR(lower_root); goto out_put; } if (!lower_root->d_inode) { err = -ENOENT; goto out_put; } if (!S_ISDIR(lower_root->d_inode->i_mode)) { err = -EINVAL; goto out_put; } set_lower_sb(sb, lower_root->d_sb); sb->s_maxbytes = lower_root->d_sb->s_maxbytes; set_lower_dentry(sb->s_root, lower_root, lower_mnt); err = dazukofs_interpose(lower_root, sb->s_root, sb, 0); if (err) goto out_put; goto out; out_put: dput(lower_root); mntput(lower_mnt); out: path_put(&nd.path); return err; } // FIXME! #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39) static struct dentry* dazukofs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { return mount_nodev(fs_type, flags, data, dazukofs_fill_super); } #else static int dazukofs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { struct super_block *sb; int err; err = get_sb_nodev(fs_type, flags, data, dazukofs_fill_super, mnt); if (err) goto out; sb = mnt->mnt_sb; err = dazukofs_parse_mount_options(data, sb); if (err) goto out_abort; err = dazukofs_read_super(sb, dev_name); if (err) goto out_abort; goto out; out_abort: dput(sb->s_root); up_write(&sb->s_umount); deactivate_super(sb); out: return err; } #endif static void init_once(void *data) { struct dazukofs_inode_info *inode_info = (struct dazukofs_inode_info *)data; memset(inode_info, 0, sizeof(struct dazukofs_inode_info)); inode_init_once(&(inode_info->vfs_inode)); } static void destroy_caches(void) { if (dazukofs_inode_info_cachep) { kmem_cache_destroy(dazukofs_inode_info_cachep); dazukofs_inode_info_cachep = NULL; } if (dazukofs_sb_info_cachep) { kmem_cache_destroy(dazukofs_sb_info_cachep); dazukofs_sb_info_cachep = NULL; } if (dazukofs_dentry_info_cachep) { kmem_cache_destroy(dazukofs_dentry_info_cachep); dazukofs_dentry_info_cachep = NULL; } if (dazukofs_file_info_cachep) { kmem_cache_destroy(dazukofs_file_info_cachep); dazukofs_file_info_cachep = NULL; } } static int init_caches(void) { dazukofs_inode_info_cachep = kmem_cache_create("dazukofs_inode_info_cache", sizeof(struct dazukofs_inode_info), 0, SLAB_HWCACHE_ALIGN, init_once); if (!dazukofs_inode_info_cachep) goto out_nomem; dazukofs_sb_info_cachep = kmem_cache_create("dazukofs_sb_info_cache", sizeof(struct dazukofs_sb_info), 0, SLAB_HWCACHE_ALIGN, NULL); if (!dazukofs_sb_info_cachep) goto out_nomem; dazukofs_dentry_info_cachep = kmem_cache_create("dazukofs_dentry_info_cache", sizeof(struct dazukofs_dentry_info), 0, SLAB_HWCACHE_ALIGN, NULL); if (!dazukofs_dentry_info_cachep) goto out_nomem; dazukofs_file_info_cachep = kmem_cache_create("dazukofs_file_info_cache", sizeof(struct dazukofs_file_info), 0, SLAB_HWCACHE_ALIGN, NULL); if (!dazukofs_file_info_cachep) goto out_nomem; return 0; out_nomem: destroy_caches(); return -ENOMEM; }
void devpts_release(struct pts_fs_info *fsi) { deactivate_super(fsi->sb); }
static int v9fs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { struct super_block *sb = NULL; struct v9fs_fcall *fcall = NULL; struct inode *inode = NULL; struct dentry *root = NULL; struct v9fs_session_info *v9ses = NULL; struct v9fs_fid *root_fid = NULL; int mode = S_IRWXUGO | S_ISVTX; uid_t uid = current->fsuid; gid_t gid = current->fsgid; int stat_result = 0; int newfid = 0; int retval = 0; dprintk(DEBUG_VFS, " \n"); v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); if (!v9ses) return -ENOMEM; if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { dprintk(DEBUG_ERROR, "problem initiating session\n"); retval = newfid; goto out_free_session; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); goto out_close_session; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto put_back_sb; } inode->i_uid = uid; inode->i_gid = gid; root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; goto put_back_sb; } sb->s_root = root; stat_result = v9fs_t_stat(v9ses, newfid, &fcall); if (stat_result < 0) { dprintk(DEBUG_ERROR, "stat error\n"); v9fs_t_clunk(v9ses, newfid); } else { /* Setup the Root Inode */ root_fid = v9fs_fid_create(v9ses, newfid); if (root_fid == NULL) { retval = -ENOMEM; goto put_back_sb; } retval = v9fs_fid_insert(root_fid, root); if (retval < 0) { kfree(fcall); goto put_back_sb; } root_fid->qid = fcall->params.rstat.stat.qid; root->d_inode->i_ino = v9fs_qid2ino(&fcall->params.rstat.stat.qid); v9fs_stat2inode(&fcall->params.rstat.stat, root->d_inode, sb); } kfree(fcall); if (stat_result < 0) { retval = stat_result; goto put_back_sb; } return simple_set_mnt(mnt, sb); out_close_session: v9fs_session_close(v9ses); out_free_session: kfree(v9ses); return retval; put_back_sb: /* deactivate_super calls v9fs_kill_super which will frees the rest */ up_write(&sb->s_umount); deactivate_super(sb); return retval; }
/* * Clone an NFS4 server record on xdev traversal (FSID-change) */ static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { struct nfs_clone_mount *data = raw_data; struct super_block *s; struct nfs_server *server; struct dentry *mntroot; int error; dprintk("--> nfs4_xdev_get_sb()\n"); /* create a new volume representation */ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ s->s_flags = flags; nfs4_clone_super(s, data->sb); } mntroot = nfs4_get_root(s, data->fh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; dprintk("<-- nfs4_xdev_get_sb() = 0\n"); return 0; out_err_nosb: nfs_free_server(server); out_err_noserver: dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); return error; error_splat_super: up_write(&s->s_umount); deactivate_super(s); dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); return error; }
/* * Get the superblock for an NFS4 mountpoint */ static int nfs4_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { struct nfs4_mount_data *data = raw_data; struct super_block *s; struct nfs_server *server; struct sockaddr_in addr; rpc_authflavor_t authflavour; struct nfs_fh mntfh; struct dentry *mntroot; char *mntpath = NULL, *hostname = NULL, ip_addr[16]; void *p; int error; if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); return -EINVAL; } if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { dprintk("%s: bad mount version\n", __FUNCTION__); return -EINVAL; } /* We now require that the mount process passes the remote address */ if (data->host_addrlen != sizeof(addr)) return -EINVAL; if (copy_from_user(&addr, data->host_addr, sizeof(addr))) return -EFAULT; if (addr.sin_family != AF_INET || addr.sin_addr.s_addr == INADDR_ANY ) { dprintk("%s: mount program didn't pass remote IP address!\n", __FUNCTION__); return -EINVAL; } /* RFC3530: The default port for NFS is 2049 */ if (addr.sin_port == 0) addr.sin_port = htons(NFS_PORT); /* Grab the authentication type */ authflavour = RPC_AUTH_UNIX; if (data->auth_flavourlen != 0) { if (data->auth_flavourlen != 1) { dprintk("%s: Invalid number of RPC auth flavours %d.\n", __FUNCTION__, data->auth_flavourlen); error = -EINVAL; goto out_err_noserver; } if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { error = -EFAULT; goto out_err_noserver; } } p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p)) goto out_err; hostname = p; p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); if (IS_ERR(p)) goto out_err; mntpath = p; dprintk("MNTPATH: %s\n", mntpath); p = nfs_copy_user_string(ip_addr, &data->client_addr, sizeof(ip_addr) - 1); if (IS_ERR(p)) goto out_err; /* Get a volume representation */ server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, authflavour, &mntfh); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(fs_type, nfs_compare_super, nfs_set_super, server); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_free; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ s->s_flags = flags; nfs4_fill_super(s); } mntroot = nfs4_get_root(s, &mntfh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; kfree(mntpath); kfree(hostname); return 0; out_err: error = PTR_ERR(p); goto out_err_noserver; out_free: nfs_free_server(server); out_err_noserver: kfree(mntpath); kfree(hostname); return error; error_splat_super: up_write(&s->s_umount); deactivate_super(s); goto out_err_noserver; }
static int nfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { struct nfs_server *server = NULL; struct super_block *s; struct nfs_fh mntfh; struct nfs_mount_data *data = raw_data; struct dentry *mntroot; int error; /* Validate the mount data */ error = nfs_validate_mount_data(data, &mntfh); if (error < 0) return error; /* Get a volume representation */ server = nfs_create_server(data, &mntfh); if (IS_ERR(server)) { error = PTR_ERR(server); goto out_err_noserver; } /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(fs_type, nfs_compare_super, nfs_set_super, server); if (IS_ERR(s)) { error = PTR_ERR(s); goto out_err_nosb; } if (s->s_fs_info != server) { nfs_free_server(server); server = NULL; } if (!s->s_root) { /* initial superblock/root creation */ s->s_flags = flags; nfs_fill_super(s, data); } mntroot = nfs_get_root(s, &mntfh); if (IS_ERR(mntroot)) { error = PTR_ERR(mntroot); goto error_splat_super; } s->s_flags |= MS_ACTIVE; mnt->mnt_sb = s; mnt->mnt_root = mntroot; return 0; out_err_nosb: nfs_free_server(server); out_err_noserver: return error; error_splat_super: up_write(&s->s_umount); deactivate_super(s); return error; }
/* * Find a superblock for the given device / mount point. * * Note: This is based on get_sb_bdev from fs/super.c with a few additions * for multiple device setup. Make sure to keep it in sync. */ static int btrfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { char *subvol_name = NULL; struct block_device *bdev = NULL; struct super_block *s; struct dentry *root; struct btrfs_fs_devices *fs_devices = NULL; fmode_t mode = FMODE_READ; int error = 0; if (!(flags & MS_RDONLY)) mode |= FMODE_WRITE; error = btrfs_parse_early_options(data, mode, fs_type, &subvol_name, &fs_devices); if (error) return error; error = btrfs_scan_one_device(dev_name, mode, fs_type, &fs_devices); if (error) goto error_free_subvol_name; error = btrfs_open_devices(fs_devices, mode, fs_type); if (error) goto error_free_subvol_name; if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { error = -EACCES; goto error_close_devices; } bdev = fs_devices->latest_bdev; s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); if (IS_ERR(s)) goto error_s; if (s->s_root) { if ((flags ^ s->s_flags) & MS_RDONLY) { up_write(&s->s_umount); deactivate_super(s); error = -EBUSY; goto error_close_devices; } btrfs_close_devices(fs_devices); } else { char b[BDEVNAME_SIZE]; s->s_flags = flags; strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); error = btrfs_fill_super(s, fs_devices, data, flags & MS_SILENT ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); goto error_free_subvol_name; } btrfs_sb(s)->fs_info->bdev_holder = fs_type; s->s_flags |= MS_ACTIVE; } if (!strcmp(subvol_name, ".")) root = dget(s->s_root); else { mutex_lock(&s->s_root->d_inode->i_mutex); root = lookup_one_len(subvol_name, s->s_root, strlen(subvol_name)); mutex_unlock(&s->s_root->d_inode->i_mutex); if (IS_ERR(root)) { up_write(&s->s_umount); deactivate_super(s); error = PTR_ERR(root); goto error_free_subvol_name; } if (!root->d_inode) { dput(root); up_write(&s->s_umount); deactivate_super(s); error = -ENXIO; goto error_free_subvol_name; } } mnt->mnt_sb = s; mnt->mnt_root = root; kfree(subvol_name); return 0; error_s: error = PTR_ERR(s); error_close_devices: btrfs_close_devices(fs_devices); error_free_subvol_name: kfree(subvol_name); return error; }
static int jffs2_get_sb_mtd(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct mtd_info *mtd, struct vfsmount *mnt) { struct super_block *sb; struct jffs2_sb_info *c; int ret; c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) return -ENOMEM; c->mtd = mtd; sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); if (IS_ERR(sb)) goto out_error; if (sb->s_root) { /* New mountpoint for JFFS2 which is already mounted */ D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", mtd->index, mtd->name)); ret = simple_set_mnt(mnt, sb); goto out_put; } D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", mtd->index, mtd->name)); /* Initialize JFFS2 superblock locks, the further initialization will be * done later */ init_MUTEX(&c->alloc_sem); init_MUTEX(&c->erase_free_sem); init_waitqueue_head(&c->erase_wait); init_waitqueue_head(&c->inocache_wq); spin_lock_init(&c->erase_completion_lock); spin_lock_init(&c->inocache_lock); sb->s_op = &jffs2_super_operations; sb->s_flags = flags | MS_NOATIME; sb->s_xattr = jffs2_xattr_handlers; #ifdef CONFIG_JFFS2_FS_POSIX_ACL sb->s_flags |= MS_POSIXACL; #endif ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); if (ret) { /* Failure case... */ up_write(&sb->s_umount); deactivate_super(sb); return ret; } sb->s_flags |= MS_ACTIVE; return simple_set_mnt(mnt, sb); out_error: ret = PTR_ERR(sb); out_put: kfree(c); put_mtd_device(mtd); return ret; }
static int nilfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) { struct nilfs_super_data sd; struct super_block *s; struct the_nilfs *nilfs; int err, need_to_close = 1; sd.bdev = open_bdev_exclusive(dev_name, flags, fs_type); if (IS_ERR(sd.bdev)) return PTR_ERR(sd.bdev); /* * To get mount instance using sget() vfs-routine, NILFS needs * much more information than normal filesystems to identify mount * instance. For snapshot mounts, not only a mount type (ro-mount * or rw-mount) but also a checkpoint number is required. */ sd.cno = 0; sd.flags = flags; if (nilfs_identify((char *)data, &sd)) { err = -EINVAL; goto failed; } nilfs = find_or_create_nilfs(sd.bdev); if (!nilfs) { err = -ENOMEM; goto failed; } mutex_lock(&nilfs->ns_mount_mutex); if (!sd.cno) { /* * Check if an exclusive mount exists or not. * Snapshot mounts coexist with a current mount * (i.e. rw-mount or ro-mount), whereas rw-mount and * ro-mount are mutually exclusive. */ down_read(&nilfs->ns_super_sem); if (nilfs->ns_current && ((nilfs->ns_current->s_super->s_flags ^ flags) & MS_RDONLY)) { up_read(&nilfs->ns_super_sem); err = -EBUSY; goto failed_unlock; } up_read(&nilfs->ns_super_sem); } /* * Find existing nilfs_sb_info struct */ sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); /* * Get super block instance holding the nilfs_sb_info struct. * A new instance is allocated if no existing mount is present or * existing instance has been unmounted. */ s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); if (sd.sbi) nilfs_put_sbinfo(sd.sbi); if (IS_ERR(s)) { err = PTR_ERR(s); goto failed_unlock; } if (!s->s_root) { char b[BDEVNAME_SIZE]; /* New superblock instance created */ s->s_flags = flags; strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id)); sb_set_blocksize(s, block_size(sd.bdev)); err = nilfs_fill_super(s, data, flags & MS_VERBOSE, nilfs); if (err) goto cancel_new; s->s_flags |= MS_ACTIVE; need_to_close = 0; } mutex_unlock(&nilfs->ns_mount_mutex); put_nilfs(nilfs); if (need_to_close) close_bdev_exclusive(sd.bdev, flags); simple_set_mnt(mnt, s); return 0; failed_unlock: mutex_unlock(&nilfs->ns_mount_mutex); put_nilfs(nilfs); failed: close_bdev_exclusive(sd.bdev, flags); return err; cancel_new: /* Abandoning the newly allocated superblock */ mutex_unlock(&nilfs->ns_mount_mutex); put_nilfs(nilfs); up_write(&s->s_umount); deactivate_super(s); /* * deactivate_super() invokes close_bdev_exclusive(). * We must finish all post-cleaning before this call; * put_nilfs() needs the block device. */ return err; }