diff options
Diffstat (limited to 'fs/ocfs2/dir.c')
-rw-r--r-- | fs/ocfs2/dir.c | 153 |
1 files changed, 50 insertions, 103 deletions
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index f1e1aed8f638..30544ce8e9f7 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
@@ -1761,11 +1761,10 @@ bail: | |||
1761 | 1761 | ||
1762 | static int ocfs2_dir_foreach_blk_id(struct inode *inode, | 1762 | static int ocfs2_dir_foreach_blk_id(struct inode *inode, |
1763 | u64 *f_version, | 1763 | u64 *f_version, |
1764 | loff_t *f_pos, void *priv, | 1764 | struct dir_context *ctx) |
1765 | filldir_t filldir, int *filldir_err) | ||
1766 | { | 1765 | { |
1767 | int ret, i, filldir_ret; | 1766 | int ret, i; |
1768 | unsigned long offset = *f_pos; | 1767 | unsigned long offset = ctx->pos; |
1769 | struct buffer_head *di_bh = NULL; | 1768 | struct buffer_head *di_bh = NULL; |
1770 | struct ocfs2_dinode *di; | 1769 | struct ocfs2_dinode *di; |
1771 | struct ocfs2_inline_data *data; | 1770 | struct ocfs2_inline_data *data; |
@@ -1781,8 +1780,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, | |||
1781 | di = (struct ocfs2_dinode *)di_bh->b_data; | 1780 | di = (struct ocfs2_dinode *)di_bh->b_data; |
1782 | data = &di->id2.i_data; | 1781 | data = &di->id2.i_data; |
1783 | 1782 | ||
1784 | while (*f_pos < i_size_read(inode)) { | 1783 | while (ctx->pos < i_size_read(inode)) { |
1785 | revalidate: | ||
1786 | /* If the dir block has changed since the last call to | 1784 | /* If the dir block has changed since the last call to |
1787 | * readdir(2), then we might be pointing to an invalid | 1785 | * readdir(2), then we might be pointing to an invalid |
1788 | * dirent right now. Scan from the start of the block | 1786 | * dirent right now. Scan from the start of the block |
@@ -1802,50 +1800,31 @@ revalidate: | |||
1802 | break; | 1800 | break; |
1803 | i += le16_to_cpu(de->rec_len); | 1801 | i += le16_to_cpu(de->rec_len); |
1804 | } | 1802 | } |
1805 | *f_pos = offset = i; | 1803 | ctx->pos = offset = i; |
1806 | *f_version = inode->i_version; | 1804 | *f_version = inode->i_version; |
1807 | } | 1805 | } |
1808 | 1806 | ||
1809 | de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos); | 1807 | de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos); |
1810 | if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) { | 1808 | if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) { |
1811 | /* On error, skip the f_pos to the end. */ | 1809 | /* On error, skip the f_pos to the end. */ |
1812 | *f_pos = i_size_read(inode); | 1810 | ctx->pos = i_size_read(inode); |
1813 | goto out; | 1811 | break; |
1814 | } | 1812 | } |
1815 | offset += le16_to_cpu(de->rec_len); | 1813 | offset += le16_to_cpu(de->rec_len); |
1816 | if (le64_to_cpu(de->inode)) { | 1814 | if (le64_to_cpu(de->inode)) { |
1817 | /* We might block in the next section | ||
1818 | * if the data destination is | ||
1819 | * currently swapped out. So, use a | ||
1820 | * version stamp to detect whether or | ||
1821 | * not the directory has been modified | ||
1822 | * during the copy operation. | ||
1823 | */ | ||
1824 | u64 version = *f_version; | ||
1825 | unsigned char d_type = DT_UNKNOWN; | 1815 | unsigned char d_type = DT_UNKNOWN; |
1826 | 1816 | ||
1827 | if (de->file_type < OCFS2_FT_MAX) | 1817 | if (de->file_type < OCFS2_FT_MAX) |
1828 | d_type = ocfs2_filetype_table[de->file_type]; | 1818 | d_type = ocfs2_filetype_table[de->file_type]; |
1829 | 1819 | ||
1830 | filldir_ret = filldir(priv, de->name, | 1820 | if (!dir_emit(ctx, de->name, de->name_len, |
1831 | de->name_len, | 1821 | le64_to_cpu(de->inode), d_type)) |
1832 | *f_pos, | 1822 | goto out; |
1833 | le64_to_cpu(de->inode), | ||
1834 | d_type); | ||
1835 | if (filldir_ret) { | ||
1836 | if (filldir_err) | ||
1837 | *filldir_err = filldir_ret; | ||
1838 | break; | ||
1839 | } | ||
1840 | if (version != *f_version) | ||
1841 | goto revalidate; | ||
1842 | } | 1823 | } |
1843 | *f_pos += le16_to_cpu(de->rec_len); | 1824 | ctx->pos += le16_to_cpu(de->rec_len); |
1844 | } | 1825 | } |
1845 | |||
1846 | out: | 1826 | out: |
1847 | brelse(di_bh); | 1827 | brelse(di_bh); |
1848 | |||
1849 | return 0; | 1828 | return 0; |
1850 | } | 1829 | } |
1851 | 1830 | ||
@@ -1855,27 +1834,26 @@ out: | |||
1855 | */ | 1834 | */ |
1856 | static int ocfs2_dir_foreach_blk_el(struct inode *inode, | 1835 | static int ocfs2_dir_foreach_blk_el(struct inode *inode, |
1857 | u64 *f_version, | 1836 | u64 *f_version, |
1858 | loff_t *f_pos, void *priv, | 1837 | struct dir_context *ctx, |
1859 | filldir_t filldir, int *filldir_err) | 1838 | bool persist) |
1860 | { | 1839 | { |
1861 | int error = 0; | ||
1862 | unsigned long offset, blk, last_ra_blk = 0; | 1840 | unsigned long offset, blk, last_ra_blk = 0; |
1863 | int i, stored; | 1841 | int i; |
1864 | struct buffer_head * bh, * tmp; | 1842 | struct buffer_head * bh, * tmp; |
1865 | struct ocfs2_dir_entry * de; | 1843 | struct ocfs2_dir_entry * de; |
1866 | struct super_block * sb = inode->i_sb; | 1844 | struct super_block * sb = inode->i_sb; |
1867 | unsigned int ra_sectors = 16; | 1845 | unsigned int ra_sectors = 16; |
1846 | int stored = 0; | ||
1868 | 1847 | ||
1869 | stored = 0; | ||
1870 | bh = NULL; | 1848 | bh = NULL; |
1871 | 1849 | ||
1872 | offset = (*f_pos) & (sb->s_blocksize - 1); | 1850 | offset = ctx->pos & (sb->s_blocksize - 1); |
1873 | 1851 | ||
1874 | while (!error && !stored && *f_pos < i_size_read(inode)) { | 1852 | while (ctx->pos < i_size_read(inode)) { |
1875 | blk = (*f_pos) >> sb->s_blocksize_bits; | 1853 | blk = ctx->pos >> sb->s_blocksize_bits; |
1876 | if (ocfs2_read_dir_block(inode, blk, &bh, 0)) { | 1854 | if (ocfs2_read_dir_block(inode, blk, &bh, 0)) { |
1877 | /* Skip the corrupt dirblock and keep trying */ | 1855 | /* Skip the corrupt dirblock and keep trying */ |
1878 | *f_pos += sb->s_blocksize - offset; | 1856 | ctx->pos += sb->s_blocksize - offset; |
1879 | continue; | 1857 | continue; |
1880 | } | 1858 | } |
1881 | 1859 | ||
@@ -1897,7 +1875,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, | |||
1897 | ra_sectors = 8; | 1875 | ra_sectors = 8; |
1898 | } | 1876 | } |
1899 | 1877 | ||
1900 | revalidate: | ||
1901 | /* If the dir block has changed since the last call to | 1878 | /* If the dir block has changed since the last call to |
1902 | * readdir(2), then we might be pointing to an invalid | 1879 | * readdir(2), then we might be pointing to an invalid |
1903 | * dirent right now. Scan from the start of the block | 1880 | * dirent right now. Scan from the start of the block |
@@ -1917,93 +1894,64 @@ revalidate: | |||
1917 | i += le16_to_cpu(de->rec_len); | 1894 | i += le16_to_cpu(de->rec_len); |
1918 | } | 1895 | } |
1919 | offset = i; | 1896 | offset = i; |
1920 | *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) | 1897 | ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1)) |
1921 | | offset; | 1898 | | offset; |
1922 | *f_version = inode->i_version; | 1899 | *f_version = inode->i_version; |
1923 | } | 1900 | } |
1924 | 1901 | ||
1925 | while (!error && *f_pos < i_size_read(inode) | 1902 | while (ctx->pos < i_size_read(inode) |
1926 | && offset < sb->s_blocksize) { | 1903 | && offset < sb->s_blocksize) { |
1927 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); | 1904 | de = (struct ocfs2_dir_entry *) (bh->b_data + offset); |
1928 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { | 1905 | if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { |
1929 | /* On error, skip the f_pos to the | 1906 | /* On error, skip the f_pos to the |
1930 | next block. */ | 1907 | next block. */ |
1931 | *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; | 1908 | ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1; |
1932 | brelse(bh); | 1909 | brelse(bh); |
1933 | goto out; | 1910 | continue; |
1934 | } | 1911 | } |
1935 | offset += le16_to_cpu(de->rec_len); | ||
1936 | if (le64_to_cpu(de->inode)) { | 1912 | if (le64_to_cpu(de->inode)) { |
1937 | /* We might block in the next section | ||
1938 | * if the data destination is | ||
1939 | * currently swapped out. So, use a | ||
1940 | * version stamp to detect whether or | ||
1941 | * not the directory has been modified | ||
1942 | * during the copy operation. | ||
1943 | */ | ||
1944 | unsigned long version = *f_version; | ||
1945 | unsigned char d_type = DT_UNKNOWN; | 1913 | unsigned char d_type = DT_UNKNOWN; |
1946 | 1914 | ||
1947 | if (de->file_type < OCFS2_FT_MAX) | 1915 | if (de->file_type < OCFS2_FT_MAX) |
1948 | d_type = ocfs2_filetype_table[de->file_type]; | 1916 | d_type = ocfs2_filetype_table[de->file_type]; |
1949 | error = filldir(priv, de->name, | 1917 | if (!dir_emit(ctx, de->name, |
1950 | de->name_len, | 1918 | de->name_len, |
1951 | *f_pos, | ||
1952 | le64_to_cpu(de->inode), | 1919 | le64_to_cpu(de->inode), |
1953 | d_type); | 1920 | d_type)) { |
1954 | if (error) { | 1921 | brelse(bh); |
1955 | if (filldir_err) | 1922 | return 0; |
1956 | *filldir_err = error; | ||
1957 | break; | ||
1958 | } | 1923 | } |
1959 | if (version != *f_version) | 1924 | stored++; |
1960 | goto revalidate; | ||
1961 | stored ++; | ||
1962 | } | 1925 | } |
1963 | *f_pos += le16_to_cpu(de->rec_len); | 1926 | offset += le16_to_cpu(de->rec_len); |
1927 | ctx->pos += le16_to_cpu(de->rec_len); | ||
1964 | } | 1928 | } |
1965 | offset = 0; | 1929 | offset = 0; |
1966 | brelse(bh); | 1930 | brelse(bh); |
1967 | bh = NULL; | 1931 | bh = NULL; |
1932 | if (!persist && stored) | ||
1933 | break; | ||
1968 | } | 1934 | } |
1969 | 1935 | return 0; | |
1970 | stored = 0; | ||
1971 | out: | ||
1972 | return stored; | ||
1973 | } | 1936 | } |
1974 | 1937 | ||
1975 | static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version, | 1938 | static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version, |
1976 | loff_t *f_pos, void *priv, filldir_t filldir, | 1939 | struct dir_context *ctx, |
1977 | int *filldir_err) | 1940 | bool persist) |
1978 | { | 1941 | { |
1979 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) | 1942 | if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) |
1980 | return ocfs2_dir_foreach_blk_id(inode, f_version, f_pos, priv, | 1943 | return ocfs2_dir_foreach_blk_id(inode, f_version, ctx); |
1981 | filldir, filldir_err); | 1944 | return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist); |
1982 | |||
1983 | return ocfs2_dir_foreach_blk_el(inode, f_version, f_pos, priv, filldir, | ||
1984 | filldir_err); | ||
1985 | } | 1945 | } |
1986 | 1946 | ||
1987 | /* | 1947 | /* |
1988 | * This is intended to be called from inside other kernel functions, | 1948 | * This is intended to be called from inside other kernel functions, |
1989 | * so we fake some arguments. | 1949 | * so we fake some arguments. |
1990 | */ | 1950 | */ |
1991 | int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | 1951 | int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx) |
1992 | filldir_t filldir) | ||
1993 | { | 1952 | { |
1994 | int ret = 0, filldir_err = 0; | ||
1995 | u64 version = inode->i_version; | 1953 | u64 version = inode->i_version; |
1996 | 1954 | ocfs2_dir_foreach_blk(inode, &version, ctx, true); | |
1997 | while (*f_pos < i_size_read(inode)) { | ||
1998 | ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv, | ||
1999 | filldir, &filldir_err); | ||
2000 | if (ret || filldir_err) | ||
2001 | break; | ||
2002 | } | ||
2003 | |||
2004 | if (ret > 0) | ||
2005 | ret = -EIO; | ||
2006 | |||
2007 | return 0; | 1955 | return 0; |
2008 | } | 1956 | } |
2009 | 1957 | ||
@@ -2011,15 +1959,15 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, | |||
2011 | * ocfs2_readdir() | 1959 | * ocfs2_readdir() |
2012 | * | 1960 | * |
2013 | */ | 1961 | */ |
2014 | int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | 1962 | int ocfs2_readdir(struct file *file, struct dir_context *ctx) |
2015 | { | 1963 | { |
2016 | int error = 0; | 1964 | int error = 0; |
2017 | struct inode *inode = file_inode(filp); | 1965 | struct inode *inode = file_inode(file); |
2018 | int lock_level = 0; | 1966 | int lock_level = 0; |
2019 | 1967 | ||
2020 | trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); | 1968 | trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); |
2021 | 1969 | ||
2022 | error = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level); | 1970 | error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level); |
2023 | if (lock_level && error >= 0) { | 1971 | if (lock_level && error >= 0) { |
2024 | /* We release EX lock which used to update atime | 1972 | /* We release EX lock which used to update atime |
2025 | * and get PR lock again to reduce contention | 1973 | * and get PR lock again to reduce contention |
@@ -2035,8 +1983,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
2035 | goto bail_nolock; | 1983 | goto bail_nolock; |
2036 | } | 1984 | } |
2037 | 1985 | ||
2038 | error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, | 1986 | error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false); |
2039 | dirent, filldir, NULL); | ||
2040 | 1987 | ||
2041 | ocfs2_inode_unlock(inode, lock_level); | 1988 | ocfs2_inode_unlock(inode, lock_level); |
2042 | if (error) | 1989 | if (error) |
@@ -2120,6 +2067,7 @@ bail: | |||
2120 | } | 2067 | } |
2121 | 2068 | ||
2122 | struct ocfs2_empty_dir_priv { | 2069 | struct ocfs2_empty_dir_priv { |
2070 | struct dir_context ctx; | ||
2123 | unsigned seen_dot; | 2071 | unsigned seen_dot; |
2124 | unsigned seen_dot_dot; | 2072 | unsigned seen_dot_dot; |
2125 | unsigned seen_other; | 2073 | unsigned seen_other; |
@@ -2204,10 +2152,9 @@ out: | |||
2204 | int ocfs2_empty_dir(struct inode *inode) | 2152 | int ocfs2_empty_dir(struct inode *inode) |
2205 | { | 2153 | { |
2206 | int ret; | 2154 | int ret; |
2207 | loff_t start = 0; | 2155 | struct ocfs2_empty_dir_priv priv = { |
2208 | struct ocfs2_empty_dir_priv priv; | 2156 | .ctx.actor = ocfs2_empty_dir_filldir, |
2209 | 2157 | }; | |
2210 | memset(&priv, 0, sizeof(priv)); | ||
2211 | 2158 | ||
2212 | if (ocfs2_dir_indexed(inode)) { | 2159 | if (ocfs2_dir_indexed(inode)) { |
2213 | ret = ocfs2_empty_dir_dx(inode, &priv); | 2160 | ret = ocfs2_empty_dir_dx(inode, &priv); |
@@ -2219,7 +2166,7 @@ int ocfs2_empty_dir(struct inode *inode) | |||
2219 | */ | 2166 | */ |
2220 | } | 2167 | } |
2221 | 2168 | ||
2222 | ret = ocfs2_dir_foreach(inode, &start, &priv, ocfs2_empty_dir_filldir); | 2169 | ret = ocfs2_dir_foreach(inode, &priv.ctx); |
2223 | if (ret) | 2170 | if (ret) |
2224 | mlog_errno(ret); | 2171 | mlog_errno(ret); |
2225 | 2172 | ||