Example #1
0
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;
}
Example #2
0
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);
}
Example #3
0
File: zfs_ctldir.c Project: EW1/zfs
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);
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
0
/*
 * 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;
}
Example #7
0
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);
}
Example #8
0
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;
}
Example #9
0
/**
 * 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);
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
void devpts_release(struct pts_fs_info *fsi)
{
	deactivate_super(fsi->sb);
}
Example #13
0
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;
}
Example #14
0
/*
 * 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;
}
Example #15
0
/*
 * 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;
}
Example #16
0
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;
}
Example #17
0
/*
 * 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;
}
Example #18
0
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;
}
Example #19
0
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;
}