diff options
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r-- | fs/gfs2/dir.c | 146 |
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; | |||
85 | typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, | 85 | 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, | ||
89 | u64 leaf_no, struct buffer_head *leaf_bh, | ||
90 | int last_dealloc); | ||
91 | |||
92 | int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, | 88 | int 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 | |||
1778 | static 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 | |||
1840 | out: | ||
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 | ||
1989 | int gfs2_dir_exhash_dealloc(struct gfs2_inode *dip) | 1910 | int 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 | |||
1973 | out: | ||
1974 | kfree(lp); | ||
1975 | |||
1976 | return error; | ||
1993 | } | 1977 | } |
1994 | 1978 | ||
1995 | /** | 1979 | /** |