aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 46e6bd2d4f07..6c68ffd6b4bb 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1890,8 +1890,8 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
1890 return 0; 1890 return 0;
1891} 1891}
1892 1892
1893static int nfsd_buffered_readdir(struct file *file, filldir_t func, 1893static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
1894 struct readdir_cd *cdp, loff_t *offsetp) 1894 struct readdir_cd *cdp, loff_t *offsetp)
1895{ 1895{
1896 struct readdir_data buf; 1896 struct readdir_data buf;
1897 struct buffered_dirent *de; 1897 struct buffered_dirent *de;
@@ -1901,11 +1901,12 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
1901 1901
1902 buf.dirent = (void *)__get_free_page(GFP_KERNEL); 1902 buf.dirent = (void *)__get_free_page(GFP_KERNEL);
1903 if (!buf.dirent) 1903 if (!buf.dirent)
1904 return -ENOMEM; 1904 return nfserrno(-ENOMEM);
1905 1905
1906 offset = *offsetp; 1906 offset = *offsetp;
1907 1907
1908 while (1) { 1908 while (1) {
1909 struct inode *dir_inode = file->f_path.dentry->d_inode;
1909 unsigned int reclen; 1910 unsigned int reclen;
1910 1911
1911 cdp->err = nfserr_eof; /* will be cleared on successful read */ 1912 cdp->err = nfserr_eof; /* will be cleared on successful read */
@@ -1924,26 +1925,38 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func,
1924 if (!size) 1925 if (!size)
1925 break; 1926 break;
1926 1927
1928 /*
1929 * Various filldir functions may end up calling back into
1930 * lookup_one_len() and the file system's ->lookup() method.
1931 * These expect i_mutex to be held, as it would within readdir.
1932 */
1933 host_err = mutex_lock_killable(&dir_inode->i_mutex);
1934 if (host_err)
1935 break;
1936
1927 de = (struct buffered_dirent *)buf.dirent; 1937 de = (struct buffered_dirent *)buf.dirent;
1928 while (size > 0) { 1938 while (size > 0) {
1929 offset = de->offset; 1939 offset = de->offset;
1930 1940
1931 if (func(cdp, de->name, de->namlen, de->offset, 1941 if (func(cdp, de->name, de->namlen, de->offset,
1932 de->ino, de->d_type)) 1942 de->ino, de->d_type))
1933 goto done; 1943 break;
1934 1944
1935 if (cdp->err != nfs_ok) 1945 if (cdp->err != nfs_ok)
1936 goto done; 1946 break;
1937 1947
1938 reclen = ALIGN(sizeof(*de) + de->namlen, 1948 reclen = ALIGN(sizeof(*de) + de->namlen,
1939 sizeof(u64)); 1949 sizeof(u64));
1940 size -= reclen; 1950 size -= reclen;
1941 de = (struct buffered_dirent *)((char *)de + reclen); 1951 de = (struct buffered_dirent *)((char *)de + reclen);
1942 } 1952 }
1953 mutex_unlock(&dir_inode->i_mutex);
1954 if (size > 0) /* We bailed out early */
1955 break;
1956
1943 offset = vfs_llseek(file, 0, SEEK_CUR); 1957 offset = vfs_llseek(file, 0, SEEK_CUR);
1944 } 1958 }
1945 1959
1946 done:
1947 free_page((unsigned long)(buf.dirent)); 1960 free_page((unsigned long)(buf.dirent));
1948 1961
1949 if (host_err) 1962 if (host_err)