Example #1
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) {
		deactivate_locked_super(sb);
		return ret;
	}

	/* go */
	sb->s_flags |= MS_ACTIVE;
	simple_set_mnt(mnt, sb);

	return 0;

	/* new mountpoint for an already mounted superblock */
already_mounted:
	DEBUG(1, "MTDSB: Device %d (\"%s\") is already mounted\n",
	      mtd->index, mtd->name);
	simple_set_mnt(mnt, sb);
	ret = 0;
	goto out_put;

out_error:
	ret = PTR_ERR(sb);
out_put:
	put_mtd_device(mtd);
	return ret;
}
Example #2
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;
	char *options;

	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;
		options = NULL;
	} else {
		ns = task_active_pid_ns(current);
		options = data;
	}

	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;
		if (!proc_parse_options(options, ns)) {
			deactivate_locked_super(sb);
			return -EINVAL;
		}
		err = proc_fill_super(sb);
		if (err) {
			deactivate_locked_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;
	}

	simple_set_mnt(mnt, sb);
	return 0;
}
Example #3
0
/*
 * devpts_get_sb()
 *
 *     If the '-o newinstance' mount option was specified, mount a new
 *     (private) instance of devpts.  PTYs created in this instance are
 *     independent of the PTYs in other devpts instances.
 *
 *     If the '-o newinstance' option was not specified, mount/remount the
 *     initial kernel mount of devpts.  This type of mount gives the
 *     legacy, single-instance semantics.
 *
 *     The 'newinstance' option is needed to support multiple namespace
 *     semantics in devpts while preserving backward compatibility of the
 *     current 'single-namespace' semantics. i.e all mounts of devpts
 *     without the 'newinstance' mount option should bind to the initial
 *     kernel mount, like get_sb_single().
 *
 *     Mounts with 'newinstance' option create a new, private namespace.
 *
 *     NOTE:
 *
 *     For single-mount semantics, devpts cannot use get_sb_single(),
 *     because get_sb_single()/sget() find and use the super-block from
 *     the most recent mount of devpts. But that recent mount may be a
 *     'newinstance' mount and get_sb_single() would pick the newinstance
 *     super-block instead of the initial super-block.
 */
static int devpts_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
	int error;
	struct pts_mount_opts opts;
	struct super_block *s;

	error = parse_mount_options(data, PARSE_MOUNT, &opts);
	if (error)
		return error;

	if (opts.newinstance)
		s = sget(fs_type, NULL, set_anon_super, NULL);
	else
		s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);

	if (IS_ERR(s))
		return PTR_ERR(s);

	if (!s->s_root) {
		s->s_flags = flags;
		error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
		if (error)
			goto out_undo_sget;
		s->s_flags |= MS_ACTIVE;
	}

	simple_set_mnt(mnt, s);

	memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));

	error = mknod_ptmx(s);
	if (error)
		goto out_dput;

	return 0;

out_dput:
	dput(s->s_root); /* undo dget() in simple_set_mnt() */

out_undo_sget:
	deactivate_locked_super(s);
	return error;
}
Example #4
0
int
vnlayer_get_sb(
    struct file_system_type *fs_type,
    int flags,
    const char *dev_name,
    void *raw_data,
    struct vfsmount *mnt
)
#endif
{
    SUPER_T *sb;
    int err;

    sb = sget(fs_type, NULL, vnlayer_set_sb, raw_data);
    if (IS_ERR(sb)) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
        return sb;
#else
        return PTR_ERR(sb);
#endif
    }
    err = vnlayer_fill_super(sb, raw_data, 0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
    if (err != 0) {
        generic_shutdown_super(sb);
        sb = ERR_PTR(err);
    }
    return sb;
#else
    if (err != 0) {
        generic_shutdown_super(sb);
    }
    else {
        /* We need to fill the mnt struct */
        simple_set_mnt(mnt, sb);
    }
    return err;
#endif
}
Example #5
0
static int
cifs_get_sb(struct file_system_type *fs_type,
            int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
    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 PTR_ERR(sb);

    sb->s_flags = flags;

    rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0);
    if (rc) {
        deactivate_locked_super(sb);
        return rc;
    }
    sb->s_flags |= MS_ACTIVE;
    simple_set_mnt(mnt, sb);
    return 0;
}
Example #6
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 #7
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;
	int mode = S_IRWXUGO | S_ISVTX;
	struct p9_fid *fid;
	int retval = 0;

	P9_DPRINTK(P9_DEBUG_VFS, " \n");

	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);
		/*
		 * we need to call session_close to tear down some
		 * of the data structure setup by session_init
		 */
		goto close_session;
	}

	sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
	if (IS_ERR(sb)) {
		retval = PTR_ERR(sb);
		goto clunk_fid;
	}
	v9fs_fill_super(sb, v9ses, flags, data);

	inode = v9fs_get_inode(sb, S_IFDIR | mode);
	if (IS_ERR(inode)) {
		retval = PTR_ERR(inode);
		goto release_sb;
	}

	root = d_alloc_root(inode);
	if (!root) {
		iput(inode);
		retval = -ENOMEM;
		goto release_sb;
	}
	sb->s_root = root;
	if (v9fs_proto_dotl(v9ses)) {
		struct p9_stat_dotl *st = NULL;
		st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
		if (IS_ERR(st)) {
			retval = PTR_ERR(st);
			goto release_sb;
		}

		v9fs_stat2inode_dotl(st, root->d_inode);
		kfree(st);
	} else {
		struct p9_wstat *st = NULL;
		st = p9_client_stat(fid);
		if (IS_ERR(st)) {
			retval = PTR_ERR(st);
			goto release_sb;
		}

		root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
		v9fs_stat2inode(st, root->d_inode, sb);

		p9stat_free(st);
		kfree(st);
	}
	retval = v9fs_get_acl(inode, fid);
	if (retval)
		goto release_sb;
	v9fs_fid_add(root, fid);

	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
	simple_set_mnt(mnt, sb);
	return 0;

clunk_fid:
	p9_client_clunk(fid);
close_session:
	v9fs_session_close(v9ses);
	kfree(v9ses);
	return retval;
release_sb:
	/*
	 * we will do the session_close and root dentry release
	 * in the below call. But we need to clunk fid, because we haven't
	 * attached the fid to dentry so it won't get clunked
	 * automatically.
	 */
	p9_client_clunk(fid);
	deactivate_locked_super(sb);
	return retval;
}
Example #8
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;
	fmode_t mode = FMODE_READ;
	struct the_nilfs *nilfs;
	int err, need_to_close = 1;

	if (!(flags & MS_RDONLY))
		mode |= FMODE_WRITE;

	sd.bdev = open_bdev_exclusive(dev_name, mode, 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;
		s->s_mode = mode;
		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_SILENT ? 1 : 0,
				       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, mode);
	simple_set_mnt(mnt, s);
	return 0;

 failed_unlock:
	mutex_unlock(&nilfs->ns_mount_mutex);
	put_nilfs(nilfs);
 failed:
	close_bdev_exclusive(sd.bdev, mode);

	return err;

 cancel_new:
	/* Abandoning the newly allocated superblock */
	mutex_unlock(&nilfs->ns_mount_mutex);
	put_nilfs(nilfs);
	deactivate_locked_super(s);
	/*
	 * deactivate_locked_super() invokes close_bdev_exclusive().
	 * We must finish all post-cleaning before this call;
	 * put_nilfs() needs the block device.
	 */
	return err;
}
Example #9
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 #10
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;
}