diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-07 16:28:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-07 16:28:32 -0400 |
commit | 77a78806c7df8d414c33031a1ca5121876910c4f (patch) | |
tree | 8206a5e1e1f3619bdfb882386c3b6a808f171277 /fs/xfs | |
parent | 7d9071a095023cd1db8fa18fa0d648dc1a5210e0 (diff) | |
parent | 5d54b8cdeaf4679c51a510dea3f8921992d0b064 (diff) |
Merge tag 'xfs-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs
Pull xfs updates from Dave Chinner:
"There isn't a whole lot to this update - it's mostly bug fixes and
they are spread pretty much all over XFS. There are some corruption
fixes, some fixes for log recovery, some fixes that prevent unount
from hanging, a lockdep annotation rework for inode locking to prevent
false positives and the usual random bunch of cleanups and minor
improvements.
Deatils:
- large rework of EFI/EFD lifecycle handling to fix log recovery
corruption issues, crashes and unmount hangs
- separate metadata UUID on disk to enable changing boot label UUID
for v5 filesystems
- fixes for gcc miscompilation on certain platforms and optimisation
levels
- remote attribute allocation and recovery corruption fixes
- inode lockdep annotation rework to fix bugs with too many
subclasses
- directory inode locking changes to prevent lockdep false positives
- a handful of minor corruption fixes
- various other small cleanups and bug fixes"
* tag 'xfs-for-linus-4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs: (42 commits)
xfs: fix error gotos in xfs_setattr_nonsize
xfs: add mssing inode cache attempts counter increment
xfs: return errors from partial I/O failures to files
libxfs: bad magic number should set da block buffer error
xfs: fix non-debug build warnings
xfs: collapse allocsize and biosize mount option handling
xfs: Fix file type directory corruption for btree directories
xfs: lockdep annotations throw warnings on non-debug builds
xfs: Fix uninitialized return value in xfs_alloc_fix_freelist()
xfs: inode lockdep annotations broke non-lockdep build
xfs: flush entire file on dio read/write to cached file
xfs: Fix xfs_attr_leafblock definition
libxfs: readahead of dir3 data blocks should use the read verifier
xfs: stop holding ILOCK over filldir callbacks
xfs: clean up inode lockdep annotations
xfs: swap leaf buffer into path struct atomically during path shift
xfs: relocate sparse inode mount warning
xfs: dquots should be stamped with sb_meta_uuid
xfs: log recovery needs to validate against sb_meta_uuid
xfs: growfs not aware of sb_meta_uuid
...
Diffstat (limited to 'fs/xfs')
55 files changed, 861 insertions, 478 deletions
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index df6828570e87..a096841bd06c 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile | |||
@@ -33,6 +33,7 @@ xfs-y += $(addprefix libxfs/, \ | |||
33 | xfs_attr.o \ | 33 | xfs_attr.o \ |
34 | xfs_attr_leaf.o \ | 34 | xfs_attr_leaf.o \ |
35 | xfs_attr_remote.o \ | 35 | xfs_attr_remote.o \ |
36 | xfs_bit.o \ | ||
36 | xfs_bmap.o \ | 37 | xfs_bmap.o \ |
37 | xfs_bmap_btree.o \ | 38 | xfs_bmap_btree.o \ |
38 | xfs_btree.o \ | 39 | xfs_btree.o \ |
@@ -63,7 +64,6 @@ xfs-$(CONFIG_XFS_RT) += $(addprefix libxfs/, \ | |||
63 | xfs-y += xfs_aops.o \ | 64 | xfs-y += xfs_aops.o \ |
64 | xfs_attr_inactive.o \ | 65 | xfs_attr_inactive.o \ |
65 | xfs_attr_list.o \ | 66 | xfs_attr_list.o \ |
66 | xfs_bit.o \ | ||
67 | xfs_bmap_util.o \ | 67 | xfs_bmap_util.o \ |
68 | xfs_buf.o \ | 68 | xfs_buf.o \ |
69 | xfs_dir2_readdir.o \ | 69 | xfs_dir2_readdir.o \ |
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index f9e9ffe6fb46..ffad7f20342f 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c | |||
@@ -464,7 +464,7 @@ xfs_agfl_verify( | |||
464 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); | 464 | struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); |
465 | int i; | 465 | int i; |
466 | 466 | ||
467 | if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_uuid)) | 467 | if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) |
468 | return false; | 468 | return false; |
469 | if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) | 469 | if (be32_to_cpu(agfl->agfl_magicnum) != XFS_AGFL_MAGIC) |
470 | return false; | 470 | return false; |
@@ -1937,7 +1937,7 @@ xfs_alloc_fix_freelist( | |||
1937 | struct xfs_alloc_arg targs; /* local allocation arguments */ | 1937 | struct xfs_alloc_arg targs; /* local allocation arguments */ |
1938 | xfs_agblock_t bno; /* freelist block */ | 1938 | xfs_agblock_t bno; /* freelist block */ |
1939 | xfs_extlen_t need; /* total blocks needed in freelist */ | 1939 | xfs_extlen_t need; /* total blocks needed in freelist */ |
1940 | int error; | 1940 | int error = 0; |
1941 | 1941 | ||
1942 | if (!pag->pagf_init) { | 1942 | if (!pag->pagf_init) { |
1943 | error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); | 1943 | error = xfs_alloc_read_agf(mp, tp, args->agno, flags, &agbp); |
@@ -2260,7 +2260,7 @@ xfs_agf_verify( | |||
2260 | struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); | 2260 | struct xfs_agf *agf = XFS_BUF_TO_AGF(bp); |
2261 | 2261 | ||
2262 | if (xfs_sb_version_hascrc(&mp->m_sb) && | 2262 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
2263 | !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_uuid)) | 2263 | !uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) |
2264 | return false; | 2264 | return false; |
2265 | 2265 | ||
2266 | if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && | 2266 | if (!(agf->agf_magicnum == cpu_to_be32(XFS_AGF_MAGIC) && |
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c index 59d521c09a17..90de071dd4c2 100644 --- a/fs/xfs/libxfs/xfs_alloc_btree.c +++ b/fs/xfs/libxfs/xfs_alloc_btree.c | |||
@@ -295,7 +295,7 @@ xfs_allocbt_verify( | |||
295 | case cpu_to_be32(XFS_ABTB_CRC_MAGIC): | 295 | case cpu_to_be32(XFS_ABTB_CRC_MAGIC): |
296 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 296 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
297 | return false; | 297 | return false; |
298 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) | 298 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) |
299 | return false; | 299 | return false; |
300 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) | 300 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) |
301 | return false; | 301 | return false; |
@@ -313,7 +313,7 @@ xfs_allocbt_verify( | |||
313 | case cpu_to_be32(XFS_ABTC_CRC_MAGIC): | 313 | case cpu_to_be32(XFS_ABTC_CRC_MAGIC): |
314 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 314 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
315 | return false; | 315 | return false; |
316 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) | 316 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) |
317 | return false; | 317 | return false; |
318 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) | 318 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) |
319 | return false; | 319 | return false; |
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 3349c9a1e845..ff065578969f 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c | |||
@@ -139,6 +139,8 @@ xfs_attr_get( | |||
139 | 139 | ||
140 | args.value = value; | 140 | args.value = value; |
141 | args.valuelen = *valuelenp; | 141 | args.valuelen = *valuelenp; |
142 | /* Entirely possible to look up a name which doesn't exist */ | ||
143 | args.op_flags = XFS_DA_OP_OKNOENT; | ||
142 | 144 | ||
143 | lock_mode = xfs_ilock_attr_map_shared(ip); | 145 | lock_mode = xfs_ilock_attr_map_shared(ip); |
144 | if (!xfs_inode_hasattr(ip)) | 146 | if (!xfs_inode_hasattr(ip)) |
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index e9d401ce93bb..33df52d97ec7 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c | |||
@@ -262,7 +262,7 @@ xfs_attr3_leaf_verify( | |||
262 | if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) | 262 | if (ichdr.magic != XFS_ATTR3_LEAF_MAGIC) |
263 | return false; | 263 | return false; |
264 | 264 | ||
265 | if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid)) | 265 | if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) |
266 | return false; | 266 | return false; |
267 | if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) | 267 | if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) |
268 | return false; | 268 | return false; |
@@ -1056,7 +1056,7 @@ xfs_attr3_leaf_create( | |||
1056 | 1056 | ||
1057 | hdr3->blkno = cpu_to_be64(bp->b_bn); | 1057 | hdr3->blkno = cpu_to_be64(bp->b_bn); |
1058 | hdr3->owner = cpu_to_be64(dp->i_ino); | 1058 | hdr3->owner = cpu_to_be64(dp->i_ino); |
1059 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); | 1059 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); |
1060 | 1060 | ||
1061 | ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); | 1061 | ichdr.freemap[0].base = sizeof(struct xfs_attr3_leaf_hdr); |
1062 | } else { | 1062 | } else { |
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index dd714037c322..f38f9bd81557 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c | |||
@@ -100,7 +100,7 @@ xfs_attr3_rmt_verify( | |||
100 | return false; | 100 | return false; |
101 | if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC)) | 101 | if (rmt->rm_magic != cpu_to_be32(XFS_ATTR3_RMT_MAGIC)) |
102 | return false; | 102 | return false; |
103 | if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_uuid)) | 103 | if (!uuid_equal(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid)) |
104 | return false; | 104 | return false; |
105 | if (be64_to_cpu(rmt->rm_blkno) != bno) | 105 | if (be64_to_cpu(rmt->rm_blkno) != bno) |
106 | return false; | 106 | return false; |
@@ -222,7 +222,7 @@ xfs_attr3_rmt_hdr_set( | |||
222 | rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC); | 222 | rmt->rm_magic = cpu_to_be32(XFS_ATTR3_RMT_MAGIC); |
223 | rmt->rm_offset = cpu_to_be32(offset); | 223 | rmt->rm_offset = cpu_to_be32(offset); |
224 | rmt->rm_bytes = cpu_to_be32(size); | 224 | rmt->rm_bytes = cpu_to_be32(size); |
225 | uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_uuid); | 225 | uuid_copy(&rmt->rm_uuid, &mp->m_sb.sb_meta_uuid); |
226 | rmt->rm_owner = cpu_to_be64(ino); | 226 | rmt->rm_owner = cpu_to_be64(ino); |
227 | rmt->rm_blkno = cpu_to_be64(bno); | 227 | rmt->rm_blkno = cpu_to_be64(bno); |
228 | 228 | ||
@@ -618,9 +618,8 @@ xfs_attr_rmtval_remove( | |||
618 | 618 | ||
619 | xfs_bmap_init(args->flist, args->firstblock); | 619 | xfs_bmap_init(args->flist, args->firstblock); |
620 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, | 620 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, |
621 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 621 | XFS_BMAPI_ATTRFORK, 1, args->firstblock, |
622 | 1, args->firstblock, args->flist, | 622 | args->flist, &done); |
623 | &done); | ||
624 | if (!error) { | 623 | if (!error) { |
625 | error = xfs_bmap_finish(&args->trans, args->flist, | 624 | error = xfs_bmap_finish(&args->trans, args->flist, |
626 | &committed); | 625 | &committed); |
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/libxfs/xfs_bit.c index 0e8885a59646..0e8885a59646 100644 --- a/fs/xfs/xfs_bit.c +++ b/fs/xfs/libxfs/xfs_bit.c | |||
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 63e05b663380..8e2010d53b07 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -5945,6 +5945,7 @@ xfs_bmap_split_extent( | |||
5945 | return xfs_trans_commit(tp); | 5945 | return xfs_trans_commit(tp); |
5946 | 5946 | ||
5947 | out: | 5947 | out: |
5948 | xfs_bmap_cancel(&free_list); | ||
5948 | xfs_trans_cancel(tp); | 5949 | xfs_trans_cancel(tp); |
5949 | return error; | 5950 | return error; |
5950 | } | 5951 | } |
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 2c44c8e50782..6b0cf6546a82 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c | |||
@@ -349,7 +349,8 @@ xfs_bmbt_to_bmdr( | |||
349 | 349 | ||
350 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 350 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
351 | ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC)); | 351 | ASSERT(rblock->bb_magic == cpu_to_be32(XFS_BMAP_CRC_MAGIC)); |
352 | ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid)); | 352 | ASSERT(uuid_equal(&rblock->bb_u.l.bb_uuid, |
353 | &mp->m_sb.sb_meta_uuid)); | ||
353 | ASSERT(rblock->bb_u.l.bb_blkno == | 354 | ASSERT(rblock->bb_u.l.bb_blkno == |
354 | cpu_to_be64(XFS_BUF_DADDR_NULL)); | 355 | cpu_to_be64(XFS_BUF_DADDR_NULL)); |
355 | } else | 356 | } else |
@@ -647,7 +648,7 @@ xfs_bmbt_verify( | |||
647 | case cpu_to_be32(XFS_BMAP_CRC_MAGIC): | 648 | case cpu_to_be32(XFS_BMAP_CRC_MAGIC): |
648 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 649 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
649 | return false; | 650 | return false; |
650 | if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid)) | 651 | if (!uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid)) |
651 | return false; | 652 | return false; |
652 | if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn) | 653 | if (be64_to_cpu(block->bb_u.l.bb_blkno) != bp->b_bn) |
653 | return false; | 654 | return false; |
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index c72283dd8d44..f7d7ee7a2607 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c | |||
@@ -65,7 +65,8 @@ xfs_btree_check_lblock( | |||
65 | 65 | ||
66 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 66 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
67 | lblock_ok = lblock_ok && | 67 | lblock_ok = lblock_ok && |
68 | uuid_equal(&block->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid) && | 68 | uuid_equal(&block->bb_u.l.bb_uuid, |
69 | &mp->m_sb.sb_meta_uuid) && | ||
69 | block->bb_u.l.bb_blkno == cpu_to_be64( | 70 | block->bb_u.l.bb_blkno == cpu_to_be64( |
70 | bp ? bp->b_bn : XFS_BUF_DADDR_NULL); | 71 | bp ? bp->b_bn : XFS_BUF_DADDR_NULL); |
71 | } | 72 | } |
@@ -115,7 +116,8 @@ xfs_btree_check_sblock( | |||
115 | 116 | ||
116 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 117 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
117 | sblock_ok = sblock_ok && | 118 | sblock_ok = sblock_ok && |
118 | uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid) && | 119 | uuid_equal(&block->bb_u.s.bb_uuid, |
120 | &mp->m_sb.sb_meta_uuid) && | ||
119 | block->bb_u.s.bb_blkno == cpu_to_be64( | 121 | block->bb_u.s.bb_blkno == cpu_to_be64( |
120 | bp ? bp->b_bn : XFS_BUF_DADDR_NULL); | 122 | bp ? bp->b_bn : XFS_BUF_DADDR_NULL); |
121 | } | 123 | } |
@@ -1000,7 +1002,7 @@ xfs_btree_init_block_int( | |||
1000 | if (flags & XFS_BTREE_CRC_BLOCKS) { | 1002 | if (flags & XFS_BTREE_CRC_BLOCKS) { |
1001 | buf->bb_u.l.bb_blkno = cpu_to_be64(blkno); | 1003 | buf->bb_u.l.bb_blkno = cpu_to_be64(blkno); |
1002 | buf->bb_u.l.bb_owner = cpu_to_be64(owner); | 1004 | buf->bb_u.l.bb_owner = cpu_to_be64(owner); |
1003 | uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_uuid); | 1005 | uuid_copy(&buf->bb_u.l.bb_uuid, &mp->m_sb.sb_meta_uuid); |
1004 | buf->bb_u.l.bb_pad = 0; | 1006 | buf->bb_u.l.bb_pad = 0; |
1005 | buf->bb_u.l.bb_lsn = 0; | 1007 | buf->bb_u.l.bb_lsn = 0; |
1006 | } | 1008 | } |
@@ -1013,7 +1015,7 @@ xfs_btree_init_block_int( | |||
1013 | if (flags & XFS_BTREE_CRC_BLOCKS) { | 1015 | if (flags & XFS_BTREE_CRC_BLOCKS) { |
1014 | buf->bb_u.s.bb_blkno = cpu_to_be64(blkno); | 1016 | buf->bb_u.s.bb_blkno = cpu_to_be64(blkno); |
1015 | buf->bb_u.s.bb_owner = cpu_to_be32(__owner); | 1017 | buf->bb_u.s.bb_owner = cpu_to_be32(__owner); |
1016 | uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid); | 1018 | uuid_copy(&buf->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid); |
1017 | buf->bb_u.s.bb_lsn = 0; | 1019 | buf->bb_u.s.bb_lsn = 0; |
1018 | } | 1020 | } |
1019 | } | 1021 | } |
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index 2385f8cd08ab..be43248a5822 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c | |||
@@ -146,7 +146,7 @@ xfs_da3_node_verify( | |||
146 | if (ichdr.magic != XFS_DA3_NODE_MAGIC) | 146 | if (ichdr.magic != XFS_DA3_NODE_MAGIC) |
147 | return false; | 147 | return false; |
148 | 148 | ||
149 | if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_uuid)) | 149 | if (!uuid_equal(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid)) |
150 | return false; | 150 | return false; |
151 | if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) | 151 | if (be64_to_cpu(hdr3->info.blkno) != bp->b_bn) |
152 | return false; | 152 | return false; |
@@ -233,6 +233,7 @@ xfs_da3_node_read_verify( | |||
233 | bp->b_ops->verify_read(bp); | 233 | bp->b_ops->verify_read(bp); |
234 | return; | 234 | return; |
235 | default: | 235 | default: |
236 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | ||
236 | break; | 237 | break; |
237 | } | 238 | } |
238 | 239 | ||
@@ -324,7 +325,7 @@ xfs_da3_node_create( | |||
324 | ichdr.magic = XFS_DA3_NODE_MAGIC; | 325 | ichdr.magic = XFS_DA3_NODE_MAGIC; |
325 | hdr3->info.blkno = cpu_to_be64(bp->b_bn); | 326 | hdr3->info.blkno = cpu_to_be64(bp->b_bn); |
326 | hdr3->info.owner = cpu_to_be64(args->dp->i_ino); | 327 | hdr3->info.owner = cpu_to_be64(args->dp->i_ino); |
327 | uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_uuid); | 328 | uuid_copy(&hdr3->info.uuid, &mp->m_sb.sb_meta_uuid); |
328 | } else { | 329 | } else { |
329 | ichdr.magic = XFS_DA_NODE_MAGIC; | 330 | ichdr.magic = XFS_DA_NODE_MAGIC; |
330 | } | 331 | } |
@@ -1822,6 +1823,7 @@ xfs_da3_path_shift( | |||
1822 | struct xfs_da_args *args; | 1823 | struct xfs_da_args *args; |
1823 | struct xfs_da_node_entry *btree; | 1824 | struct xfs_da_node_entry *btree; |
1824 | struct xfs_da3_icnode_hdr nodehdr; | 1825 | struct xfs_da3_icnode_hdr nodehdr; |
1826 | struct xfs_buf *bp; | ||
1825 | xfs_dablk_t blkno = 0; | 1827 | xfs_dablk_t blkno = 0; |
1826 | int level; | 1828 | int level; |
1827 | int error; | 1829 | int error; |
@@ -1866,20 +1868,24 @@ xfs_da3_path_shift( | |||
1866 | */ | 1868 | */ |
1867 | for (blk++, level++; level < path->active; blk++, level++) { | 1869 | for (blk++, level++; level < path->active; blk++, level++) { |
1868 | /* | 1870 | /* |
1869 | * Release the old block. | 1871 | * Read the next child block into a local buffer. |
1870 | * (if it's dirty, trans won't actually let go) | ||
1871 | */ | 1872 | */ |
1872 | if (release) | 1873 | error = xfs_da3_node_read(args->trans, dp, blkno, -1, &bp, |
1873 | xfs_trans_brelse(args->trans, blk->bp); | 1874 | args->whichfork); |
1875 | if (error) | ||
1876 | return error; | ||
1874 | 1877 | ||
1875 | /* | 1878 | /* |
1876 | * Read the next child block. | 1879 | * Release the old block (if it's dirty, the trans doesn't |
1880 | * actually let go) and swap the local buffer into the path | ||
1881 | * structure. This ensures failure of the above read doesn't set | ||
1882 | * a NULL buffer in an active slot in the path. | ||
1877 | */ | 1883 | */ |
1884 | if (release) | ||
1885 | xfs_trans_brelse(args->trans, blk->bp); | ||
1878 | blk->blkno = blkno; | 1886 | blk->blkno = blkno; |
1879 | error = xfs_da3_node_read(args->trans, dp, blkno, -1, | 1887 | blk->bp = bp; |
1880 | &blk->bp, args->whichfork); | 1888 | |
1881 | if (error) | ||
1882 | return error; | ||
1883 | info = blk->bp->b_addr; | 1889 | info = blk->bp->b_addr; |
1884 | ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || | 1890 | ASSERT(info->magic == cpu_to_be16(XFS_DA_NODE_MAGIC) || |
1885 | info->magic == cpu_to_be16(XFS_DA3_NODE_MAGIC) || | 1891 | info->magic == cpu_to_be16(XFS_DA3_NODE_MAGIC) || |
@@ -2351,8 +2357,8 @@ xfs_da_shrink_inode( | |||
2351 | * the last block to the place we want to kill. | 2357 | * the last block to the place we want to kill. |
2352 | */ | 2358 | */ |
2353 | error = xfs_bunmapi(tp, dp, dead_blkno, count, | 2359 | error = xfs_bunmapi(tp, dp, dead_blkno, count, |
2354 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, | 2360 | xfs_bmapi_aflag(w), 0, args->firstblock, |
2355 | 0, args->firstblock, args->flist, &done); | 2361 | args->flist, &done); |
2356 | if (error == -ENOSPC) { | 2362 | if (error == -ENOSPC) { |
2357 | if (w != XFS_DATA_FORK) | 2363 | if (w != XFS_DATA_FORK) |
2358 | break; | 2364 | break; |
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 74bcbabfa523..b14bbd6bb05f 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h | |||
@@ -680,8 +680,15 @@ typedef struct xfs_attr_leaf_name_remote { | |||
680 | typedef struct xfs_attr_leafblock { | 680 | typedef struct xfs_attr_leafblock { |
681 | xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ | 681 | xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */ |
682 | xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ | 682 | xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */ |
683 | xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */ | 683 | /* |
684 | xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */ | 684 | * The rest of the block contains the following structures after the |
685 | * leaf entries, growing from the bottom up. The variables are never | ||
686 | * referenced and definining them can actually make gcc optimize away | ||
687 | * accesses to the 'entries' array above index 0 so don't do that. | ||
688 | * | ||
689 | * xfs_attr_leaf_name_local_t namelist; | ||
690 | * xfs_attr_leaf_name_remote_t valuelist; | ||
691 | */ | ||
685 | } xfs_attr_leafblock_t; | 692 | } xfs_attr_leafblock_t; |
686 | 693 | ||
687 | /* | 694 | /* |
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index a69fb3a1e161..9de401d297e5 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c | |||
@@ -362,6 +362,7 @@ xfs_dir_lookup( | |||
362 | struct xfs_da_args *args; | 362 | struct xfs_da_args *args; |
363 | int rval; | 363 | int rval; |
364 | int v; /* type-checking value */ | 364 | int v; /* type-checking value */ |
365 | int lock_mode; | ||
365 | 366 | ||
366 | ASSERT(S_ISDIR(dp->i_d.di_mode)); | 367 | ASSERT(S_ISDIR(dp->i_d.di_mode)); |
367 | XFS_STATS_INC(xs_dir_lookup); | 368 | XFS_STATS_INC(xs_dir_lookup); |
@@ -387,6 +388,7 @@ xfs_dir_lookup( | |||
387 | if (ci_name) | 388 | if (ci_name) |
388 | args->op_flags |= XFS_DA_OP_CILOOKUP; | 389 | args->op_flags |= XFS_DA_OP_CILOOKUP; |
389 | 390 | ||
391 | lock_mode = xfs_ilock_data_map_shared(dp); | ||
390 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | 392 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
391 | rval = xfs_dir2_sf_lookup(args); | 393 | rval = xfs_dir2_sf_lookup(args); |
392 | goto out_check_rval; | 394 | goto out_check_rval; |
@@ -419,6 +421,7 @@ out_check_rval: | |||
419 | } | 421 | } |
420 | } | 422 | } |
421 | out_free: | 423 | out_free: |
424 | xfs_iunlock(dp, lock_mode); | ||
422 | kmem_free(args); | 425 | kmem_free(args); |
423 | return rval; | 426 | return rval; |
424 | } | 427 | } |
@@ -674,25 +677,22 @@ xfs_dir2_shrink_inode( | |||
674 | mp = dp->i_mount; | 677 | mp = dp->i_mount; |
675 | tp = args->trans; | 678 | tp = args->trans; |
676 | da = xfs_dir2_db_to_da(args->geo, db); | 679 | da = xfs_dir2_db_to_da(args->geo, db); |
677 | /* | 680 | |
678 | * Unmap the fsblock(s). | 681 | /* Unmap the fsblock(s). */ |
679 | */ | 682 | error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, |
680 | if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, | 683 | args->firstblock, args->flist, &done); |
681 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, | 684 | if (error) { |
682 | &done))) { | ||
683 | /* | 685 | /* |
684 | * ENOSPC actually can happen if we're in a removename with | 686 | * ENOSPC actually can happen if we're in a removename with no |
685 | * no space reservation, and the resulting block removal | 687 | * space reservation, and the resulting block removal would |
686 | * would cause a bmap btree split or conversion from extents | 688 | * cause a bmap btree split or conversion from extents to btree. |
687 | * to btree. This can only happen for un-fragmented | 689 | * This can only happen for un-fragmented directory blocks, |
688 | * directory blocks, since you need to be punching out | 690 | * since you need to be punching out the middle of an extent. |
689 | * the middle of an extent. | 691 | * In this case we need to leave the block in the file, and not |
690 | * In this case we need to leave the block in the file, | 692 | * binval it. So the block has to be in a consistent empty |
691 | * and not binval it. | 693 | * state and appropriately logged. We don't free up the buffer, |
692 | * So the block has to be in a consistent empty state | 694 | * the caller can tell it hasn't happened since it got an error |
693 | * and appropriately logged. | 695 | * back. |
694 | * We don't free up the buffer, the caller can tell it | ||
695 | * hasn't happened since it got an error back. | ||
696 | */ | 696 | */ |
697 | return error; | 697 | return error; |
698 | } | 698 | } |
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c index 9354e190b82e..4778d1dd511a 100644 --- a/fs/xfs/libxfs/xfs_dir2_block.c +++ b/fs/xfs/libxfs/xfs_dir2_block.c | |||
@@ -67,7 +67,7 @@ xfs_dir3_block_verify( | |||
67 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 67 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
68 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) | 68 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) |
69 | return false; | 69 | return false; |
70 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) | 70 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
71 | return false; | 71 | return false; |
72 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) | 72 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
73 | return false; | 73 | return false; |
@@ -157,7 +157,7 @@ xfs_dir3_block_init( | |||
157 | hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); | 157 | hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC); |
158 | hdr3->blkno = cpu_to_be64(bp->b_bn); | 158 | hdr3->blkno = cpu_to_be64(bp->b_bn); |
159 | hdr3->owner = cpu_to_be64(dp->i_ino); | 159 | hdr3->owner = cpu_to_be64(dp->i_ino); |
160 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); | 160 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); |
161 | return; | 161 | return; |
162 | 162 | ||
163 | } | 163 | } |
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c index de1ea16f5748..824131e71bc5 100644 --- a/fs/xfs/libxfs/xfs_dir2_data.c +++ b/fs/xfs/libxfs/xfs_dir2_data.c | |||
@@ -220,7 +220,7 @@ xfs_dir3_data_verify( | |||
220 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 220 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
221 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) | 221 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_DATA_MAGIC)) |
222 | return false; | 222 | return false; |
223 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) | 223 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
224 | return false; | 224 | return false; |
225 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) | 225 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
226 | return false; | 226 | return false; |
@@ -252,7 +252,8 @@ xfs_dir3_data_reada_verify( | |||
252 | return; | 252 | return; |
253 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): | 253 | case cpu_to_be32(XFS_DIR2_DATA_MAGIC): |
254 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): | 254 | case cpu_to_be32(XFS_DIR3_DATA_MAGIC): |
255 | xfs_dir3_data_verify(bp); | 255 | bp->b_ops = &xfs_dir3_data_buf_ops; |
256 | bp->b_ops->verify_read(bp); | ||
256 | return; | 257 | return; |
257 | default: | 258 | default: |
258 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | 259 | xfs_buf_ioerror(bp, -EFSCORRUPTED); |
@@ -604,7 +605,7 @@ xfs_dir3_data_init( | |||
604 | hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); | 605 | hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC); |
605 | hdr3->blkno = cpu_to_be64(bp->b_bn); | 606 | hdr3->blkno = cpu_to_be64(bp->b_bn); |
606 | hdr3->owner = cpu_to_be64(dp->i_ino); | 607 | hdr3->owner = cpu_to_be64(dp->i_ino); |
607 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid); | 608 | uuid_copy(&hdr3->uuid, &mp->m_sb.sb_meta_uuid); |
608 | 609 | ||
609 | } else | 610 | } else |
610 | hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); | 611 | hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); |
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c index 106119955400..f300240ebb8d 100644 --- a/fs/xfs/libxfs/xfs_dir2_leaf.c +++ b/fs/xfs/libxfs/xfs_dir2_leaf.c | |||
@@ -160,7 +160,7 @@ xfs_dir3_leaf_verify( | |||
160 | 160 | ||
161 | if (leaf3->info.hdr.magic != cpu_to_be16(magic3)) | 161 | if (leaf3->info.hdr.magic != cpu_to_be16(magic3)) |
162 | return false; | 162 | return false; |
163 | if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_uuid)) | 163 | if (!uuid_equal(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid)) |
164 | return false; | 164 | return false; |
165 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) | 165 | if (be64_to_cpu(leaf3->info.blkno) != bp->b_bn) |
166 | return false; | 166 | return false; |
@@ -310,7 +310,7 @@ xfs_dir3_leaf_init( | |||
310 | : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); | 310 | : cpu_to_be16(XFS_DIR3_LEAFN_MAGIC); |
311 | leaf3->info.blkno = cpu_to_be64(bp->b_bn); | 311 | leaf3->info.blkno = cpu_to_be64(bp->b_bn); |
312 | leaf3->info.owner = cpu_to_be64(owner); | 312 | leaf3->info.owner = cpu_to_be64(owner); |
313 | uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_uuid); | 313 | uuid_copy(&leaf3->info.uuid, &mp->m_sb.sb_meta_uuid); |
314 | } else { | 314 | } else { |
315 | memset(leaf, 0, sizeof(*leaf)); | 315 | memset(leaf, 0, sizeof(*leaf)); |
316 | leaf->hdr.info.magic = cpu_to_be16(type); | 316 | leaf->hdr.info.magic = cpu_to_be16(type); |
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 41b80d3d3877..cc28e924545b 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c | |||
@@ -93,7 +93,7 @@ xfs_dir3_free_verify( | |||
93 | 93 | ||
94 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) | 94 | if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) |
95 | return false; | 95 | return false; |
96 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid)) | 96 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
97 | return false; | 97 | return false; |
98 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) | 98 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
99 | return false; | 99 | return false; |
@@ -226,7 +226,7 @@ xfs_dir3_free_get_buf( | |||
226 | 226 | ||
227 | hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); | 227 | hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); |
228 | hdr3->hdr.owner = cpu_to_be64(dp->i_ino); | 228 | hdr3->hdr.owner = cpu_to_be64(dp->i_ino); |
229 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); | 229 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); |
230 | } else | 230 | } else |
231 | hdr.magic = XFS_DIR2_FREE_MAGIC; | 231 | hdr.magic = XFS_DIR2_FREE_MAGIC; |
232 | dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); | 232 | dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); |
@@ -1845,8 +1845,7 @@ xfs_dir2_node_addname_int( | |||
1845 | 1845 | ||
1846 | if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) { | 1846 | if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) { |
1847 | xfs_alert(mp, | 1847 | xfs_alert(mp, |
1848 | "%s: dir ino %llu needed freesp block %lld for\n" | 1848 | "%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld ifbno %llu lastfbno %d", |
1849 | " data block %lld, got %lld ifbno %llu lastfbno %d", | ||
1850 | __func__, (unsigned long long)dp->i_ino, | 1849 | __func__, (unsigned long long)dp->i_ino, |
1851 | (long long)dp->d_ops->db_to_fdb( | 1850 | (long long)dp->d_ops->db_to_fdb( |
1852 | args->geo, dbno), | 1851 | args->geo, dbno), |
@@ -2132,6 +2131,7 @@ xfs_dir2_node_replace( | |||
2132 | int error; /* error return value */ | 2131 | int error; /* error return value */ |
2133 | int i; /* btree level */ | 2132 | int i; /* btree level */ |
2134 | xfs_ino_t inum; /* new inode number */ | 2133 | xfs_ino_t inum; /* new inode number */ |
2134 | int ftype; /* new file type */ | ||
2135 | xfs_dir2_leaf_t *leaf; /* leaf structure */ | 2135 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
2136 | xfs_dir2_leaf_entry_t *lep; /* leaf entry being changed */ | 2136 | xfs_dir2_leaf_entry_t *lep; /* leaf entry being changed */ |
2137 | int rval; /* internal return value */ | 2137 | int rval; /* internal return value */ |
@@ -2145,7 +2145,14 @@ xfs_dir2_node_replace( | |||
2145 | state = xfs_da_state_alloc(); | 2145 | state = xfs_da_state_alloc(); |
2146 | state->args = args; | 2146 | state->args = args; |
2147 | state->mp = args->dp->i_mount; | 2147 | state->mp = args->dp->i_mount; |
2148 | |||
2149 | /* | ||
2150 | * We have to save new inode number and ftype since | ||
2151 | * xfs_da3_node_lookup_int() is going to overwrite them | ||
2152 | */ | ||
2148 | inum = args->inumber; | 2153 | inum = args->inumber; |
2154 | ftype = args->filetype; | ||
2155 | |||
2149 | /* | 2156 | /* |
2150 | * Lookup the entry to change in the btree. | 2157 | * Lookup the entry to change in the btree. |
2151 | */ | 2158 | */ |
@@ -2183,7 +2190,7 @@ xfs_dir2_node_replace( | |||
2183 | * Fill in the new inode number and log the entry. | 2190 | * Fill in the new inode number and log the entry. |
2184 | */ | 2191 | */ |
2185 | dep->inumber = cpu_to_be64(inum); | 2192 | dep->inumber = cpu_to_be64(inum); |
2186 | args->dp->d_ops->data_put_ftype(dep, args->filetype); | 2193 | args->dp->d_ops->data_put_ftype(dep, ftype); |
2187 | xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); | 2194 | xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); |
2188 | rval = 0; | 2195 | rval = 0; |
2189 | } | 2196 | } |
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c index 6fbf2d853a54..5331b7f0460c 100644 --- a/fs/xfs/libxfs/xfs_dquot_buf.c +++ b/fs/xfs/libxfs/xfs_dquot_buf.c | |||
@@ -163,7 +163,7 @@ xfs_dqcheck( | |||
163 | d->dd_diskdq.d_id = cpu_to_be32(id); | 163 | d->dd_diskdq.d_id = cpu_to_be32(id); |
164 | 164 | ||
165 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 165 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
166 | uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); | 166 | uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); |
167 | xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), | 167 | xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), |
168 | XFS_DQUOT_CRC_OFF); | 168 | XFS_DQUOT_CRC_OFF); |
169 | } | 169 | } |
@@ -198,7 +198,7 @@ xfs_dquot_buf_verify_crc( | |||
198 | if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), | 198 | if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), |
199 | XFS_DQUOT_CRC_OFF)) | 199 | XFS_DQUOT_CRC_OFF)) |
200 | return false; | 200 | return false; |
201 | if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid)) | 201 | if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_meta_uuid)) |
202 | return false; | 202 | return false; |
203 | } | 203 | } |
204 | return true; | 204 | return true; |
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index a0ae572051de..9590a069e556 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h | |||
@@ -100,7 +100,7 @@ typedef struct xfs_sb { | |||
100 | xfs_rfsblock_t sb_dblocks; /* number of data blocks */ | 100 | xfs_rfsblock_t sb_dblocks; /* number of data blocks */ |
101 | xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ | 101 | xfs_rfsblock_t sb_rblocks; /* number of realtime blocks */ |
102 | xfs_rtblock_t sb_rextents; /* number of realtime extents */ | 102 | xfs_rtblock_t sb_rextents; /* number of realtime extents */ |
103 | uuid_t sb_uuid; /* file system unique id */ | 103 | uuid_t sb_uuid; /* user-visible file system unique id */ |
104 | xfs_fsblock_t sb_logstart; /* starting block of log if internal */ | 104 | xfs_fsblock_t sb_logstart; /* starting block of log if internal */ |
105 | xfs_ino_t sb_rootino; /* root inode number */ | 105 | xfs_ino_t sb_rootino; /* root inode number */ |
106 | xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ | 106 | xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ |
@@ -174,6 +174,7 @@ typedef struct xfs_sb { | |||
174 | 174 | ||
175 | xfs_ino_t sb_pquotino; /* project quota inode */ | 175 | xfs_ino_t sb_pquotino; /* project quota inode */ |
176 | xfs_lsn_t sb_lsn; /* last write sequence */ | 176 | xfs_lsn_t sb_lsn; /* last write sequence */ |
177 | uuid_t sb_meta_uuid; /* metadata file system unique id */ | ||
177 | 178 | ||
178 | /* must be padded to 64 bit alignment */ | 179 | /* must be padded to 64 bit alignment */ |
179 | } xfs_sb_t; | 180 | } xfs_sb_t; |
@@ -190,7 +191,7 @@ typedef struct xfs_dsb { | |||
190 | __be64 sb_dblocks; /* number of data blocks */ | 191 | __be64 sb_dblocks; /* number of data blocks */ |
191 | __be64 sb_rblocks; /* number of realtime blocks */ | 192 | __be64 sb_rblocks; /* number of realtime blocks */ |
192 | __be64 sb_rextents; /* number of realtime extents */ | 193 | __be64 sb_rextents; /* number of realtime extents */ |
193 | uuid_t sb_uuid; /* file system unique id */ | 194 | uuid_t sb_uuid; /* user-visible file system unique id */ |
194 | __be64 sb_logstart; /* starting block of log if internal */ | 195 | __be64 sb_logstart; /* starting block of log if internal */ |
195 | __be64 sb_rootino; /* root inode number */ | 196 | __be64 sb_rootino; /* root inode number */ |
196 | __be64 sb_rbmino; /* bitmap inode for realtime extents */ | 197 | __be64 sb_rbmino; /* bitmap inode for realtime extents */ |
@@ -260,6 +261,7 @@ typedef struct xfs_dsb { | |||
260 | 261 | ||
261 | __be64 sb_pquotino; /* project quota inode */ | 262 | __be64 sb_pquotino; /* project quota inode */ |
262 | __be64 sb_lsn; /* last write sequence */ | 263 | __be64 sb_lsn; /* last write sequence */ |
264 | uuid_t sb_meta_uuid; /* metadata file system unique id */ | ||
263 | 265 | ||
264 | /* must be padded to 64 bit alignment */ | 266 | /* must be padded to 64 bit alignment */ |
265 | } xfs_dsb_t; | 267 | } xfs_dsb_t; |
@@ -458,9 +460,11 @@ xfs_sb_has_ro_compat_feature( | |||
458 | 460 | ||
459 | #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ | 461 | #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ |
460 | #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ | 462 | #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ |
463 | #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ | ||
461 | #define XFS_SB_FEAT_INCOMPAT_ALL \ | 464 | #define XFS_SB_FEAT_INCOMPAT_ALL \ |
462 | (XFS_SB_FEAT_INCOMPAT_FTYPE| \ | 465 | (XFS_SB_FEAT_INCOMPAT_FTYPE| \ |
463 | XFS_SB_FEAT_INCOMPAT_SPINODES) | 466 | XFS_SB_FEAT_INCOMPAT_SPINODES| \ |
467 | XFS_SB_FEAT_INCOMPAT_META_UUID) | ||
464 | 468 | ||
465 | #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL | 469 | #define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL |
466 | static inline bool | 470 | static inline bool |
@@ -515,6 +519,18 @@ static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) | |||
515 | } | 519 | } |
516 | 520 | ||
517 | /* | 521 | /* |
522 | * XFS_SB_FEAT_INCOMPAT_META_UUID indicates that the metadata UUID | ||
523 | * is stored separately from the user-visible UUID; this allows the | ||
524 | * user-visible UUID to be changed on V5 filesystems which have a | ||
525 | * filesystem UUID stamped into every piece of metadata. | ||
526 | */ | ||
527 | static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) | ||
528 | { | ||
529 | return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && | ||
530 | (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); | ||
531 | } | ||
532 | |||
533 | /* | ||
518 | * end of superblock version macros | 534 | * end of superblock version macros |
519 | */ | 535 | */ |
520 | 536 | ||
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 66efc702452a..54deb2d12ac6 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c | |||
@@ -338,7 +338,8 @@ xfs_ialloc_inode_init( | |||
338 | if (version == 3) { | 338 | if (version == 3) { |
339 | free->di_ino = cpu_to_be64(ino); | 339 | free->di_ino = cpu_to_be64(ino); |
340 | ino++; | 340 | ino++; |
341 | uuid_copy(&free->di_uuid, &mp->m_sb.sb_uuid); | 341 | uuid_copy(&free->di_uuid, |
342 | &mp->m_sb.sb_meta_uuid); | ||
342 | xfs_dinode_calc_crc(mp, free); | 343 | xfs_dinode_calc_crc(mp, free); |
343 | } else if (tp) { | 344 | } else if (tp) { |
344 | /* just log the inode core */ | 345 | /* just log the inode core */ |
@@ -2232,7 +2233,7 @@ xfs_imap_lookup( | |||
2232 | } | 2233 | } |
2233 | 2234 | ||
2234 | xfs_trans_brelse(tp, agbp); | 2235 | xfs_trans_brelse(tp, agbp); |
2235 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 2236 | xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); |
2236 | if (error) | 2237 | if (error) |
2237 | return error; | 2238 | return error; |
2238 | 2239 | ||
@@ -2500,7 +2501,7 @@ xfs_agi_verify( | |||
2500 | struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); | 2501 | struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); |
2501 | 2502 | ||
2502 | if (xfs_sb_version_hascrc(&mp->m_sb) && | 2503 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
2503 | !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid)) | 2504 | !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid)) |
2504 | return false; | 2505 | return false; |
2505 | /* | 2506 | /* |
2506 | * Validate the magic number of the agi block. | 2507 | * Validate the magic number of the agi block. |
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 674ad8f760be..f39b285beb19 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c | |||
@@ -239,7 +239,7 @@ xfs_inobt_verify( | |||
239 | case cpu_to_be32(XFS_FIBT_CRC_MAGIC): | 239 | case cpu_to_be32(XFS_FIBT_CRC_MAGIC): |
240 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 240 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
241 | return false; | 241 | return false; |
242 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_uuid)) | 242 | if (!uuid_equal(&block->bb_u.s.bb_uuid, &mp->m_sb.sb_meta_uuid)) |
243 | return false; | 243 | return false; |
244 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) | 244 | if (block->bb_u.s.bb_blkno != cpu_to_be64(bp->b_bn)) |
245 | return false; | 245 | return false; |
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 6526e7696184..268c00f4f83a 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c | |||
@@ -304,7 +304,7 @@ xfs_dinode_verify( | |||
304 | return false; | 304 | return false; |
305 | if (be64_to_cpu(dip->di_ino) != ip->i_ino) | 305 | if (be64_to_cpu(dip->di_ino) != ip->i_ino) |
306 | return false; | 306 | return false; |
307 | if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_uuid)) | 307 | if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) |
308 | return false; | 308 | return false; |
309 | return true; | 309 | return true; |
310 | } | 310 | } |
@@ -366,7 +366,7 @@ xfs_iread( | |||
366 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 366 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
367 | ip->i_d.di_version = 3; | 367 | ip->i_d.di_version = 3; |
368 | ip->i_d.di_ino = ip->i_ino; | 368 | ip->i_d.di_ino = ip->i_ino; |
369 | uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid); | 369 | uuid_copy(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid); |
370 | } else | 370 | } else |
371 | ip->i_d.di_version = 2; | 371 | ip->i_d.di_version = 2; |
372 | return 0; | 372 | return 0; |
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index df9851c46b5c..47425140f343 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
@@ -131,10 +131,11 @@ xfs_mount_validate_sb( | |||
131 | if (xfs_sb_has_compat_feature(sbp, | 131 | if (xfs_sb_has_compat_feature(sbp, |
132 | XFS_SB_FEAT_COMPAT_UNKNOWN)) { | 132 | XFS_SB_FEAT_COMPAT_UNKNOWN)) { |
133 | xfs_warn(mp, | 133 | xfs_warn(mp, |
134 | "Superblock has unknown compatible features (0x%x) enabled.\n" | 134 | "Superblock has unknown compatible features (0x%x) enabled.", |
135 | "Using a more recent kernel is recommended.", | ||
136 | (sbp->sb_features_compat & | 135 | (sbp->sb_features_compat & |
137 | XFS_SB_FEAT_COMPAT_UNKNOWN)); | 136 | XFS_SB_FEAT_COMPAT_UNKNOWN)); |
137 | xfs_warn(mp, | ||
138 | "Using a more recent kernel is recommended."); | ||
138 | } | 139 | } |
139 | 140 | ||
140 | if (xfs_sb_has_ro_compat_feature(sbp, | 141 | if (xfs_sb_has_ro_compat_feature(sbp, |
@@ -145,18 +146,21 @@ xfs_mount_validate_sb( | |||
145 | XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); | 146 | XFS_SB_FEAT_RO_COMPAT_UNKNOWN)); |
146 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { | 147 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { |
147 | xfs_warn(mp, | 148 | xfs_warn(mp, |
148 | "Attempted to mount read-only compatible filesystem read-write.\n" | 149 | "Attempted to mount read-only compatible filesystem read-write."); |
150 | xfs_warn(mp, | ||
149 | "Filesystem can only be safely mounted read only."); | 151 | "Filesystem can only be safely mounted read only."); |
152 | |||
150 | return -EINVAL; | 153 | return -EINVAL; |
151 | } | 154 | } |
152 | } | 155 | } |
153 | if (xfs_sb_has_incompat_feature(sbp, | 156 | if (xfs_sb_has_incompat_feature(sbp, |
154 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { | 157 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)) { |
155 | xfs_warn(mp, | 158 | xfs_warn(mp, |
156 | "Superblock has unknown incompatible features (0x%x) enabled.\n" | 159 | "Superblock has unknown incompatible features (0x%x) enabled.", |
157 | "Filesystem can not be safely mounted by this kernel.", | ||
158 | (sbp->sb_features_incompat & | 160 | (sbp->sb_features_incompat & |
159 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)); | 161 | XFS_SB_FEAT_INCOMPAT_UNKNOWN)); |
162 | xfs_warn(mp, | ||
163 | "Filesystem can not be safely mounted by this kernel."); | ||
160 | return -EINVAL; | 164 | return -EINVAL; |
161 | } | 165 | } |
162 | } | 166 | } |
@@ -182,9 +186,6 @@ xfs_mount_validate_sb( | |||
182 | if (xfs_sb_version_hassparseinodes(sbp)) { | 186 | if (xfs_sb_version_hassparseinodes(sbp)) { |
183 | uint32_t align; | 187 | uint32_t align; |
184 | 188 | ||
185 | xfs_alert(mp, | ||
186 | "EXPERIMENTAL sparse inode feature enabled. Use at your own risk!"); | ||
187 | |||
188 | align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize | 189 | align = XFS_INODES_PER_CHUNK * sbp->sb_inodesize |
189 | >> sbp->sb_blocklog; | 190 | >> sbp->sb_blocklog; |
190 | if (sbp->sb_inoalignmt != align) { | 191 | if (sbp->sb_inoalignmt != align) { |
@@ -398,6 +399,14 @@ __xfs_sb_from_disk( | |||
398 | to->sb_spino_align = be32_to_cpu(from->sb_spino_align); | 399 | to->sb_spino_align = be32_to_cpu(from->sb_spino_align); |
399 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); | 400 | to->sb_pquotino = be64_to_cpu(from->sb_pquotino); |
400 | to->sb_lsn = be64_to_cpu(from->sb_lsn); | 401 | to->sb_lsn = be64_to_cpu(from->sb_lsn); |
402 | /* | ||
403 | * sb_meta_uuid is only on disk if it differs from sb_uuid and the | ||
404 | * feature flag is set; if not set we keep it only in memory. | ||
405 | */ | ||
406 | if (xfs_sb_version_hasmetauuid(to)) | ||
407 | uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); | ||
408 | else | ||
409 | uuid_copy(&to->sb_meta_uuid, &from->sb_uuid); | ||
401 | /* Convert on-disk flags to in-memory flags? */ | 410 | /* Convert on-disk flags to in-memory flags? */ |
402 | if (convert_xquota) | 411 | if (convert_xquota) |
403 | xfs_sb_quota_from_disk(to); | 412 | xfs_sb_quota_from_disk(to); |
@@ -539,6 +548,8 @@ xfs_sb_to_disk( | |||
539 | cpu_to_be32(from->sb_features_log_incompat); | 548 | cpu_to_be32(from->sb_features_log_incompat); |
540 | to->sb_spino_align = cpu_to_be32(from->sb_spino_align); | 549 | to->sb_spino_align = cpu_to_be32(from->sb_spino_align); |
541 | to->sb_lsn = cpu_to_be64(from->sb_lsn); | 550 | to->sb_lsn = cpu_to_be64(from->sb_lsn); |
551 | if (xfs_sb_version_hasmetauuid(from)) | ||
552 | uuid_copy(&to->sb_meta_uuid, &from->sb_meta_uuid); | ||
542 | } | 553 | } |
543 | } | 554 | } |
544 | 555 | ||
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c index e7e26bd6468f..8f8af05b3f13 100644 --- a/fs/xfs/libxfs/xfs_symlink_remote.c +++ b/fs/xfs/libxfs/xfs_symlink_remote.c | |||
@@ -63,7 +63,7 @@ xfs_symlink_hdr_set( | |||
63 | dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC); | 63 | dsl->sl_magic = cpu_to_be32(XFS_SYMLINK_MAGIC); |
64 | dsl->sl_offset = cpu_to_be32(offset); | 64 | dsl->sl_offset = cpu_to_be32(offset); |
65 | dsl->sl_bytes = cpu_to_be32(size); | 65 | dsl->sl_bytes = cpu_to_be32(size); |
66 | uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_uuid); | 66 | uuid_copy(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid); |
67 | dsl->sl_owner = cpu_to_be64(ino); | 67 | dsl->sl_owner = cpu_to_be64(ino); |
68 | dsl->sl_blkno = cpu_to_be64(bp->b_bn); | 68 | dsl->sl_blkno = cpu_to_be64(bp->b_bn); |
69 | bp->b_ops = &xfs_symlink_buf_ops; | 69 | bp->b_ops = &xfs_symlink_buf_ops; |
@@ -107,7 +107,7 @@ xfs_symlink_verify( | |||
107 | return false; | 107 | return false; |
108 | if (dsl->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC)) | 108 | if (dsl->sl_magic != cpu_to_be32(XFS_SYMLINK_MAGIC)) |
109 | return false; | 109 | return false; |
110 | if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_uuid)) | 110 | if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid)) |
111 | return false; | 111 | return false; |
112 | if (bp->b_bn != be64_to_cpu(dsl->sl_blkno)) | 112 | if (bp->b_bn != be64_to_cpu(dsl->sl_blkno)) |
113 | return false; | 113 | return false; |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index cc2a321f774b..50ab2879b9da 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -353,7 +353,8 @@ xfs_end_bio( | |||
353 | { | 353 | { |
354 | xfs_ioend_t *ioend = bio->bi_private; | 354 | xfs_ioend_t *ioend = bio->bi_private; |
355 | 355 | ||
356 | ioend->io_error = bio->bi_error; | 356 | if (!ioend->io_error) |
357 | ioend->io_error = bio->bi_error; | ||
357 | 358 | ||
358 | /* Toss bio and pass work off to an xfsdatad thread */ | 359 | /* Toss bio and pass work off to an xfsdatad thread */ |
359 | bio->bi_private = NULL; | 360 | bio->bi_private = NULL; |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 0f34886cf726..3bf4ad0d19e4 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -67,16 +67,15 @@ xfs_fsb_to_db(struct xfs_inode *ip, xfs_fsblock_t fsb) | |||
67 | */ | 67 | */ |
68 | int /* error */ | 68 | int /* error */ |
69 | xfs_bmap_finish( | 69 | xfs_bmap_finish( |
70 | xfs_trans_t **tp, /* transaction pointer addr */ | 70 | struct xfs_trans **tp, /* transaction pointer addr */ |
71 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 71 | struct xfs_bmap_free *flist, /* i/o: list extents to free */ |
72 | int *committed) /* xact committed or not */ | 72 | int *committed)/* xact committed or not */ |
73 | { | 73 | { |
74 | xfs_efd_log_item_t *efd; /* extent free data */ | 74 | struct xfs_efd_log_item *efd; /* extent free data */ |
75 | xfs_efi_log_item_t *efi; /* extent free intention */ | 75 | struct xfs_efi_log_item *efi; /* extent free intention */ |
76 | int error; /* error return value */ | 76 | int error; /* error return value */ |
77 | xfs_bmap_free_item_t *free; /* free extent item */ | 77 | struct xfs_bmap_free_item *free; /* free extent item */ |
78 | xfs_mount_t *mp; /* filesystem mount structure */ | 78 | struct xfs_bmap_free_item *next; /* next item on free list */ |
79 | xfs_bmap_free_item_t *next; /* next item on free list */ | ||
80 | 79 | ||
81 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); | 80 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); |
82 | if (flist->xbf_count == 0) { | 81 | if (flist->xbf_count == 0) { |
@@ -88,40 +87,48 @@ xfs_bmap_finish( | |||
88 | xfs_trans_log_efi_extent(*tp, efi, free->xbfi_startblock, | 87 | xfs_trans_log_efi_extent(*tp, efi, free->xbfi_startblock, |
89 | free->xbfi_blockcount); | 88 | free->xbfi_blockcount); |
90 | 89 | ||
91 | error = xfs_trans_roll(tp, NULL); | 90 | error = __xfs_trans_roll(tp, NULL, committed); |
92 | *committed = 1; | 91 | if (error) { |
93 | /* | 92 | /* |
94 | * We have a new transaction, so we should return committed=1, | 93 | * If the transaction was committed, drop the EFD reference |
95 | * even though we're returning an error. | 94 | * since we're bailing out of here. The other reference is |
96 | */ | 95 | * dropped when the EFI hits the AIL. |
97 | if (error) | 96 | * |
97 | * If the transaction was not committed, the EFI is freed by the | ||
98 | * EFI item unlock handler on abort. Also, we have a new | ||
99 | * transaction so we should return committed=1 even though we're | ||
100 | * returning an error. | ||
101 | */ | ||
102 | if (*committed) { | ||
103 | xfs_efi_release(efi); | ||
104 | xfs_force_shutdown((*tp)->t_mountp, | ||
105 | (error == -EFSCORRUPTED) ? | ||
106 | SHUTDOWN_CORRUPT_INCORE : | ||
107 | SHUTDOWN_META_IO_ERROR); | ||
108 | } else { | ||
109 | *committed = 1; | ||
110 | } | ||
111 | |||
98 | return error; | 112 | return error; |
113 | } | ||
99 | 114 | ||
115 | /* | ||
116 | * Get an EFD and free each extent in the list, logging to the EFD in | ||
117 | * the process. The remaining bmap free list is cleaned up by the caller | ||
118 | * on error. | ||
119 | */ | ||
100 | efd = xfs_trans_get_efd(*tp, efi, flist->xbf_count); | 120 | efd = xfs_trans_get_efd(*tp, efi, flist->xbf_count); |
101 | for (free = flist->xbf_first; free != NULL; free = next) { | 121 | for (free = flist->xbf_first; free != NULL; free = next) { |
102 | next = free->xbfi_next; | 122 | next = free->xbfi_next; |
103 | if ((error = xfs_free_extent(*tp, free->xbfi_startblock, | 123 | |
104 | free->xbfi_blockcount))) { | 124 | error = xfs_trans_free_extent(*tp, efd, free->xbfi_startblock, |
105 | /* | 125 | free->xbfi_blockcount); |
106 | * The bmap free list will be cleaned up at a | 126 | if (error) |
107 | * higher level. The EFI will be canceled when | ||
108 | * this transaction is aborted. | ||
109 | * Need to force shutdown here to make sure it | ||
110 | * happens, since this transaction may not be | ||
111 | * dirty yet. | ||
112 | */ | ||
113 | mp = (*tp)->t_mountp; | ||
114 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
115 | xfs_force_shutdown(mp, | ||
116 | (error == -EFSCORRUPTED) ? | ||
117 | SHUTDOWN_CORRUPT_INCORE : | ||
118 | SHUTDOWN_META_IO_ERROR); | ||
119 | return error; | 127 | return error; |
120 | } | 128 | |
121 | xfs_trans_log_efd_extent(*tp, efd, free->xbfi_startblock, | ||
122 | free->xbfi_blockcount); | ||
123 | xfs_bmap_del_free(flist, NULL, free); | 129 | xfs_bmap_del_free(flist, NULL, free); |
124 | } | 130 | } |
131 | |||
125 | return 0; | 132 | return 0; |
126 | } | 133 | } |
127 | 134 | ||
@@ -1467,7 +1474,7 @@ xfs_shift_file_space( | |||
1467 | XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, | 1474 | XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, |
1468 | XFS_QMOPT_RES_REGBLKS); | 1475 | XFS_QMOPT_RES_REGBLKS); |
1469 | if (error) | 1476 | if (error) |
1470 | goto out; | 1477 | goto out_trans_cancel; |
1471 | 1478 | ||
1472 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 1479 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
1473 | 1480 | ||
@@ -1481,18 +1488,20 @@ xfs_shift_file_space( | |||
1481 | &done, stop_fsb, &first_block, &free_list, | 1488 | &done, stop_fsb, &first_block, &free_list, |
1482 | direction, XFS_BMAP_MAX_SHIFT_EXTENTS); | 1489 | direction, XFS_BMAP_MAX_SHIFT_EXTENTS); |
1483 | if (error) | 1490 | if (error) |
1484 | goto out; | 1491 | goto out_bmap_cancel; |
1485 | 1492 | ||
1486 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1493 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1487 | if (error) | 1494 | if (error) |
1488 | goto out; | 1495 | goto out_bmap_cancel; |
1489 | 1496 | ||
1490 | error = xfs_trans_commit(tp); | 1497 | error = xfs_trans_commit(tp); |
1491 | } | 1498 | } |
1492 | 1499 | ||
1493 | return error; | 1500 | return error; |
1494 | 1501 | ||
1495 | out: | 1502 | out_bmap_cancel: |
1503 | xfs_bmap_cancel(&free_list); | ||
1504 | out_trans_cancel: | ||
1496 | xfs_trans_cancel(tp); | 1505 | xfs_trans_cancel(tp); |
1497 | return error; | 1506 | return error; |
1498 | } | 1507 | } |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 01bd6781974e..8ecffb35935b 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -438,7 +438,6 @@ _xfs_buf_find( | |||
438 | xfs_buf_flags_t flags, | 438 | xfs_buf_flags_t flags, |
439 | xfs_buf_t *new_bp) | 439 | xfs_buf_t *new_bp) |
440 | { | 440 | { |
441 | size_t numbytes; | ||
442 | struct xfs_perag *pag; | 441 | struct xfs_perag *pag; |
443 | struct rb_node **rbp; | 442 | struct rb_node **rbp; |
444 | struct rb_node *parent; | 443 | struct rb_node *parent; |
@@ -450,10 +449,9 @@ _xfs_buf_find( | |||
450 | 449 | ||
451 | for (i = 0; i < nmaps; i++) | 450 | for (i = 0; i < nmaps; i++) |
452 | numblks += map[i].bm_len; | 451 | numblks += map[i].bm_len; |
453 | numbytes = BBTOB(numblks); | ||
454 | 452 | ||
455 | /* Check for IOs smaller than the sector size / not sector aligned */ | 453 | /* Check for IOs smaller than the sector size / not sector aligned */ |
456 | ASSERT(!(numbytes < btp->bt_meta_sectorsize)); | 454 | ASSERT(!(BBTOB(numblks) < btp->bt_meta_sectorsize)); |
457 | ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_meta_sectormask)); | 455 | ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_meta_sectormask)); |
458 | 456 | ||
459 | /* | 457 | /* |
@@ -1532,9 +1530,10 @@ xfs_wait_buftarg( | |||
1532 | list_del_init(&bp->b_lru); | 1530 | list_del_init(&bp->b_lru); |
1533 | if (bp->b_flags & XBF_WRITE_FAIL) { | 1531 | if (bp->b_flags & XBF_WRITE_FAIL) { |
1534 | xfs_alert(btp->bt_mount, | 1532 | xfs_alert(btp->bt_mount, |
1535 | "Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n" | 1533 | "Corruption Alert: Buffer at block 0x%llx had permanent write failures!", |
1536 | "Please run xfs_repair to determine the extent of the problem.", | ||
1537 | (long long)bp->b_bn); | 1534 | (long long)bp->b_bn); |
1535 | xfs_alert(btp->bt_mount, | ||
1536 | "Please run xfs_repair to determine the extent of the problem."); | ||
1538 | } | 1537 | } |
1539 | xfs_buf_rele(bp); | 1538 | xfs_buf_rele(bp); |
1540 | } | 1539 | } |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 092d652bc03d..7e986da34f6c 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -647,11 +647,7 @@ xfs_buf_item_unlock( | |||
647 | xfs_buf_item_relse(bp); | 647 | xfs_buf_item_relse(bp); |
648 | else if (aborted) { | 648 | else if (aborted) { |
649 | ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); | 649 | ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp)); |
650 | if (lip->li_flags & XFS_LI_IN_AIL) { | 650 | xfs_trans_ail_remove(lip, SHUTDOWN_LOG_IO_ERROR); |
651 | spin_lock(&lip->li_ailp->xa_lock); | ||
652 | xfs_trans_ail_delete(lip->li_ailp, lip, | ||
653 | SHUTDOWN_LOG_IO_ERROR); | ||
654 | } | ||
655 | xfs_buf_item_relse(bp); | 651 | xfs_buf_item_relse(bp); |
656 | } | 652 | } |
657 | } | 653 | } |
@@ -750,13 +746,13 @@ xfs_buf_item_free_format( | |||
750 | * buffer (see xfs_buf_attach_iodone() below), then put the | 746 | * buffer (see xfs_buf_attach_iodone() below), then put the |
751 | * buf log item at the front. | 747 | * buf log item at the front. |
752 | */ | 748 | */ |
753 | void | 749 | int |
754 | xfs_buf_item_init( | 750 | xfs_buf_item_init( |
755 | xfs_buf_t *bp, | 751 | struct xfs_buf *bp, |
756 | xfs_mount_t *mp) | 752 | struct xfs_mount *mp) |
757 | { | 753 | { |
758 | xfs_log_item_t *lip = bp->b_fspriv; | 754 | struct xfs_log_item *lip = bp->b_fspriv; |
759 | xfs_buf_log_item_t *bip; | 755 | struct xfs_buf_log_item *bip; |
760 | int chunks; | 756 | int chunks; |
761 | int map_size; | 757 | int map_size; |
762 | int error; | 758 | int error; |
@@ -770,12 +766,11 @@ xfs_buf_item_init( | |||
770 | */ | 766 | */ |
771 | ASSERT(bp->b_target->bt_mount == mp); | 767 | ASSERT(bp->b_target->bt_mount == mp); |
772 | if (lip != NULL && lip->li_type == XFS_LI_BUF) | 768 | if (lip != NULL && lip->li_type == XFS_LI_BUF) |
773 | return; | 769 | return 0; |
774 | 770 | ||
775 | bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); | 771 | bip = kmem_zone_zalloc(xfs_buf_item_zone, KM_SLEEP); |
776 | xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops); | 772 | xfs_log_item_init(mp, &bip->bli_item, XFS_LI_BUF, &xfs_buf_item_ops); |
777 | bip->bli_buf = bp; | 773 | bip->bli_buf = bp; |
778 | xfs_buf_hold(bp); | ||
779 | 774 | ||
780 | /* | 775 | /* |
781 | * chunks is the number of XFS_BLF_CHUNK size pieces the buffer | 776 | * chunks is the number of XFS_BLF_CHUNK size pieces the buffer |
@@ -788,6 +783,11 @@ xfs_buf_item_init( | |||
788 | */ | 783 | */ |
789 | error = xfs_buf_item_get_format(bip, bp->b_map_count); | 784 | error = xfs_buf_item_get_format(bip, bp->b_map_count); |
790 | ASSERT(error == 0); | 785 | ASSERT(error == 0); |
786 | if (error) { /* to stop gcc throwing set-but-unused warnings */ | ||
787 | kmem_zone_free(xfs_buf_item_zone, bip); | ||
788 | return error; | ||
789 | } | ||
790 | |||
791 | 791 | ||
792 | for (i = 0; i < bip->bli_format_count; i++) { | 792 | for (i = 0; i < bip->bli_format_count; i++) { |
793 | chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), | 793 | chunks = DIV_ROUND_UP(BBTOB(bp->b_maps[i].bm_len), |
@@ -807,6 +807,8 @@ xfs_buf_item_init( | |||
807 | if (bp->b_fspriv) | 807 | if (bp->b_fspriv) |
808 | bip->bli_item.li_bio_list = bp->b_fspriv; | 808 | bip->bli_item.li_bio_list = bp->b_fspriv; |
809 | bp->b_fspriv = bip; | 809 | bp->b_fspriv = bip; |
810 | xfs_buf_hold(bp); | ||
811 | return 0; | ||
810 | } | 812 | } |
811 | 813 | ||
812 | 814 | ||
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 3f3455a41510..f7eba99d19dd 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -61,7 +61,7 @@ typedef struct xfs_buf_log_item { | |||
61 | struct xfs_buf_log_format __bli_format; /* embedded in-log header */ | 61 | struct xfs_buf_log_format __bli_format; /* embedded in-log header */ |
62 | } xfs_buf_log_item_t; | 62 | } xfs_buf_log_item_t; |
63 | 63 | ||
64 | void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); | 64 | int xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); |
65 | void xfs_buf_item_relse(struct xfs_buf *); | 65 | void xfs_buf_item_relse(struct xfs_buf *); |
66 | void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint); | 66 | void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint); |
67 | uint xfs_buf_item_dirty(xfs_buf_log_item_t *); | 67 | uint xfs_buf_item_dirty(xfs_buf_log_item_t *); |
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c index 098cd78fe708..a989a9c7edb7 100644 --- a/fs/xfs/xfs_dir2_readdir.c +++ b/fs/xfs/xfs_dir2_readdir.c | |||
@@ -171,6 +171,7 @@ xfs_dir2_block_getdents( | |||
171 | int wantoff; /* starting block offset */ | 171 | int wantoff; /* starting block offset */ |
172 | xfs_off_t cook; | 172 | xfs_off_t cook; |
173 | struct xfs_da_geometry *geo = args->geo; | 173 | struct xfs_da_geometry *geo = args->geo; |
174 | int lock_mode; | ||
174 | 175 | ||
175 | /* | 176 | /* |
176 | * If the block number in the offset is out of range, we're done. | 177 | * If the block number in the offset is out of range, we're done. |
@@ -178,7 +179,9 @@ xfs_dir2_block_getdents( | |||
178 | if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) | 179 | if (xfs_dir2_dataptr_to_db(geo, ctx->pos) > geo->datablk) |
179 | return 0; | 180 | return 0; |
180 | 181 | ||
182 | lock_mode = xfs_ilock_data_map_shared(dp); | ||
181 | error = xfs_dir3_block_read(NULL, dp, &bp); | 183 | error = xfs_dir3_block_read(NULL, dp, &bp); |
184 | xfs_iunlock(dp, lock_mode); | ||
182 | if (error) | 185 | if (error) |
183 | return error; | 186 | return error; |
184 | 187 | ||
@@ -529,9 +532,12 @@ xfs_dir2_leaf_getdents( | |||
529 | * current buffer, need to get another one. | 532 | * current buffer, need to get another one. |
530 | */ | 533 | */ |
531 | if (!bp || ptr >= (char *)bp->b_addr + geo->blksize) { | 534 | if (!bp || ptr >= (char *)bp->b_addr + geo->blksize) { |
535 | int lock_mode; | ||
532 | 536 | ||
537 | lock_mode = xfs_ilock_data_map_shared(dp); | ||
533 | error = xfs_dir2_leaf_readbuf(args, bufsize, map_info, | 538 | error = xfs_dir2_leaf_readbuf(args, bufsize, map_info, |
534 | &curoff, &bp); | 539 | &curoff, &bp); |
540 | xfs_iunlock(dp, lock_mode); | ||
535 | if (error || !map_info->map_valid) | 541 | if (error || !map_info->map_valid) |
536 | break; | 542 | break; |
537 | 543 | ||
@@ -653,7 +659,6 @@ xfs_readdir( | |||
653 | struct xfs_da_args args = { NULL }; | 659 | struct xfs_da_args args = { NULL }; |
654 | int rval; | 660 | int rval; |
655 | int v; | 661 | int v; |
656 | uint lock_mode; | ||
657 | 662 | ||
658 | trace_xfs_readdir(dp); | 663 | trace_xfs_readdir(dp); |
659 | 664 | ||
@@ -666,7 +671,7 @@ xfs_readdir( | |||
666 | args.dp = dp; | 671 | args.dp = dp; |
667 | args.geo = dp->i_mount->m_dir_geo; | 672 | args.geo = dp->i_mount->m_dir_geo; |
668 | 673 | ||
669 | lock_mode = xfs_ilock_data_map_shared(dp); | 674 | xfs_ilock(dp, XFS_IOLOCK_SHARED); |
670 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 675 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
671 | rval = xfs_dir2_sf_getdents(&args, ctx); | 676 | rval = xfs_dir2_sf_getdents(&args, ctx); |
672 | else if ((rval = xfs_dir2_isblock(&args, &v))) | 677 | else if ((rval = xfs_dir2_isblock(&args, &v))) |
@@ -675,7 +680,7 @@ xfs_readdir( | |||
675 | rval = xfs_dir2_block_getdents(&args, ctx); | 680 | rval = xfs_dir2_block_getdents(&args, ctx); |
676 | else | 681 | else |
677 | rval = xfs_dir2_leaf_getdents(&args, ctx, bufsize); | 682 | rval = xfs_dir2_leaf_getdents(&args, ctx, bufsize); |
678 | xfs_iunlock(dp, lock_mode); | 683 | xfs_iunlock(dp, XFS_IOLOCK_SHARED); |
679 | 684 | ||
680 | return rval; | 685 | return rval; |
681 | } | 686 | } |
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 4143dc75dca4..30cb3afb67f0 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -251,7 +251,7 @@ xfs_qm_init_dquot_blk( | |||
251 | d->dd_diskdq.d_id = cpu_to_be32(curid); | 251 | d->dd_diskdq.d_id = cpu_to_be32(curid); |
252 | d->dd_diskdq.d_flags = type; | 252 | d->dd_diskdq.d_flags = type; |
253 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 253 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
254 | uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); | 254 | uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); |
255 | xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), | 255 | xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), |
256 | XFS_DQUOT_CRC_OFF); | 256 | XFS_DQUOT_CRC_OFF); |
257 | } | 257 | } |
@@ -954,12 +954,8 @@ xfs_qm_dqflush( | |||
954 | struct xfs_log_item *lip = &dqp->q_logitem.qli_item; | 954 | struct xfs_log_item *lip = &dqp->q_logitem.qli_item; |
955 | dqp->dq_flags &= ~XFS_DQ_DIRTY; | 955 | dqp->dq_flags &= ~XFS_DQ_DIRTY; |
956 | 956 | ||
957 | spin_lock(&mp->m_ail->xa_lock); | 957 | xfs_trans_ail_remove(lip, SHUTDOWN_CORRUPT_INCORE); |
958 | if (lip->li_flags & XFS_LI_IN_AIL) | 958 | |
959 | xfs_trans_ail_delete(mp->m_ail, lip, | ||
960 | SHUTDOWN_CORRUPT_INCORE); | ||
961 | else | ||
962 | spin_unlock(&mp->m_ail->xa_lock); | ||
963 | error = -EIO; | 959 | error = -EIO; |
964 | goto out_unlock; | 960 | goto out_unlock; |
965 | } | 961 | } |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index adc8f8fdd145..4aa0153214f9 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -47,28 +47,6 @@ xfs_efi_item_free( | |||
47 | } | 47 | } |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * Freeing the efi requires that we remove it from the AIL if it has already | ||
51 | * been placed there. However, the EFI may not yet have been placed in the AIL | ||
52 | * when called by xfs_efi_release() from EFD processing due to the ordering of | ||
53 | * committed vs unpin operations in bulk insert operations. Hence the reference | ||
54 | * count to ensure only the last caller frees the EFI. | ||
55 | */ | ||
56 | STATIC void | ||
57 | __xfs_efi_release( | ||
58 | struct xfs_efi_log_item *efip) | ||
59 | { | ||
60 | struct xfs_ail *ailp = efip->efi_item.li_ailp; | ||
61 | |||
62 | if (atomic_dec_and_test(&efip->efi_refcount)) { | ||
63 | spin_lock(&ailp->xa_lock); | ||
64 | /* xfs_trans_ail_delete() drops the AIL lock. */ | ||
65 | xfs_trans_ail_delete(ailp, &efip->efi_item, | ||
66 | SHUTDOWN_LOG_IO_ERROR); | ||
67 | xfs_efi_item_free(efip); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * This returns the number of iovecs needed to log the given efi item. | 50 | * This returns the number of iovecs needed to log the given efi item. |
73 | * We only need 1 iovec for an efi item. It just logs the efi_log_format | 51 | * We only need 1 iovec for an efi item. It just logs the efi_log_format |
74 | * structure. | 52 | * structure. |
@@ -128,12 +106,12 @@ xfs_efi_item_pin( | |||
128 | } | 106 | } |
129 | 107 | ||
130 | /* | 108 | /* |
131 | * While EFIs cannot really be pinned, the unpin operation is the last place at | 109 | * The unpin operation is the last place an EFI is manipulated in the log. It is |
132 | * which the EFI is manipulated during a transaction. If we are being asked to | 110 | * either inserted in the AIL or aborted in the event of a log I/O error. In |
133 | * remove the EFI it's because the transaction has been cancelled and by | 111 | * either case, the EFI transaction has been successfully committed to make it |
134 | * definition that means the EFI cannot be in the AIL so remove it from the | 112 | * this far. Therefore, we expect whoever committed the EFI to either construct |
135 | * transaction and free it. Otherwise coordinate with xfs_efi_release() | 113 | * and commit the EFD or drop the EFD's reference in the event of error. Simply |
136 | * to determine who gets to free the EFI. | 114 | * drop the log's EFI reference now that the log is done with it. |
137 | */ | 115 | */ |
138 | STATIC void | 116 | STATIC void |
139 | xfs_efi_item_unpin( | 117 | xfs_efi_item_unpin( |
@@ -141,15 +119,7 @@ xfs_efi_item_unpin( | |||
141 | int remove) | 119 | int remove) |
142 | { | 120 | { |
143 | struct xfs_efi_log_item *efip = EFI_ITEM(lip); | 121 | struct xfs_efi_log_item *efip = EFI_ITEM(lip); |
144 | 122 | xfs_efi_release(efip); | |
145 | if (remove) { | ||
146 | ASSERT(!(lip->li_flags & XFS_LI_IN_AIL)); | ||
147 | if (lip->li_desc) | ||
148 | xfs_trans_del_item(lip); | ||
149 | xfs_efi_item_free(efip); | ||
150 | return; | ||
151 | } | ||
152 | __xfs_efi_release(efip); | ||
153 | } | 123 | } |
154 | 124 | ||
155 | /* | 125 | /* |
@@ -167,6 +137,11 @@ xfs_efi_item_push( | |||
167 | return XFS_ITEM_PINNED; | 137 | return XFS_ITEM_PINNED; |
168 | } | 138 | } |
169 | 139 | ||
140 | /* | ||
141 | * The EFI has been either committed or aborted if the transaction has been | ||
142 | * cancelled. If the transaction was cancelled, an EFD isn't going to be | ||
143 | * constructed and thus we free the EFI here directly. | ||
144 | */ | ||
170 | STATIC void | 145 | STATIC void |
171 | xfs_efi_item_unlock( | 146 | xfs_efi_item_unlock( |
172 | struct xfs_log_item *lip) | 147 | struct xfs_log_item *lip) |
@@ -301,23 +276,19 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) | |||
301 | } | 276 | } |
302 | 277 | ||
303 | /* | 278 | /* |
304 | * This is called by the efd item code below to release references to the given | 279 | * Freeing the efi requires that we remove it from the AIL if it has already |
305 | * efi item. Each efd calls this with the number of extents that it has | 280 | * been placed there. However, the EFI may not yet have been placed in the AIL |
306 | * logged, and when the sum of these reaches the total number of extents logged | 281 | * when called by xfs_efi_release() from EFD processing due to the ordering of |
307 | * by this efi item we can free the efi item. | 282 | * committed vs unpin operations in bulk insert operations. Hence the reference |
283 | * count to ensure only the last caller frees the EFI. | ||
308 | */ | 284 | */ |
309 | void | 285 | void |
310 | xfs_efi_release(xfs_efi_log_item_t *efip, | 286 | xfs_efi_release( |
311 | uint nextents) | 287 | struct xfs_efi_log_item *efip) |
312 | { | 288 | { |
313 | ASSERT(atomic_read(&efip->efi_next_extent) >= nextents); | 289 | if (atomic_dec_and_test(&efip->efi_refcount)) { |
314 | if (atomic_sub_and_test(nextents, &efip->efi_next_extent)) { | 290 | xfs_trans_ail_remove(&efip->efi_item, SHUTDOWN_LOG_IO_ERROR); |
315 | /* recovery needs us to drop the EFI reference, too */ | 291 | xfs_efi_item_free(efip); |
316 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) | ||
317 | __xfs_efi_release(efip); | ||
318 | |||
319 | __xfs_efi_release(efip); | ||
320 | /* efip may now have been freed, do not reference it again. */ | ||
321 | } | 292 | } |
322 | } | 293 | } |
323 | 294 | ||
@@ -415,20 +386,27 @@ xfs_efd_item_push( | |||
415 | return XFS_ITEM_PINNED; | 386 | return XFS_ITEM_PINNED; |
416 | } | 387 | } |
417 | 388 | ||
389 | /* | ||
390 | * The EFD is either committed or aborted if the transaction is cancelled. If | ||
391 | * the transaction is cancelled, drop our reference to the EFI and free the EFD. | ||
392 | */ | ||
418 | STATIC void | 393 | STATIC void |
419 | xfs_efd_item_unlock( | 394 | xfs_efd_item_unlock( |
420 | struct xfs_log_item *lip) | 395 | struct xfs_log_item *lip) |
421 | { | 396 | { |
422 | if (lip->li_flags & XFS_LI_ABORTED) | 397 | struct xfs_efd_log_item *efdp = EFD_ITEM(lip); |
423 | xfs_efd_item_free(EFD_ITEM(lip)); | 398 | |
399 | if (lip->li_flags & XFS_LI_ABORTED) { | ||
400 | xfs_efi_release(efdp->efd_efip); | ||
401 | xfs_efd_item_free(efdp); | ||
402 | } | ||
424 | } | 403 | } |
425 | 404 | ||
426 | /* | 405 | /* |
427 | * When the efd item is committed to disk, all we need to do | 406 | * When the efd item is committed to disk, all we need to do is delete our |
428 | * is delete our reference to our partner efi item and then | 407 | * reference to our partner efi item and then free ourselves. Since we're |
429 | * free ourselves. Since we're freeing ourselves we must | 408 | * freeing ourselves we must return -1 to keep the transaction code from further |
430 | * return -1 to keep the transaction code from further referencing | 409 | * referencing this item. |
431 | * this item. | ||
432 | */ | 410 | */ |
433 | STATIC xfs_lsn_t | 411 | STATIC xfs_lsn_t |
434 | xfs_efd_item_committed( | 412 | xfs_efd_item_committed( |
@@ -438,13 +416,14 @@ xfs_efd_item_committed( | |||
438 | struct xfs_efd_log_item *efdp = EFD_ITEM(lip); | 416 | struct xfs_efd_log_item *efdp = EFD_ITEM(lip); |
439 | 417 | ||
440 | /* | 418 | /* |
441 | * If we got a log I/O error, it's always the case that the LR with the | 419 | * Drop the EFI reference regardless of whether the EFD has been |
442 | * EFI got unpinned and freed before the EFD got aborted. | 420 | * aborted. Once the EFD transaction is constructed, it is the sole |
421 | * responsibility of the EFD to release the EFI (even if the EFI is | ||
422 | * aborted due to log I/O error). | ||
443 | */ | 423 | */ |
444 | if (!(lip->li_flags & XFS_LI_ABORTED)) | 424 | xfs_efi_release(efdp->efd_efip); |
445 | xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); | ||
446 | |||
447 | xfs_efd_item_free(efdp); | 425 | xfs_efd_item_free(efdp); |
426 | |||
448 | return (xfs_lsn_t)-1; | 427 | return (xfs_lsn_t)-1; |
449 | } | 428 | } |
450 | 429 | ||
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h index 0ffbce32d569..8fa8651705e1 100644 --- a/fs/xfs/xfs_extfree_item.h +++ b/fs/xfs/xfs_extfree_item.h | |||
@@ -39,9 +39,28 @@ struct kmem_zone; | |||
39 | * "extent free done" log item described below. | 39 | * "extent free done" log item described below. |
40 | * | 40 | * |
41 | * The EFI is reference counted so that it is not freed prior to both the EFI | 41 | * The EFI is reference counted so that it is not freed prior to both the EFI |
42 | * and EFD being committed and unpinned. This ensures that when the last | 42 | * and EFD being committed and unpinned. This ensures the EFI is inserted into |
43 | * reference goes away the EFI will always be in the AIL as it has been | 43 | * the AIL even in the event of out of order EFI/EFD processing. In other words, |
44 | * unpinned, regardless of whether the EFD is processed before or after the EFI. | 44 | * an EFI is born with two references: |
45 | * | ||
46 | * 1.) an EFI held reference to track EFI AIL insertion | ||
47 | * 2.) an EFD held reference to track EFD commit | ||
48 | * | ||
49 | * On allocation, both references are the responsibility of the caller. Once the | ||
50 | * EFI is added to and dirtied in a transaction, ownership of reference one | ||
51 | * transfers to the transaction. The reference is dropped once the EFI is | ||
52 | * inserted to the AIL or in the event of failure along the way (e.g., commit | ||
53 | * failure, log I/O error, etc.). Note that the caller remains responsible for | ||
54 | * the EFD reference under all circumstances to this point. The caller has no | ||
55 | * means to detect failure once the transaction is committed, however. | ||
56 | * Therefore, an EFD is required after this point, even in the event of | ||
57 | * unrelated failure. | ||
58 | * | ||
59 | * Once an EFD is allocated and dirtied in a transaction, reference two | ||
60 | * transfers to the transaction. The EFD reference is dropped once it reaches | ||
61 | * the unpin handler. Similar to the EFI, the reference also drops in the event | ||
62 | * of commit failure or log I/O errors. Note that the EFD is not inserted in the | ||
63 | * AIL, so at this point both the EFI and EFD are freed. | ||
45 | */ | 64 | */ |
46 | typedef struct xfs_efi_log_item { | 65 | typedef struct xfs_efi_log_item { |
47 | xfs_log_item_t efi_item; | 66 | xfs_log_item_t efi_item; |
@@ -77,5 +96,6 @@ xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, | |||
77 | int xfs_efi_copy_format(xfs_log_iovec_t *buf, | 96 | int xfs_efi_copy_format(xfs_log_iovec_t *buf, |
78 | xfs_efi_log_format_t *dst_efi_fmt); | 97 | xfs_efi_log_format_t *dst_efi_fmt); |
79 | void xfs_efi_item_free(xfs_efi_log_item_t *); | 98 | void xfs_efi_item_free(xfs_efi_log_item_t *); |
99 | void xfs_efi_release(struct xfs_efi_log_item *); | ||
80 | 100 | ||
81 | #endif /* __XFS_EXTFREE_ITEM_H__ */ | 101 | #endif /* __XFS_EXTFREE_ITEM_H__ */ |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index db4acc1c3e73..de2c2376242b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -317,24 +317,33 @@ xfs_file_read_iter( | |||
317 | return -EIO; | 317 | return -EIO; |
318 | 318 | ||
319 | /* | 319 | /* |
320 | * Locking is a bit tricky here. If we take an exclusive lock | 320 | * Locking is a bit tricky here. If we take an exclusive lock for direct |
321 | * for direct IO, we effectively serialise all new concurrent | 321 | * IO, we effectively serialise all new concurrent read IO to this file |
322 | * read IO to this file and block it behind IO that is currently in | 322 | * and block it behind IO that is currently in progress because IO in |
323 | * progress because IO in progress holds the IO lock shared. We only | 323 | * progress holds the IO lock shared. We only need to hold the lock |
324 | * need to hold the lock exclusive to blow away the page cache, so | 324 | * exclusive to blow away the page cache, so only take lock exclusively |
325 | * only take lock exclusively if the page cache needs invalidation. | 325 | * if the page cache needs invalidation. This allows the normal direct |
326 | * This allows the normal direct IO case of no page cache pages to | 326 | * IO case of no page cache pages to proceeed concurrently without |
327 | * proceeed concurrently without serialisation. | 327 | * serialisation. |
328 | */ | 328 | */ |
329 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); | 329 | xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); |
330 | if ((ioflags & XFS_IO_ISDIRECT) && inode->i_mapping->nrpages) { | 330 | if ((ioflags & XFS_IO_ISDIRECT) && inode->i_mapping->nrpages) { |
331 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); | 331 | xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); |
332 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); | 332 | xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); |
333 | 333 | ||
334 | /* | ||
335 | * The generic dio code only flushes the range of the particular | ||
336 | * I/O. Because we take an exclusive lock here, this whole | ||
337 | * sequence is considerably more expensive for us. This has a | ||
338 | * noticeable performance impact for any file with cached pages, | ||
339 | * even when outside of the range of the particular I/O. | ||
340 | * | ||
341 | * Hence, amortize the cost of the lock against a full file | ||
342 | * flush and reduce the chances of repeated iolock cycles going | ||
343 | * forward. | ||
344 | */ | ||
334 | if (inode->i_mapping->nrpages) { | 345 | if (inode->i_mapping->nrpages) { |
335 | ret = filemap_write_and_wait_range( | 346 | ret = filemap_write_and_wait(VFS_I(ip)->i_mapping); |
336 | VFS_I(ip)->i_mapping, | ||
337 | pos, pos + size - 1); | ||
338 | if (ret) { | 347 | if (ret) { |
339 | xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL); | 348 | xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL); |
340 | return ret; | 349 | return ret; |
@@ -345,9 +354,7 @@ xfs_file_read_iter( | |||
345 | * we fail to invalidate a page, but this should never | 354 | * we fail to invalidate a page, but this should never |
346 | * happen on XFS. Warn if it does fail. | 355 | * happen on XFS. Warn if it does fail. |
347 | */ | 356 | */ |
348 | ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, | 357 | ret = invalidate_inode_pages2(VFS_I(ip)->i_mapping); |
349 | pos >> PAGE_CACHE_SHIFT, | ||
350 | (pos + size - 1) >> PAGE_CACHE_SHIFT); | ||
351 | WARN_ON_ONCE(ret); | 358 | WARN_ON_ONCE(ret); |
352 | ret = 0; | 359 | ret = 0; |
353 | } | 360 | } |
@@ -733,19 +740,19 @@ xfs_file_dio_aio_write( | |||
733 | pos = iocb->ki_pos; | 740 | pos = iocb->ki_pos; |
734 | end = pos + count - 1; | 741 | end = pos + count - 1; |
735 | 742 | ||
743 | /* | ||
744 | * See xfs_file_read_iter() for why we do a full-file flush here. | ||
745 | */ | ||
736 | if (mapping->nrpages) { | 746 | if (mapping->nrpages) { |
737 | ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 747 | ret = filemap_write_and_wait(VFS_I(ip)->i_mapping); |
738 | pos, end); | ||
739 | if (ret) | 748 | if (ret) |
740 | goto out; | 749 | goto out; |
741 | /* | 750 | /* |
742 | * Invalidate whole pages. This can return an error if | 751 | * Invalidate whole pages. This can return an error if we fail |
743 | * we fail to invalidate a page, but this should never | 752 | * to invalidate a page, but this should never happen on XFS. |
744 | * happen on XFS. Warn if it does fail. | 753 | * Warn if it does fail. |
745 | */ | 754 | */ |
746 | ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, | 755 | ret = invalidate_inode_pages2(VFS_I(ip)->i_mapping); |
747 | pos >> PAGE_CACHE_SHIFT, | ||
748 | end >> PAGE_CACHE_SHIFT); | ||
749 | WARN_ON_ONCE(ret); | 756 | WARN_ON_ONCE(ret); |
750 | ret = 0; | 757 | ret = 0; |
751 | } | 758 | } |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 9b3438a7680f..ee3aaa0a5317 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -250,7 +250,7 @@ xfs_growfs_data_private( | |||
250 | agf->agf_freeblks = cpu_to_be32(tmpsize); | 250 | agf->agf_freeblks = cpu_to_be32(tmpsize); |
251 | agf->agf_longest = cpu_to_be32(tmpsize); | 251 | agf->agf_longest = cpu_to_be32(tmpsize); |
252 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 252 | if (xfs_sb_version_hascrc(&mp->m_sb)) |
253 | uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_uuid); | 253 | uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); |
254 | 254 | ||
255 | error = xfs_bwrite(bp); | 255 | error = xfs_bwrite(bp); |
256 | xfs_buf_relse(bp); | 256 | xfs_buf_relse(bp); |
@@ -273,7 +273,7 @@ xfs_growfs_data_private( | |||
273 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 273 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
274 | agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); | 274 | agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); |
275 | agfl->agfl_seqno = cpu_to_be32(agno); | 275 | agfl->agfl_seqno = cpu_to_be32(agno); |
276 | uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_uuid); | 276 | uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid); |
277 | } | 277 | } |
278 | 278 | ||
279 | agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, bp); | 279 | agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, bp); |
@@ -309,7 +309,7 @@ xfs_growfs_data_private( | |||
309 | agi->agi_newino = cpu_to_be32(NULLAGINO); | 309 | agi->agi_newino = cpu_to_be32(NULLAGINO); |
310 | agi->agi_dirino = cpu_to_be32(NULLAGINO); | 310 | agi->agi_dirino = cpu_to_be32(NULLAGINO); |
311 | if (xfs_sb_version_hascrc(&mp->m_sb)) | 311 | if (xfs_sb_version_hascrc(&mp->m_sb)) |
312 | uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid); | 312 | uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid); |
313 | if (xfs_sb_version_hasfinobt(&mp->m_sb)) { | 313 | if (xfs_sb_version_hasfinobt(&mp->m_sb)) { |
314 | agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp)); | 314 | agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp)); |
315 | agi->agi_free_level = cpu_to_be32(1); | 315 | agi->agi_free_level = cpu_to_be32(1); |
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 76a9f2783282..0a326bd64d4e 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c | |||
@@ -412,6 +412,8 @@ xfs_iget( | |||
412 | if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount) | 412 | if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount) |
413 | return -EINVAL; | 413 | return -EINVAL; |
414 | 414 | ||
415 | XFS_STATS_INC(xs_ig_attempts); | ||
416 | |||
415 | /* get the perag structure and ensure that it's inode capable */ | 417 | /* get the perag structure and ensure that it's inode capable */ |
416 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino)); | 418 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino)); |
417 | agino = XFS_INO_TO_AGINO(mp, ino); | 419 | agino = XFS_INO_TO_AGINO(mp, ino); |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 3da9f4da4f3d..dc40a6d5ae0d 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -164,7 +164,7 @@ xfs_ilock( | |||
164 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); | 164 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); |
165 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 165 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
166 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 166 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
167 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); | 167 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0); |
168 | 168 | ||
169 | if (lock_flags & XFS_IOLOCK_EXCL) | 169 | if (lock_flags & XFS_IOLOCK_EXCL) |
170 | mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags)); | 170 | mrupdate_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags)); |
@@ -212,7 +212,7 @@ xfs_ilock_nowait( | |||
212 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); | 212 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); |
213 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 213 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
214 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 214 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
215 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); | 215 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0); |
216 | 216 | ||
217 | if (lock_flags & XFS_IOLOCK_EXCL) { | 217 | if (lock_flags & XFS_IOLOCK_EXCL) { |
218 | if (!mrtryupdate(&ip->i_iolock)) | 218 | if (!mrtryupdate(&ip->i_iolock)) |
@@ -281,7 +281,7 @@ xfs_iunlock( | |||
281 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); | 281 | (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); |
282 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != | 282 | ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != |
283 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); | 283 | (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); |
284 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); | 284 | ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_SUBCLASS_MASK)) == 0); |
285 | ASSERT(lock_flags != 0); | 285 | ASSERT(lock_flags != 0); |
286 | 286 | ||
287 | if (lock_flags & XFS_IOLOCK_EXCL) | 287 | if (lock_flags & XFS_IOLOCK_EXCL) |
@@ -363,31 +363,57 @@ int xfs_lock_delays; | |||
363 | #endif | 363 | #endif |
364 | 364 | ||
365 | /* | 365 | /* |
366 | * xfs_lockdep_subclass_ok() is only used in an ASSERT, so is only called when | ||
367 | * DEBUG or XFS_WARN is set. And MAX_LOCKDEP_SUBCLASSES is then only defined | ||
368 | * when CONFIG_LOCKDEP is set. Hence the complex define below to avoid build | ||
369 | * errors and warnings. | ||
370 | */ | ||
371 | #if (defined(DEBUG) || defined(XFS_WARN)) && defined(CONFIG_LOCKDEP) | ||
372 | static bool | ||
373 | xfs_lockdep_subclass_ok( | ||
374 | int subclass) | ||
375 | { | ||
376 | return subclass < MAX_LOCKDEP_SUBCLASSES; | ||
377 | } | ||
378 | #else | ||
379 | #define xfs_lockdep_subclass_ok(subclass) (true) | ||
380 | #endif | ||
381 | |||
382 | /* | ||
366 | * Bump the subclass so xfs_lock_inodes() acquires each lock with a different | 383 | * Bump the subclass so xfs_lock_inodes() acquires each lock with a different |
367 | * value. This shouldn't be called for page fault locking, but we also need to | 384 | * value. This can be called for any type of inode lock combination, including |
368 | * ensure we don't overrun the number of lockdep subclasses for the iolock or | 385 | * parent locking. Care must be taken to ensure we don't overrun the subclass |
369 | * mmaplock as that is limited to 12 by the mmap lock lockdep annotations. | 386 | * storage fields in the class mask we build. |
370 | */ | 387 | */ |
371 | static inline int | 388 | static inline int |
372 | xfs_lock_inumorder(int lock_mode, int subclass) | 389 | xfs_lock_inumorder(int lock_mode, int subclass) |
373 | { | 390 | { |
391 | int class = 0; | ||
392 | |||
393 | ASSERT(!(lock_mode & (XFS_ILOCK_PARENT | XFS_ILOCK_RTBITMAP | | ||
394 | XFS_ILOCK_RTSUM))); | ||
395 | ASSERT(xfs_lockdep_subclass_ok(subclass)); | ||
396 | |||
374 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) { | 397 | if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) { |
375 | ASSERT(subclass + XFS_LOCK_INUMORDER < | 398 | ASSERT(subclass <= XFS_IOLOCK_MAX_SUBCLASS); |
376 | (1 << (XFS_MMAPLOCK_SHIFT - XFS_IOLOCK_SHIFT))); | 399 | ASSERT(xfs_lockdep_subclass_ok(subclass + |
377 | lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT; | 400 | XFS_IOLOCK_PARENT_VAL)); |
401 | class += subclass << XFS_IOLOCK_SHIFT; | ||
402 | if (lock_mode & XFS_IOLOCK_PARENT) | ||
403 | class += XFS_IOLOCK_PARENT_VAL << XFS_IOLOCK_SHIFT; | ||
378 | } | 404 | } |
379 | 405 | ||
380 | if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) { | 406 | if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) { |
381 | ASSERT(subclass + XFS_LOCK_INUMORDER < | 407 | ASSERT(subclass <= XFS_MMAPLOCK_MAX_SUBCLASS); |
382 | (1 << (XFS_ILOCK_SHIFT - XFS_MMAPLOCK_SHIFT))); | 408 | class += subclass << XFS_MMAPLOCK_SHIFT; |
383 | lock_mode |= (subclass + XFS_LOCK_INUMORDER) << | ||
384 | XFS_MMAPLOCK_SHIFT; | ||
385 | } | 409 | } |
386 | 410 | ||
387 | if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) | 411 | if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) { |
388 | lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT; | 412 | ASSERT(subclass <= XFS_ILOCK_MAX_SUBCLASS); |
413 | class += subclass << XFS_ILOCK_SHIFT; | ||
414 | } | ||
389 | 415 | ||
390 | return lock_mode; | 416 | return (lock_mode & ~XFS_LOCK_SUBCLASS_MASK) | class; |
391 | } | 417 | } |
392 | 418 | ||
393 | /* | 419 | /* |
@@ -399,6 +425,11 @@ xfs_lock_inumorder(int lock_mode, int subclass) | |||
399 | * transaction (such as truncate). This can result in deadlock since the long | 425 | * transaction (such as truncate). This can result in deadlock since the long |
400 | * running trans might need to wait for the inode we just locked in order to | 426 | * running trans might need to wait for the inode we just locked in order to |
401 | * push the tail and free space in the log. | 427 | * push the tail and free space in the log. |
428 | * | ||
429 | * xfs_lock_inodes() can only be used to lock one type of lock at a time - | ||
430 | * the iolock, the mmaplock or the ilock, but not more than one at a time. If we | ||
431 | * lock more than one at a time, lockdep will report false positives saying we | ||
432 | * have violated locking orders. | ||
402 | */ | 433 | */ |
403 | void | 434 | void |
404 | xfs_lock_inodes( | 435 | xfs_lock_inodes( |
@@ -409,8 +440,29 @@ xfs_lock_inodes( | |||
409 | int attempts = 0, i, j, try_lock; | 440 | int attempts = 0, i, j, try_lock; |
410 | xfs_log_item_t *lp; | 441 | xfs_log_item_t *lp; |
411 | 442 | ||
412 | /* currently supports between 2 and 5 inodes */ | 443 | /* |
444 | * Currently supports between 2 and 5 inodes with exclusive locking. We | ||
445 | * support an arbitrary depth of locking here, but absolute limits on | ||
446 | * inodes depend on the the type of locking and the limits placed by | ||
447 | * lockdep annotations in xfs_lock_inumorder. These are all checked by | ||
448 | * the asserts. | ||
449 | */ | ||
413 | ASSERT(ips && inodes >= 2 && inodes <= 5); | 450 | ASSERT(ips && inodes >= 2 && inodes <= 5); |
451 | ASSERT(lock_mode & (XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL | | ||
452 | XFS_ILOCK_EXCL)); | ||
453 | ASSERT(!(lock_mode & (XFS_IOLOCK_SHARED | XFS_MMAPLOCK_SHARED | | ||
454 | XFS_ILOCK_SHARED))); | ||
455 | ASSERT(!(lock_mode & XFS_IOLOCK_EXCL) || | ||
456 | inodes <= XFS_IOLOCK_MAX_SUBCLASS + 1); | ||
457 | ASSERT(!(lock_mode & XFS_MMAPLOCK_EXCL) || | ||
458 | inodes <= XFS_MMAPLOCK_MAX_SUBCLASS + 1); | ||
459 | ASSERT(!(lock_mode & XFS_ILOCK_EXCL) || | ||
460 | inodes <= XFS_ILOCK_MAX_SUBCLASS + 1); | ||
461 | |||
462 | if (lock_mode & XFS_IOLOCK_EXCL) { | ||
463 | ASSERT(!(lock_mode & (XFS_MMAPLOCK_EXCL | XFS_ILOCK_EXCL))); | ||
464 | } else if (lock_mode & XFS_MMAPLOCK_EXCL) | ||
465 | ASSERT(!(lock_mode & XFS_ILOCK_EXCL)); | ||
414 | 466 | ||
415 | try_lock = 0; | 467 | try_lock = 0; |
416 | i = 0; | 468 | i = 0; |
@@ -629,30 +681,29 @@ xfs_lookup( | |||
629 | { | 681 | { |
630 | xfs_ino_t inum; | 682 | xfs_ino_t inum; |
631 | int error; | 683 | int error; |
632 | uint lock_mode; | ||
633 | 684 | ||
634 | trace_xfs_lookup(dp, name); | 685 | trace_xfs_lookup(dp, name); |
635 | 686 | ||
636 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 687 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
637 | return -EIO; | 688 | return -EIO; |
638 | 689 | ||
639 | lock_mode = xfs_ilock_data_map_shared(dp); | 690 | xfs_ilock(dp, XFS_IOLOCK_SHARED); |
640 | error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name); | 691 | error = xfs_dir_lookup(NULL, dp, name, &inum, ci_name); |
641 | xfs_iunlock(dp, lock_mode); | ||
642 | |||
643 | if (error) | 692 | if (error) |
644 | goto out; | 693 | goto out_unlock; |
645 | 694 | ||
646 | error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp); | 695 | error = xfs_iget(dp->i_mount, NULL, inum, 0, 0, ipp); |
647 | if (error) | 696 | if (error) |
648 | goto out_free_name; | 697 | goto out_free_name; |
649 | 698 | ||
699 | xfs_iunlock(dp, XFS_IOLOCK_SHARED); | ||
650 | return 0; | 700 | return 0; |
651 | 701 | ||
652 | out_free_name: | 702 | out_free_name: |
653 | if (ci_name) | 703 | if (ci_name) |
654 | kmem_free(ci_name->name); | 704 | kmem_free(ci_name->name); |
655 | out: | 705 | out_unlock: |
706 | xfs_iunlock(dp, XFS_IOLOCK_SHARED); | ||
656 | *ipp = NULL; | 707 | *ipp = NULL; |
657 | return error; | 708 | return error; |
658 | } | 709 | } |
@@ -787,7 +838,7 @@ xfs_ialloc( | |||
787 | 838 | ||
788 | if (ip->i_d.di_version == 3) { | 839 | if (ip->i_d.di_version == 3) { |
789 | ASSERT(ip->i_d.di_ino == ino); | 840 | ASSERT(ip->i_d.di_ino == ino); |
790 | ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_uuid)); | 841 | ASSERT(uuid_equal(&ip->i_d.di_uuid, &mp->m_sb.sb_meta_uuid)); |
791 | ip->i_d.di_crc = 0; | 842 | ip->i_d.di_crc = 0; |
792 | ip->i_d.di_changecount = 1; | 843 | ip->i_d.di_changecount = 1; |
793 | ip->i_d.di_lsn = 0; | 844 | ip->i_d.di_lsn = 0; |
@@ -1149,7 +1200,8 @@ xfs_create( | |||
1149 | goto out_trans_cancel; | 1200 | goto out_trans_cancel; |
1150 | 1201 | ||
1151 | 1202 | ||
1152 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); | 1203 | xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL | |
1204 | XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); | ||
1153 | unlock_dp_on_error = true; | 1205 | unlock_dp_on_error = true; |
1154 | 1206 | ||
1155 | xfs_bmap_init(&free_list, &first_block); | 1207 | xfs_bmap_init(&free_list, &first_block); |
@@ -1175,11 +1227,8 @@ xfs_create( | |||
1175 | */ | 1227 | */ |
1176 | error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, | 1228 | error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, |
1177 | prid, resblks > 0, &ip, &committed); | 1229 | prid, resblks > 0, &ip, &committed); |
1178 | if (error) { | 1230 | if (error) |
1179 | if (error == -ENOSPC) | ||
1180 | goto out_trans_cancel; | ||
1181 | goto out_trans_cancel; | 1231 | goto out_trans_cancel; |
1182 | } | ||
1183 | 1232 | ||
1184 | /* | 1233 | /* |
1185 | * Now we join the directory inode to the transaction. We do not do it | 1234 | * Now we join the directory inode to the transaction. We do not do it |
@@ -1188,7 +1237,7 @@ xfs_create( | |||
1188 | * the transaction cancel unlocking dp so don't do it explicitly in the | 1237 | * the transaction cancel unlocking dp so don't do it explicitly in the |
1189 | * error path. | 1238 | * error path. |
1190 | */ | 1239 | */ |
1191 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 1240 | xfs_trans_ijoin(tp, dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
1192 | unlock_dp_on_error = false; | 1241 | unlock_dp_on_error = false; |
1193 | 1242 | ||
1194 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, | 1243 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, |
@@ -1261,7 +1310,7 @@ xfs_create( | |||
1261 | xfs_qm_dqrele(pdqp); | 1310 | xfs_qm_dqrele(pdqp); |
1262 | 1311 | ||
1263 | if (unlock_dp_on_error) | 1312 | if (unlock_dp_on_error) |
1264 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 1313 | xfs_iunlock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
1265 | return error; | 1314 | return error; |
1266 | } | 1315 | } |
1267 | 1316 | ||
@@ -1318,11 +1367,8 @@ xfs_create_tmpfile( | |||
1318 | 1367 | ||
1319 | error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, | 1368 | error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, |
1320 | prid, resblks > 0, &ip, NULL); | 1369 | prid, resblks > 0, &ip, NULL); |
1321 | if (error) { | 1370 | if (error) |
1322 | if (error == -ENOSPC) | ||
1323 | goto out_trans_cancel; | ||
1324 | goto out_trans_cancel; | 1371 | goto out_trans_cancel; |
1325 | } | ||
1326 | 1372 | ||
1327 | if (mp->m_flags & XFS_MOUNT_WSYNC) | 1373 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
1328 | xfs_trans_set_sync(tp); | 1374 | xfs_trans_set_sync(tp); |
@@ -1409,10 +1455,11 @@ xfs_link( | |||
1409 | if (error) | 1455 | if (error) |
1410 | goto error_return; | 1456 | goto error_return; |
1411 | 1457 | ||
1458 | xfs_ilock(tdp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); | ||
1412 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); | 1459 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); |
1413 | 1460 | ||
1414 | xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL); | 1461 | xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL); |
1415 | xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL); | 1462 | xfs_trans_ijoin(tp, tdp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
1416 | 1463 | ||
1417 | /* | 1464 | /* |
1418 | * If we are using project inheritance, we only allow hard link | 1465 | * If we are using project inheritance, we only allow hard link |
@@ -1791,14 +1838,15 @@ xfs_inactive_ifree( | |||
1791 | xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); | 1838 | xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); |
1792 | 1839 | ||
1793 | /* | 1840 | /* |
1794 | * Just ignore errors at this point. There is nothing we can | 1841 | * Just ignore errors at this point. There is nothing we can do except |
1795 | * do except to try to keep going. Make sure it's not a silent | 1842 | * to try to keep going. Make sure it's not a silent error. |
1796 | * error. | ||
1797 | */ | 1843 | */ |
1798 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1844 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1799 | if (error) | 1845 | if (error) { |
1800 | xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", | 1846 | xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", |
1801 | __func__, error); | 1847 | __func__, error); |
1848 | xfs_bmap_cancel(&free_list); | ||
1849 | } | ||
1802 | error = xfs_trans_commit(tp); | 1850 | error = xfs_trans_commit(tp); |
1803 | if (error) | 1851 | if (error) |
1804 | xfs_notice(mp, "%s: xfs_trans_commit returned error %d", | 1852 | xfs_notice(mp, "%s: xfs_trans_commit returned error %d", |
@@ -2515,9 +2563,10 @@ xfs_remove( | |||
2515 | goto out_trans_cancel; | 2563 | goto out_trans_cancel; |
2516 | } | 2564 | } |
2517 | 2565 | ||
2566 | xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); | ||
2518 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); | 2567 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); |
2519 | 2568 | ||
2520 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 2569 | xfs_trans_ijoin(tp, dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
2521 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 2570 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
2522 | 2571 | ||
2523 | /* | 2572 | /* |
@@ -2898,6 +2947,12 @@ xfs_rename( | |||
2898 | * whether the target directory is the same as the source | 2947 | * whether the target directory is the same as the source |
2899 | * directory, we can lock from 2 to 4 inodes. | 2948 | * directory, we can lock from 2 to 4 inodes. |
2900 | */ | 2949 | */ |
2950 | if (!new_parent) | ||
2951 | xfs_ilock(src_dp, XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); | ||
2952 | else | ||
2953 | xfs_lock_two_inodes(src_dp, target_dp, | ||
2954 | XFS_IOLOCK_EXCL | XFS_IOLOCK_PARENT); | ||
2955 | |||
2901 | xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL); | 2956 | xfs_lock_inodes(inodes, num_inodes, XFS_ILOCK_EXCL); |
2902 | 2957 | ||
2903 | /* | 2958 | /* |
@@ -2905,9 +2960,9 @@ xfs_rename( | |||
2905 | * we can rely on either trans_commit or trans_cancel to unlock | 2960 | * we can rely on either trans_commit or trans_cancel to unlock |
2906 | * them. | 2961 | * them. |
2907 | */ | 2962 | */ |
2908 | xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL); | 2963 | xfs_trans_ijoin(tp, src_dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
2909 | if (new_parent) | 2964 | if (new_parent) |
2910 | xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL); | 2965 | xfs_trans_ijoin(tp, target_dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
2911 | xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL); | 2966 | xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL); |
2912 | if (target_ip) | 2967 | if (target_ip) |
2913 | xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL); | 2968 | xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL); |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 8f22d20368d8..ca9e11989cbd 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -284,9 +284,9 @@ static inline int xfs_isiflocked(struct xfs_inode *ip) | |||
284 | * Flags for lockdep annotations. | 284 | * Flags for lockdep annotations. |
285 | * | 285 | * |
286 | * XFS_LOCK_PARENT - for directory operations that require locking a | 286 | * XFS_LOCK_PARENT - for directory operations that require locking a |
287 | * parent directory inode and a child entry inode. The parent gets locked | 287 | * parent directory inode and a child entry inode. IOLOCK requires nesting, |
288 | * with this flag so it gets a lockdep subclass of 1 and the child entry | 288 | * MMAPLOCK does not support this class, ILOCK requires a single subclass |
289 | * lock will have a lockdep subclass of 0. | 289 | * to differentiate parent from child. |
290 | * | 290 | * |
291 | * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary | 291 | * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary |
292 | * inodes do not participate in the normal lock order, and thus have their | 292 | * inodes do not participate in the normal lock order, and thus have their |
@@ -295,30 +295,63 @@ static inline int xfs_isiflocked(struct xfs_inode *ip) | |||
295 | * XFS_LOCK_INUMORDER - for locking several inodes at the some time | 295 | * XFS_LOCK_INUMORDER - for locking several inodes at the some time |
296 | * with xfs_lock_inodes(). This flag is used as the starting subclass | 296 | * with xfs_lock_inodes(). This flag is used as the starting subclass |
297 | * and each subsequent lock acquired will increment the subclass by one. | 297 | * and each subsequent lock acquired will increment the subclass by one. |
298 | * So the first lock acquired will have a lockdep subclass of 4, the | 298 | * However, MAX_LOCKDEP_SUBCLASSES == 8, which means we are greatly |
299 | * second lock will have a lockdep subclass of 5, and so on. It is | 299 | * limited to the subclasses we can represent via nesting. We need at least |
300 | * the responsibility of the class builder to shift this to the correct | 300 | * 5 inodes nest depth for the ILOCK through rename, and we also have to support |
301 | * portion of the lock_mode lockdep mask. | 301 | * XFS_ILOCK_PARENT, which gives 6 subclasses. Then we have XFS_ILOCK_RTBITMAP |
302 | * and XFS_ILOCK_RTSUM, which are another 2 unique subclasses, so that's all | ||
303 | * 8 subclasses supported by lockdep. | ||
304 | * | ||
305 | * This also means we have to number the sub-classes in the lowest bits of | ||
306 | * the mask we keep, and we have to ensure we never exceed 3 bits of lockdep | ||
307 | * mask and we can't use bit-masking to build the subclasses. What a mess. | ||
308 | * | ||
309 | * Bit layout: | ||
310 | * | ||
311 | * Bit Lock Region | ||
312 | * 16-19 XFS_IOLOCK_SHIFT dependencies | ||
313 | * 20-23 XFS_MMAPLOCK_SHIFT dependencies | ||
314 | * 24-31 XFS_ILOCK_SHIFT dependencies | ||
315 | * | ||
316 | * IOLOCK values | ||
317 | * | ||
318 | * 0-3 subclass value | ||
319 | * 4-7 PARENT subclass values | ||
320 | * | ||
321 | * MMAPLOCK values | ||
322 | * | ||
323 | * 0-3 subclass value | ||
324 | * 4-7 unused | ||
325 | * | ||
326 | * ILOCK values | ||
327 | * 0-4 subclass values | ||
328 | * 5 PARENT subclass (not nestable) | ||
329 | * 6 RTBITMAP subclass (not nestable) | ||
330 | * 7 RTSUM subclass (not nestable) | ||
331 | * | ||
302 | */ | 332 | */ |
303 | #define XFS_LOCK_PARENT 1 | 333 | #define XFS_IOLOCK_SHIFT 16 |
304 | #define XFS_LOCK_RTBITMAP 2 | 334 | #define XFS_IOLOCK_PARENT_VAL 4 |
305 | #define XFS_LOCK_RTSUM 3 | 335 | #define XFS_IOLOCK_MAX_SUBCLASS (XFS_IOLOCK_PARENT_VAL - 1) |
306 | #define XFS_LOCK_INUMORDER 4 | 336 | #define XFS_IOLOCK_DEP_MASK 0x000f0000 |
307 | 337 | #define XFS_IOLOCK_PARENT (XFS_IOLOCK_PARENT_VAL << XFS_IOLOCK_SHIFT) | |
308 | #define XFS_IOLOCK_SHIFT 16 | 338 | |
309 | #define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT) | 339 | #define XFS_MMAPLOCK_SHIFT 20 |
310 | 340 | #define XFS_MMAPLOCK_NUMORDER 0 | |
311 | #define XFS_MMAPLOCK_SHIFT 20 | 341 | #define XFS_MMAPLOCK_MAX_SUBCLASS 3 |
312 | 342 | #define XFS_MMAPLOCK_DEP_MASK 0x00f00000 | |
313 | #define XFS_ILOCK_SHIFT 24 | 343 | |
314 | #define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT) | 344 | #define XFS_ILOCK_SHIFT 24 |
315 | #define XFS_ILOCK_RTBITMAP (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT) | 345 | #define XFS_ILOCK_PARENT_VAL 5 |
316 | #define XFS_ILOCK_RTSUM (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT) | 346 | #define XFS_ILOCK_MAX_SUBCLASS (XFS_ILOCK_PARENT_VAL - 1) |
317 | 347 | #define XFS_ILOCK_RTBITMAP_VAL 6 | |
318 | #define XFS_IOLOCK_DEP_MASK 0x000f0000 | 348 | #define XFS_ILOCK_RTSUM_VAL 7 |
319 | #define XFS_MMAPLOCK_DEP_MASK 0x00f00000 | 349 | #define XFS_ILOCK_DEP_MASK 0xff000000 |
320 | #define XFS_ILOCK_DEP_MASK 0xff000000 | 350 | #define XFS_ILOCK_PARENT (XFS_ILOCK_PARENT_VAL << XFS_ILOCK_SHIFT) |
321 | #define XFS_LOCK_DEP_MASK (XFS_IOLOCK_DEP_MASK | \ | 351 | #define XFS_ILOCK_RTBITMAP (XFS_ILOCK_RTBITMAP_VAL << XFS_ILOCK_SHIFT) |
352 | #define XFS_ILOCK_RTSUM (XFS_ILOCK_RTSUM_VAL << XFS_ILOCK_SHIFT) | ||
353 | |||
354 | #define XFS_LOCK_SUBCLASS_MASK (XFS_IOLOCK_DEP_MASK | \ | ||
322 | XFS_MMAPLOCK_DEP_MASK | \ | 355 | XFS_MMAPLOCK_DEP_MASK | \ |
323 | XFS_ILOCK_DEP_MASK) | 356 | XFS_ILOCK_DEP_MASK) |
324 | 357 | ||
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index bf13a5a7e2f4..62bd80f4edd9 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -703,17 +703,10 @@ xfs_iflush_abort( | |||
703 | xfs_inode_log_item_t *iip = ip->i_itemp; | 703 | xfs_inode_log_item_t *iip = ip->i_itemp; |
704 | 704 | ||
705 | if (iip) { | 705 | if (iip) { |
706 | struct xfs_ail *ailp = iip->ili_item.li_ailp; | ||
707 | if (iip->ili_item.li_flags & XFS_LI_IN_AIL) { | 706 | if (iip->ili_item.li_flags & XFS_LI_IN_AIL) { |
708 | spin_lock(&ailp->xa_lock); | 707 | xfs_trans_ail_remove(&iip->ili_item, |
709 | if (iip->ili_item.li_flags & XFS_LI_IN_AIL) { | 708 | stale ? SHUTDOWN_LOG_IO_ERROR : |
710 | /* xfs_trans_ail_delete() drops the AIL lock. */ | ||
711 | xfs_trans_ail_delete(ailp, &iip->ili_item, | ||
712 | stale ? | ||
713 | SHUTDOWN_LOG_IO_ERROR : | ||
714 | SHUTDOWN_CORRUPT_INCORE); | 709 | SHUTDOWN_CORRUPT_INCORE); |
715 | } else | ||
716 | spin_unlock(&ailp->xa_lock); | ||
717 | } | 710 | } |
718 | iip->ili_logged = 0; | 711 | iip->ili_logged = 0; |
719 | /* | 712 | /* |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 766b23f86ce9..8294132e6a3c 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -609,7 +609,7 @@ xfs_setattr_nonsize( | |||
609 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); | 609 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_NOT_SIZE); |
610 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); | 610 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 0, 0); |
611 | if (error) | 611 | if (error) |
612 | goto out_dqrele; | 612 | goto out_trans_cancel; |
613 | 613 | ||
614 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 614 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
615 | 615 | ||
@@ -640,7 +640,7 @@ xfs_setattr_nonsize( | |||
640 | NULL, capable(CAP_FOWNER) ? | 640 | NULL, capable(CAP_FOWNER) ? |
641 | XFS_QMOPT_FORCE_RES : 0); | 641 | XFS_QMOPT_FORCE_RES : 0); |
642 | if (error) /* out of quota */ | 642 | if (error) /* out of quota */ |
643 | goto out_trans_cancel; | 643 | goto out_unlock; |
644 | } | 644 | } |
645 | } | 645 | } |
646 | 646 | ||
@@ -729,10 +729,10 @@ xfs_setattr_nonsize( | |||
729 | 729 | ||
730 | return 0; | 730 | return 0; |
731 | 731 | ||
732 | out_unlock: | ||
733 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
732 | out_trans_cancel: | 734 | out_trans_cancel: |
733 | xfs_trans_cancel(tp); | 735 | xfs_trans_cancel(tp); |
734 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
735 | out_dqrele: | ||
736 | xfs_qm_dqrele(udqp); | 736 | xfs_qm_dqrele(udqp); |
737 | xfs_qm_dqrele(gdqp); | 737 | xfs_qm_dqrele(gdqp); |
738 | return error; | 738 | return error; |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index f41b0c3fddab..930ebd86beba 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -473,7 +473,8 @@ xfs_bulkstat( | |||
473 | * pending error, then we are done. | 473 | * pending error, then we are done. |
474 | */ | 474 | */ |
475 | del_cursor: | 475 | del_cursor: |
476 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 476 | xfs_btree_del_cursor(cur, error ? |
477 | XFS_BTREE_ERROR : XFS_BTREE_NOERROR); | ||
477 | xfs_buf_relse(agbp); | 478 | xfs_buf_relse(agbp); |
478 | if (error) | 479 | if (error) |
479 | break; | 480 | break; |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 08d4fe46f0fa..aaadee0969c9 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -668,9 +668,9 @@ xfs_log_mount( | |||
668 | ASSERT(0); | 668 | ASSERT(0); |
669 | goto out_free_log; | 669 | goto out_free_log; |
670 | } | 670 | } |
671 | xfs_crit(mp, "Log size out of supported range."); | ||
671 | xfs_crit(mp, | 672 | xfs_crit(mp, |
672 | "Log size out of supported range. Continuing onwards, but if log hangs are\n" | 673 | "Continuing onwards, but if log hangs are experienced then please report this message in the bug report."); |
673 | "experienced then please report this message in the bug report."); | ||
674 | } | 674 | } |
675 | 675 | ||
676 | /* | 676 | /* |
@@ -700,6 +700,7 @@ xfs_log_mount( | |||
700 | if (error) { | 700 | if (error) { |
701 | xfs_warn(mp, "log mount/recovery failed: error %d", | 701 | xfs_warn(mp, "log mount/recovery failed: error %d", |
702 | error); | 702 | error); |
703 | xlog_recover_cancel(mp->m_log); | ||
703 | goto out_destroy_ail; | 704 | goto out_destroy_ail; |
704 | } | 705 | } |
705 | } | 706 | } |
@@ -740,18 +741,35 @@ out: | |||
740 | * it. | 741 | * it. |
741 | */ | 742 | */ |
742 | int | 743 | int |
743 | xfs_log_mount_finish(xfs_mount_t *mp) | 744 | xfs_log_mount_finish( |
745 | struct xfs_mount *mp) | ||
744 | { | 746 | { |
745 | int error = 0; | 747 | int error = 0; |
746 | 748 | ||
747 | if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { | 749 | if (mp->m_flags & XFS_MOUNT_NORECOVERY) { |
748 | error = xlog_recover_finish(mp->m_log); | ||
749 | if (!error) | ||
750 | xfs_log_work_queue(mp); | ||
751 | } else { | ||
752 | ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); | 750 | ASSERT(mp->m_flags & XFS_MOUNT_RDONLY); |
751 | return 0; | ||
753 | } | 752 | } |
754 | 753 | ||
754 | error = xlog_recover_finish(mp->m_log); | ||
755 | if (!error) | ||
756 | xfs_log_work_queue(mp); | ||
757 | |||
758 | return error; | ||
759 | } | ||
760 | |||
761 | /* | ||
762 | * The mount has failed. Cancel the recovery if it hasn't completed and destroy | ||
763 | * the log. | ||
764 | */ | ||
765 | int | ||
766 | xfs_log_mount_cancel( | ||
767 | struct xfs_mount *mp) | ||
768 | { | ||
769 | int error; | ||
770 | |||
771 | error = xlog_recover_cancel(mp->m_log); | ||
772 | xfs_log_unmount(mp); | ||
755 | 773 | ||
756 | return error; | 774 | return error; |
757 | } | 775 | } |
@@ -1142,11 +1160,13 @@ xlog_space_left( | |||
1142 | * In this case we just want to return the size of the | 1160 | * In this case we just want to return the size of the |
1143 | * log as the amount of space left. | 1161 | * log as the amount of space left. |
1144 | */ | 1162 | */ |
1163 | xfs_alert(log->l_mp, "xlog_space_left: head behind tail"); | ||
1145 | xfs_alert(log->l_mp, | 1164 | xfs_alert(log->l_mp, |
1146 | "xlog_space_left: head behind tail\n" | 1165 | " tail_cycle = %d, tail_bytes = %d", |
1147 | " tail_cycle = %d, tail_bytes = %d\n" | 1166 | tail_cycle, tail_bytes); |
1148 | " GH cycle = %d, GH bytes = %d", | 1167 | xfs_alert(log->l_mp, |
1149 | tail_cycle, tail_bytes, head_cycle, head_bytes); | 1168 | " GH cycle = %d, GH bytes = %d", |
1169 | head_cycle, head_bytes); | ||
1150 | ASSERT(0); | 1170 | ASSERT(0); |
1151 | free_bytes = log->l_logsize; | 1171 | free_bytes = log->l_logsize; |
1152 | } | 1172 | } |
@@ -1652,8 +1672,13 @@ xlog_cksum( | |||
1652 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { | 1672 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb)) { |
1653 | union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead; | 1673 | union xlog_in_core2 *xhdr = (union xlog_in_core2 *)rhead; |
1654 | int i; | 1674 | int i; |
1675 | int xheads; | ||
1676 | |||
1677 | xheads = size / XLOG_HEADER_CYCLE_SIZE; | ||
1678 | if (size % XLOG_HEADER_CYCLE_SIZE) | ||
1679 | xheads++; | ||
1655 | 1680 | ||
1656 | for (i = 1; i < log->l_iclog_heads; i++) { | 1681 | for (i = 1; i < xheads; i++) { |
1657 | crc = crc32c(crc, &xhdr[i].hic_xheader, | 1682 | crc = crc32c(crc, &xhdr[i].hic_xheader, |
1658 | sizeof(struct xlog_rec_ext_header)); | 1683 | sizeof(struct xlog_rec_ext_header)); |
1659 | } | 1684 | } |
@@ -2028,26 +2053,24 @@ xlog_print_tic_res( | |||
2028 | "SWAPEXT" | 2053 | "SWAPEXT" |
2029 | }; | 2054 | }; |
2030 | 2055 | ||
2031 | xfs_warn(mp, | 2056 | xfs_warn(mp, "xlog_write: reservation summary:"); |
2032 | "xlog_write: reservation summary:\n" | 2057 | xfs_warn(mp, " trans type = %s (%u)", |
2033 | " trans type = %s (%u)\n" | 2058 | ((ticket->t_trans_type <= 0 || |
2034 | " unit res = %d bytes\n" | 2059 | ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? |
2035 | " current res = %d bytes\n" | ||
2036 | " total reg = %u bytes (o/flow = %u bytes)\n" | ||
2037 | " ophdrs = %u (ophdr space = %u bytes)\n" | ||
2038 | " ophdr + reg = %u bytes\n" | ||
2039 | " num regions = %u", | ||
2040 | ((ticket->t_trans_type <= 0 || | ||
2041 | ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? | ||
2042 | "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), | 2060 | "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), |
2043 | ticket->t_trans_type, | 2061 | ticket->t_trans_type); |
2044 | ticket->t_unit_res, | 2062 | xfs_warn(mp, " unit res = %d bytes", |
2045 | ticket->t_curr_res, | 2063 | ticket->t_unit_res); |
2046 | ticket->t_res_arr_sum, ticket->t_res_o_flow, | 2064 | xfs_warn(mp, " current res = %d bytes", |
2047 | ticket->t_res_num_ophdrs, ophdr_spc, | 2065 | ticket->t_curr_res); |
2048 | ticket->t_res_arr_sum + | 2066 | xfs_warn(mp, " total reg = %u bytes (o/flow = %u bytes)", |
2049 | ticket->t_res_o_flow + ophdr_spc, | 2067 | ticket->t_res_arr_sum, ticket->t_res_o_flow); |
2050 | ticket->t_res_num); | 2068 | xfs_warn(mp, " ophdrs = %u (ophdr space = %u bytes)", |
2069 | ticket->t_res_num_ophdrs, ophdr_spc); | ||
2070 | xfs_warn(mp, " ophdr + reg = %u bytes", | ||
2071 | ticket->t_res_arr_sum + ticket->t_res_o_flow + ophdr_spc); | ||
2072 | xfs_warn(mp, " num regions = %u", | ||
2073 | ticket->t_res_num); | ||
2051 | 2074 | ||
2052 | for (i = 0; i < ticket->t_res_num; i++) { | 2075 | for (i = 0; i < ticket->t_res_num; i++) { |
2053 | uint r_type = ticket->t_res_arr[i].r_type; | 2076 | uint r_type = ticket->t_res_arr[i].r_type; |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index fa27aaec72cb..09d91d3166cd 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -147,6 +147,7 @@ int xfs_log_mount(struct xfs_mount *mp, | |||
147 | xfs_daddr_t start_block, | 147 | xfs_daddr_t start_block, |
148 | int num_bblocks); | 148 | int num_bblocks); |
149 | int xfs_log_mount_finish(struct xfs_mount *mp); | 149 | int xfs_log_mount_finish(struct xfs_mount *mp); |
150 | int xfs_log_mount_cancel(struct xfs_mount *); | ||
150 | xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); | 151 | xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); |
151 | xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp); | 152 | xfs_lsn_t xlog_assign_tail_lsn_locked(struct xfs_mount *mp); |
152 | void xfs_log_space_wake(struct xfs_mount *mp); | 153 | void xfs_log_space_wake(struct xfs_mount *mp); |
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index abc2ccbff739..4e7649351f5a 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -307,7 +307,13 @@ xlog_cil_insert_items( | |||
307 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) | 307 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
308 | continue; | 308 | continue; |
309 | 309 | ||
310 | list_move_tail(&lip->li_cil, &cil->xc_cil); | 310 | /* |
311 | * Only move the item if it isn't already at the tail. This is | ||
312 | * to prevent a transient list_empty() state when reinserting | ||
313 | * an item that is already the only item in the CIL. | ||
314 | */ | ||
315 | if (!list_is_last(&lip->li_cil, &cil->xc_cil)) | ||
316 | list_move_tail(&lip->li_cil, &cil->xc_cil); | ||
311 | } | 317 | } |
312 | 318 | ||
313 | /* account for space used by new iovec headers */ | 319 | /* account for space used by new iovec headers */ |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 1c87c8abfbed..950f3f94720c 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -426,6 +426,8 @@ xlog_recover( | |||
426 | extern int | 426 | extern int |
427 | xlog_recover_finish( | 427 | xlog_recover_finish( |
428 | struct xlog *log); | 428 | struct xlog *log); |
429 | extern int | ||
430 | xlog_recover_cancel(struct xlog *); | ||
429 | 431 | ||
430 | extern __le32 xlog_cksum(struct xlog *log, struct xlog_rec_header *rhead, | 432 | extern __le32 xlog_cksum(struct xlog *log, struct xlog_rec_header *rhead, |
431 | char *dp, int size); | 433 | char *dp, int size); |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 480ebba8464f..512a0945d52a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1895,15 +1895,25 @@ xlog_recover_get_buf_lsn( | |||
1895 | */ | 1895 | */ |
1896 | goto recover_immediately; | 1896 | goto recover_immediately; |
1897 | case XFS_SB_MAGIC: | 1897 | case XFS_SB_MAGIC: |
1898 | /* | ||
1899 | * superblock uuids are magic. We may or may not have a | ||
1900 | * sb_meta_uuid on disk, but it will be set in the in-core | ||
1901 | * superblock. We set the uuid pointer for verification | ||
1902 | * according to the superblock feature mask to ensure we check | ||
1903 | * the relevant UUID in the superblock. | ||
1904 | */ | ||
1898 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); | 1905 | lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn); |
1899 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; | 1906 | if (xfs_sb_version_hasmetauuid(&mp->m_sb)) |
1907 | uuid = &((struct xfs_dsb *)blk)->sb_meta_uuid; | ||
1908 | else | ||
1909 | uuid = &((struct xfs_dsb *)blk)->sb_uuid; | ||
1900 | break; | 1910 | break; |
1901 | default: | 1911 | default: |
1902 | break; | 1912 | break; |
1903 | } | 1913 | } |
1904 | 1914 | ||
1905 | if (lsn != (xfs_lsn_t)-1) { | 1915 | if (lsn != (xfs_lsn_t)-1) { |
1906 | if (!uuid_equal(&mp->m_sb.sb_uuid, uuid)) | 1916 | if (!uuid_equal(&mp->m_sb.sb_meta_uuid, uuid)) |
1907 | goto recover_immediately; | 1917 | goto recover_immediately; |
1908 | return lsn; | 1918 | return lsn; |
1909 | } | 1919 | } |
@@ -2933,16 +2943,16 @@ xlog_recover_efi_pass2( | |||
2933 | struct xlog_recover_item *item, | 2943 | struct xlog_recover_item *item, |
2934 | xfs_lsn_t lsn) | 2944 | xfs_lsn_t lsn) |
2935 | { | 2945 | { |
2936 | int error; | 2946 | int error; |
2937 | xfs_mount_t *mp = log->l_mp; | 2947 | struct xfs_mount *mp = log->l_mp; |
2938 | xfs_efi_log_item_t *efip; | 2948 | struct xfs_efi_log_item *efip; |
2939 | xfs_efi_log_format_t *efi_formatp; | 2949 | struct xfs_efi_log_format *efi_formatp; |
2940 | 2950 | ||
2941 | efi_formatp = item->ri_buf[0].i_addr; | 2951 | efi_formatp = item->ri_buf[0].i_addr; |
2942 | 2952 | ||
2943 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2953 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
2944 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), | 2954 | error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format); |
2945 | &(efip->efi_format)))) { | 2955 | if (error) { |
2946 | xfs_efi_item_free(efip); | 2956 | xfs_efi_item_free(efip); |
2947 | return error; | 2957 | return error; |
2948 | } | 2958 | } |
@@ -2950,20 +2960,23 @@ xlog_recover_efi_pass2( | |||
2950 | 2960 | ||
2951 | spin_lock(&log->l_ailp->xa_lock); | 2961 | spin_lock(&log->l_ailp->xa_lock); |
2952 | /* | 2962 | /* |
2953 | * xfs_trans_ail_update() drops the AIL lock. | 2963 | * The EFI has two references. One for the EFD and one for EFI to ensure |
2964 | * it makes it into the AIL. Insert the EFI into the AIL directly and | ||
2965 | * drop the EFI reference. Note that xfs_trans_ail_update() drops the | ||
2966 | * AIL lock. | ||
2954 | */ | 2967 | */ |
2955 | xfs_trans_ail_update(log->l_ailp, &efip->efi_item, lsn); | 2968 | xfs_trans_ail_update(log->l_ailp, &efip->efi_item, lsn); |
2969 | xfs_efi_release(efip); | ||
2956 | return 0; | 2970 | return 0; |
2957 | } | 2971 | } |
2958 | 2972 | ||
2959 | 2973 | ||
2960 | /* | 2974 | /* |
2961 | * This routine is called when an efd format structure is found in | 2975 | * This routine is called when an EFD format structure is found in a committed |
2962 | * a committed transaction in the log. It's purpose is to cancel | 2976 | * transaction in the log. Its purpose is to cancel the corresponding EFI if it |
2963 | * the corresponding efi if it was still in the log. To do this | 2977 | * was still in the log. To do this it searches the AIL for the EFI with an id |
2964 | * it searches the AIL for the efi with an id equal to that in the | 2978 | * equal to that in the EFD format structure. If we find it we drop the EFD |
2965 | * efd format structure. If we find it, we remove the efi from the | 2979 | * reference, which removes the EFI from the AIL and frees it. |
2966 | * AIL and free it. | ||
2967 | */ | 2980 | */ |
2968 | STATIC int | 2981 | STATIC int |
2969 | xlog_recover_efd_pass2( | 2982 | xlog_recover_efd_pass2( |
@@ -2985,8 +2998,8 @@ xlog_recover_efd_pass2( | |||
2985 | efi_id = efd_formatp->efd_efi_id; | 2998 | efi_id = efd_formatp->efd_efi_id; |
2986 | 2999 | ||
2987 | /* | 3000 | /* |
2988 | * Search for the efi with the id in the efd format structure | 3001 | * Search for the EFI with the id in the EFD format structure in the |
2989 | * in the AIL. | 3002 | * AIL. |
2990 | */ | 3003 | */ |
2991 | spin_lock(&ailp->xa_lock); | 3004 | spin_lock(&ailp->xa_lock); |
2992 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); | 3005 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); |
@@ -2995,18 +3008,18 @@ xlog_recover_efd_pass2( | |||
2995 | efip = (xfs_efi_log_item_t *)lip; | 3008 | efip = (xfs_efi_log_item_t *)lip; |
2996 | if (efip->efi_format.efi_id == efi_id) { | 3009 | if (efip->efi_format.efi_id == efi_id) { |
2997 | /* | 3010 | /* |
2998 | * xfs_trans_ail_delete() drops the | 3011 | * Drop the EFD reference to the EFI. This |
2999 | * AIL lock. | 3012 | * removes the EFI from the AIL and frees it. |
3000 | */ | 3013 | */ |
3001 | xfs_trans_ail_delete(ailp, lip, | 3014 | spin_unlock(&ailp->xa_lock); |
3002 | SHUTDOWN_CORRUPT_INCORE); | 3015 | xfs_efi_release(efip); |
3003 | xfs_efi_item_free(efip); | ||
3004 | spin_lock(&ailp->xa_lock); | 3016 | spin_lock(&ailp->xa_lock); |
3005 | break; | 3017 | break; |
3006 | } | 3018 | } |
3007 | } | 3019 | } |
3008 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3020 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3009 | } | 3021 | } |
3022 | |||
3010 | xfs_trans_ail_cursor_done(&cur); | 3023 | xfs_trans_ail_cursor_done(&cur); |
3011 | spin_unlock(&ailp->xa_lock); | 3024 | spin_unlock(&ailp->xa_lock); |
3012 | 3025 | ||
@@ -3034,6 +3047,11 @@ xlog_recover_do_icreate_pass2( | |||
3034 | unsigned int count; | 3047 | unsigned int count; |
3035 | unsigned int isize; | 3048 | unsigned int isize; |
3036 | xfs_agblock_t length; | 3049 | xfs_agblock_t length; |
3050 | int blks_per_cluster; | ||
3051 | int bb_per_cluster; | ||
3052 | int cancel_count; | ||
3053 | int nbufs; | ||
3054 | int i; | ||
3037 | 3055 | ||
3038 | icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; | 3056 | icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; |
3039 | if (icl->icl_type != XFS_LI_ICREATE) { | 3057 | if (icl->icl_type != XFS_LI_ICREATE) { |
@@ -3092,22 +3110,45 @@ xlog_recover_do_icreate_pass2( | |||
3092 | } | 3110 | } |
3093 | 3111 | ||
3094 | /* | 3112 | /* |
3095 | * Inode buffers can be freed. Do not replay the inode initialisation as | 3113 | * The icreate transaction can cover multiple cluster buffers and these |
3096 | * we could be overwriting something written after this inode buffer was | 3114 | * buffers could have been freed and reused. Check the individual |
3097 | * cancelled. | 3115 | * buffers for cancellation so we don't overwrite anything written after |
3116 | * a cancellation. | ||
3117 | */ | ||
3118 | blks_per_cluster = xfs_icluster_size_fsb(mp); | ||
3119 | bb_per_cluster = XFS_FSB_TO_BB(mp, blks_per_cluster); | ||
3120 | nbufs = length / blks_per_cluster; | ||
3121 | for (i = 0, cancel_count = 0; i < nbufs; i++) { | ||
3122 | xfs_daddr_t daddr; | ||
3123 | |||
3124 | daddr = XFS_AGB_TO_DADDR(mp, agno, | ||
3125 | agbno + i * blks_per_cluster); | ||
3126 | if (xlog_check_buffer_cancelled(log, daddr, bb_per_cluster, 0)) | ||
3127 | cancel_count++; | ||
3128 | } | ||
3129 | |||
3130 | /* | ||
3131 | * We currently only use icreate for a single allocation at a time. This | ||
3132 | * means we should expect either all or none of the buffers to be | ||
3133 | * cancelled. Be conservative and skip replay if at least one buffer is | ||
3134 | * cancelled, but warn the user that something is awry if the buffers | ||
3135 | * are not consistent. | ||
3098 | * | 3136 | * |
3099 | * XXX: we need to iterate all buffers and only init those that are not | 3137 | * XXX: This must be refined to only skip cancelled clusters once we use |
3100 | * cancelled. I think that a more fine grained factoring of | 3138 | * icreate for multiple chunk allocations. |
3101 | * xfs_ialloc_inode_init may be appropriate here to enable this to be | ||
3102 | * done easily. | ||
3103 | */ | 3139 | */ |
3104 | if (xlog_check_buffer_cancelled(log, | 3140 | ASSERT(!cancel_count || cancel_count == nbufs); |
3105 | XFS_AGB_TO_DADDR(mp, agno, agbno), length, 0)) | 3141 | if (cancel_count) { |
3142 | if (cancel_count != nbufs) | ||
3143 | xfs_warn(mp, | ||
3144 | "WARNING: partial inode chunk cancellation, skipped icreate."); | ||
3145 | trace_xfs_log_recover_icreate_cancel(log, icl); | ||
3106 | return 0; | 3146 | return 0; |
3147 | } | ||
3107 | 3148 | ||
3108 | xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, length, | 3149 | trace_xfs_log_recover_icreate_recover(log, icl); |
3109 | be32_to_cpu(icl->icl_gen)); | 3150 | return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, |
3110 | return 0; | 3151 | length, be32_to_cpu(icl->icl_gen)); |
3111 | } | 3152 | } |
3112 | 3153 | ||
3113 | STATIC void | 3154 | STATIC void |
@@ -3385,14 +3426,24 @@ xlog_recover_add_to_cont_trans( | |||
3385 | char *ptr, *old_ptr; | 3426 | char *ptr, *old_ptr; |
3386 | int old_len; | 3427 | int old_len; |
3387 | 3428 | ||
3429 | /* | ||
3430 | * If the transaction is empty, the header was split across this and the | ||
3431 | * previous record. Copy the rest of the header. | ||
3432 | */ | ||
3388 | if (list_empty(&trans->r_itemq)) { | 3433 | if (list_empty(&trans->r_itemq)) { |
3389 | /* finish copying rest of trans header */ | 3434 | ASSERT(len < sizeof(struct xfs_trans_header)); |
3435 | if (len > sizeof(struct xfs_trans_header)) { | ||
3436 | xfs_warn(log->l_mp, "%s: bad header length", __func__); | ||
3437 | return -EIO; | ||
3438 | } | ||
3439 | |||
3390 | xlog_recover_add_item(&trans->r_itemq); | 3440 | xlog_recover_add_item(&trans->r_itemq); |
3391 | ptr = (char *)&trans->r_theader + | 3441 | ptr = (char *)&trans->r_theader + |
3392 | sizeof(xfs_trans_header_t) - len; | 3442 | sizeof(struct xfs_trans_header) - len; |
3393 | memcpy(ptr, dp, len); | 3443 | memcpy(ptr, dp, len); |
3394 | return 0; | 3444 | return 0; |
3395 | } | 3445 | } |
3446 | |||
3396 | /* take the tail entry */ | 3447 | /* take the tail entry */ |
3397 | item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); | 3448 | item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); |
3398 | 3449 | ||
@@ -3441,7 +3492,19 @@ xlog_recover_add_to_trans( | |||
3441 | ASSERT(0); | 3492 | ASSERT(0); |
3442 | return -EIO; | 3493 | return -EIO; |
3443 | } | 3494 | } |
3444 | if (len == sizeof(xfs_trans_header_t)) | 3495 | |
3496 | if (len > sizeof(struct xfs_trans_header)) { | ||
3497 | xfs_warn(log->l_mp, "%s: bad header length", __func__); | ||
3498 | ASSERT(0); | ||
3499 | return -EIO; | ||
3500 | } | ||
3501 | |||
3502 | /* | ||
3503 | * The transaction header can be arbitrarily split across op | ||
3504 | * records. If we don't have the whole thing here, copy what we | ||
3505 | * do have and handle the rest in the next record. | ||
3506 | */ | ||
3507 | if (len == sizeof(struct xfs_trans_header)) | ||
3445 | xlog_recover_add_item(&trans->r_itemq); | 3508 | xlog_recover_add_item(&trans->r_itemq); |
3446 | memcpy(&trans->r_theader, dp, len); | 3509 | memcpy(&trans->r_theader, dp, len); |
3447 | return 0; | 3510 | return 0; |
@@ -3744,7 +3807,7 @@ xlog_recover_process_efi( | |||
3744 | * free the memory associated with it. | 3807 | * free the memory associated with it. |
3745 | */ | 3808 | */ |
3746 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); | 3809 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); |
3747 | xfs_efi_release(efip, efip->efi_format.efi_nextents); | 3810 | xfs_efi_release(efip); |
3748 | return -EIO; | 3811 | return -EIO; |
3749 | } | 3812 | } |
3750 | } | 3813 | } |
@@ -3757,11 +3820,11 @@ xlog_recover_process_efi( | |||
3757 | 3820 | ||
3758 | for (i = 0; i < efip->efi_format.efi_nextents; i++) { | 3821 | for (i = 0; i < efip->efi_format.efi_nextents; i++) { |
3759 | extp = &(efip->efi_format.efi_extents[i]); | 3822 | extp = &(efip->efi_format.efi_extents[i]); |
3760 | error = xfs_free_extent(tp, extp->ext_start, extp->ext_len); | 3823 | error = xfs_trans_free_extent(tp, efdp, extp->ext_start, |
3824 | extp->ext_len); | ||
3761 | if (error) | 3825 | if (error) |
3762 | goto abort_error; | 3826 | goto abort_error; |
3763 | xfs_trans_log_efd_extent(tp, efdp, extp->ext_start, | 3827 | |
3764 | extp->ext_len); | ||
3765 | } | 3828 | } |
3766 | 3829 | ||
3767 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); | 3830 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); |
@@ -3793,10 +3856,10 @@ abort_error: | |||
3793 | */ | 3856 | */ |
3794 | STATIC int | 3857 | STATIC int |
3795 | xlog_recover_process_efis( | 3858 | xlog_recover_process_efis( |
3796 | struct xlog *log) | 3859 | struct xlog *log) |
3797 | { | 3860 | { |
3798 | xfs_log_item_t *lip; | 3861 | struct xfs_log_item *lip; |
3799 | xfs_efi_log_item_t *efip; | 3862 | struct xfs_efi_log_item *efip; |
3800 | int error = 0; | 3863 | int error = 0; |
3801 | struct xfs_ail_cursor cur; | 3864 | struct xfs_ail_cursor cur; |
3802 | struct xfs_ail *ailp; | 3865 | struct xfs_ail *ailp; |
@@ -3820,7 +3883,7 @@ xlog_recover_process_efis( | |||
3820 | /* | 3883 | /* |
3821 | * Skip EFIs that we've already processed. | 3884 | * Skip EFIs that we've already processed. |
3822 | */ | 3885 | */ |
3823 | efip = (xfs_efi_log_item_t *)lip; | 3886 | efip = container_of(lip, struct xfs_efi_log_item, efi_item); |
3824 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) { | 3887 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) { |
3825 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3888 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3826 | continue; | 3889 | continue; |
@@ -3840,6 +3903,50 @@ out: | |||
3840 | } | 3903 | } |
3841 | 3904 | ||
3842 | /* | 3905 | /* |
3906 | * A cancel occurs when the mount has failed and we're bailing out. Release all | ||
3907 | * pending EFIs so they don't pin the AIL. | ||
3908 | */ | ||
3909 | STATIC int | ||
3910 | xlog_recover_cancel_efis( | ||
3911 | struct xlog *log) | ||
3912 | { | ||
3913 | struct xfs_log_item *lip; | ||
3914 | struct xfs_efi_log_item *efip; | ||
3915 | int error = 0; | ||
3916 | struct xfs_ail_cursor cur; | ||
3917 | struct xfs_ail *ailp; | ||
3918 | |||
3919 | ailp = log->l_ailp; | ||
3920 | spin_lock(&ailp->xa_lock); | ||
3921 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); | ||
3922 | while (lip != NULL) { | ||
3923 | /* | ||
3924 | * We're done when we see something other than an EFI. | ||
3925 | * There should be no EFIs left in the AIL now. | ||
3926 | */ | ||
3927 | if (lip->li_type != XFS_LI_EFI) { | ||
3928 | #ifdef DEBUG | ||
3929 | for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) | ||
3930 | ASSERT(lip->li_type != XFS_LI_EFI); | ||
3931 | #endif | ||
3932 | break; | ||
3933 | } | ||
3934 | |||
3935 | efip = container_of(lip, struct xfs_efi_log_item, efi_item); | ||
3936 | |||
3937 | spin_unlock(&ailp->xa_lock); | ||
3938 | xfs_efi_release(efip); | ||
3939 | spin_lock(&ailp->xa_lock); | ||
3940 | |||
3941 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | ||
3942 | } | ||
3943 | |||
3944 | xfs_trans_ail_cursor_done(&cur); | ||
3945 | spin_unlock(&ailp->xa_lock); | ||
3946 | return error; | ||
3947 | } | ||
3948 | |||
3949 | /* | ||
3843 | * This routine performs a transaction to null out a bad inode pointer | 3950 | * This routine performs a transaction to null out a bad inode pointer |
3844 | * in an agi unlinked inode hash bucket. | 3951 | * in an agi unlinked inode hash bucket. |
3845 | */ | 3952 | */ |
@@ -4532,11 +4639,13 @@ xlog_recover( | |||
4532 | xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, | 4639 | xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, |
4533 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { | 4640 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { |
4534 | xfs_warn(log->l_mp, | 4641 | xfs_warn(log->l_mp, |
4535 | "Superblock has unknown incompatible log features (0x%x) enabled.\n" | 4642 | "Superblock has unknown incompatible log features (0x%x) enabled.", |
4536 | "The log can not be fully and/or safely recovered by this kernel.\n" | ||
4537 | "Please recover the log on a kernel that supports the unknown features.", | ||
4538 | (log->l_mp->m_sb.sb_features_log_incompat & | 4643 | (log->l_mp->m_sb.sb_features_log_incompat & |
4539 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); | 4644 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)); |
4645 | xfs_warn(log->l_mp, | ||
4646 | "The log can not be fully and/or safely recovered by this kernel."); | ||
4647 | xfs_warn(log->l_mp, | ||
4648 | "Please recover the log on a kernel that supports the unknown features."); | ||
4540 | return -EINVAL; | 4649 | return -EINVAL; |
4541 | } | 4650 | } |
4542 | 4651 | ||
@@ -4612,6 +4721,17 @@ xlog_recover_finish( | |||
4612 | return 0; | 4721 | return 0; |
4613 | } | 4722 | } |
4614 | 4723 | ||
4724 | int | ||
4725 | xlog_recover_cancel( | ||
4726 | struct xlog *log) | ||
4727 | { | ||
4728 | int error = 0; | ||
4729 | |||
4730 | if (log->l_flags & XLOG_RECOVERY_NEEDED) | ||
4731 | error = xlog_recover_cancel_efis(log); | ||
4732 | |||
4733 | return error; | ||
4734 | } | ||
4615 | 4735 | ||
4616 | #if defined(DEBUG) | 4736 | #if defined(DEBUG) |
4617 | /* | 4737 | /* |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 461e791efad7..bf92e0c037c7 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -615,14 +615,14 @@ xfs_default_resblks(xfs_mount_t *mp) | |||
615 | */ | 615 | */ |
616 | int | 616 | int |
617 | xfs_mountfs( | 617 | xfs_mountfs( |
618 | xfs_mount_t *mp) | 618 | struct xfs_mount *mp) |
619 | { | 619 | { |
620 | xfs_sb_t *sbp = &(mp->m_sb); | 620 | struct xfs_sb *sbp = &(mp->m_sb); |
621 | xfs_inode_t *rip; | 621 | struct xfs_inode *rip; |
622 | __uint64_t resblks; | 622 | __uint64_t resblks; |
623 | uint quotamount = 0; | 623 | uint quotamount = 0; |
624 | uint quotaflags = 0; | 624 | uint quotaflags = 0; |
625 | int error = 0; | 625 | int error = 0; |
626 | 626 | ||
627 | xfs_sb_mount_common(mp, sbp); | 627 | xfs_sb_mount_common(mp, sbp); |
628 | 628 | ||
@@ -799,7 +799,9 @@ xfs_mountfs( | |||
799 | } | 799 | } |
800 | 800 | ||
801 | /* | 801 | /* |
802 | * log's mount-time initialization. Perform 1st part recovery if needed | 802 | * Log's mount-time initialization. The first part of recovery can place |
803 | * some items on the AIL, to be handled when recovery is finished or | ||
804 | * cancelled. | ||
803 | */ | 805 | */ |
804 | error = xfs_log_mount(mp, mp->m_logdev_targp, | 806 | error = xfs_log_mount(mp, mp->m_logdev_targp, |
805 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), | 807 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), |
@@ -910,9 +912,9 @@ xfs_mountfs( | |||
910 | } | 912 | } |
911 | 913 | ||
912 | /* | 914 | /* |
913 | * Finish recovering the file system. This part needed to be | 915 | * Finish recovering the file system. This part needed to be delayed |
914 | * delayed until after the root and real-time bitmap inodes | 916 | * until after the root and real-time bitmap inodes were consistently |
915 | * were consistently read in. | 917 | * read in. |
916 | */ | 918 | */ |
917 | error = xfs_log_mount_finish(mp); | 919 | error = xfs_log_mount_finish(mp); |
918 | if (error) { | 920 | if (error) { |
@@ -955,8 +957,10 @@ xfs_mountfs( | |||
955 | xfs_rtunmount_inodes(mp); | 957 | xfs_rtunmount_inodes(mp); |
956 | out_rele_rip: | 958 | out_rele_rip: |
957 | IRELE(rip); | 959 | IRELE(rip); |
960 | cancel_delayed_work_sync(&mp->m_reclaim_work); | ||
961 | xfs_reclaim_inodes(mp, SYNC_WAIT); | ||
958 | out_log_dealloc: | 962 | out_log_dealloc: |
959 | xfs_log_unmount(mp); | 963 | xfs_log_mount_cancel(mp); |
960 | out_fail_wait: | 964 | out_fail_wait: |
961 | if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) | 965 | if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp) |
962 | xfs_wait_buftarg(mp->m_logdev_targp); | 966 | xfs_wait_buftarg(mp->m_logdev_targp); |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index f4e8c06eee26..ab1bac6a3a1c 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -757,31 +757,30 @@ xfs_rtallocate_extent_size( | |||
757 | /* | 757 | /* |
758 | * Allocate space to the bitmap or summary file, and zero it, for growfs. | 758 | * Allocate space to the bitmap or summary file, and zero it, for growfs. |
759 | */ | 759 | */ |
760 | STATIC int /* error */ | 760 | STATIC int |
761 | xfs_growfs_rt_alloc( | 761 | xfs_growfs_rt_alloc( |
762 | xfs_mount_t *mp, /* file system mount point */ | 762 | struct xfs_mount *mp, /* file system mount point */ |
763 | xfs_extlen_t oblocks, /* old count of blocks */ | 763 | xfs_extlen_t oblocks, /* old count of blocks */ |
764 | xfs_extlen_t nblocks, /* new count of blocks */ | 764 | xfs_extlen_t nblocks, /* new count of blocks */ |
765 | xfs_inode_t *ip) /* inode (bitmap/summary) */ | 765 | struct xfs_inode *ip) /* inode (bitmap/summary) */ |
766 | { | 766 | { |
767 | xfs_fileoff_t bno; /* block number in file */ | 767 | xfs_fileoff_t bno; /* block number in file */ |
768 | xfs_buf_t *bp; /* temporary buffer for zeroing */ | 768 | struct xfs_buf *bp; /* temporary buffer for zeroing */ |
769 | int committed; /* transaction committed flag */ | 769 | int committed; /* transaction committed flag */ |
770 | xfs_daddr_t d; /* disk block address */ | 770 | xfs_daddr_t d; /* disk block address */ |
771 | int error; /* error return value */ | 771 | int error; /* error return value */ |
772 | xfs_fsblock_t firstblock; /* first block allocated in xaction */ | 772 | xfs_fsblock_t firstblock;/* first block allocated in xaction */ |
773 | xfs_bmap_free_t flist; /* list of freed blocks */ | 773 | struct xfs_bmap_free flist; /* list of freed blocks */ |
774 | xfs_fsblock_t fsbno; /* filesystem block for bno */ | 774 | xfs_fsblock_t fsbno; /* filesystem block for bno */ |
775 | xfs_bmbt_irec_t map; /* block map output */ | 775 | struct xfs_bmbt_irec map; /* block map output */ |
776 | int nmap; /* number of block maps */ | 776 | int nmap; /* number of block maps */ |
777 | int resblks; /* space reservation */ | 777 | int resblks; /* space reservation */ |
778 | struct xfs_trans *tp; | ||
778 | 779 | ||
779 | /* | 780 | /* |
780 | * Allocate space to the file, as necessary. | 781 | * Allocate space to the file, as necessary. |
781 | */ | 782 | */ |
782 | while (oblocks < nblocks) { | 783 | while (oblocks < nblocks) { |
783 | xfs_trans_t *tp; | ||
784 | |||
785 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); | 784 | tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFSRT_ALLOC); |
786 | resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); | 785 | resblks = XFS_GROWFSRT_SPACE_RES(mp, nblocks - oblocks); |
787 | /* | 786 | /* |
@@ -790,7 +789,7 @@ xfs_growfs_rt_alloc( | |||
790 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc, | 789 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtalloc, |
791 | resblks, 0); | 790 | resblks, 0); |
792 | if (error) | 791 | if (error) |
793 | goto error_cancel; | 792 | goto out_trans_cancel; |
794 | /* | 793 | /* |
795 | * Lock the inode. | 794 | * Lock the inode. |
796 | */ | 795 | */ |
@@ -808,16 +807,16 @@ xfs_growfs_rt_alloc( | |||
808 | if (!error && nmap < 1) | 807 | if (!error && nmap < 1) |
809 | error = -ENOSPC; | 808 | error = -ENOSPC; |
810 | if (error) | 809 | if (error) |
811 | goto error_cancel; | 810 | goto out_bmap_cancel; |
812 | /* | 811 | /* |
813 | * Free any blocks freed up in the transaction, then commit. | 812 | * Free any blocks freed up in the transaction, then commit. |
814 | */ | 813 | */ |
815 | error = xfs_bmap_finish(&tp, &flist, &committed); | 814 | error = xfs_bmap_finish(&tp, &flist, &committed); |
816 | if (error) | 815 | if (error) |
817 | goto error_cancel; | 816 | goto out_bmap_cancel; |
818 | error = xfs_trans_commit(tp); | 817 | error = xfs_trans_commit(tp); |
819 | if (error) | 818 | if (error) |
820 | goto error; | 819 | return error; |
821 | /* | 820 | /* |
822 | * Now we need to clear the allocated blocks. | 821 | * Now we need to clear the allocated blocks. |
823 | * Do this one block per transaction, to keep it simple. | 822 | * Do this one block per transaction, to keep it simple. |
@@ -832,7 +831,7 @@ xfs_growfs_rt_alloc( | |||
832 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, | 831 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_growrtzero, |
833 | 0, 0); | 832 | 0, 0); |
834 | if (error) | 833 | if (error) |
835 | goto error_cancel; | 834 | goto out_trans_cancel; |
836 | /* | 835 | /* |
837 | * Lock the bitmap inode. | 836 | * Lock the bitmap inode. |
838 | */ | 837 | */ |
@@ -846,9 +845,7 @@ xfs_growfs_rt_alloc( | |||
846 | mp->m_bsize, 0); | 845 | mp->m_bsize, 0); |
847 | if (bp == NULL) { | 846 | if (bp == NULL) { |
848 | error = -EIO; | 847 | error = -EIO; |
849 | error_cancel: | 848 | goto out_trans_cancel; |
850 | xfs_trans_cancel(tp); | ||
851 | goto error; | ||
852 | } | 849 | } |
853 | memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); | 850 | memset(bp->b_addr, 0, mp->m_sb.sb_blocksize); |
854 | xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); | 851 | xfs_trans_log_buf(tp, bp, 0, mp->m_sb.sb_blocksize - 1); |
@@ -857,16 +854,20 @@ error_cancel: | |||
857 | */ | 854 | */ |
858 | error = xfs_trans_commit(tp); | 855 | error = xfs_trans_commit(tp); |
859 | if (error) | 856 | if (error) |
860 | goto error; | 857 | return error; |
861 | } | 858 | } |
862 | /* | 859 | /* |
863 | * Go on to the next extent, if any. | 860 | * Go on to the next extent, if any. |
864 | */ | 861 | */ |
865 | oblocks = map.br_startoff + map.br_blockcount; | 862 | oblocks = map.br_startoff + map.br_blockcount; |
866 | } | 863 | } |
864 | |||
867 | return 0; | 865 | return 0; |
868 | 866 | ||
869 | error: | 867 | out_bmap_cancel: |
868 | xfs_bmap_cancel(&flist); | ||
869 | out_trans_cancel: | ||
870 | xfs_trans_cancel(tp); | ||
870 | return error; | 871 | return error; |
871 | } | 872 | } |
872 | 873 | ||
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bbd9b1f10ffb..904f637cfa5f 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -261,16 +261,8 @@ xfs_parseargs( | |||
261 | mp->m_rtname = kstrndup(value, MAXNAMELEN, GFP_KERNEL); | 261 | mp->m_rtname = kstrndup(value, MAXNAMELEN, GFP_KERNEL); |
262 | if (!mp->m_rtname) | 262 | if (!mp->m_rtname) |
263 | return -ENOMEM; | 263 | return -ENOMEM; |
264 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { | 264 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE) || |
265 | if (!value || !*value) { | 265 | !strcmp(this_char, MNTOPT_BIOSIZE)) { |
266 | xfs_warn(mp, "%s option requires an argument", | ||
267 | this_char); | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | if (kstrtoint(value, 10, &iosize)) | ||
271 | return -EINVAL; | ||
272 | iosizelog = ffs(iosize) - 1; | ||
273 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { | ||
274 | if (!value || !*value) { | 266 | if (!value || !*value) { |
275 | xfs_warn(mp, "%s option requires an argument", | 267 | xfs_warn(mp, "%s option requires an argument", |
276 | this_char); | 268 | this_char); |
@@ -1528,6 +1520,10 @@ xfs_fs_fill_super( | |||
1528 | } | 1520 | } |
1529 | } | 1521 | } |
1530 | 1522 | ||
1523 | if (xfs_sb_version_hassparseinodes(&mp->m_sb)) | ||
1524 | xfs_alert(mp, | ||
1525 | "EXPERIMENTAL sparse inode feature enabled. Use at your own risk!"); | ||
1526 | |||
1531 | error = xfs_mountfs(mp); | 1527 | error = xfs_mountfs(mp); |
1532 | if (error) | 1528 | if (error) |
1533 | goto out_filestream_unmount; | 1529 | goto out_filestream_unmount; |
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 4be27b0210af..996481eeb491 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -240,7 +240,8 @@ xfs_symlink( | |||
240 | if (error) | 240 | if (error) |
241 | goto out_trans_cancel; | 241 | goto out_trans_cancel; |
242 | 242 | ||
243 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); | 243 | xfs_ilock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL | |
244 | XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); | ||
244 | unlock_dp_on_error = true; | 245 | unlock_dp_on_error = true; |
245 | 246 | ||
246 | /* | 247 | /* |
@@ -288,7 +289,7 @@ xfs_symlink( | |||
288 | * the transaction cancel unlocking dp so don't do it explicitly in the | 289 | * the transaction cancel unlocking dp so don't do it explicitly in the |
289 | * error path. | 290 | * error path. |
290 | */ | 291 | */ |
291 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 292 | xfs_trans_ijoin(tp, dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
292 | unlock_dp_on_error = false; | 293 | unlock_dp_on_error = false; |
293 | 294 | ||
294 | /* | 295 | /* |
@@ -421,7 +422,7 @@ out_release_inode: | |||
421 | xfs_qm_dqrele(pdqp); | 422 | xfs_qm_dqrele(pdqp); |
422 | 423 | ||
423 | if (unlock_dp_on_error) | 424 | if (unlock_dp_on_error) |
424 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 425 | xfs_iunlock(dp, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
425 | return error; | 426 | return error; |
426 | } | 427 | } |
427 | 428 | ||
@@ -501,7 +502,7 @@ xfs_inactive_symlink_rmt( | |||
501 | /* | 502 | /* |
502 | * Unmap the dead block(s) to the free_list. | 503 | * Unmap the dead block(s) to the free_list. |
503 | */ | 504 | */ |
504 | error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, | 505 | error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, |
505 | &first_block, &free_list, &done); | 506 | &first_block, &free_list, &done); |
506 | if (error) | 507 | if (error) |
507 | goto error_bmap_cancel; | 508 | goto error_bmap_cancel; |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 8d916d33d93d..9aeeb21bc3d0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -2089,6 +2089,40 @@ DEFINE_LOG_RECOVER_INO_ITEM(xfs_log_recover_inode_recover); | |||
2089 | DEFINE_LOG_RECOVER_INO_ITEM(xfs_log_recover_inode_cancel); | 2089 | DEFINE_LOG_RECOVER_INO_ITEM(xfs_log_recover_inode_cancel); |
2090 | DEFINE_LOG_RECOVER_INO_ITEM(xfs_log_recover_inode_skip); | 2090 | DEFINE_LOG_RECOVER_INO_ITEM(xfs_log_recover_inode_skip); |
2091 | 2091 | ||
2092 | DECLARE_EVENT_CLASS(xfs_log_recover_icreate_item_class, | ||
2093 | TP_PROTO(struct xlog *log, struct xfs_icreate_log *in_f), | ||
2094 | TP_ARGS(log, in_f), | ||
2095 | TP_STRUCT__entry( | ||
2096 | __field(dev_t, dev) | ||
2097 | __field(xfs_agnumber_t, agno) | ||
2098 | __field(xfs_agblock_t, agbno) | ||
2099 | __field(unsigned int, count) | ||
2100 | __field(unsigned int, isize) | ||
2101 | __field(xfs_agblock_t, length) | ||
2102 | __field(unsigned int, gen) | ||
2103 | ), | ||
2104 | TP_fast_assign( | ||
2105 | __entry->dev = log->l_mp->m_super->s_dev; | ||
2106 | __entry->agno = be32_to_cpu(in_f->icl_ag); | ||
2107 | __entry->agbno = be32_to_cpu(in_f->icl_agbno); | ||
2108 | __entry->count = be32_to_cpu(in_f->icl_count); | ||
2109 | __entry->isize = be32_to_cpu(in_f->icl_isize); | ||
2110 | __entry->length = be32_to_cpu(in_f->icl_length); | ||
2111 | __entry->gen = be32_to_cpu(in_f->icl_gen); | ||
2112 | ), | ||
2113 | TP_printk("dev %d:%d agno %u agbno %u count %u isize %u length %u " | ||
2114 | "gen %u", MAJOR(__entry->dev), MINOR(__entry->dev), | ||
2115 | __entry->agno, __entry->agbno, __entry->count, __entry->isize, | ||
2116 | __entry->length, __entry->gen) | ||
2117 | ) | ||
2118 | #define DEFINE_LOG_RECOVER_ICREATE_ITEM(name) \ | ||
2119 | DEFINE_EVENT(xfs_log_recover_icreate_item_class, name, \ | ||
2120 | TP_PROTO(struct xlog *log, struct xfs_icreate_log *in_f), \ | ||
2121 | TP_ARGS(log, in_f)) | ||
2122 | |||
2123 | DEFINE_LOG_RECOVER_ICREATE_ITEM(xfs_log_recover_icreate_cancel); | ||
2124 | DEFINE_LOG_RECOVER_ICREATE_ITEM(xfs_log_recover_icreate_recover); | ||
2125 | |||
2092 | DECLARE_EVENT_CLASS(xfs_discard_class, | 2126 | DECLARE_EVENT_CLASS(xfs_discard_class, |
2093 | TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, | 2127 | TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, |
2094 | xfs_agblock_t agbno, xfs_extlen_t len), | 2128 | xfs_agblock_t agbno, xfs_extlen_t len), |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 0582a27107d4..a0ab1dae9c31 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -1019,9 +1019,10 @@ xfs_trans_cancel( | |||
1019 | * chunk we've been working on and get a new transaction to continue. | 1019 | * chunk we've been working on and get a new transaction to continue. |
1020 | */ | 1020 | */ |
1021 | int | 1021 | int |
1022 | xfs_trans_roll( | 1022 | __xfs_trans_roll( |
1023 | struct xfs_trans **tpp, | 1023 | struct xfs_trans **tpp, |
1024 | struct xfs_inode *dp) | 1024 | struct xfs_inode *dp, |
1025 | int *committed) | ||
1025 | { | 1026 | { |
1026 | struct xfs_trans *trans; | 1027 | struct xfs_trans *trans; |
1027 | struct xfs_trans_res tres; | 1028 | struct xfs_trans_res tres; |
@@ -1052,6 +1053,7 @@ xfs_trans_roll( | |||
1052 | if (error) | 1053 | if (error) |
1053 | return error; | 1054 | return error; |
1054 | 1055 | ||
1056 | *committed = 1; | ||
1055 | trans = *tpp; | 1057 | trans = *tpp; |
1056 | 1058 | ||
1057 | /* | 1059 | /* |
@@ -1074,3 +1076,12 @@ xfs_trans_roll( | |||
1074 | xfs_trans_ijoin(trans, dp, 0); | 1076 | xfs_trans_ijoin(trans, dp, 0); |
1075 | return 0; | 1077 | return 0; |
1076 | } | 1078 | } |
1079 | |||
1080 | int | ||
1081 | xfs_trans_roll( | ||
1082 | struct xfs_trans **tpp, | ||
1083 | struct xfs_inode *dp) | ||
1084 | { | ||
1085 | int committed = 0; | ||
1086 | return __xfs_trans_roll(tpp, dp, &committed); | ||
1087 | } | ||
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 3b21b4e5e467..4643070d7cae 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -213,7 +213,6 @@ void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *, uint); | |||
213 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); | 213 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); |
214 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); | 214 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); |
215 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); | 215 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); |
216 | void xfs_efi_release(struct xfs_efi_log_item *, uint); | ||
217 | void xfs_trans_log_efi_extent(xfs_trans_t *, | 216 | void xfs_trans_log_efi_extent(xfs_trans_t *, |
218 | struct xfs_efi_log_item *, | 217 | struct xfs_efi_log_item *, |
219 | xfs_fsblock_t, | 218 | xfs_fsblock_t, |
@@ -221,11 +220,11 @@ void xfs_trans_log_efi_extent(xfs_trans_t *, | |||
221 | struct xfs_efd_log_item *xfs_trans_get_efd(xfs_trans_t *, | 220 | struct xfs_efd_log_item *xfs_trans_get_efd(xfs_trans_t *, |
222 | struct xfs_efi_log_item *, | 221 | struct xfs_efi_log_item *, |
223 | uint); | 222 | uint); |
224 | void xfs_trans_log_efd_extent(xfs_trans_t *, | 223 | int xfs_trans_free_extent(struct xfs_trans *, |
225 | struct xfs_efd_log_item *, | 224 | struct xfs_efd_log_item *, xfs_fsblock_t, |
226 | xfs_fsblock_t, | 225 | xfs_extlen_t); |
227 | xfs_extlen_t); | ||
228 | int xfs_trans_commit(struct xfs_trans *); | 226 | int xfs_trans_commit(struct xfs_trans *); |
227 | int __xfs_trans_roll(struct xfs_trans **, struct xfs_inode *, int *); | ||
229 | int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); | 228 | int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); |
230 | void xfs_trans_cancel(xfs_trans_t *); | 229 | void xfs_trans_cancel(xfs_trans_t *); |
231 | int xfs_trans_ail_init(struct xfs_mount *); | 230 | int xfs_trans_ail_init(struct xfs_mount *); |
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 284397dd7990..a96ae540eb62 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
26 | #include "xfs_trans_priv.h" | 26 | #include "xfs_trans_priv.h" |
27 | #include "xfs_extfree_item.h" | 27 | #include "xfs_extfree_item.h" |
28 | #include "xfs_alloc.h" | ||
28 | 29 | ||
29 | /* | 30 | /* |
30 | * This routine is called to allocate an "extent free intention" | 31 | * This routine is called to allocate an "extent free intention" |
@@ -108,19 +109,30 @@ xfs_trans_get_efd(xfs_trans_t *tp, | |||
108 | } | 109 | } |
109 | 110 | ||
110 | /* | 111 | /* |
111 | * This routine is called to indicate that the described | 112 | * Free an extent and log it to the EFD. Note that the transaction is marked |
112 | * extent is to be logged as having been freed. It should | 113 | * dirty regardless of whether the extent free succeeds or fails to support the |
113 | * be called once for each extent freed. | 114 | * EFI/EFD lifecycle rules. |
114 | */ | 115 | */ |
115 | void | 116 | int |
116 | xfs_trans_log_efd_extent(xfs_trans_t *tp, | 117 | xfs_trans_free_extent( |
117 | xfs_efd_log_item_t *efdp, | 118 | struct xfs_trans *tp, |
118 | xfs_fsblock_t start_block, | 119 | struct xfs_efd_log_item *efdp, |
119 | xfs_extlen_t ext_len) | 120 | xfs_fsblock_t start_block, |
121 | xfs_extlen_t ext_len) | ||
120 | { | 122 | { |
121 | uint next_extent; | 123 | uint next_extent; |
122 | xfs_extent_t *extp; | 124 | struct xfs_extent *extp; |
125 | int error; | ||
123 | 126 | ||
127 | error = xfs_free_extent(tp, start_block, ext_len); | ||
128 | |||
129 | /* | ||
130 | * Mark the transaction dirty, even on error. This ensures the | ||
131 | * transaction is aborted, which: | ||
132 | * | ||
133 | * 1.) releases the EFI and frees the EFD | ||
134 | * 2.) shuts down the filesystem | ||
135 | */ | ||
124 | tp->t_flags |= XFS_TRANS_DIRTY; | 136 | tp->t_flags |= XFS_TRANS_DIRTY; |
125 | efdp->efd_item.li_desc->lid_flags |= XFS_LID_DIRTY; | 137 | efdp->efd_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
126 | 138 | ||
@@ -130,4 +142,6 @@ xfs_trans_log_efd_extent(xfs_trans_t *tp, | |||
130 | extp->ext_start = start_block; | 142 | extp->ext_start = start_block; |
131 | extp->ext_len = ext_len; | 143 | extp->ext_len = ext_len; |
132 | efdp->efd_next_extent++; | 144 | efdp->efd_next_extent++; |
145 | |||
146 | return error; | ||
133 | } | 147 | } |
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 1b736294558a..49931b72da8a 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h | |||
@@ -119,6 +119,21 @@ xfs_trans_ail_delete( | |||
119 | xfs_trans_ail_delete_bulk(ailp, &lip, 1, shutdown_type); | 119 | xfs_trans_ail_delete_bulk(ailp, &lip, 1, shutdown_type); |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline void | ||
123 | xfs_trans_ail_remove( | ||
124 | struct xfs_log_item *lip, | ||
125 | int shutdown_type) | ||
126 | { | ||
127 | struct xfs_ail *ailp = lip->li_ailp; | ||
128 | |||
129 | spin_lock(&ailp->xa_lock); | ||
130 | /* xfs_trans_ail_delete() drops the AIL lock */ | ||
131 | if (lip->li_flags & XFS_LI_IN_AIL) | ||
132 | xfs_trans_ail_delete(ailp, lip, shutdown_type); | ||
133 | else | ||
134 | spin_unlock(&ailp->xa_lock); | ||
135 | } | ||
136 | |||
122 | void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); | 137 | void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); |
123 | void xfs_ail_push_all(struct xfs_ail *); | 138 | void xfs_ail_push_all(struct xfs_ail *); |
124 | void xfs_ail_push_all_sync(struct xfs_ail *); | 139 | void xfs_ail_push_all_sync(struct xfs_ail *); |