xfs_flush_buftarg(btp, 1);
if (external)
xfs_blkdev_put(btp->pbr_bdev);
+ iput(btp->pbr_mapping->host);
kmem_free(btp, sizeof(*btp));
}
truncate_inode_pages(btp->pbr_mapping, 0LL);
}
-void
+int
xfs_setsize_buftarg(
xfs_buftarg_t *btp,
unsigned int blocksize,
printk(KERN_WARNING
"XFS: Cannot set_blocksize to %u on device %s\n",
sectorsize, XFS_BUFTARG_NAME(btp));
+ return EINVAL;
}
+ return 0;
+}
+
+STATIC int
+xfs_mapping_buftarg(
+ xfs_buftarg_t *btp,
+ struct block_device *bdev)
+{
+ struct inode *inode;
+ struct address_space *mapping;
+ struct backing_dev_info *bdi;
+
+ inode = new_inode(bdev->bd_inode->i_sb);
+ if (!inode) {
+ printk(KERN_WARNING
+ "XFS: Cannot allocate mapping inode for device %s\n",
+ XFS_BUFTARG_NAME(btp));
+ return ENOMEM;
+ }
+ inode->i_mode = S_IFBLK;
+ inode->i_bdev = bdev;
+ inode->i_rdev = bdev->bd_dev;
+ mapping = &inode->i_data;
+ bdi = blk_get_backing_dev_info(bdev);
+ if (!bdi)
+ bdi = &default_backing_dev_info;
+ mapping->backing_dev_info = bdi;
+ mapping_set_gfp_mask(mapping, GFP_KERNEL);
+ btp->pbr_mapping = mapping;
+ return 0;
}
xfs_buftarg_t *
btp->pbr_dev = bdev->bd_dev;
btp->pbr_bdev = bdev;
- btp->pbr_mapping = bdev->bd_inode->i_mapping;
- xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev));
-
+ if (xfs_setsize_buftarg(btp, PAGE_CACHE_SIZE, bdev_hardsect_size(bdev)))
+ goto error;
+ if (xfs_mapping_buftarg(btp, bdev))
+ goto error;
return btp;
+
+error:
+ kmem_free(btp, sizeof(*btp));
+ return NULL;
}
ddev = vfsp->vfs_super->s_bdev;
logdev = rtdev = NULL;
+ /*
+ * Setup xfs_mount function vectors from available behaviors
+ */
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
+ mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
+ mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
+ p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
+ mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
+
/*
* Open real time and log devices - order is important.
*/
}
}
- /*
- * Setup xfs_mount function vectors from available behaviors
- */
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
- mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
- mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
- p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
- mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
-
/*
* Setup xfs_mount buffer target pointers
*/
+ error = ENOMEM;
mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
- if (rtdev)
+ if (!mp->m_ddev_targp) {
+ xfs_blkdev_put(logdev);
+ xfs_blkdev_put(rtdev);
+ return error;
+ }
+ if (rtdev) {
mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev);
+ if (!mp->m_rtdev_targp)
+ goto error0;
+ }
mp->m_logdev_targp = (logdev && logdev != ddev) ?
xfs_alloc_buftarg(logdev) : mp->m_ddev_targp;
+ if (!mp->m_logdev_targp)
+ goto error0;
/*
* Setup flags based on mount(2) options and then the superblock
*/
error = xfs_start_flags(vfsp, args, mp);
if (error)
- goto error;
+ goto error1;
error = xfs_readsb(mp);
if (error)
- goto error;
+ goto error1;
error = xfs_finish_flags(vfsp, args, mp);
- if (error) {
- xfs_freesb(mp);
- goto error;
- }
+ if (error)
+ goto error2;
/*
* Setup xfs_mount buffer target pointers based on superblock
*/
- xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
- mp->m_sb.sb_sectsize);
- if (logdev && logdev != ddev) {
+ error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
+ mp->m_sb.sb_sectsize);
+ if (!error && logdev && logdev != ddev) {
unsigned int log_sector_size = BBSIZE;
if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
log_sector_size = mp->m_sb.sb_logsectsize;
- xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize,
- log_sector_size);
+ error = xfs_setsize_buftarg(mp->m_logdev_targp,
+ mp->m_sb.sb_blocksize,
+ log_sector_size);
}
- if (rtdev)
- xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
- mp->m_sb.sb_blocksize);
+ if (!error && rtdev)
+ error = xfs_setsize_buftarg(mp->m_rtdev_targp,
+ mp->m_sb.sb_blocksize,
+ mp->m_sb.sb_sectsize);
+ if (error)
+ goto error2;
- if (!(error = XFS_IOINIT(vfsp, args, flags)))
+ error = XFS_IOINIT(vfsp, args, flags);
+ if (!error)
return 0;
-
- error:
+error2:
+ if (mp->m_sb_bp)
+ xfs_freesb(mp);
+error1:
xfs_binval(mp->m_ddev_targp);
- if (logdev != NULL && logdev != ddev) {
+ if (logdev && logdev != ddev)
xfs_binval(mp->m_logdev_targp);
- }
- if (rtdev != NULL) {
+ if (rtdev)
xfs_binval(mp->m_rtdev_targp);
- }
- xfs_unmountfs_close(mp, NULL);
+error0:
+ xfs_unmountfs_close(mp, credp);
return error;
}