diff options
author | Bob Peterson <rpeterso@redhat.com> | 2011-03-22 13:54:03 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2011-04-20 03:53:56 -0400 |
commit | d24a7a439a329b60f8e168c03e80566519e09be2 (patch) | |
tree | a1e46fcf0cbe16e9338164da9442447a84872dc2 /fs/gfs2 | |
parent | 0d95326d9bd39f6eae80b91392b308c5fa8b1a0f (diff) |
GFS2: Combine transaction from gfs2_dir_exhash_dealloc
At the end of function gfs2_dir_exhash_dealloc, it was setting the dinode
type to "file" to prevent directory corruption in case of a crash.
It was doing so in its own journal transaction. This patch makes the
change occur when the last call is make to leaf_dealloc, since it needs
to rewrite the directory dinode at that time anyway.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/dir.c | 49 |
1 files changed, 14 insertions, 35 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 0bb5f6bed591..bd575871f0f2 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -86,7 +86,7 @@ typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, | |||
86 | const struct qstr *name, void *opaque); | 86 | const struct qstr *name, void *opaque); |
87 | 87 | ||
88 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | 88 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, |
89 | u64 leaf_no); | 89 | u64 leaf_no, int last_dealloc); |
90 | 90 | ||
91 | int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, | 91 | int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, |
92 | struct buffer_head **bhp) | 92 | struct buffer_head **bhp) |
@@ -1781,10 +1781,10 @@ static int foreach_leaf(struct gfs2_inode *dip) | |||
1781 | struct gfs2_leaf *leaf; | 1781 | struct gfs2_leaf *leaf; |
1782 | u32 hsize, len; | 1782 | u32 hsize, len; |
1783 | u32 ht_offset, lp_offset, ht_offset_cur = -1; | 1783 | u32 ht_offset, lp_offset, ht_offset_cur = -1; |
1784 | u32 index = 0; | 1784 | u32 index = 0, next_index; |
1785 | __be64 *lp; | 1785 | __be64 *lp; |
1786 | u64 leaf_no; | 1786 | u64 leaf_no; |
1787 | int error = 0; | 1787 | int error = 0, last; |
1788 | 1788 | ||
1789 | hsize = 1 << dip->i_depth; | 1789 | hsize = 1 << dip->i_depth; |
1790 | if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) { | 1790 | if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) { |
@@ -1819,13 +1819,13 @@ static int foreach_leaf(struct gfs2_inode *dip) | |||
1819 | goto out; | 1819 | goto out; |
1820 | leaf = (struct gfs2_leaf *)bh->b_data; | 1820 | leaf = (struct gfs2_leaf *)bh->b_data; |
1821 | len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth)); | 1821 | len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth)); |
1822 | next_index = (index & ~(len - 1)) + len; | ||
1823 | last = ((next_index >= hsize) ? 1 : 0); | ||
1822 | brelse(bh); | 1824 | brelse(bh); |
1823 | 1825 | error = leaf_dealloc(dip, index, len, leaf_no, last); | |
1824 | error = leaf_dealloc(dip, index, len, leaf_no); | ||
1825 | if (error) | 1826 | if (error) |
1826 | goto out; | 1827 | goto out; |
1827 | 1828 | index = next_index; | |
1828 | index = (index & ~(len - 1)) + len; | ||
1829 | } else | 1829 | } else |
1830 | index++; | 1830 | index++; |
1831 | } | 1831 | } |
@@ -1847,13 +1847,13 @@ out: | |||
1847 | * @index: the hash table offset in the directory | 1847 | * @index: the hash table offset in the directory |
1848 | * @len: the number of pointers to this leaf | 1848 | * @len: the number of pointers to this leaf |
1849 | * @leaf_no: the leaf number | 1849 | * @leaf_no: the leaf number |
1850 | * @data: not used | 1850 | * last_dealloc: 1 if this is the final dealloc for the leaf, else 0 |
1851 | * | 1851 | * |
1852 | * Returns: errno | 1852 | * Returns: errno |
1853 | */ | 1853 | */ |
1854 | 1854 | ||
1855 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | 1855 | static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, |
1856 | u64 leaf_no) | 1856 | u64 leaf_no, int last_dealloc) |
1857 | { | 1857 | { |
1858 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | 1858 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); |
1859 | struct gfs2_leaf *tmp_leaf; | 1859 | struct gfs2_leaf *tmp_leaf; |
@@ -1940,6 +1940,10 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, | |||
1940 | goto out_end_trans; | 1940 | goto out_end_trans; |
1941 | 1941 | ||
1942 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); | 1942 | gfs2_trans_add_bh(dip->i_gl, dibh, 1); |
1943 | /* On the last dealloc, make this a regular file in case we crash. | ||
1944 | (We don't want to free these blocks a second time.) */ | ||
1945 | if (last_dealloc) | ||
1946 | dip->i_inode.i_mode = S_IFREG; | ||
1943 | gfs2_dinode_out(dip, dibh->b_data); | 1947 | gfs2_dinode_out(dip, dibh->b_data); |
1944 | brelse(dibh); | 1948 | brelse(dibh); |
1945 | 1949 | ||
@@ -1971,33 +1975,8 @@ out: | |||
1971 | 1975 | ||
1972 | int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) | 1976 | int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) |
1973 | { | 1977 | { |
1974 | struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); | ||
1975 | struct buffer_head *bh; | ||
1976 | int error; | ||
1977 | |||
1978 | /* Dealloc on-disk leaves to FREEMETA state */ | 1978 | /* Dealloc on-disk leaves to FREEMETA state */ |
1979 | error = foreach_leaf(dip); | 1979 | return foreach_leaf(dip); |
1980 | if (error) | ||
1981 | return error; | ||
1982 | |||
1983 | /* Make this a regular file in case we crash. | ||
1984 | (We don't want to free these blocks a second time.) */ | ||
1985 | |||
1986 | error = gfs2_trans_begin(sdp, RES_DINODE, 0); | ||
1987 | if (error) | ||
1988 | return error; | ||
1989 | |||
1990 | error = gfs2_meta_inode_buffer(dip, &bh); | ||
1991 | if (!error) { | ||
1992 | gfs2_trans_add_bh(dip->i_gl, bh, 1); | ||
1993 | ((struct gfs2_dinode *)bh->b_data)->di_mode = | ||
1994 | cpu_to_be32(S_IFREG); | ||
1995 | brelse(bh); | ||
1996 | } | ||
1997 | |||
1998 | gfs2_trans_end(sdp); | ||
1999 | |||
2000 | return error; | ||
2001 | } | 1980 | } |
2002 | 1981 | ||
2003 | /** | 1982 | /** |