]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/xfs-account-for-allocated-blocks-when-expanding-directories
Move xen patchset to new version's subdir.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / xfs-account-for-allocated-blocks-when-expanding-directories
CommitLineData
00e5a55c
BS
1From: David Chinner <david@fromorbit.com>
2References: bnc#450658
3Subject: [XFS] Account for allocated blocks when expanding directories
4Patch-mainline: ?
5
6When we create a directory, we reserve a number of blocks for the maximum
7possible expansion of of the directory due to various btree splits,
8freespace allocation, etc. Unfortunately, each allocation is not reflected
9in the total number of blocks still available to the transaction, so the
10maximal reservation is used over and over again.
11
12This leads to problems where an allocation group has only enough blocks
13for *some* of the allocations required for the directory modification.
14After the first N allocations, the remaining blocks in the allocation
15group drops below the total reservation, and subsequent allocations fail
16because the allocator will not allow the allocation to proceed if the AG
17does not have the enough blocks available for the entire allocation total.
18
19This results in an ENOSPC occurring after an allocation has already
20occurred. This results in aborting the directory operation (leaving the
21directory in an inconsistent state) and cancelling a dirty transaction,
22which results in a filesystem shutdown.
23
24Avoid the problem by reflecting the number of blocks allocated in any
25directory expansion in the total number of blocks available to the
26modification in progress. This prevents a directory modification from
27being aborted part way through with an ENOSPC.
28
29SGI-PV: 988144
30
31SGI-Modid: xfs-linux-melb:xfs-kern:32340a
32
33Signed-off-by: David Chinner <david@fromorbit.com>
34Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
35Acked-by: Jan Kara <jack@suse.cz>
36
37diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
38index 9e561a9..a11a839 100644
39--- a/fs/xfs/xfs_da_btree.c
40+++ b/fs/xfs/xfs_da_btree.c
41@@ -1566,11 +1566,14 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
42 int nmap, error, w, count, c, got, i, mapi;
43 xfs_trans_t *tp;
44 xfs_mount_t *mp;
45+ xfs_drfsbno_t nblks;
46
47 dp = args->dp;
48 mp = dp->i_mount;
49 w = args->whichfork;
50 tp = args->trans;
51+ nblks = dp->i_d.di_nblocks;
52+
53 /*
54 * For new directories adjust the file offset and block count.
55 */
56@@ -1647,6 +1650,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno)
57 }
58 if (mapp != &map)
59 kmem_free(mapp);
60+ /* account for newly allocated blocks in reserved blocks total */
61+ args->total -= dp->i_d.di_nblocks - nblks;
62 *new_blkno = (xfs_dablk_t)bno;
63 return 0;
64 }
65diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
66index 80e0dc5..1afb122 100644
67--- a/fs/xfs/xfs_dir2.c
68+++ b/fs/xfs/xfs_dir2.c
69@@ -525,11 +525,13 @@ xfs_dir2_grow_inode(
70 xfs_mount_t *mp;
71 int nmap; /* number of bmap entries */
72 xfs_trans_t *tp;
73+ xfs_drfsbno_t nblks;
74
75 xfs_dir2_trace_args_s("grow_inode", args, space);
76 dp = args->dp;
77 tp = args->trans;
78 mp = dp->i_mount;
79+ nblks = dp->i_d.di_nblocks;
80 /*
81 * Set lowest possible block in the space requested.
82 */
83@@ -622,7 +624,11 @@ xfs_dir2_grow_inode(
84 */
85 if (mapp != &map)
86 kmem_free(mapp);
87+
88+ /* account for newly allocated blocks in reserved blocks total */
89+ args->total -= dp->i_d.di_nblocks - nblks;
90 *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno);
91+
92 /*
93 * Update file's size if this is the data space and it grew.
94 */