Commit 0789d8fc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs

* 'for-linus' of git://oss.sgi.com/xfs/xfs:
  xfs: only issues a cache flush on unmount if barriers are enabled
  xfs: prevent lockdep false positive in xfs_iget_cache_miss
  xfs: prevent kernel crash due to corrupted inode log format
parents ebdcc81c c141b292
...@@ -34,6 +34,12 @@ ...@@ -34,6 +34,12 @@
#include <linux/backing-dev.h> #include <linux/backing-dev.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include "xfs_sb.h"
#include "xfs_inum.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
static kmem_zone_t *xfs_buf_zone; static kmem_zone_t *xfs_buf_zone;
STATIC int xfsbufd(void *); STATIC int xfsbufd(void *);
STATIC int xfsbufd_wakeup(int, gfp_t); STATIC int xfsbufd_wakeup(int, gfp_t);
...@@ -1435,9 +1441,11 @@ xfs_unregister_buftarg( ...@@ -1435,9 +1441,11 @@ xfs_unregister_buftarg(
void void
xfs_free_buftarg( xfs_free_buftarg(
xfs_buftarg_t *btp) struct xfs_mount *mp,
struct xfs_buftarg *btp)
{ {
xfs_flush_buftarg(btp, 1); xfs_flush_buftarg(btp, 1);
if (mp->m_flags & XFS_MOUNT_BARRIER)
xfs_blkdev_issue_flush(btp); xfs_blkdev_issue_flush(btp);
xfs_free_bufhash(btp); xfs_free_bufhash(btp);
iput(btp->bt_mapping->host); iput(btp->bt_mapping->host);
......
...@@ -413,7 +413,7 @@ static inline int XFS_bwrite(xfs_buf_t *bp) ...@@ -413,7 +413,7 @@ static inline int XFS_bwrite(xfs_buf_t *bp)
* Handling of buftargs. * Handling of buftargs.
*/ */
extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int); extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
extern void xfs_free_buftarg(xfs_buftarg_t *); extern void xfs_free_buftarg(struct xfs_mount *, struct xfs_buftarg *);
extern void xfs_wait_buftarg(xfs_buftarg_t *); extern void xfs_wait_buftarg(xfs_buftarg_t *);
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int); extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
extern int xfs_flush_buftarg(xfs_buftarg_t *, int); extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
......
...@@ -734,15 +734,15 @@ xfs_close_devices( ...@@ -734,15 +734,15 @@ xfs_close_devices(
{ {
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) { if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) {
struct block_device *logdev = mp->m_logdev_targp->bt_bdev; struct block_device *logdev = mp->m_logdev_targp->bt_bdev;
xfs_free_buftarg(mp->m_logdev_targp); xfs_free_buftarg(mp, mp->m_logdev_targp);
xfs_blkdev_put(logdev); xfs_blkdev_put(logdev);
} }
if (mp->m_rtdev_targp) { if (mp->m_rtdev_targp) {
struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev; struct block_device *rtdev = mp->m_rtdev_targp->bt_bdev;
xfs_free_buftarg(mp->m_rtdev_targp); xfs_free_buftarg(mp, mp->m_rtdev_targp);
xfs_blkdev_put(rtdev); xfs_blkdev_put(rtdev);
} }
xfs_free_buftarg(mp->m_ddev_targp); xfs_free_buftarg(mp, mp->m_ddev_targp);
} }
/* /*
...@@ -811,9 +811,9 @@ xfs_open_devices( ...@@ -811,9 +811,9 @@ xfs_open_devices(
out_free_rtdev_targ: out_free_rtdev_targ:
if (mp->m_rtdev_targp) if (mp->m_rtdev_targp)
xfs_free_buftarg(mp->m_rtdev_targp); xfs_free_buftarg(mp, mp->m_rtdev_targp);
out_free_ddev_targ: out_free_ddev_targ:
xfs_free_buftarg(mp->m_ddev_targp); xfs_free_buftarg(mp, mp->m_ddev_targp);
out_close_rtdev: out_close_rtdev:
if (rtdev) if (rtdev)
xfs_blkdev_put(rtdev); xfs_blkdev_put(rtdev);
......
...@@ -246,9 +246,6 @@ xfs_iget_cache_miss( ...@@ -246,9 +246,6 @@ xfs_iget_cache_miss(
goto out_destroy; goto out_destroy;
} }
if (lock_flags)
xfs_ilock(ip, lock_flags);
/* /*
* Preload the radix tree so we can insert safely under the * Preload the radix tree so we can insert safely under the
* write spinlock. Note that we cannot sleep inside the preload * write spinlock. Note that we cannot sleep inside the preload
...@@ -256,7 +253,16 @@ xfs_iget_cache_miss( ...@@ -256,7 +253,16 @@ xfs_iget_cache_miss(
*/ */
if (radix_tree_preload(GFP_KERNEL)) { if (radix_tree_preload(GFP_KERNEL)) {
error = EAGAIN; error = EAGAIN;
goto out_unlock; goto out_destroy;
}
/*
* Because the inode hasn't been added to the radix-tree yet it can't
* be found by another thread, so we can do the non-sleeping lock here.
*/
if (lock_flags) {
if (!xfs_ilock_nowait(ip, lock_flags))
BUG();
} }
mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1); mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
...@@ -284,7 +290,6 @@ xfs_iget_cache_miss( ...@@ -284,7 +290,6 @@ xfs_iget_cache_miss(
out_preload_end: out_preload_end:
write_unlock(&pag->pag_ici_lock); write_unlock(&pag->pag_ici_lock);
radix_tree_preload_end(); radix_tree_preload_end();
out_unlock:
if (lock_flags) if (lock_flags)
xfs_iunlock(ip, lock_flags); xfs_iunlock(ip, lock_flags);
out_destroy: out_destroy:
......
...@@ -1455,10 +1455,19 @@ xlog_recover_add_to_trans( ...@@ -1455,10 +1455,19 @@ xlog_recover_add_to_trans(
item = item->ri_prev; item = item->ri_prev;
if (item->ri_total == 0) { /* first region to be added */ if (item->ri_total == 0) { /* first region to be added */
if (in_f->ilf_size == 0 ||
in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) {
xlog_warn(
"XFS: bad number of regions (%d) in inode log format",
in_f->ilf_size);
ASSERT(0);
return XFS_ERROR(EIO);
}
item->ri_total = in_f->ilf_size; item->ri_total = in_f->ilf_size;
ASSERT(item->ri_total <= XLOG_MAX_REGIONS_IN_ITEM); item->ri_buf =
item->ri_buf = kmem_zalloc((item->ri_total * kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t),
sizeof(xfs_log_iovec_t)), KM_SLEEP); KM_SLEEP);
} }
ASSERT(item->ri_total > item->ri_cnt); ASSERT(item->ri_total > item->ri_cnt);
/* Description region is ri_buf[0] */ /* Description region is ri_buf[0] */
......
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