Commit 8c88cd21 authored by Christoph Hellwig's avatar Christoph Hellwig

share some code between get_sb_bdev and xfs log/rtdev handling

parent 1b85674e
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/namei.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -796,3 +797,82 @@ const char *__bdevname(dev_t dev) ...@@ -796,3 +797,82 @@ const char *__bdevname(dev_t dev)
sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev)); sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
return buffer; return buffer;
} }
/**
* open_bdev_excl - open a block device by name and set it up for use
*
* @path: special file representing the block device
* @flags: %MS_RDONLY for opening read-only
* @kind: usage (same as the 4th paramter to blkdev_get)
* @holder: owner for exclusion
*
* Open the blockdevice described by the special file at @path, claim it
* for the @holder and properly set it up for @kind usage.
*/
struct block_device *open_bdev_excl(const char *path, int flags,
int kind, void *holder)
{
struct inode *inode;
struct block_device *bdev;
struct nameidata nd;
mode_t mode = FMODE_READ;
int error = 0;
if (!path || !*path)
return ERR_PTR(-EINVAL);
error = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (error)
return ERR_PTR(error);
inode = nd.dentry->d_inode;
error = -ENOTBLK;
if (!S_ISBLK(inode->i_mode))
goto path_release;
error = -EACCES;
if (nd.mnt->mnt_flags & MNT_NODEV)
goto path_release;
error = bd_acquire(inode);
if (error)
goto path_release;
bdev = inode->i_bdev;
/* Done with lookups */
path_release(&nd);
if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;
error = blkdev_get(bdev, mode, 0, kind);
if (error)
return ERR_PTR(error);
error = -EACCES;
if (!(flags & MS_RDONLY) && bdev_read_only(bdev))
goto blkdev_put;
error = bd_claim(bdev, holder);
if (error)
goto blkdev_put;
return bdev;
blkdev_put:
blkdev_put(bdev, BDEV_FS);
return ERR_PTR(error);
path_release:
path_release(&nd);
return ERR_PTR(error);
}
/**
* close_bdev_excl - release a blockdevice openen by open_bdev_excl()
*
* @bdev: blockdevice to close
* @kind: usage (same as the 4th paramter to blkdev_get)
*
* This is the counterpart to open_bdev_excl().
*/
void close_bdev_excl(struct block_device *bdev, int kind)
{
bd_release(bdev);
blkdev_put(bdev, kind);
}
...@@ -463,55 +463,25 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, ...@@ -463,55 +463,25 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
int flags, char *dev_name, void * data, int flags, char *dev_name, void * data,
int (*fill_super)(struct super_block *, void *, int)) int (*fill_super)(struct super_block *, void *, int))
{ {
struct inode *inode;
struct block_device *bdev; struct block_device *bdev;
struct super_block * s; struct super_block *s;
struct nameidata nd;
int error = 0; int error = 0;
mode_t mode = FMODE_READ; /* we always need it ;-) */
/* What device it is? */ bdev = open_bdev_excl(dev_name, flags, BDEV_FS, fs_type);
if (!dev_name || !*dev_name) if (IS_ERR(bdev))
return ERR_PTR(-EINVAL); return (struct super_block *)bdev;
error = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
if (error)
return ERR_PTR(error);
inode = nd.dentry->d_inode;
error = -ENOTBLK;
if (!S_ISBLK(inode->i_mode))
goto out;
error = -EACCES;
if (nd.mnt->mnt_flags & MNT_NODEV)
goto out;
error = bd_acquire(inode);
if (error)
goto out;
bdev = inode->i_bdev;
/* Done with lookups, semaphore down */
if (!(flags & MS_RDONLY))
mode |= FMODE_WRITE;
error = blkdev_get(bdev, mode, 0, BDEV_FS);
if (error)
goto out;
error = -EACCES;
if (!(flags & MS_RDONLY) && bdev_read_only(bdev))
goto out1;
error = bd_claim(bdev, fs_type);
if (error)
goto out1;
s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
if (IS_ERR(s)) { if (IS_ERR(s))
bd_release(bdev); goto out;
blkdev_put(bdev, BDEV_FS);
} else if (s->s_root) { if (s->s_root) {
if ((flags ^ s->s_flags) & MS_RDONLY) { if ((flags ^ s->s_flags) & MS_RDONLY) {
up_write(&s->s_umount); up_write(&s->s_umount);
deactivate_super(s); deactivate_super(s);
s = ERR_PTR(-EBUSY); s = ERR_PTR(-EBUSY);
} }
bd_release(bdev); goto out;
blkdev_put(bdev, BDEV_FS);
} else { } else {
s->s_flags = flags; s->s_flags = flags;
strncpy(s->s_id, bdevname(bdev), sizeof(s->s_id)); strncpy(s->s_id, bdevname(bdev), sizeof(s->s_id));
...@@ -525,14 +495,12 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, ...@@ -525,14 +495,12 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
} else } else
s->s_flags |= MS_ACTIVE; s->s_flags |= MS_ACTIVE;
} }
path_release(&nd);
return s; return s;
out1:
blkdev_put(bdev, BDEV_FS);
out: out:
path_release(&nd); close_bdev_excl(bdev, BDEV_FS);
return ERR_PTR(error); return s;
} }
void kill_block_super(struct super_block *sb) void kill_block_super(struct super_block *sb)
...@@ -540,8 +508,7 @@ void kill_block_super(struct super_block *sb) ...@@ -540,8 +508,7 @@ void kill_block_super(struct super_block *sb)
struct block_device *bdev = sb->s_bdev; struct block_device *bdev = sb->s_bdev;
generic_shutdown_super(sb); generic_shutdown_super(sb);
set_blocksize(bdev, sb->s_old_blocksize); set_blocksize(bdev, sb->s_old_blocksize);
bd_release(bdev); close_bdev_excl(bdev, BDEV_FS);
blkdev_put(bdev, BDEV_FS);
} }
struct super_block *get_sb_nodev(struct file_system_type *fs_type, struct super_block *get_sb_nodev(struct file_system_type *fs_type,
......
...@@ -466,31 +466,20 @@ xfs_initialize_vnode( ...@@ -466,31 +466,20 @@ xfs_initialize_vnode(
} }
} }
/*ARGSUSED*/
int int
xfs_blkdev_get( xfs_blkdev_get(
xfs_mount_t *mp, xfs_mount_t *mp,
const char *name, const char *name,
struct block_device **bdevp) struct block_device **bdevp)
{ {
struct nameidata nd; int error = 0;
int error;
error = path_lookup(name, LOOKUP_FOLLOW, &nd); *bdevp = open_bdev_excl(name, 0, BDEV_FS, mp);
if (error) { if (IS_ERR(*bdevp)) {
error = PTR_ERR(*bdevp);
printk("XFS: Invalid device [%s], error=%d\n", name, error); printk("XFS: Invalid device [%s], error=%d\n", name, error);
return -error;
}
/* I think we actually want bd_acquire here.. --hch */
*bdevp = bdget(kdev_t_to_nr(nd.dentry->d_inode->i_rdev));
if (*bdevp) {
error = blkdev_get(*bdevp, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
} else {
error = -ENOMEM;
} }
path_release(&nd);
return -error; return -error;
} }
...@@ -499,7 +488,7 @@ xfs_blkdev_put( ...@@ -499,7 +488,7 @@ xfs_blkdev_put(
struct block_device *bdev) struct block_device *bdev)
{ {
if (bdev) if (bdev)
blkdev_put(bdev, BDEV_FS); close_bdev_excl(bdev, BDEV_FS);
} }
void void
......
...@@ -1096,15 +1096,20 @@ extern int bd_claim(struct block_device *, void *); ...@@ -1096,15 +1096,20 @@ extern int bd_claim(struct block_device *, void *);
extern void bd_release(struct block_device *); extern void bd_release(struct block_device *);
extern void blk_run_queues(void); extern void blk_run_queues(void);
/* fs/devices.c */ /* fs/char_dev.c */
extern int register_chrdev(unsigned int, const char *, struct file_operations *); extern int register_chrdev(unsigned int, const char *, struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *); extern int unregister_chrdev(unsigned int, const char *);
extern int chrdev_open(struct inode *, struct file *); extern int chrdev_open(struct inode *, struct file *);
/* fs/block_dev.c */
extern const char *__bdevname(dev_t); extern const char *__bdevname(dev_t);
extern inline const char *bdevname(struct block_device *bdev) extern inline const char *bdevname(struct block_device *bdev)
{ {
return __bdevname(bdev->bd_dev); return __bdevname(bdev->bd_dev);
} }
extern struct block_device *open_bdev_excl(const char *, int, int, void *);
extern void close_bdev_excl(struct block_device *, int);
extern const char * cdevname(kdev_t); extern const char * cdevname(kdev_t);
extern const char * kdevname(kdev_t); extern const char * kdevname(kdev_t);
extern void init_special_inode(struct inode *, umode_t, dev_t); extern void init_special_inode(struct inode *, umode_t, dev_t);
......
...@@ -203,6 +203,8 @@ EXPORT_SYMBOL(bdget); ...@@ -203,6 +203,8 @@ EXPORT_SYMBOL(bdget);
EXPORT_SYMBOL(bdput); EXPORT_SYMBOL(bdput);
EXPORT_SYMBOL(bd_claim); EXPORT_SYMBOL(bd_claim);
EXPORT_SYMBOL(bd_release); EXPORT_SYMBOL(bd_release);
EXPORT_SYMBOL(open_bdev_excl);
EXPORT_SYMBOL(close_bdev_excl);
EXPORT_SYMBOL(__brelse); EXPORT_SYMBOL(__brelse);
EXPORT_SYMBOL(__bforget); EXPORT_SYMBOL(__bforget);
EXPORT_SYMBOL(ll_rw_block); EXPORT_SYMBOL(ll_rw_block);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment