Commit 1c3d71d9 authored by Christoph Hellwig's avatar Christoph Hellwig

XFS: More mount cleanups

Modid: 2.5.x-xfs:slinx:128571a
parent 71660e15
......@@ -264,55 +264,6 @@ printk("XFS: osyncisdsync is now the default, and will soon be deprecated.\n");
return 0;
}
/*
* Convert one device special file to a dev_t.
* Helper routine, used only by spectodevs below.
*/
STATIC int
spectodev(
const char *name,
const char *id,
dev_t *dev)
{
struct nameidata nd;
int error;
error = path_lookup(name, LOOKUP_FOLLOW, &nd);
if (error)
return error;
*dev = kdev_t_to_nr(nd.dentry->d_inode->i_rdev);
path_release(&nd);
return 0;
}
/*
* Convert device special files to dev_t for data, log, realtime.
*/
int
spectodevs(
struct super_block *sb,
struct xfs_mount_args *args,
dev_t *ddevp,
dev_t *logdevp,
dev_t *rtdevp)
{
int rval = 0;
*ddevp = sb->s_dev;
if (args->logname[0])
rval = spectodev(args->logname, "log", logdevp);
else
*logdevp = sb->s_dev;
if (args->rtname[0] && !rval)
rval = spectodev(args->rtname, "realtime", rtdevp);
else
*rtdevp = 0;
return rval;
}
STATIC kmem_cache_t * linvfs_inode_cachep;
......
......@@ -80,18 +80,8 @@
((s)->s_fs_info = vfsp)
struct xfs_mount_args;
extern void
linvfs_set_inode_ops(
struct inode *inode);
extern int
spectodevs(
struct super_block *sb,
struct xfs_mount_args *args,
dev_t *ddevp,
dev_t *logdevp,
dev_t *rtdevp);
#endif /* __XFS_SUPER_H__ */
......@@ -145,7 +145,6 @@ typedef struct pb_target {
struct block_device *pbr_bdev;
struct address_space *pbr_mapping;
unsigned int pbr_blocksize;
unsigned int pbr_blocksize_bits;
} pb_target_t;
/*
......@@ -303,18 +302,6 @@ extern int pagebuf_lock_value( /* return count on lock */
extern int pagebuf_lock( /* lock buffer */
page_buf_t *); /* buffer to lock */
extern void pagebuf_lock_disable( /* disable buffer locking */
struct pb_target *, /* inode for buffers */
int); /* do blkdev_put? */
extern struct pb_target *pagebuf_lock_enable(
dev_t,
int); /* do blkdev_get? */
extern void pagebuf_target_blocksize(
pb_target_t *,
unsigned int); /* block size */
extern void pagebuf_target_clear(struct pb_target *);
extern void pagebuf_unlock( /* unlock buffer */
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
......@@ -58,10 +57,6 @@
#include "page_buf_internal.h"
#ifndef EVMS_MAJOR
#define EVMS_MAJOR 117
#endif
/*
* pagebuf_cond_lock
*
......@@ -126,82 +121,6 @@ pagebuf_lock(
return 0;
}
/*
* pagebuf_lock_disable
*
* pagebuf_lock_disable disables buffer object locking for an inode.
* remove_super() does a blkdev_put for us on the data device, hence
* the do_blkdev_put argument.
*/
void
pagebuf_lock_disable(
pb_target_t *target,
int do_blkdev_put)
{
pagebuf_delwri_flush(target, PBDF_WAIT, NULL);
if (do_blkdev_put)
blkdev_put(target->pbr_bdev, BDEV_FS);
kfree(target);
}
/*
* pagebuf_lock_enable
*
* get_sb_bdev() does a blkdev_get for us on the data device, hence
* the do_blkdev_get argument.
*/
pb_target_t *
pagebuf_lock_enable(
dev_t dev,
int do_blkdev_get)
{
struct block_device *bdev;
pb_target_t *target;
int error = -ENOMEM;
target = kmalloc(sizeof(pb_target_t), GFP_KERNEL);
if (unlikely(!target))
return ERR_PTR(error);
bdev = bdget(dev);
if (unlikely(!bdev))
goto fail;
if (do_blkdev_get) {
error = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
if (unlikely(error))
goto fail;
}
target->pbr_dev = dev;
target->pbr_bdev = bdev;
target->pbr_mapping = bdev->bd_inode->i_mapping;
pagebuf_target_blocksize(target, PAGE_CACHE_SIZE);
if ((MAJOR(dev) == MD_MAJOR) || (MAJOR(dev) == EVMS_MAJOR))
target->pbr_flags = PBR_ALIGNED_ONLY;
else if (MAJOR(dev) == LVM_BLK_MAJOR)
target->pbr_flags = PBR_SECTOR_ONLY;
else
target->pbr_flags = 0;
return target;
fail:
kfree(target);
return ERR_PTR(error);
}
void
pagebuf_target_blocksize(
pb_target_t *target,
unsigned int blocksize)
{
target->pbr_blocksize = blocksize;
target->pbr_blocksize_bits = ffs(blocksize) - 1;
}
void
pagebuf_target_clear(
pb_target_t *target)
......
......@@ -31,6 +31,13 @@
*/
#include <xfs.h>
#include <linux/major.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
#ifndef EVMS_MAJOR
#define EVMS_MAJOR 117
#endif
STATIC void xfs_mount_reset_sbqflags(xfs_mount_t *);
STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
......@@ -1149,15 +1156,17 @@ xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
int have_logdev = (mp->m_logdev_targp != mp->m_ddev_targp);
if (mp->m_ddev_targp) {
pagebuf_lock_disable(mp->m_ddev_targp, 0);
xfs_free_buftarg(mp->m_ddev_targp);
mp->m_ddev_targp = NULL;
}
if (mp->m_rtdev_targp) {
pagebuf_lock_disable(mp->m_rtdev_targp, 1);
xfs_blkdev_put(mp->m_rtdev_targp->pbr_bdev);
xfs_free_buftarg(mp->m_rtdev_targp);
mp->m_rtdev_targp = NULL;
}
if (mp->m_logdev_targp && have_logdev) {
pagebuf_lock_disable(mp->m_logdev_targp, 1);
xfs_blkdev_put(mp->m_logdev_targp->pbr_bdev);
xfs_free_buftarg(mp->m_logdev_targp);
mp->m_logdev_targp = NULL;
}
}
......@@ -1725,3 +1734,71 @@ xfs_check_frozen(
if (level == XFS_FREEZE_TRANS)
atomic_inc(&mp->m_active_trans);
}
int
xfs_blkdev_get(
const char *name,
struct block_device **bdevp)
{
struct nameidata nd;
int error = 0;
error = path_lookup(name, LOOKUP_FOLLOW, &nd);
if (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;
}
void
xfs_blkdev_put(
struct block_device *bdev)
{
blkdev_put(bdev, BDEV_FS);
}
void
xfs_free_buftarg(
xfs_buftarg_t *btp)
{
pagebuf_delwri_flush(btp, PBDF_WAIT, NULL);
kfree(btp);
}
xfs_buftarg_t *
xfs_alloc_buftarg(
struct block_device *bdev)
{
xfs_buftarg_t *btp;
btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
btp->pbr_dev = bdev->bd_dev;
btp->pbr_bdev = bdev;
btp->pbr_mapping = bdev->bd_inode->i_mapping;
btp->pbr_blocksize = PAGE_CACHE_SIZE;
switch (MAJOR(btp->pbr_dev)) {
case MD_MAJOR:
case EVMS_MAJOR:
btp->pbr_flags = PBR_ALIGNED_ONLY;
break;
case LVM_BLK_MAJOR:
btp->pbr_flags = PBR_SECTOR_ONLY;
break;
}
return btp;
}
......@@ -436,6 +436,11 @@ int xfs_syncsub(xfs_mount_t *, int, int, int *);
void xfs_initialize_perag(xfs_mount_t *, int);
void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t);
int xfs_blkdev_get(const char *, struct block_device **);
void xfs_blkdev_put(struct block_device *);
struct xfs_buftarg *xfs_alloc_buftarg(struct block_device *);
void xfs_free_buftarg(struct xfs_buftarg *);
/*
* Flags for freeze operations.
*/
......
......@@ -392,144 +392,114 @@ xfs_finish_flags(
}
/*
* xfs_cmountfs
* xfs_mount
*
* The file system configurations are:
* (1) device (partition) with data and internal log
* (2) logical volume with data and log subvolumes.
* (3) logical volume with data, log, and realtime subvolumes.
*
* This function is the common mount file system function for XFS.
* The Linux VFS took care of finding and opening the data volume for
* us. We have to handle the other two (if present) here.
*/
STATIC int
xfs_cmountfs(
xfs_mount(
vfs_t *vfsp,
dev_t ddev,
dev_t logdev,
dev_t rtdev,
struct xfs_mount_args *ap,
struct cred *cr)
struct xfs_mount_args *args,
cred_t *credp)
{
xfs_mount_t *mp;
struct block_device *ddev, *logdev, *rtdev;
int ronly = (vfsp->vfs_flag & VFS_RDONLY);
int error = 0;
/*
* Allocate VFS private data (xfs mount structure).
*/
mp = xfs_mount_init();
vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
ddev = vfsp->vfs_super->s_bdev;
logdev = rtdev = NULL;
/*
* Open data, real time, and log devices now - order is important.
* Open real time and log devices - order is important.
*/
mp->m_ddev_targp = pagebuf_lock_enable(ddev, 0);
if (IS_ERR(mp->m_ddev_targp)) {
error = PTR_ERR(mp->m_ddev_targp);
goto error2;
if (args->logname[0]) {
error = xfs_blkdev_get(args->logname, &logdev);
if (error)
return error;
}
if (rtdev != 0) {
mp->m_rtdev_targp = pagebuf_lock_enable(rtdev, 1);
if (IS_ERR(mp->m_rtdev_targp)) {
error = PTR_ERR(mp->m_rtdev_targp);
pagebuf_lock_disable(mp->m_ddev_targp, 0);
goto error2;
if (args->rtname[0]) {
error = xfs_blkdev_get(args->rtname, &rtdev);
if (error) {
xfs_blkdev_put(logdev);
return error;
}
if (rtdev == ddev || rtdev == logdev) {
cmn_err(CE_WARN,
"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
error = EINVAL;
pagebuf_lock_disable(mp->m_ddev_targp, 0);
goto error2;
xfs_blkdev_put(logdev);
xfs_blkdev_put(rtdev);
return EINVAL;
}
/* Set the realtime device's block size */
set_blocksize(mp->m_rtdev_targp->pbr_bdev, 512);
}
if (logdev != ddev) {
mp->m_logdev_targp = pagebuf_lock_enable(logdev, 1);
if (IS_ERR(mp->m_logdev_targp)) {
error = PTR_ERR(mp->m_logdev_targp);
pagebuf_lock_disable(mp->m_ddev_targp, 1);
if (mp->m_rtdev_targp)
pagebuf_lock_disable(mp->m_rtdev_targp, 1);
goto error2;
}
/*
* Allocate VFS private data (xfs mount structure).
*/
mp = xfs_mount_init();
/* Set the log device's block size */
set_blocksize(mp->m_logdev_targp->pbr_bdev, 512);
vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
if (rtdev != NULL) {
mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
set_blocksize(rtdev, 512);
}
if (logdev != NULL && logdev != ddev) {
mp->m_logdev_targp = xfs_alloc_buftarg(logdev);
set_blocksize(logdev, 512);
} else {
mp->m_logdev_targp = mp->m_ddev_targp;
}
if ((error = xfs_start_flags(ap, mp, ronly)))
goto error3;
error = xfs_start_flags(args, mp, ronly);
if (error)
goto error;
if ((error = xfs_readsb(mp)))
goto error3;
error = xfs_readsb(mp);
if (error)
goto error;
if ((error = xfs_finish_flags(ap, mp, ronly))) {
error = xfs_finish_flags(args, mp, ronly);
if (error) {
xfs_freesb(mp);
goto error3;
goto error;
}
pagebuf_target_blocksize(mp->m_ddev_targp, mp->m_sb.sb_blocksize);
if (logdev != 0 && logdev != ddev)
pagebuf_target_blocksize(mp->m_logdev_targp,
mp->m_sb.sb_blocksize);
if (rtdev != 0)
pagebuf_target_blocksize(mp->m_rtdev_targp,
mp->m_sb.sb_blocksize);
mp->m_ddev_targp->pbr_blocksize = mp->m_sb.sb_blocksize;
if (logdev != 0 && logdev != ddev) {
mp->m_logdev_targp->pbr_blocksize = mp->m_sb.sb_blocksize;
}
if (rtdev != 0) {
mp->m_rtdev_targp->pbr_blocksize = mp->m_sb.sb_blocksize;
}
mp->m_cxfstype = XFS_CXFS_NOT;
error = xfs_mountfs(vfsp, mp, ddev, 0);
error = xfs_mountfs(vfsp, mp, ddev->bd_dev, 0);
if (error)
goto error3;
goto error;
return 0;
error3:
/* It's impossible to get here before buftargs are filled */
error:
xfs_binval(mp->m_ddev_targp);
pagebuf_lock_disable(mp->m_ddev_targp, 0);
if (logdev && logdev != ddev) {
if (logdev != NULL && logdev != ddev) {
xfs_binval(mp->m_logdev_targp);
pagebuf_lock_disable(mp->m_logdev_targp, 1);
}
if (rtdev != 0) {
if (rtdev != NULL) {
xfs_binval(mp->m_rtdev_targp);
pagebuf_lock_disable(mp->m_rtdev_targp, 1);
}
error2:
if (error) {
xfs_mount_free(mp, 1);
}
xfs_unmountfs_close(mp, NULL);
xfs_mount_free(mp, 1);
return error;
}
/*
* xfs_mount
*
* The file system configurations are:
* (1) device (partition) with data and internal log
* (2) logical volume with data and log subvolumes.
* (3) logical volume with data, log, and realtime subvolumes.
*/
STATIC int
xfs_mount(
vfs_t *vfsp,
struct xfs_mount_args *args,
cred_t *credp)
{
dev_t ddev;
dev_t logdev;
dev_t rtdev;
int error;
error = spectodevs(vfsp->vfs_super, args, &ddev, &logdev, &rtdev);
if (!error)
error = xfs_cmountfs(vfsp, ddev, logdev, rtdev, args, credp);
return (error);
}
/*
* xfs_ibusy searches for a busy inode in the mounted file system.
*
......
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