/* assumes ctl_mtx is held */
static void _unload_ssd(struct ssd_info * ssd)
{
	if (NULL == ssd)
		return;

	/* first remove it from the set of cache devices, no more
	 * requests will be queued to this device beyond this point */
	if (ssd->cdev) {
		sce_rmcdev(ssd->cdev);
		ssd->cdev = NULL;
	}

	/* make offline and quiesce requests already in flight */
	if (ssd->online) {
		ssd->online = 0;
		list_del_rcu(&ssd->list);
		wmb();
		synchronize_rcu(); /* wait for references to quiesce */
		while(atomic_read(&ssd->nr_ref))
			schedule();
		gctx.nr_ssd--;
	}

	if (ssd->bdev) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
		blkdev_put(ssd->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
		close_bdev_exclusive(ssd->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
#else
		ERR("Kernel version < 2.6.28 currently not supported.\n");
#endif
		ssd->bdev = NULL;
	}
}
Example #2
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 #3
0
/******************************************************************************
 *
 * axfs_get_sb_block
 *
 * Description:
 *      Populates a axfs_fill_super_info struct after sanity checking the
 *    block device
 *
 * Parameters:
 *    (IN) fs_type - pointer to file_system_type
 *
 *    (IN) flags - mount flags
 *
 *    (IN) dev_name - block device name passed in from mount
 *
 *    (IN) secondary_blk_dev - block device name enter from mount -o
 *
 * Returns:
 *    pointer to a axfs_file_super_info or an error pointer
 *
 *****************************************************************************/
static struct axfs_fill_super_info *axfs_get_sb_block(struct file_system_type *fs_type,
				   int flags, const char *dev_name, char *secondary_blk_dev)
{
	struct nameidata nd;
	struct buffer_head *bh = NULL;
	struct axfs_fill_super_info *output;
	struct block_device *bdev = NULL;
	int err;

	err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
	if (err)
		return ERR_PTR(-EINVAL);

	if (secondary_blk_dev) {
		printk(KERN_ERR "axfs: can't mount 2 block device's \"%s\" and \"%s\"\n", dev_name, secondary_blk_dev);
		err = -EINVAL;
		goto path_out;
	}

	if (!S_ISBLK(nd.path.dentry->d_inode->i_mode)) {
		err = -EINVAL;
		goto path_out;
	}

	if (nd.path.mnt->mnt_flags & MNT_NODEV) {
		err = -EACCES;
		goto path_out;
	}

	bdev = open_bdev_exclusive(dev_name, flags, fs_type);

	if (IS_ERR(bdev)){
		err = PTR_ERR(bdev);
		goto path_out;
	}

	bh = __bread(bdev, 0, bdev->bd_block_size);
	if (!bh) {
		err = -EIO;
		goto out;
	}

	output = (struct axfs_fill_super_info *)vmalloc(sizeof(struct axfs_fill_super_info));
	if(!output) {
		err = -ENOMEM;
		goto out;
	}
	output->onmedia_super_block = (struct axfs_super_onmedia *)vmalloc(sizeof(struct axfs_super_onmedia));
	if(!output->onmedia_super_block) {
		err = -ENOMEM;
		goto out;
	}
	memcpy((char *)output->onmedia_super_block, bh->b_data, sizeof(struct axfs_super_onmedia));

	if(IS_ERR(output)) {
		err = PTR_ERR(output);
		goto out;
	}

	output->physical_start_address = 0;
	output->virtual_start_address = 0;

	path_put(&nd.path);
	close_bdev_exclusive(bdev, flags);
	free_buffer_head(bh);

	return output;

out:
	close_bdev_exclusive(bdev,flags);
	if (bh) {
		free_buffer_head(bh);
	}

path_out:
	path_put(&nd.path);
	printk(KERN_NOTICE "axfs_get_sb_block(): Invalid device \"%s\"\n",
	       dev_name);
	return ERR_PTR(err);
}
Example #4
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 dentry *root_dentry;
	int err, s_new = false;

	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);

	sd.cno = 0;
	sd.flags = flags;
	if (nilfs_identify((char *)data, &sd)) {
		err = -EINVAL;
		goto failed;
	}

	/*
	 * once the super is inserted into the list by sget, s_umount
	 * will protect the lockfs code from trying to start a snapshot
	 * while we are mounting
	 */
	mutex_lock(&sd.bdev->bd_fsfreeze_mutex);
	if (sd.bdev->bd_fsfreeze_count > 0) {
		mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
		err = -EBUSY;
		goto failed;
	}
	s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev);
	mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
	if (IS_ERR(s)) {
		err = PTR_ERR(s);
		goto failed;
	}

	if (!s->s_root) {
		char b[BDEVNAME_SIZE];

		s_new = true;

		/* 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);
		if (err)
			goto failed_super;

		s->s_flags |= MS_ACTIVE;
	} else if (!sd.cno) {
		int busy = false;

		if (nilfs_tree_was_touched(s->s_root)) {
			busy = nilfs_try_to_shrink_tree(s->s_root);
			if (busy && (flags ^ s->s_flags) & MS_RDONLY) {
				printk(KERN_ERR "NILFS: the device already "
				       "has a %s mount.\n",
				       (s->s_flags & MS_RDONLY) ?
				       "read-only" : "read/write");
				err = -EBUSY;
				goto failed_super;
			}
		}
		if (!busy) {
			/*
			 * Try remount to setup mount states if the current
			 * tree is not mounted and only snapshots use this sb.
			 */
			err = nilfs_remount(s, &flags, data);
			if (err)
				goto failed_super;
		}
	}

	if (sd.cno) {
		err = nilfs_attach_snapshot(s, sd.cno, &root_dentry);
		if (err)
			goto failed_super;
	} else {
		root_dentry = dget(s->s_root);
	}

	if (!s_new)
		close_bdev_exclusive(sd.bdev, mode);

	mnt->mnt_sb = s;
	mnt->mnt_root = root_dentry;
	return 0;

 failed_super:
	deactivate_locked_super(s);

 failed:
	if (!s_new)
		close_bdev_exclusive(sd.bdev, mode);
	return err;
}