Commit 23db8620 authored by Al Viro's avatar Al Viro

[readdir] convert nfs

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 725bebb2
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
static int nfs_opendir(struct inode *, struct file *); static int nfs_opendir(struct inode *, struct file *);
static int nfs_closedir(struct inode *, struct file *); static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t); static int nfs_readdir(struct file *, struct dir_context *);
static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int); static loff_t nfs_llseek_dir(struct file *, loff_t, int);
static void nfs_readdir_clear_array(struct page*); static void nfs_readdir_clear_array(struct page*);
...@@ -54,7 +54,7 @@ static void nfs_readdir_clear_array(struct page*); ...@@ -54,7 +54,7 @@ static void nfs_readdir_clear_array(struct page*);
const struct file_operations nfs_dir_operations = { const struct file_operations nfs_dir_operations = {
.llseek = nfs_llseek_dir, .llseek = nfs_llseek_dir,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = nfs_readdir, .iterate = nfs_readdir,
.open = nfs_opendir, .open = nfs_opendir,
.release = nfs_closedir, .release = nfs_closedir,
.fsync = nfs_fsync_dir, .fsync = nfs_fsync_dir,
...@@ -147,6 +147,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); ...@@ -147,6 +147,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int);
typedef struct { typedef struct {
struct file *file; struct file *file;
struct page *page; struct page *page;
struct dir_context *ctx;
unsigned long page_index; unsigned long page_index;
u64 *dir_cookie; u64 *dir_cookie;
u64 last_cookie; u64 last_cookie;
...@@ -252,7 +253,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) ...@@ -252,7 +253,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
static static
int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
{ {
loff_t diff = desc->file->f_pos - desc->current_index; loff_t diff = desc->ctx->pos - desc->current_index;
unsigned int index; unsigned int index;
if (diff < 0) if (diff < 0)
...@@ -289,7 +290,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des ...@@ -289,7 +290,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
|| (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) {
ctx->duped = 0; ctx->duped = 0;
ctx->attr_gencount = nfsi->attr_gencount; ctx->attr_gencount = nfsi->attr_gencount;
} else if (new_pos < desc->file->f_pos) { } else if (new_pos < desc->ctx->pos) {
if (ctx->duped > 0 if (ctx->duped > 0
&& ctx->dup_cookie == *desc->dir_cookie) { && ctx->dup_cookie == *desc->dir_cookie) {
if (printk_ratelimit()) { if (printk_ratelimit()) {
...@@ -307,7 +308,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des ...@@ -307,7 +308,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
ctx->dup_cookie = *desc->dir_cookie; ctx->dup_cookie = *desc->dir_cookie;
ctx->duped = -1; ctx->duped = -1;
} }
desc->file->f_pos = new_pos; desc->ctx->pos = new_pos;
desc->cache_entry_index = i; desc->cache_entry_index = i;
return 0; return 0;
} }
...@@ -405,13 +406,13 @@ int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) ...@@ -405,13 +406,13 @@ int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
} }
static static
bool nfs_use_readdirplus(struct inode *dir, struct file *filp) bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx)
{ {
if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS))
return false; return false;
if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags))
return true; return true;
if (filp->f_pos == 0) if (ctx->pos == 0)
return true; return true;
return false; return false;
} }
...@@ -702,8 +703,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) ...@@ -702,8 +703,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
* Once we've found the start of the dirent within a page: fill 'er up... * Once we've found the start of the dirent within a page: fill 'er up...
*/ */
static static
int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
filldir_t filldir)
{ {
struct file *file = desc->file; struct file *file = desc->file;
int i = 0; int i = 0;
...@@ -721,13 +721,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -721,13 +721,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
struct nfs_cache_array_entry *ent; struct nfs_cache_array_entry *ent;
ent = &array->array[i]; ent = &array->array[i];
if (filldir(dirent, ent->string.name, ent->string.len, if (!dir_emit(desc->ctx, ent->string.name, ent->string.len,
file->f_pos, nfs_compat_user_ino64(ent->ino), nfs_compat_user_ino64(ent->ino), ent->d_type)) {
ent->d_type) < 0) {
desc->eof = 1; desc->eof = 1;
break; break;
} }
file->f_pos++; desc->ctx->pos++;
if (i < (array->size-1)) if (i < (array->size-1))
*desc->dir_cookie = array->array[i+1].cookie; *desc->dir_cookie = array->array[i+1].cookie;
else else
...@@ -759,8 +758,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -759,8 +758,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
* directory in the page cache by the time we get here. * directory in the page cache by the time we get here.
*/ */
static inline static inline
int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, int uncached_readdir(nfs_readdir_descriptor_t *desc)
filldir_t filldir)
{ {
struct page *page = NULL; struct page *page = NULL;
int status; int status;
...@@ -785,7 +783,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -785,7 +783,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
if (status < 0) if (status < 0)
goto out_release; goto out_release;
status = nfs_do_filldir(desc, dirent, filldir); status = nfs_do_filldir(desc);
out: out:
dfprintk(DIRCACHE, "NFS: %s: returns %d\n", dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
...@@ -800,35 +798,36 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, ...@@ -800,35 +798,36 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
last cookie cache takes care of the common case of reading the last cookie cache takes care of the common case of reading the
whole directory. whole directory.
*/ */
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) static int nfs_readdir(struct file *file, struct dir_context *ctx)
{ {
struct dentry *dentry = filp->f_path.dentry; struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
nfs_readdir_descriptor_t my_desc, nfs_readdir_descriptor_t my_desc,
*desc = &my_desc; *desc = &my_desc;
struct nfs_open_dir_context *dir_ctx = filp->private_data; struct nfs_open_dir_context *dir_ctx = file->private_data;
int res; int res;
dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_parent->d_name.name, dentry->d_name.name,
(long long)filp->f_pos); (long long)ctx->pos);
nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); nfs_inc_stats(inode, NFSIOS_VFSGETDENTS);
/* /*
* filp->f_pos points to the dirent entry number. * ctx->pos points to the dirent entry number.
* *desc->dir_cookie has the cookie for the next entry. We have * *desc->dir_cookie has the cookie for the next entry. We have
* to either find the entry with the appropriate number or * to either find the entry with the appropriate number or
* revalidate the cookie. * revalidate the cookie.
*/ */
memset(desc, 0, sizeof(*desc)); memset(desc, 0, sizeof(*desc));
desc->file = filp; desc->file = file;
desc->ctx = ctx;
desc->dir_cookie = &dir_ctx->dir_cookie; desc->dir_cookie = &dir_ctx->dir_cookie;
desc->decode = NFS_PROTO(inode)->decode_dirent; desc->decode = NFS_PROTO(inode)->decode_dirent;
desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0; desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0;
nfs_block_sillyrename(dentry); nfs_block_sillyrename(dentry);
res = nfs_revalidate_mapping(inode, filp->f_mapping); res = nfs_revalidate_mapping(inode, file->f_mapping);
if (res < 0) if (res < 0)
goto out; goto out;
...@@ -840,7 +839,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -840,7 +839,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* This means either end of directory */ /* This means either end of directory */
if (*desc->dir_cookie && desc->eof == 0) { if (*desc->dir_cookie && desc->eof == 0) {
/* Or that the server has 'lost' a cookie */ /* Or that the server has 'lost' a cookie */
res = uncached_readdir(desc, dirent, filldir); res = uncached_readdir(desc);
if (res == 0) if (res == 0)
continue; continue;
} }
...@@ -857,7 +856,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -857,7 +856,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if (res < 0) if (res < 0)
break; break;
res = nfs_do_filldir(desc, dirent, filldir); res = nfs_do_filldir(desc);
if (res < 0) if (res < 0)
break; break;
} while (!desc->eof); } while (!desc->eof);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment