aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-05-29 19:45:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-05-29 19:45:45 -0400
commit1be44e234b672eadbf1d96eb172ef21f5ff6a2c9 (patch)
tree99bb11c447d5c1e8159f9ec9774c1fbdbf43152e
parent2a6451718627eb60e85691053cb9820ae7ed3913 (diff)
parent22419ac9fe5e79483596cebdbd1d1209c18bac1a (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.c8
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h2
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c31
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c9
-rw-r--r--fs/xfs/xfs_attr_inactive.c83
-rw-r--r--fs/xfs/xfs_file.c2
-rw-r--r--fs/xfs/xfs_inode.c22
-rw-r--r--fs/xfs/xfs_mount.c34
-rw-r--r--include/linux/percpu_counter.h13
-rw-r--r--lib/percpu_counter.c6
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 */
577STATIC void 577void
578xfs_attr_fork_reset( 578xfs_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);
53int xfs_attr_shortform_list(struct xfs_attr_list_context *context); 53int xfs_attr_shortform_list(struct xfs_attr_list_context *context);
54int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); 54int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);
55int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); 55int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
56 56void 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 */
383int 391int
384xfs_attr_inactive(xfs_inode_t *dp) 392xfs_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;