aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2011-03-22 13:54:03 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2011-04-20 03:53:56 -0400
commitd24a7a439a329b60f8e168c03e80566519e09be2 (patch)
treea1e46fcf0cbe16e9338164da9442447a84872dc2 /fs/gfs2/dir.c
parent0d95326d9bd39f6eae80b91392b308c5fa8b1a0f (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/dir.c')
-rw-r--r--fs/gfs2/dir.c49
1 files changed, 14 insertions, 35 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 0bb5f6bed59..bd575871f0f 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
88static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, 88static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len,
89 u64 leaf_no); 89 u64 leaf_no, int last_dealloc);
90 90
91int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, 91int 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
1855static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, 1855static 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
1972int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) 1976int 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/**