diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:28:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 12:28:37 -0400 |
commit | 63580e51bb3e7ec459501165884e5f815a7a9322 (patch) | |
tree | 2130de984dda95996bc7922734feb465a13fca70 /fs/nfs | |
parent | 7747bd4bceb3079572695d3942294a6c7b265557 (diff) | |
parent | ac6614b76478e68173ccf7ad4e9e98035cc9c21d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull VFS patches (part 1) from Al Viro:
"The major change in this pile is ->readdir() replacement with
->iterate(), dealing with ->f_pos races in ->readdir() instances for
good.
There's a lot more, but I'd prefer to split the pull request into
several stages and this is the first obvious cutoff point."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (67 commits)
[readdir] constify ->actor
[readdir] ->readdir() is gone
[readdir] convert ecryptfs
[readdir] convert coda
[readdir] convert ocfs2
[readdir] convert fatfs
[readdir] convert xfs
[readdir] convert btrfs
[readdir] convert hostfs
[readdir] convert afs
[readdir] convert ncpfs
[readdir] convert hfsplus
[readdir] convert hfs
[readdir] convert befs
[readdir] convert cifs
[readdir] convert freevxfs
[readdir] convert fuse
[readdir] convert hpfs
reiserfs: switch reiserfs_readdir_dentry to inode
reiserfs: is_privroot_deh() needs only directory inode, actually
...
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e093e73178b7..5d051419527b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | static int nfs_opendir(struct inode *, struct file *); | 47 | static int nfs_opendir(struct inode *, struct file *); |
48 | static int nfs_closedir(struct inode *, struct file *); | 48 | static int nfs_closedir(struct inode *, struct file *); |
49 | static int nfs_readdir(struct file *, void *, filldir_t); | 49 | static int nfs_readdir(struct file *, struct dir_context *); |
50 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); | 50 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); |
51 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 51 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
52 | static void nfs_readdir_clear_array(struct page*); | 52 | static void nfs_readdir_clear_array(struct page*); |
@@ -54,7 +54,7 @@ static void nfs_readdir_clear_array(struct page*); | |||
54 | const struct file_operations nfs_dir_operations = { | 54 | const struct file_operations nfs_dir_operations = { |
55 | .llseek = nfs_llseek_dir, | 55 | .llseek = nfs_llseek_dir, |
56 | .read = generic_read_dir, | 56 | .read = generic_read_dir, |
57 | .readdir = nfs_readdir, | 57 | .iterate = nfs_readdir, |
58 | .open = nfs_opendir, | 58 | .open = nfs_opendir, |
59 | .release = nfs_closedir, | 59 | .release = nfs_closedir, |
60 | .fsync = nfs_fsync_dir, | 60 | .fsync = nfs_fsync_dir, |
@@ -147,6 +147,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); | |||
147 | typedef struct { | 147 | typedef struct { |
148 | struct file *file; | 148 | struct file *file; |
149 | struct page *page; | 149 | struct page *page; |
150 | struct dir_context *ctx; | ||
150 | unsigned long page_index; | 151 | unsigned long page_index; |
151 | u64 *dir_cookie; | 152 | u64 *dir_cookie; |
152 | u64 last_cookie; | 153 | u64 last_cookie; |
@@ -252,7 +253,7 @@ out: | |||
252 | static | 253 | static |
253 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | 254 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) |
254 | { | 255 | { |
255 | loff_t diff = desc->file->f_pos - desc->current_index; | 256 | loff_t diff = desc->ctx->pos - desc->current_index; |
256 | unsigned int index; | 257 | unsigned int index; |
257 | 258 | ||
258 | if (diff < 0) | 259 | if (diff < 0) |
@@ -289,7 +290,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
289 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { | 290 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { |
290 | ctx->duped = 0; | 291 | ctx->duped = 0; |
291 | ctx->attr_gencount = nfsi->attr_gencount; | 292 | ctx->attr_gencount = nfsi->attr_gencount; |
292 | } else if (new_pos < desc->file->f_pos) { | 293 | } else if (new_pos < desc->ctx->pos) { |
293 | if (ctx->duped > 0 | 294 | if (ctx->duped > 0 |
294 | && ctx->dup_cookie == *desc->dir_cookie) { | 295 | && ctx->dup_cookie == *desc->dir_cookie) { |
295 | if (printk_ratelimit()) { | 296 | if (printk_ratelimit()) { |
@@ -307,7 +308,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
307 | ctx->dup_cookie = *desc->dir_cookie; | 308 | ctx->dup_cookie = *desc->dir_cookie; |
308 | ctx->duped = -1; | 309 | ctx->duped = -1; |
309 | } | 310 | } |
310 | desc->file->f_pos = new_pos; | 311 | desc->ctx->pos = new_pos; |
311 | desc->cache_entry_index = i; | 312 | desc->cache_entry_index = i; |
312 | return 0; | 313 | return 0; |
313 | } | 314 | } |
@@ -405,13 +406,13 @@ different: | |||
405 | } | 406 | } |
406 | 407 | ||
407 | static | 408 | static |
408 | bool nfs_use_readdirplus(struct inode *dir, struct file *filp) | 409 | bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx) |
409 | { | 410 | { |
410 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) | 411 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) |
411 | return false; | 412 | return false; |
412 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) | 413 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) |
413 | return true; | 414 | return true; |
414 | if (filp->f_pos == 0) | 415 | if (ctx->pos == 0) |
415 | return true; | 416 | return true; |
416 | return false; | 417 | return false; |
417 | } | 418 | } |
@@ -702,8 +703,7 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc) | |||
702 | * Once we've found the start of the dirent within a page: fill 'er up... | 703 | * Once we've found the start of the dirent within a page: fill 'er up... |
703 | */ | 704 | */ |
704 | static | 705 | static |
705 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | 706 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc) |
706 | filldir_t filldir) | ||
707 | { | 707 | { |
708 | struct file *file = desc->file; | 708 | struct file *file = desc->file; |
709 | int i = 0; | 709 | int i = 0; |
@@ -721,13 +721,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
721 | struct nfs_cache_array_entry *ent; | 721 | struct nfs_cache_array_entry *ent; |
722 | 722 | ||
723 | ent = &array->array[i]; | 723 | ent = &array->array[i]; |
724 | if (filldir(dirent, ent->string.name, ent->string.len, | 724 | if (!dir_emit(desc->ctx, ent->string.name, ent->string.len, |
725 | file->f_pos, nfs_compat_user_ino64(ent->ino), | 725 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { |
726 | ent->d_type) < 0) { | ||
727 | desc->eof = 1; | 726 | desc->eof = 1; |
728 | break; | 727 | break; |
729 | } | 728 | } |
730 | file->f_pos++; | 729 | desc->ctx->pos++; |
731 | if (i < (array->size-1)) | 730 | if (i < (array->size-1)) |
732 | *desc->dir_cookie = array->array[i+1].cookie; | 731 | *desc->dir_cookie = array->array[i+1].cookie; |
733 | else | 732 | else |
@@ -759,8 +758,7 @@ out: | |||
759 | * directory in the page cache by the time we get here. | 758 | * directory in the page cache by the time we get here. |
760 | */ | 759 | */ |
761 | static inline | 760 | static inline |
762 | int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | 761 | int uncached_readdir(nfs_readdir_descriptor_t *desc) |
763 | filldir_t filldir) | ||
764 | { | 762 | { |
765 | struct page *page = NULL; | 763 | struct page *page = NULL; |
766 | int status; | 764 | int status; |
@@ -785,7 +783,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
785 | if (status < 0) | 783 | if (status < 0) |
786 | goto out_release; | 784 | goto out_release; |
787 | 785 | ||
788 | status = nfs_do_filldir(desc, dirent, filldir); | 786 | status = nfs_do_filldir(desc); |
789 | 787 | ||
790 | out: | 788 | out: |
791 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", | 789 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", |
@@ -800,35 +798,36 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
800 | last cookie cache takes care of the common case of reading the | 798 | last cookie cache takes care of the common case of reading the |
801 | whole directory. | 799 | whole directory. |
802 | */ | 800 | */ |
803 | static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 801 | static int nfs_readdir(struct file *file, struct dir_context *ctx) |
804 | { | 802 | { |
805 | struct dentry *dentry = filp->f_path.dentry; | 803 | struct dentry *dentry = file->f_path.dentry; |
806 | struct inode *inode = dentry->d_inode; | 804 | struct inode *inode = dentry->d_inode; |
807 | nfs_readdir_descriptor_t my_desc, | 805 | nfs_readdir_descriptor_t my_desc, |
808 | *desc = &my_desc; | 806 | *desc = &my_desc; |
809 | struct nfs_open_dir_context *dir_ctx = filp->private_data; | 807 | struct nfs_open_dir_context *dir_ctx = file->private_data; |
810 | int res; | 808 | int res; |
811 | 809 | ||
812 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 810 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
813 | dentry->d_parent->d_name.name, dentry->d_name.name, | 811 | dentry->d_parent->d_name.name, dentry->d_name.name, |
814 | (long long)filp->f_pos); | 812 | (long long)ctx->pos); |
815 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); | 813 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); |
816 | 814 | ||
817 | /* | 815 | /* |
818 | * filp->f_pos points to the dirent entry number. | 816 | * ctx->pos points to the dirent entry number. |
819 | * *desc->dir_cookie has the cookie for the next entry. We have | 817 | * *desc->dir_cookie has the cookie for the next entry. We have |
820 | * to either find the entry with the appropriate number or | 818 | * to either find the entry with the appropriate number or |
821 | * revalidate the cookie. | 819 | * revalidate the cookie. |
822 | */ | 820 | */ |
823 | memset(desc, 0, sizeof(*desc)); | 821 | memset(desc, 0, sizeof(*desc)); |
824 | 822 | ||
825 | desc->file = filp; | 823 | desc->file = file; |
824 | desc->ctx = ctx; | ||
826 | desc->dir_cookie = &dir_ctx->dir_cookie; | 825 | desc->dir_cookie = &dir_ctx->dir_cookie; |
827 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 826 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
828 | desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0; | 827 | desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; |
829 | 828 | ||
830 | nfs_block_sillyrename(dentry); | 829 | nfs_block_sillyrename(dentry); |
831 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 830 | res = nfs_revalidate_mapping(inode, file->f_mapping); |
832 | if (res < 0) | 831 | if (res < 0) |
833 | goto out; | 832 | goto out; |
834 | 833 | ||
@@ -840,7 +839,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
840 | /* This means either end of directory */ | 839 | /* This means either end of directory */ |
841 | if (*desc->dir_cookie && desc->eof == 0) { | 840 | if (*desc->dir_cookie && desc->eof == 0) { |
842 | /* Or that the server has 'lost' a cookie */ | 841 | /* Or that the server has 'lost' a cookie */ |
843 | res = uncached_readdir(desc, dirent, filldir); | 842 | res = uncached_readdir(desc); |
844 | if (res == 0) | 843 | if (res == 0) |
845 | continue; | 844 | continue; |
846 | } | 845 | } |
@@ -857,7 +856,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
857 | if (res < 0) | 856 | if (res < 0) |
858 | break; | 857 | break; |
859 | 858 | ||
860 | res = nfs_do_filldir(desc, dirent, filldir); | 859 | res = nfs_do_filldir(desc); |
861 | if (res < 0) | 860 | if (res < 0) |
862 | break; | 861 | break; |
863 | } while (!desc->eof); | 862 | } while (!desc->eof); |