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;
((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__ */
struct block_device *pbr_bdev;
struct address_space *pbr_mapping;
unsigned int pbr_blocksize;
- unsigned int pbr_blocksize_bits;
} pb_target_t;
/*
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
#include "page_buf_internal.h"
-#ifndef EVMS_MAJOR
-#define EVMS_MAJOR 117
-#endif
-
/*
* pagebuf_cond_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)
*/
#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);
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;
}
}
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;
+}
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.
*/
}
/*
- * 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.
*