aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r--fs/gfs2/dir.c146
1 files changed, 65 insertions, 81 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 1f5a7ac97f7d..f7a31374ff82 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -85,10 +85,6 @@ struct qstr gfs2_qdotdot __read_mostly;
85typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, 85typedef 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,
89 u64 leaf_no, struct buffer_head *leaf_bh,
90 int last_dealloc);
91
92int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, 88int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block,
93 struct buffer_head **bhp) 89 struct buffer_head **bhp)
94{ 90{
@@ -1769,81 +1765,6 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
1769} 1765}
1770 1766
1771/** 1767/**
1772 * foreach_leaf - call a function for each leaf in a directory
1773 * @dip: the directory
1774 *
1775 * Returns: errno
1776 */
1777
1778static int foreach_leaf(struct gfs2_inode *dip)
1779{
1780 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
1781 struct buffer_head *bh;
1782 struct gfs2_leaf *leaf;
1783 u32 hsize, len;
1784 u32 ht_offset, lp_offset, ht_offset_cur = -1;
1785 u32 index = 0, next_index;
1786 __be64 *lp;
1787 u64 leaf_no;
1788 int error = 0, last;
1789
1790 hsize = 1 << dip->i_depth;
1791 if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
1792 gfs2_consist_inode(dip);
1793 return -EIO;
1794 }
1795
1796 lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
1797 if (!lp)
1798 return -ENOMEM;
1799
1800 while (index < hsize) {
1801 lp_offset = index & (sdp->sd_hash_ptrs - 1);
1802 ht_offset = index - lp_offset;
1803
1804 if (ht_offset_cur != ht_offset) {
1805 error = gfs2_dir_read_data(dip, (char *)lp,
1806 ht_offset * sizeof(__be64),
1807 sdp->sd_hash_bsize, 1);
1808 if (error != sdp->sd_hash_bsize) {
1809 if (error >= 0)
1810 error = -EIO;
1811 goto out;
1812 }
1813 ht_offset_cur = ht_offset;
1814 }
1815
1816 leaf_no = be64_to_cpu(lp[lp_offset]);
1817 if (leaf_no) {
1818 error = get_leaf(dip, leaf_no, &bh);
1819 if (error)
1820 goto out;
1821 leaf = (struct gfs2_leaf *)bh->b_data;
1822 len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
1823 next_index = (index & ~(len - 1)) + len;
1824 last = ((next_index >= hsize) ? 1 : 0);
1825 error = leaf_dealloc(dip, index, len, leaf_no, bh,
1826 last);
1827 brelse(bh);
1828 if (error)
1829 goto out;
1830 index = next_index;
1831 } else
1832 index++;
1833 }
1834
1835 if (index != hsize) {
1836 gfs2_consist_inode(dip);
1837 error = -EIO;
1838 }
1839
1840out:
1841 kfree(lp);
1842
1843 return error;
1844}
1845
1846/**
1847 * leaf_dealloc - Deallocate a directory leaf 1768 * leaf_dealloc - Deallocate a directory leaf
1848 * @dip: the directory 1769 * @dip: the directory
1849 * @index: the hash table offset in the directory 1770 * @index: the hash table offset in the directory
@@ -1988,8 +1909,71 @@ out:
1988 1909
1989int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) 1910int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip)
1990{ 1911{
1991 /* Dealloc on-disk leaves to FREEMETA state */ 1912 struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode);
1992 return foreach_leaf(dip); 1913 struct buffer_head *bh;
1914 struct gfs2_leaf *leaf;
1915 u32 hsize, len;
1916 u32 ht_offset, lp_offset, ht_offset_cur = -1;
1917 u32 index = 0, next_index;
1918 __be64 *lp;
1919 u64 leaf_no;
1920 int error = 0, last;
1921
1922 hsize = 1 << dip->i_depth;
1923 if (hsize * sizeof(u64) != i_size_read(&dip->i_inode)) {
1924 gfs2_consist_inode(dip);
1925 return -EIO;
1926 }
1927
1928 lp = kmalloc(sdp->sd_hash_bsize, GFP_NOFS);
1929 if (!lp)
1930 return -ENOMEM;
1931
1932 while (index < hsize) {
1933 lp_offset = index & (sdp->sd_hash_ptrs - 1);
1934 ht_offset = index - lp_offset;
1935
1936 if (ht_offset_cur != ht_offset) {
1937 error = gfs2_dir_read_data(dip, (char *)lp,
1938 ht_offset * sizeof(__be64),
1939 sdp->sd_hash_bsize, 1);
1940 if (error != sdp->sd_hash_bsize) {
1941 if (error >= 0)
1942 error = -EIO;
1943 goto out;
1944 }
1945 ht_offset_cur = ht_offset;
1946 }
1947
1948 leaf_no = be64_to_cpu(lp[lp_offset]);
1949 if (leaf_no) {
1950 error = get_leaf(dip, leaf_no, &bh);
1951 if (error)
1952 goto out;
1953 leaf = (struct gfs2_leaf *)bh->b_data;
1954 len = 1 << (dip->i_depth - be16_to_cpu(leaf->lf_depth));
1955
1956 next_index = (index & ~(len - 1)) + len;
1957 last = ((next_index >= hsize) ? 1 : 0);
1958 error = leaf_dealloc(dip, index, len, leaf_no, bh,
1959 last);
1960 brelse(bh);
1961 if (error)
1962 goto out;
1963 index = next_index;
1964 } else
1965 index++;
1966 }
1967
1968 if (index != hsize) {
1969 gfs2_consist_inode(dip);
1970 error = -EIO;
1971 }
1972
1973out:
1974 kfree(lp);
1975
1976 return error;
1993} 1977}
1994 1978
1995/** 1979/**