diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-29 19:45:45 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-05-29 19:45:45 -0400 |
| commit | 1be44e234b672eadbf1d96eb172ef21f5ff6a2c9 (patch) | |
| tree | 99bb11c447d5c1e8159f9ec9774c1fbdbf43152e | |
| parent | 2a6451718627eb60e85691053cb9820ae7ed3913 (diff) | |
| parent | 22419ac9fe5e79483596cebdbd1d1209c18bac1a (diff) | |
Merge tag 'xfs-for-linus-4.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs
Pull xfs fixes from Dave Chinner:
"This is a little larger than I'd like late in the release cycle, but
all the fixes are for regressions introduced in the 4.1-rc1 merge, or
are needed back in -stable kernels fairly quickly as they are
filesystem corruption or userspace visible correctness issues.
Changes in this update:
- regression fix for new rename whiteout code
- regression fixes for new superblock generic per-cpu counter code
- fix for incorrect error return sign introduced in 3.17
- metadata corruption fixes that need to go back to -stable kernels"
* tag 'xfs-for-linus-4.1-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs:
xfs: fix broken i_nlink accounting for whiteout tmpfile inode
xfs: xfs_iozero can return positive errno
xfs: xfs_attr_inactive leaves inconsistent attr fork state behind
xfs: extent size hints can round up extents past MAXEXTLEN
xfs: inode and free block counters need to use __percpu_counter_compare
percpu_counter: batch size aware __percpu_counter_compare()
xfs: use percpu_counter_read_positive for mp->m_icount
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.c | 8 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.h | 2 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 31 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.c | 9 | ||||
| -rw-r--r-- | fs/xfs/xfs_attr_inactive.c | 83 | ||||
| -rw-r--r-- | fs/xfs/xfs_file.c | 2 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode.c | 22 | ||||
| -rw-r--r-- | fs/xfs/xfs_mount.c | 34 | ||||
| -rw-r--r-- | include/linux/percpu_counter.h | 13 | ||||
| -rw-r--r-- | lib/percpu_counter.c | 6 |
10 files changed, 127 insertions, 83 deletions
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 04e79d57bca6..e9d401ce93bb 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c | |||
| @@ -574,8 +574,8 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) | |||
| 574 | * After the last attribute is removed revert to original inode format, | 574 | * After the last attribute is removed revert to original inode format, |
| 575 | * making all literal area available to the data fork once more. | 575 | * making all literal area available to the data fork once more. |
| 576 | */ | 576 | */ |
| 577 | STATIC void | 577 | void |
| 578 | xfs_attr_fork_reset( | 578 | xfs_attr_fork_remove( |
| 579 | struct xfs_inode *ip, | 579 | struct xfs_inode *ip, |
| 580 | struct xfs_trans *tp) | 580 | struct xfs_trans *tp) |
| 581 | { | 581 | { |
| @@ -641,7 +641,7 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
| 641 | (mp->m_flags & XFS_MOUNT_ATTR2) && | 641 | (mp->m_flags & XFS_MOUNT_ATTR2) && |
| 642 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && | 642 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && |
| 643 | !(args->op_flags & XFS_DA_OP_ADDNAME)) { | 643 | !(args->op_flags & XFS_DA_OP_ADDNAME)) { |
| 644 | xfs_attr_fork_reset(dp, args->trans); | 644 | xfs_attr_fork_remove(dp, args->trans); |
| 645 | } else { | 645 | } else { |
| 646 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | 646 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); |
| 647 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | 647 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); |
| @@ -905,7 +905,7 @@ xfs_attr3_leaf_to_shortform( | |||
| 905 | if (forkoff == -1) { | 905 | if (forkoff == -1) { |
| 906 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); | 906 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); |
| 907 | ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); | 907 | ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); |
| 908 | xfs_attr_fork_reset(dp, args->trans); | 908 | xfs_attr_fork_remove(dp, args->trans); |
| 909 | goto out; | 909 | goto out; |
| 910 | } | 910 | } |
| 911 | 911 | ||
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h index 025c4b820c03..882c8d338891 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.h +++ b/fs/xfs/libxfs/xfs_attr_leaf.h | |||
| @@ -53,7 +53,7 @@ int xfs_attr_shortform_remove(struct xfs_da_args *args); | |||
| 53 | int xfs_attr_shortform_list(struct xfs_attr_list_context *context); | 53 | int xfs_attr_shortform_list(struct xfs_attr_list_context *context); |
| 54 | int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); | 54 | int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); |
| 55 | int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); | 55 | int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); |
| 56 | 56 | void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp); | |
| 57 | 57 | ||
| 58 | /* | 58 | /* |
| 59 | * Internal routines when attribute fork size == XFS_LBSIZE(mp). | 59 | * Internal routines when attribute fork size == XFS_LBSIZE(mp). |
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index aeffeaaac0ec..f1026e86dabc 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
| @@ -3224,12 +3224,24 @@ xfs_bmap_extsize_align( | |||
| 3224 | align_alen += temp; | 3224 | align_alen += temp; |
| 3225 | align_off -= temp; | 3225 | align_off -= temp; |
| 3226 | } | 3226 | } |
| 3227 | |||
| 3228 | /* Same adjustment for the end of the requested area. */ | ||
| 3229 | temp = (align_alen % extsz); | ||
| 3230 | if (temp) | ||
| 3231 | align_alen += extsz - temp; | ||
| 3232 | |||
| 3227 | /* | 3233 | /* |
| 3228 | * Same adjustment for the end of the requested area. | 3234 | * For large extent hint sizes, the aligned extent might be larger than |
| 3235 | * MAXEXTLEN. In that case, reduce the size by an extsz so that it pulls | ||
| 3236 | * the length back under MAXEXTLEN. The outer allocation loops handle | ||
| 3237 | * short allocation just fine, so it is safe to do this. We only want to | ||
| 3238 | * do it when we are forced to, though, because it means more allocation | ||
| 3239 | * operations are required. | ||
| 3229 | */ | 3240 | */ |
| 3230 | if ((temp = (align_alen % extsz))) { | 3241 | while (align_alen > MAXEXTLEN) |
| 3231 | align_alen += extsz - temp; | 3242 | align_alen -= extsz; |
| 3232 | } | 3243 | ASSERT(align_alen <= MAXEXTLEN); |
| 3244 | |||
| 3233 | /* | 3245 | /* |
| 3234 | * If the previous block overlaps with this proposed allocation | 3246 | * If the previous block overlaps with this proposed allocation |
| 3235 | * then move the start forward without adjusting the length. | 3247 | * then move the start forward without adjusting the length. |
| @@ -3318,7 +3330,9 @@ xfs_bmap_extsize_align( | |||
| 3318 | return -EINVAL; | 3330 | return -EINVAL; |
| 3319 | } else { | 3331 | } else { |
| 3320 | ASSERT(orig_off >= align_off); | 3332 | ASSERT(orig_off >= align_off); |
| 3321 | ASSERT(orig_end <= align_off + align_alen); | 3333 | /* see MAXEXTLEN handling above */ |
| 3334 | ASSERT(orig_end <= align_off + align_alen || | ||
| 3335 | align_alen + extsz > MAXEXTLEN); | ||
| 3322 | } | 3336 | } |
| 3323 | 3337 | ||
| 3324 | #ifdef DEBUG | 3338 | #ifdef DEBUG |
| @@ -4099,13 +4113,6 @@ xfs_bmapi_reserve_delalloc( | |||
| 4099 | /* Figure out the extent size, adjust alen */ | 4113 | /* Figure out the extent size, adjust alen */ |
| 4100 | extsz = xfs_get_extsz_hint(ip); | 4114 | extsz = xfs_get_extsz_hint(ip); |
| 4101 | if (extsz) { | 4115 | if (extsz) { |
| 4102 | /* | ||
| 4103 | * Make sure we don't exceed a single extent length when we | ||
| 4104 | * align the extent by reducing length we are going to | ||
| 4105 | * allocate by the maximum amount extent size aligment may | ||
| 4106 | * require. | ||
| 4107 | */ | ||
| 4108 | alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1)); | ||
| 4109 | error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, | 4116 | error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, |
| 4110 | 1, 0, &aoff, &alen); | 4117 | 1, 0, &aoff, &alen); |
| 4111 | ASSERT(!error); | 4118 | ASSERT(!error); |
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 07349a183a11..1c9e75521250 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c | |||
| @@ -376,7 +376,7 @@ xfs_ialloc_ag_alloc( | |||
| 376 | */ | 376 | */ |
| 377 | newlen = args.mp->m_ialloc_inos; | 377 | newlen = args.mp->m_ialloc_inos; |
| 378 | if (args.mp->m_maxicount && | 378 | if (args.mp->m_maxicount && |
| 379 | percpu_counter_read(&args.mp->m_icount) + newlen > | 379 | percpu_counter_read_positive(&args.mp->m_icount) + newlen > |
| 380 | args.mp->m_maxicount) | 380 | args.mp->m_maxicount) |
| 381 | return -ENOSPC; | 381 | return -ENOSPC; |
| 382 | args.minlen = args.maxlen = args.mp->m_ialloc_blks; | 382 | args.minlen = args.maxlen = args.mp->m_ialloc_blks; |
| @@ -1339,10 +1339,13 @@ xfs_dialloc( | |||
| 1339 | * If we have already hit the ceiling of inode blocks then clear | 1339 | * If we have already hit the ceiling of inode blocks then clear |
| 1340 | * okalloc so we scan all available agi structures for a free | 1340 | * okalloc so we scan all available agi structures for a free |
| 1341 | * inode. | 1341 | * inode. |
| 1342 | * | ||
| 1343 | * Read rough value of mp->m_icount by percpu_counter_read_positive, | ||
| 1344 | * which will sacrifice the preciseness but improve the performance. | ||
| 1342 | */ | 1345 | */ |
| 1343 | if (mp->m_maxicount && | 1346 | if (mp->m_maxicount && |
| 1344 | percpu_counter_read(&mp->m_icount) + mp->m_ialloc_inos > | 1347 | percpu_counter_read_positive(&mp->m_icount) + mp->m_ialloc_inos |
| 1345 | mp->m_maxicount) { | 1348 | > mp->m_maxicount) { |
| 1346 | noroom = 1; | 1349 | noroom = 1; |
| 1347 | okalloc = 0; | 1350 | okalloc = 0; |
| 1348 | } | 1351 | } |
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c index f9c1c64782d3..3fbf167cfb4c 100644 --- a/fs/xfs/xfs_attr_inactive.c +++ b/fs/xfs/xfs_attr_inactive.c | |||
| @@ -380,23 +380,31 @@ xfs_attr3_root_inactive( | |||
| 380 | return error; | 380 | return error; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | /* | ||
| 384 | * xfs_attr_inactive kills all traces of an attribute fork on an inode. It | ||
| 385 | * removes both the on-disk and in-memory inode fork. Note that this also has to | ||
| 386 | * handle the condition of inodes without attributes but with an attribute fork | ||
| 387 | * configured, so we can't use xfs_inode_hasattr() here. | ||
| 388 | * | ||
| 389 | * The in-memory attribute fork is removed even on error. | ||
| 390 | */ | ||
| 383 | int | 391 | int |
| 384 | xfs_attr_inactive(xfs_inode_t *dp) | 392 | xfs_attr_inactive( |
| 393 | struct xfs_inode *dp) | ||
| 385 | { | 394 | { |
| 386 | xfs_trans_t *trans; | 395 | struct xfs_trans *trans; |
| 387 | xfs_mount_t *mp; | 396 | struct xfs_mount *mp; |
