diff options
33 files changed, 587 insertions, 329 deletions
@@ -319,6 +319,12 @@ static int dax_insert_mapping(struct inode *inode, struct buffer_head *bh, | |||
319 | * @vma: The virtual memory area where the fault occurred | 319 | * @vma: The virtual memory area where the fault occurred |
320 | * @vmf: The description of the fault | 320 | * @vmf: The description of the fault |
321 | * @get_block: The filesystem method used to translate file offsets to blocks | 321 | * @get_block: The filesystem method used to translate file offsets to blocks |
322 | * @complete_unwritten: The filesystem method used to convert unwritten blocks | ||
323 | * to written so the data written to them is exposed. This is required for | ||
324 | * required by write faults for filesystems that will return unwritten | ||
325 | * extent mappings from @get_block, but it is optional for reads as | ||
326 | * dax_insert_mapping() will always zero unwritten blocks. If the fs does | ||
327 | * not support unwritten extents, the it should pass NULL. | ||
322 | * | 328 | * |
323 | * When a page fault occurs, filesystems may call this helper in their | 329 | * When a page fault occurs, filesystems may call this helper in their |
324 | * fault handler for DAX files. __dax_fault() assumes the caller has done all | 330 | * fault handler for DAX files. __dax_fault() assumes the caller has done all |
@@ -437,8 +443,12 @@ int __dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf, | |||
437 | * as for normal BH based IO completions. | 443 | * as for normal BH based IO completions. |
438 | */ | 444 | */ |
439 | error = dax_insert_mapping(inode, &bh, vma, vmf); | 445 | error = dax_insert_mapping(inode, &bh, vma, vmf); |
440 | if (buffer_unwritten(&bh)) | 446 | if (buffer_unwritten(&bh)) { |
441 | complete_unwritten(&bh, !error); | 447 | if (complete_unwritten) |
448 | complete_unwritten(&bh, !error); | ||
449 | else | ||
450 | WARN_ON_ONCE(!(vmf->flags & FAULT_FLAG_WRITE)); | ||
451 | } | ||
442 | 452 | ||
443 | out: | 453 | out: |
444 | if (error == -ENOMEM) | 454 | if (error == -ENOMEM) |
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_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index eba0d1e91a93..f38f9bd81557 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c | |||
@@ -159,11 +159,10 @@ xfs_attr3_rmt_write_verify( | |||
159 | struct xfs_buf *bp) | 159 | struct xfs_buf *bp) |
160 | { | 160 | { |
161 | struct xfs_mount *mp = bp->b_target->bt_mount; | 161 | struct xfs_mount *mp = bp->b_target->bt_mount; |
162 | struct xfs_buf_log_item *bip = bp->b_fspriv; | 162 | int blksize = mp->m_attr_geo->blksize; |
163 | char *ptr; | 163 | char *ptr; |
164 | int len; | 164 | int len; |
165 | xfs_daddr_t bno; | 165 | xfs_daddr_t bno; |
166 | int blksize = mp->m_attr_geo->blksize; | ||
167 | 166 | ||
168 | /* no verification of non-crc buffers */ | 167 | /* no verification of non-crc buffers */ |
169 | if (!xfs_sb_version_hascrc(&mp->m_sb)) | 168 | if (!xfs_sb_version_hascrc(&mp->m_sb)) |
@@ -175,16 +174,22 @@ xfs_attr3_rmt_write_verify( | |||
175 | ASSERT(len >= blksize); | 174 | ASSERT(len >= blksize); |
176 | 175 | ||
177 | while (len > 0) { | 176 | while (len > 0) { |
177 | struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr; | ||
178 | |||
178 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { | 179 | if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) { |
179 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | 180 | xfs_buf_ioerror(bp, -EFSCORRUPTED); |
180 | xfs_verifier_error(bp); | 181 | xfs_verifier_error(bp); |
181 | return; | 182 | return; |
182 | } | 183 | } |
183 | if (bip) { | ||
184 | struct xfs_attr3_rmt_hdr *rmt; | ||
185 | 184 | ||
186 | rmt = (struct xfs_attr3_rmt_hdr *)ptr; | 185 | /* |
187 | rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn); | 186 | * Ensure we aren't writing bogus LSNs to disk. See |
187 | * xfs_attr3_rmt_hdr_set() for the explanation. | ||
188 | */ | ||
189 | if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) { | ||
190 | xfs_buf_ioerror(bp, -EFSCORRUPTED); | ||
191 | xfs_verifier_error(bp); | ||
192 | return; | ||
188 | } | 193 | } |
189 | xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); | 194 | xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF); |
190 | 195 | ||
@@ -221,6 +226,18 @@ xfs_attr3_rmt_hdr_set( | |||
221 | rmt->rm_owner = cpu_to_be64(ino); | 226 | rmt->rm_owner = cpu_to_be64(ino); |
222 | rmt->rm_blkno = cpu_to_be64(bno); | 227 | rmt->rm_blkno = cpu_to_be64(bno); |
223 | 228 | ||
229 | /* | ||
230 | * Remote attribute blocks are written synchronously, so we don't | ||
231 | * have an LSN that we can stamp in them that makes any sense to log | ||
232 | * recovery. To ensure that log recovery handles overwrites of these | ||
233 | * blocks sanely (i.e. once they've been freed and reallocated as some | ||
234 | * other type of metadata) we need to ensure that the LSN has a value | ||
235 | * that tells log recovery to ignore the LSN and overwrite the buffer | ||
236 | * with whatever is in it's log. To do this, we use the magic | ||
237 | * NULLCOMMITLSN to indicate that the LSN is invalid. | ||
238 | */ | ||
239 | rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN); | ||
240 | |||
224 | return sizeof(struct xfs_attr3_rmt_hdr); | 241 | return sizeof(struct xfs_attr3_rmt_hdr); |
225 | } | 242 | } |
226 | 243 | ||
@@ -434,14 +451,21 @@ xfs_attr_rmtval_set( | |||
434 | 451 | ||
435 | /* | 452 | /* |
436 | * Allocate a single extent, up to the size of the value. | 453 | * Allocate a single extent, up to the size of the value. |
454 | * | ||
455 | * Note that we have to consider this a data allocation as we | ||
456 | * write the remote attribute without logging the contents. | ||
457 | * Hence we must ensure that we aren't using blocks that are on | ||
458 | * the busy list so that we don't overwrite blocks which have | ||
459 | * recently been freed but their transactions are not yet | ||
460 | * committed to disk. If we overwrite the contents of a busy | ||
461 | * extent and then crash then the block may not contain the | ||
462 | * correct metadata after log recovery occurs. | ||
437 | */ | 463 | */ |
438 | xfs_bmap_init(args->flist, args->firstblock); | 464 | xfs_bmap_init(args->flist, args->firstblock); |
439 | nmap = 1; | 465 | nmap = 1; |
440 | error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, | 466 | error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, |
441 | blkcnt, | 467 | blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, |
442 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 468 | args->total, &map, &nmap, args->flist); |
443 | args->firstblock, args->total, &map, &nmap, | ||
444 | args->flist); | ||
445 | if (!error) { | 469 | if (!error) { |
446 | error = xfs_bmap_finish(&args->trans, args->flist, | 470 | error = xfs_bmap_finish(&args->trans, args->flist, |
447 | &committed); | 471 | &committed); |
@@ -594,9 +618,8 @@ xfs_attr_rmtval_remove( | |||
594 | 618 | ||
595 | xfs_bmap_init(args->flist, args->firstblock); | 619 | xfs_bmap_init(args->flist, args->firstblock); |
596 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, | 620 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, |
597 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 621 | XFS_BMAPI_ATTRFORK, 1, args->firstblock, |
598 | 1, args->firstblock, args->flist, | 622 | args->flist, &done); |
599 | &done); | ||
600 | if (!error) { | 623 | if (!error) { |
601 | error = xfs_bmap_finish(&args->trans, args->flist, | 624 | error = xfs_bmap_finish(&args->trans, args->flist, |
602 | &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_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index f6a8631dc771..cd2201f5ab52 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c | |||
@@ -2356,8 +2356,8 @@ xfs_da_shrink_inode( | |||
2356 | * the last block to the place we want to kill. | 2356 | * the last block to the place we want to kill. |
2357 | */ | 2357 | */ |
2358 | error = xfs_bunmapi(tp, dp, dead_blkno, count, | 2358 | error = xfs_bunmapi(tp, dp, dead_blkno, count, |
2359 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, | 2359 | xfs_bmapi_aflag(w), 0, args->firstblock, |
2360 | 0, args->firstblock, args->flist, &done); | 2360 | args->flist, &done); |
2361 | if (error == -ENOSPC) { | 2361 | if (error == -ENOSPC) { |
2362 | if (w != XFS_DATA_FORK) | 2362 | if (w != XFS_DATA_FORK) |
2363 | break; | 2363 | break; |
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 42799d88ecc0..9de401d297e5 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c | |||
@@ -677,25 +677,22 @@ xfs_dir2_shrink_inode( | |||
677 | mp = dp->i_mount; | 677 | mp = dp->i_mount; |
678 | tp = args->trans; | 678 | tp = args->trans; |
679 | da = xfs_dir2_db_to_da(args->geo, db); | 679 | da = xfs_dir2_db_to_da(args->geo, db); |
680 | /* | 680 | |
681 | * Unmap the fsblock(s). | 681 | /* Unmap the fsblock(s). */ |
682 | */ | 682 | error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, |
683 | if ((error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, | 683 | args->firstblock, args->flist, &done); |
684 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, | 684 | if (error) { |
685 | &done))) { | ||
686 | /* | 685 | /* |
687 | * ENOSPC actually can happen if we're in a removename with | 686 | * ENOSPC actually can happen if we're in a removename with no |
688 | * no space reservation, and the resulting block removal | 687 | * space reservation, and the resulting block removal would |
689 | * would cause a bmap btree split or conversion from extents | 688 | * cause a bmap btree split or conversion from extents to btree. |
690 | * to btree. This can only happen for un-fragmented | 689 | * This can only happen for un-fragmented directory blocks, |
691 | * directory blocks, since you need to be punching out | 690 | * since you need to be punching out the middle of an extent. |
692 | * the middle of an extent. | 691 | * In this case we need to leave the block in the file, and not |
693 | * 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 |
694 | * and not binval it. | 693 | * state and appropriately logged. We don't free up the buffer, |
695 | * 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 |
696 | * and appropriately logged. | 695 | * back. |
697 | * We don't free up the buffer, the caller can tell it | ||
698 | * hasn't happened since it got an error back. | ||
699 | */ | 696 | */ |
700 | return error; | 697 | return error; |
701 | } | 698 | } |
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c index 527b7337a43b..6687489412a0 100644 --- a/fs/xfs/libxfs/xfs_dir2_node.c +++ b/fs/xfs/libxfs/xfs_dir2_node.c | |||
@@ -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), |
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index ce63e0431f3e..54deb2d12ac6 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c | |||
@@ -2233,7 +2233,7 @@ xfs_imap_lookup( | |||
2233 | } | 2233 | } |
2234 | 2234 | ||
2235 | xfs_trans_brelse(tp, agbp); | 2235 | xfs_trans_brelse(tp, agbp); |
2236 | xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); | 2236 | xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); |
2237 | if (error) | 2237 | if (error) |
2238 | return error; | 2238 | return error; |
2239 | 2239 | ||
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 9c87f66ab929..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 | } |
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 a4b7d92e946c..d7dbd8120aaa 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -1533,9 +1533,10 @@ xfs_wait_buftarg( | |||
1533 | list_del_init(&bp->b_lru); | 1533 | list_del_init(&bp->b_lru); |
1534 | if (bp->b_flags & XBF_WRITE_FAIL) { | 1534 | if (bp->b_flags & XBF_WRITE_FAIL) { |
1535 | xfs_alert(btp->bt_mount, | 1535 | xfs_alert(btp->bt_mount, |
1536 | "Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n" | 1536 | "Corruption Alert: Buffer at block 0x%llx had permanent write failures!", |
1537 | "Please run xfs_repair to determine the extent of the problem.", | ||
1538 | (long long)bp->b_bn); | 1537 | (long long)bp->b_bn); |
1538 | xfs_alert(btp->bt_mount, | ||
1539 | "Please run xfs_repair to determine the extent of the problem."); | ||
1539 | } | 1540 | } |
1540 | xfs_buf_rele(bp); | 1541 | xfs_buf_rele(bp); |
1541 | } | 1542 | } |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 092d652bc03d..919057e0a45b 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 | } |
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index b1b26b6a0735..30cb3afb67f0 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -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 2d91ab066370..de2c2376242b 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -1521,18 +1521,27 @@ xfs_filemap_fault( | |||
1521 | struct vm_area_struct *vma, | 1521 | struct vm_area_struct *vma, |
1522 | struct vm_fault *vmf) | 1522 | struct vm_fault *vmf) |
1523 | { | 1523 | { |
1524 | struct xfs_inode *ip = XFS_I(file_inode(vma->vm_file)); | 1524 | struct inode *inode = file_inode(vma->vm_file); |
1525 | int ret; | 1525 | int ret; |
1526 | 1526 | ||
1527 | trace_xfs_filemap_fault(ip); | 1527 | trace_xfs_filemap_fault(XFS_I(inode)); |
1528 | 1528 | ||
1529 | /* DAX can shortcut the normal fault path on write faults! */ | 1529 | /* DAX can shortcut the normal fault path on write faults! */ |
1530 | if ((vmf->flags & FAULT_FLAG_WRITE) && IS_DAX(VFS_I(ip))) | 1530 | if ((vmf->flags & FAULT_FLAG_WRITE) && IS_DAX(inode)) |
1531 | return xfs_filemap_page_mkwrite(vma, vmf); | 1531 | return xfs_filemap_page_mkwrite(vma, vmf); |
1532 | 1532 | ||
1533 | xfs_ilock(ip, XFS_MMAPLOCK_SHARED); | 1533 | xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); |
1534 | ret = filemap_fault(vma, vmf); | 1534 | if (IS_DAX(inode)) { |
1535 | xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); | 1535 | /* |
1536 | * we do not want to trigger unwritten extent conversion on read | ||
1537 | * faults - that is unnecessary overhead and would also require | ||
1538 | * changes to xfs_get_blocks_direct() to map unwritten extent | ||
1539 | * ioend for conversion on read-only mappings. | ||
1540 | */ | ||
1541 | ret = __dax_fault(vma, vmf, xfs_get_blocks_direct, NULL); | ||
1542 | } else | ||
1543 | ret = filemap_fault(vma, vmf); | ||
1544 | xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); | ||
1536 | 1545 | ||
1537 | return ret; | 1546 | return ret; |
1538 | } | 1547 | } |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index aa00ccc0bd78..30555f8fd44b 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1221,11 +1221,8 @@ xfs_create( | |||
1221 | */ | 1221 | */ |
1222 | error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, | 1222 | error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, |
1223 | prid, resblks > 0, &ip, &committed); | 1223 | prid, resblks > 0, &ip, &committed); |
1224 | if (error) { | 1224 | if (error) |
1225 | if (error == -ENOSPC) | ||
1226 | goto out_trans_cancel; | ||
1227 | goto out_trans_cancel; | 1225 | goto out_trans_cancel; |
1228 | } | ||
1229 | 1226 | ||
1230 | /* | 1227 | /* |
1231 | * Now we join the directory inode to the transaction. We do not do it | 1228 | * Now we join the directory inode to the transaction. We do not do it |
@@ -1364,11 +1361,8 @@ xfs_create_tmpfile( | |||
1364 | 1361 | ||
1365 | error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, | 1362 | error = xfs_dir_ialloc(&tp, dp, mode, 1, 0, |
1366 | prid, resblks > 0, &ip, NULL); | 1363 | prid, resblks > 0, &ip, NULL); |
1367 | if (error) { | 1364 | if (error) |
1368 | if (error == -ENOSPC) | ||
1369 | goto out_trans_cancel; | ||
1370 | goto out_trans_cancel; | 1365 | goto out_trans_cancel; |
1371 | } | ||
1372 | 1366 | ||
1373 | if (mp->m_flags & XFS_MOUNT_WSYNC) | 1367 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
1374 | xfs_trans_set_sync(tp); | 1368 | xfs_trans_set_sync(tp); |
@@ -1838,14 +1832,15 @@ xfs_inactive_ifree( | |||
1838 | xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); | 1832 | xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_ICOUNT, -1); |
1839 | 1833 | ||
1840 | /* | 1834 | /* |
1841 | * Just ignore errors at this point. There is nothing we can | 1835 | * Just ignore errors at this point. There is nothing we can do except |
1842 | * do except to try to keep going. Make sure it's not a silent | 1836 | * to try to keep going. Make sure it's not a silent error. |
1843 | * error. | ||
1844 | */ | 1837 | */ |
1845 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1838 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1846 | if (error) | 1839 | if (error) { |
1847 | xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", | 1840 | xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", |
1848 | __func__, error); | 1841 | __func__, error); |
1842 | xfs_bmap_cancel(&free_list); | ||
1843 | } | ||
1849 | error = xfs_trans_commit(tp); | 1844 | error = xfs_trans_commit(tp); |
1850 | if (error) | 1845 | if (error) |
1851 | xfs_notice(mp, "%s: xfs_trans_commit returned error %d", | 1846 | xfs_notice(mp, "%s: xfs_trans_commit returned error %d", |
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_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 86c3de477a9d..512a0945d52a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1886,9 +1886,14 @@ xlog_recover_get_buf_lsn( | |||
1886 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; | 1886 | uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid; |
1887 | break; | 1887 | break; |
1888 | case XFS_ATTR3_RMT_MAGIC: | 1888 | case XFS_ATTR3_RMT_MAGIC: |
1889 | lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn); | 1889 | /* |
1890 | uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid; | 1890 | * Remote attr blocks are written synchronously, rather than |
1891 | break; | 1891 | * being logged. That means they do not contain a valid LSN |
1892 | * (i.e. transactionally ordered) in them, and hence any time we | ||
1893 | * see a buffer to replay over the top of a remote attribute | ||
1894 | * block we should simply do so. | ||
1895 | */ | ||
1896 | goto recover_immediately; | ||
1892 | case XFS_SB_MAGIC: | 1897 | case XFS_SB_MAGIC: |
1893 | /* | 1898 | /* |
1894 | * superblock uuids are magic. We may or may not have a | 1899 | * superblock uuids are magic. We may or may not have a |
@@ -2938,16 +2943,16 @@ xlog_recover_efi_pass2( | |||
2938 | struct xlog_recover_item *item, | 2943 | struct xlog_recover_item *item, |
2939 | xfs_lsn_t lsn) | 2944 | xfs_lsn_t lsn) |
2940 | { | 2945 | { |
2941 | int error; | 2946 | int error; |
2942 | xfs_mount_t *mp = log->l_mp; | 2947 | struct xfs_mount *mp = log->l_mp; |
2943 | xfs_efi_log_item_t *efip; | 2948 | struct xfs_efi_log_item *efip; |
2944 | xfs_efi_log_format_t *efi_formatp; | 2949 | struct xfs_efi_log_format *efi_formatp; |
2945 | 2950 | ||
2946 | efi_formatp = item->ri_buf[0].i_addr; | 2951 | efi_formatp = item->ri_buf[0].i_addr; |
2947 | 2952 | ||
2948 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2953 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
2949 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), | 2954 | error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format); |
2950 | &(efip->efi_format)))) { | 2955 | if (error) { |
2951 | xfs_efi_item_free(efip); | 2956 | xfs_efi_item_free(efip); |
2952 | return error; | 2957 | return error; |
2953 | } | 2958 | } |
@@ -2955,20 +2960,23 @@ xlog_recover_efi_pass2( | |||
2955 | 2960 | ||
2956 | spin_lock(&log->l_ailp->xa_lock); | 2961 | spin_lock(&log->l_ailp->xa_lock); |
2957 | /* | 2962 | /* |
2958 | * 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. | ||
2959 | */ | 2967 | */ |
2960 | 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); | ||
2961 | return 0; | 2970 | return 0; |
2962 | } | 2971 | } |
2963 | 2972 | ||
2964 | 2973 | ||
2965 | /* | 2974 | /* |
2966 | * 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 |
2967 | * 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 |
2968 | * 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 |
2969 | * 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 |
2970 | * 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. |
2971 | * AIL and free it. | ||
2972 | */ | 2980 | */ |
2973 | STATIC int | 2981 | STATIC int |
2974 | xlog_recover_efd_pass2( | 2982 | xlog_recover_efd_pass2( |
@@ -2990,8 +2998,8 @@ xlog_recover_efd_pass2( | |||
2990 | efi_id = efd_formatp->efd_efi_id; | 2998 | efi_id = efd_formatp->efd_efi_id; |
2991 | 2999 | ||
2992 | /* | 3000 | /* |
2993 | * 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 |
2994 | * in the AIL. | 3002 | * AIL. |
2995 | */ | 3003 | */ |
2996 | spin_lock(&ailp->xa_lock); | 3004 | spin_lock(&ailp->xa_lock); |
2997 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); | 3005 | lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); |
@@ -3000,18 +3008,18 @@ xlog_recover_efd_pass2( | |||
3000 | efip = (xfs_efi_log_item_t *)lip; | 3008 | efip = (xfs_efi_log_item_t *)lip; |
3001 | if (efip->efi_format.efi_id == efi_id) { | 3009 | if (efip->efi_format.efi_id == efi_id) { |
3002 | /* | 3010 | /* |
3003 | * xfs_trans_ail_delete() drops the | 3011 | * Drop the EFD reference to the EFI. This |
3004 | * AIL lock. | 3012 | * removes the EFI from the AIL and frees it. |
3005 | */ | 3013 | */ |
3006 | xfs_trans_ail_delete(ailp, lip, | 3014 | spin_unlock(&ailp->xa_lock); |
3007 | SHUTDOWN_CORRUPT_INCORE); | 3015 | xfs_efi_release(efip); |
3008 | xfs_efi_item_free(efip); | ||
3009 | spin_lock(&ailp->xa_lock); | 3016 | spin_lock(&ailp->xa_lock); |
3010 | break; | 3017 | break; |
3011 | } | 3018 | } |
3012 | } | 3019 | } |
3013 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3020 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3014 | } | 3021 | } |
3022 | |||
3015 | xfs_trans_ail_cursor_done(&cur); | 3023 | xfs_trans_ail_cursor_done(&cur); |
3016 | spin_unlock(&ailp->xa_lock); | 3024 | spin_unlock(&ailp->xa_lock); |
3017 | 3025 | ||
@@ -3039,6 +3047,11 @@ xlog_recover_do_icreate_pass2( | |||
3039 | unsigned int count; | 3047 | unsigned int count; |
3040 | unsigned int isize; | 3048 | unsigned int isize; |
3041 | 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; | ||
3042 | 3055 | ||
3043 | icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; | 3056 | icl = (struct xfs_icreate_log *)item->ri_buf[0].i_addr; |
3044 | if (icl->icl_type != XFS_LI_ICREATE) { | 3057 | if (icl->icl_type != XFS_LI_ICREATE) { |
@@ -3097,22 +3110,45 @@ xlog_recover_do_icreate_pass2( | |||
3097 | } | 3110 | } |
3098 | 3111 | ||
3099 | /* | 3112 | /* |
3100 | * Inode buffers can be freed. Do not replay the inode initialisation as | 3113 | * The icreate transaction can cover multiple cluster buffers and these |
3101 | * we could be overwriting something written after this inode buffer was | 3114 | * buffers could have been freed and reused. Check the individual |
3102 | * 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. | ||
3103 | * | 3136 | * |
3104 | * 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 |
3105 | * cancelled. I think that a more fine grained factoring of | 3138 | * icreate for multiple chunk allocations. |
3106 | * xfs_ialloc_inode_init may be appropriate here to enable this to be | ||
3107 | * done easily. | ||
3108 | */ | 3139 | */ |
3109 | if (xlog_check_buffer_cancelled(log, | 3140 | ASSERT(!cancel_count || cancel_count == nbufs); |
3110 | 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); | ||
3111 | return 0; | 3146 | return 0; |
3147 | } | ||
3112 | 3148 | ||
3113 | xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, length, | 3149 | trace_xfs_log_recover_icreate_recover(log, icl); |
3114 | be32_to_cpu(icl->icl_gen)); | 3150 | return xfs_ialloc_inode_init(mp, NULL, buffer_list, count, agno, agbno, |
3115 | return 0; | 3151 | length, be32_to_cpu(icl->icl_gen)); |
3116 | } | 3152 | } |
3117 | 3153 | ||
3118 | STATIC void | 3154 | STATIC void |
@@ -3390,14 +3426,24 @@ xlog_recover_add_to_cont_trans( | |||
3390 | char *ptr, *old_ptr; | 3426 | char *ptr, *old_ptr; |
3391 | int old_len; | 3427 | int old_len; |
3392 | 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 | */ | ||
3393 | if (list_empty(&trans->r_itemq)) { | 3433 | if (list_empty(&trans->r_itemq)) { |
3394 | /* 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 | |||
3395 | xlog_recover_add_item(&trans->r_itemq); | 3440 | xlog_recover_add_item(&trans->r_itemq); |
3396 | ptr = (char *)&trans->r_theader + | 3441 | ptr = (char *)&trans->r_theader + |
3397 | sizeof(xfs_trans_header_t) - len; | 3442 | sizeof(struct xfs_trans_header) - len; |
3398 | memcpy(ptr, dp, len); | 3443 | memcpy(ptr, dp, len); |
3399 | return 0; | 3444 | return 0; |
3400 | } | 3445 | } |
3446 | |||
3401 | /* take the tail entry */ | 3447 | /* take the tail entry */ |
3402 | 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); |
3403 | 3449 | ||
@@ -3446,7 +3492,19 @@ xlog_recover_add_to_trans( | |||
3446 | ASSERT(0); | 3492 | ASSERT(0); |
3447 | return -EIO; | 3493 | return -EIO; |
3448 | } | 3494 | } |
3449 | 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)) | ||
3450 | xlog_recover_add_item(&trans->r_itemq); | 3508 | xlog_recover_add_item(&trans->r_itemq); |
3451 | memcpy(&trans->r_theader, dp, len); | 3509 | memcpy(&trans->r_theader, dp, len); |
3452 | return 0; | 3510 | return 0; |
@@ -3749,7 +3807,7 @@ xlog_recover_process_efi( | |||
3749 | * free the memory associated with it. | 3807 | * free the memory associated with it. |
3750 | */ | 3808 | */ |
3751 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); | 3809 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); |
3752 | xfs_efi_release(efip, efip->efi_format.efi_nextents); | 3810 | xfs_efi_release(efip); |
3753 | return -EIO; | 3811 | return -EIO; |
3754 | } | 3812 | } |
3755 | } | 3813 | } |
@@ -3762,11 +3820,11 @@ xlog_recover_process_efi( | |||
3762 | 3820 | ||
3763 | for (i = 0; i < efip->efi_format.efi_nextents; i++) { | 3821 | for (i = 0; i < efip->efi_format.efi_nextents; i++) { |
3764 | extp = &(efip->efi_format.efi_extents[i]); | 3822 | extp = &(efip->efi_format.efi_extents[i]); |
3765 | 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); | ||
3766 | if (error) | 3825 | if (error) |
3767 | goto abort_error; | 3826 | goto abort_error; |
3768 | xfs_trans_log_efd_extent(tp, efdp, extp->ext_start, | 3827 | |
3769 | extp->ext_len); | ||
3770 | } | 3828 | } |
3771 | 3829 | ||
3772 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); | 3830 | set_bit(XFS_EFI_RECOVERED, &efip->efi_flags); |
@@ -3798,10 +3856,10 @@ abort_error: | |||
3798 | */ | 3856 | */ |
3799 | STATIC int | 3857 | STATIC int |
3800 | xlog_recover_process_efis( | 3858 | xlog_recover_process_efis( |
3801 | struct xlog *log) | 3859 | struct xlog *log) |
3802 | { | 3860 | { |
3803 | xfs_log_item_t *lip; | 3861 | struct xfs_log_item *lip; |
3804 | xfs_efi_log_item_t *efip; | 3862 | struct xfs_efi_log_item *efip; |
3805 | int error = 0; | 3863 | int error = 0; |
3806 | struct xfs_ail_cursor cur; | 3864 | struct xfs_ail_cursor cur; |
3807 | struct xfs_ail *ailp; | 3865 | struct xfs_ail *ailp; |
@@ -3825,7 +3883,7 @@ xlog_recover_process_efis( | |||
3825 | /* | 3883 | /* |
3826 | * Skip EFIs that we've already processed. | 3884 | * Skip EFIs that we've already processed. |
3827 | */ | 3885 | */ |
3828 | efip = (xfs_efi_log_item_t *)lip; | 3886 | efip = container_of(lip, struct xfs_efi_log_item, efi_item); |
3829 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) { | 3887 | if (test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)) { |
3830 | lip = xfs_trans_ail_cursor_next(ailp, &cur); | 3888 | lip = xfs_trans_ail_cursor_next(ailp, &cur); |
3831 | continue; | 3889 | continue; |
@@ -3845,6 +3903,50 @@ out: | |||
3845 | } | 3903 | } |
3846 | 3904 | ||
3847 | /* | 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 | /* | ||
3848 | * 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 |
3849 | * in an agi unlinked inode hash bucket. | 3951 | * in an agi unlinked inode hash bucket. |
3850 | */ | 3952 | */ |
@@ -4537,11 +4639,13 @@ xlog_recover( | |||
4537 | xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, | 4639 | xfs_sb_has_incompat_log_feature(&log->l_mp->m_sb, |
4538 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { | 4640 | XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN)) { |
4539 | xfs_warn(log->l_mp, | 4641 | xfs_warn(log->l_mp, |
4540 | "Superblock has unknown incompatible log features (0x%x) enabled.\n" | 4642 | "Superblock has unknown incompatible log features (0x%x) enabled.", |
4541 | "The log can not be fully and/or safely recovered by this kernel.\n" | ||
4542 | "Please recover the log on a kernel that supports the unknown features.", | ||
4543 | (log->l_mp->m_sb.sb_features_log_incompat & | 4643 | (log->l_mp->m_sb.sb_features_log_incompat & |
4544 | 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."); | ||
4545 | return -EINVAL; | 4649 | return -EINVAL; |
4546 | } | 4650 | } |
4547 | 4651 | ||
@@ -4617,6 +4721,17 @@ xlog_recover_finish( | |||
4617 | return 0; | 4721 | return 0; |
4618 | } | 4722 | } |
4619 | 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 | } | ||
4620 | 4735 | ||
4621 | #if defined(DEBUG) | 4736 | #if defined(DEBUG) |
4622 | /* | 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_symlink.c b/fs/xfs/xfs_symlink.c index 7a01486eff06..996481eeb491 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -502,7 +502,7 @@ xfs_inactive_symlink_rmt( | |||
502 | /* | 502 | /* |
503 | * Unmap the dead block(s) to the free_list. | 503 | * Unmap the dead block(s) to the free_list. |
504 | */ | 504 | */ |
505 | error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, | 505 | error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, |
506 | &first_block, &free_list, &done); | 506 | &first_block, &free_list, &done); |
507 | if (error) | 507 | if (error) |
508 | 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 *); |