diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 143 |
1 files changed, 75 insertions, 68 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index e093e73178b7..e474ca2b2bfe 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/pagevec.h> | 33 | #include <linux/pagevec.h> |
34 | #include <linux/namei.h> | 34 | #include <linux/namei.h> |
35 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
36 | #include <linux/swap.h> | ||
36 | #include <linux/sched.h> | 37 | #include <linux/sched.h> |
37 | #include <linux/kmemleak.h> | 38 | #include <linux/kmemleak.h> |
38 | #include <linux/xattr.h> | 39 | #include <linux/xattr.h> |
@@ -46,7 +47,7 @@ | |||
46 | 47 | ||
47 | static int nfs_opendir(struct inode *, struct file *); | 48 | static int nfs_opendir(struct inode *, struct file *); |
48 | static int nfs_closedir(struct inode *, struct file *); | 49 | static int nfs_closedir(struct inode *, struct file *); |
49 | static int nfs_readdir(struct file *, void *, filldir_t); | 50 | static int nfs_readdir(struct file *, struct dir_context *); |
50 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); | 51 | static int nfs_fsync_dir(struct file *, loff_t, loff_t, int); |
51 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 52 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
52 | static void nfs_readdir_clear_array(struct page*); | 53 | static void nfs_readdir_clear_array(struct page*); |
@@ -54,7 +55,7 @@ static void nfs_readdir_clear_array(struct page*); | |||
54 | const struct file_operations nfs_dir_operations = { | 55 | const struct file_operations nfs_dir_operations = { |
55 | .llseek = nfs_llseek_dir, | 56 | .llseek = nfs_llseek_dir, |
56 | .read = generic_read_dir, | 57 | .read = generic_read_dir, |
57 | .readdir = nfs_readdir, | 58 | .iterate = nfs_readdir, |
58 | .open = nfs_opendir, | 59 | .open = nfs_opendir, |
59 | .release = nfs_closedir, | 60 | .release = nfs_closedir, |
60 | .fsync = nfs_fsync_dir, | 61 | .fsync = nfs_fsync_dir, |
@@ -147,6 +148,7 @@ typedef int (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, int); | |||
147 | typedef struct { | 148 | typedef struct { |
148 | struct file *file; | 149 | struct file *file; |
149 | struct page *page; | 150 | struct page *page; |
151 | struct dir_context *ctx; | ||
150 | unsigned long page_index; | 152 | unsigned long page_index; |
151 | u64 *dir_cookie; | 153 | u64 *dir_cookie; |
152 | u64 last_cookie; | 154 | u64 last_cookie; |
@@ -252,7 +254,7 @@ out: | |||
252 | static | 254 | static |
253 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | 255 | int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) |
254 | { | 256 | { |
255 | loff_t diff = desc->file->f_pos - desc->current_index; | 257 | loff_t diff = desc->ctx->pos - desc->current_index; |
256 | unsigned int index; | 258 | unsigned int index; |
257 | 259 | ||
258 | if (diff < 0) | 260 | if (diff < 0) |
@@ -289,7 +291,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))) { | 291 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { |
290 | ctx->duped = 0; | 292 | ctx->duped = 0; |
291 | ctx->attr_gencount = nfsi->attr_gencount; | 293 | ctx->attr_gencount = nfsi->attr_gencount; |
292 | } else if (new_pos < desc->file->f_pos) { | 294 | } else if (new_pos < desc->ctx->pos) { |
293 | if (ctx->duped > 0 | 295 | if (ctx->duped > 0 |
294 | && ctx->dup_cookie == *desc->dir_cookie) { | 296 | && ctx->dup_cookie == *desc->dir_cookie) { |
295 | if (printk_ratelimit()) { | 297 | if (printk_ratelimit()) { |
@@ -307,7 +309,7 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
307 | ctx->dup_cookie = *desc->dir_cookie; | 309 | ctx->dup_cookie = *desc->dir_cookie; |
308 | ctx->duped = -1; | 310 | ctx->duped = -1; |
309 | } | 311 | } |
310 | desc->file->f_pos = new_pos; | 312 | desc->ctx->pos = new_pos; |
311 | desc->cache_entry_index = i; | 313 | desc->cache_entry_index = i; |
312 | return 0; | 314 | return 0; |
313 | } | 315 | } |
@@ -405,13 +407,13 @@ different: | |||
405 | } | 407 | } |
406 | 408 | ||
407 | static | 409 | static |
408 | bool nfs_use_readdirplus(struct inode *dir, struct file *filp) | 410 | bool nfs_use_readdirplus(struct inode *dir, struct dir_context *ctx) |
409 | { | 411 | { |
410 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) | 412 | if (!nfs_server_capable(dir, NFS_CAP_READDIRPLUS)) |
411 | return false; | 413 | return false; |
412 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) | 414 | if (test_and_clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(dir)->flags)) |
413 | return true; | 415 | return true; |
414 | if (filp->f_pos == 0) | 416 | if (ctx->pos == 0) |
415 | return true; | 417 | return true; |
416 | return false; | 418 | return false; |
417 | } | 419 | } |
@@ -435,6 +437,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
435 | struct dentry *alias; | 437 | struct dentry *alias; |
436 | struct inode *dir = parent->d_inode; | 438 | struct inode *dir = parent->d_inode; |
437 | struct inode *inode; | 439 | struct inode *inode; |
440 | int status; | ||
438 | 441 | ||
439 | if (filename.name[0] == '.') { | 442 | if (filename.name[0] == '.') { |
440 | if (filename.len == 1) | 443 | if (filename.len == 1) |
@@ -447,7 +450,10 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
447 | dentry = d_lookup(parent, &filename); | 450 | dentry = d_lookup(parent, &filename); |
448 | if (dentry != NULL) { | 451 | if (dentry != NULL) { |
449 | if (nfs_same_file(dentry, entry)) { | 452 | if (nfs_same_file(dentry, entry)) { |
450 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 453 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
454 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); | ||
455 | if (!status) | ||
456 | nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); | ||
451 | goto out; | 457 | goto out; |
452 | } else { | 458 | } else { |
453 | if (d_invalidate(dentry) != 0) | 459 | if (d_invalidate(dentry) != 0) |
@@ -460,7 +466,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
460 | if (dentry == NULL) | 466 | if (dentry == NULL) |
461 | return; | 467 | return; |
462 | 468 | ||
463 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr); | 469 | inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr, entry->label); |
464 | if (IS_ERR(inode)) | 470 | if (IS_ERR(inode)) |
465 | goto out; | 471 | goto out; |
466 | 472 | ||
@@ -585,10 +591,16 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
585 | if (entry.fh == NULL || entry.fattr == NULL) | 591 | if (entry.fh == NULL || entry.fattr == NULL) |
586 | goto out; | 592 | goto out; |
587 | 593 | ||
594 | entry.label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); | ||
595 | if (IS_ERR(entry.label)) { | ||
596 | status = PTR_ERR(entry.label); | ||
597 | goto out; | ||
598 | } | ||
599 | |||
588 | array = nfs_readdir_get_array(page); | 600 | array = nfs_readdir_get_array(page); |
589 | if (IS_ERR(array)) { | 601 | if (IS_ERR(array)) { |
590 | status = PTR_ERR(array); | 602 | status = PTR_ERR(array); |
591 | goto out; | 603 | goto out_label_free; |
592 | } | 604 | } |
593 | memset(array, 0, sizeof(struct nfs_cache_array)); | 605 | memset(array, 0, sizeof(struct nfs_cache_array)); |
594 | array->eof_index = -1; | 606 | array->eof_index = -1; |
@@ -614,6 +626,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, | |||
614 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); | 626 | nfs_readdir_free_large_page(pages_ptr, pages, array_size); |
615 | out_release_array: | 627 | out_release_array: |
616 | nfs_readdir_release_array(page); | 628 | nfs_readdir_release_array(page); |
629 | out_label_free: | ||
630 | nfs4_label_free(entry.label); | ||
617 | out: | 631 | out: |
618 | nfs_free_fattr(entry.fattr); | 632 | nfs_free_fattr(entry.fattr); |
619 | nfs_free_fhandle(entry.fh); | 633 | nfs_free_fhandle(entry.fh); |
@@ -702,8 +716,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... | 716 | * Once we've found the start of the dirent within a page: fill 'er up... |
703 | */ | 717 | */ |
704 | static | 718 | static |
705 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | 719 | int nfs_do_filldir(nfs_readdir_descriptor_t *desc) |
706 | filldir_t filldir) | ||
707 | { | 720 | { |
708 | struct file *file = desc->file; | 721 | struct file *file = desc->file; |
709 | int i = 0; | 722 | int i = 0; |
@@ -721,13 +734,12 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
721 | struct nfs_cache_array_entry *ent; | 734 | struct nfs_cache_array_entry *ent; |
722 | 735 | ||
723 | ent = &array->array[i]; | 736 | ent = &array->array[i]; |
724 | if (filldir(dirent, ent->string.name, ent->string.len, | 737 | if (!dir_emit(desc->ctx, ent->string.name, ent->string.len, |
725 | file->f_pos, nfs_compat_user_ino64(ent->ino), | 738 | nfs_compat_user_ino64(ent->ino), ent->d_type)) { |
726 | ent->d_type) < 0) { | ||
727 | desc->eof = 1; | 739 | desc->eof = 1; |
728 | break; | 740 | break; |
729 | } | 741 | } |
730 | file->f_pos++; | 742 | desc->ctx->pos++; |
731 | if (i < (array->size-1)) | 743 | if (i < (array->size-1)) |
732 | *desc->dir_cookie = array->array[i+1].cookie; | 744 | *desc->dir_cookie = array->array[i+1].cookie; |
733 | else | 745 | else |
@@ -759,8 +771,7 @@ out: | |||
759 | * directory in the page cache by the time we get here. | 771 | * directory in the page cache by the time we get here. |
760 | */ | 772 | */ |
761 | static inline | 773 | static inline |
762 | int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | 774 | int uncached_readdir(nfs_readdir_descriptor_t *desc) |
763 | filldir_t filldir) | ||
764 | { | 775 | { |
765 | struct page *page = NULL; | 776 | struct page *page = NULL; |
766 | int status; | 777 | int status; |
@@ -785,7 +796,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
785 | if (status < 0) | 796 | if (status < 0) |
786 | goto out_release; | 797 | goto out_release; |
787 | 798 | ||
788 | status = nfs_do_filldir(desc, dirent, filldir); | 799 | status = nfs_do_filldir(desc); |
789 | 800 | ||
790 | out: | 801 | out: |
791 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", | 802 | dfprintk(DIRCACHE, "NFS: %s: returns %d\n", |
@@ -800,35 +811,37 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
800 | last cookie cache takes care of the common case of reading the | 811 | last cookie cache takes care of the common case of reading the |
801 | whole directory. | 812 | whole directory. |
802 | */ | 813 | */ |
803 | static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | 814 | static int nfs_readdir(struct file *file, struct dir_context *ctx) |
804 | { | 815 | { |
805 | struct dentry *dentry = filp->f_path.dentry; | 816 | struct dentry *dentry = file->f_path.dentry; |
806 | struct inode *inode = dentry->d_inode; | 817 | struct inode *inode = dentry->d_inode; |
807 | nfs_readdir_descriptor_t my_desc, | 818 | nfs_readdir_descriptor_t my_desc, |
808 | *desc = &my_desc; | 819 | *desc = &my_desc; |
809 | struct nfs_open_dir_context *dir_ctx = filp->private_data; | 820 | struct nfs_open_dir_context *dir_ctx = file->private_data; |
810 | int res; | 821 | int res = 0; |
811 | 822 | ||
812 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", | 823 | dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n", |
813 | dentry->d_parent->d_name.name, dentry->d_name.name, | 824 | dentry->d_parent->d_name.name, dentry->d_name.name, |
814 | (long long)filp->f_pos); | 825 | (long long)ctx->pos); |
815 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); | 826 | nfs_inc_stats(inode, NFSIOS_VFSGETDENTS); |
816 | 827 | ||
817 | /* | 828 | /* |
818 | * filp->f_pos points to the dirent entry number. | 829 | * ctx->pos points to the dirent entry number. |
819 | * *desc->dir_cookie has the cookie for the next entry. We have | 830 | * *desc->dir_cookie has the cookie for the next entry. We have |
820 | * to either find the entry with the appropriate number or | 831 | * to either find the entry with the appropriate number or |
821 | * revalidate the cookie. | 832 | * revalidate the cookie. |
822 | */ | 833 | */ |
823 | memset(desc, 0, sizeof(*desc)); | 834 | memset(desc, 0, sizeof(*desc)); |
824 | 835 | ||
825 | desc->file = filp; | 836 | desc->file = file; |
837 | desc->ctx = ctx; | ||
826 | desc->dir_cookie = &dir_ctx->dir_cookie; | 838 | desc->dir_cookie = &dir_ctx->dir_cookie; |
827 | desc->decode = NFS_PROTO(inode)->decode_dirent; | 839 | desc->decode = NFS_PROTO(inode)->decode_dirent; |
828 | desc->plus = nfs_use_readdirplus(inode, filp) ? 1 : 0; | 840 | desc->plus = nfs_use_readdirplus(inode, ctx) ? 1 : 0; |
829 | 841 | ||
830 | nfs_block_sillyrename(dentry); | 842 | nfs_block_sillyrename(dentry); |
831 | res = nfs_revalidate_mapping(inode, filp->f_mapping); | 843 | if (ctx->pos == 0 || nfs_attribute_cache_expired(inode)) |
844 | res = nfs_revalidate_mapping(inode, file->f_mapping); | ||
832 | if (res < 0) | 845 | if (res < 0) |
833 | goto out; | 846 | goto out; |
834 | 847 | ||
@@ -840,7 +853,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
840 | /* This means either end of directory */ | 853 | /* This means either end of directory */ |
841 | if (*desc->dir_cookie && desc->eof == 0) { | 854 | if (*desc->dir_cookie && desc->eof == 0) { |
842 | /* Or that the server has 'lost' a cookie */ | 855 | /* Or that the server has 'lost' a cookie */ |
843 | res = uncached_readdir(desc, dirent, filldir); | 856 | res = uncached_readdir(desc); |
844 | if (res == 0) | 857 | if (res == 0) |
845 | continue; | 858 | continue; |
846 | } | 859 | } |
@@ -857,7 +870,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
857 | if (res < 0) | 870 | if (res < 0) |
858 | break; | 871 | break; |
859 | 872 | ||
860 | res = nfs_do_filldir(desc, dirent, filldir); | 873 | res = nfs_do_filldir(desc); |
861 | if (res < 0) | 874 | if (res < 0) |
862 | break; | 875 | break; |
863 | } while (!desc->eof); | 876 | } while (!desc->eof); |
@@ -1040,6 +1053,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1040 | struct dentry *parent; | 1053 | struct dentry *parent; |
1041 | struct nfs_fh *fhandle = NULL; | 1054 | struct nfs_fh *fhandle = NULL; |
1042 | struct nfs_fattr *fattr = NULL; | 1055 | struct nfs_fattr *fattr = NULL; |
1056 | struct nfs4_label *label = NULL; | ||
1043 | int error; | 1057 | int error; |
1044 | 1058 | ||
1045 | if (flags & LOOKUP_RCU) | 1059 | if (flags & LOOKUP_RCU) |
@@ -1082,7 +1096,11 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1082 | if (fhandle == NULL || fattr == NULL) | 1096 | if (fhandle == NULL || fattr == NULL) |
1083 | goto out_error; | 1097 | goto out_error; |
1084 | 1098 | ||
1085 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1099 | label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT); |
1100 | if (IS_ERR(label)) | ||
1101 | goto out_error; | ||
1102 | |||
1103 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); | ||
1086 | if (error) | 1104 | if (error) |
1087 | goto out_bad; | 1105 | goto out_bad; |
1088 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) | 1106 | if (nfs_compare_fh(NFS_FH(inode), fhandle)) |
@@ -1090,8 +1108,12 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1090 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1108 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
1091 | goto out_bad; | 1109 | goto out_bad; |
1092 | 1110 | ||
1111 | nfs_setsecurity(inode, fattr, label); | ||
1112 | |||
1093 | nfs_free_fattr(fattr); | 1113 | nfs_free_fattr(fattr); |
1094 | nfs_free_fhandle(fhandle); | 1114 | nfs_free_fhandle(fhandle); |
1115 | nfs4_label_free(label); | ||
1116 | |||
1095 | out_set_verifier: | 1117 | out_set_verifier: |
1096 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1118 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1097 | out_valid: | 1119 | out_valid: |
@@ -1108,6 +1130,7 @@ out_zap_parent: | |||
1108 | out_bad: | 1130 | out_bad: |
1109 | nfs_free_fattr(fattr); | 1131 | nfs_free_fattr(fattr); |
1110 | nfs_free_fhandle(fhandle); | 1132 | nfs_free_fhandle(fhandle); |
1133 | nfs4_label_free(label); | ||
1111 | nfs_mark_for_revalidate(dir); | 1134 | nfs_mark_for_revalidate(dir); |
1112 | if (inode && S_ISDIR(inode->i_mode)) { | 1135 | if (inode && S_ISDIR(inode->i_mode)) { |
1113 | /* Purge readdir caches. */ | 1136 | /* Purge readdir caches. */ |
@@ -1128,6 +1151,7 @@ out_zap_parent: | |||
1128 | out_error: | 1151 | out_error: |
1129 | nfs_free_fattr(fattr); | 1152 | nfs_free_fattr(fattr); |
1130 | nfs_free_fhandle(fhandle); | 1153 | nfs_free_fhandle(fhandle); |
1154 | nfs4_label_free(label); | ||
1131 | dput(parent); | 1155 | dput(parent); |
1132 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", | 1156 | dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) lookup returned error %d\n", |
1133 | __func__, dentry->d_parent->d_name.name, | 1157 | __func__, dentry->d_parent->d_name.name, |
@@ -1256,6 +1280,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1256 | struct inode *inode = NULL; | 1280 | struct inode *inode = NULL; |
1257 | struct nfs_fh *fhandle = NULL; | 1281 | struct nfs_fh *fhandle = NULL; |
1258 | struct nfs_fattr *fattr = NULL; | 1282 | struct nfs_fattr *fattr = NULL; |
1283 | struct nfs4_label *label = NULL; | ||
1259 | int error; | 1284 | int error; |
1260 | 1285 | ||
1261 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", | 1286 | dfprintk(VFS, "NFS: lookup(%s/%s)\n", |
@@ -1282,17 +1307,21 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in | |||
1282 | if (fhandle == NULL || fattr == NULL) | 1307 | if (fhandle == NULL || fattr == NULL) |
1283 | goto out; | 1308 | goto out; |
1284 | 1309 | ||
1310 | label = nfs4_label_alloc(NFS_SERVER(dir), GFP_NOWAIT); | ||
1311 | if (IS_ERR(label)) | ||
1312 | goto out; | ||
1313 | |||
1285 | parent = dentry->d_parent; | 1314 | parent = dentry->d_parent; |
1286 | /* Protect against concurrent sillydeletes */ | 1315 | /* Protect against concurrent sillydeletes */ |
1287 | nfs_block_sillyrename(parent); | 1316 | nfs_block_sillyrename(parent); |
1288 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1317 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); |
1289 | if (error == -ENOENT) | 1318 | if (error == -ENOENT) |
1290 | goto no_entry; | 1319 | goto no_entry; |
1291 | if (error < 0) { | 1320 | if (error < 0) { |
1292 | res = ERR_PTR(error); | 1321 | res = ERR_PTR(error); |
1293 | goto out_unblock_sillyrename; | 1322 | goto out_unblock_sillyrename; |
1294 | } | 1323 | } |
1295 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1324 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1296 | res = ERR_CAST(inode); | 1325 | res = ERR_CAST(inode); |
1297 | if (IS_ERR(res)) | 1326 | if (IS_ERR(res)) |
1298 | goto out_unblock_sillyrename; | 1327 | goto out_unblock_sillyrename; |
@@ -1310,6 +1339,7 @@ no_entry: | |||
1310 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1339 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1311 | out_unblock_sillyrename: | 1340 | out_unblock_sillyrename: |
1312 | nfs_unblock_sillyrename(parent); | 1341 | nfs_unblock_sillyrename(parent); |
1342 | nfs4_label_free(label); | ||
1313 | out: | 1343 | out: |
1314 | nfs_free_fattr(fattr); | 1344 | nfs_free_fattr(fattr); |
1315 | nfs_free_fhandle(fhandle); | 1345 | nfs_free_fhandle(fhandle); |
@@ -1357,18 +1387,6 @@ static int nfs_finish_open(struct nfs_open_context *ctx, | |||
1357 | { | 1387 | { |
1358 | int err; | 1388 | int err; |
1359 | 1389 | ||
1360 | if (ctx->dentry != dentry) { | ||
1361 | dput(ctx->dentry); | ||
1362 | ctx->dentry = dget(dentry); | ||
1363 | } | ||
1364 | |||
1365 | /* If the open_intent is for execute, we have an extra check to make */ | ||
1366 | if (ctx->mode & FMODE_EXEC) { | ||
1367 | err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags); | ||
1368 | if (err < 0) | ||
1369 | goto out; | ||
1370 | } | ||
1371 | |||
1372 | err = finish_open(file, dentry, do_open, opened); | 1390 | err = finish_open(file, dentry, do_open, opened); |
1373 | if (err) | 1391 | if (err) |
1374 | goto out; | 1392 | goto out; |
@@ -1427,13 +1445,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1427 | 1445 | ||
1428 | nfs_block_sillyrename(dentry->d_parent); | 1446 | nfs_block_sillyrename(dentry->d_parent); |
1429 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); | 1447 | inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr); |
1430 | d_drop(dentry); | 1448 | nfs_unblock_sillyrename(dentry->d_parent); |
1431 | if (IS_ERR(inode)) { | 1449 | if (IS_ERR(inode)) { |
1432 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1433 | put_nfs_open_context(ctx); | 1450 | put_nfs_open_context(ctx); |
1434 | err = PTR_ERR(inode); | 1451 | err = PTR_ERR(inode); |
1435 | switch (err) { | 1452 | switch (err) { |
1436 | case -ENOENT: | 1453 | case -ENOENT: |
1454 | d_drop(dentry); | ||
1437 | d_add(dentry, NULL); | 1455 | d_add(dentry, NULL); |
1438 | break; | 1456 | break; |
1439 | case -EISDIR: | 1457 | case -EISDIR: |
@@ -1449,16 +1467,8 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1449 | } | 1467 | } |
1450 | goto out; | 1468 | goto out; |
1451 | } | 1469 | } |
1452 | res = d_add_unique(dentry, inode); | ||
1453 | if (res != NULL) | ||
1454 | dentry = res; | ||
1455 | |||
1456 | nfs_unblock_sillyrename(dentry->d_parent); | ||
1457 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | ||
1458 | |||
1459 | err = nfs_finish_open(ctx, dentry, file, open_flags, opened); | ||
1460 | 1470 | ||
1461 | dput(res); | 1471 | err = nfs_finish_open(ctx, ctx->dentry, file, open_flags, opened); |
1462 | out: | 1472 | out: |
1463 | return err; | 1473 | return err; |
1464 | 1474 | ||
@@ -1528,7 +1538,8 @@ no_open: | |||
1528 | * Code common to create, mkdir, and mknod. | 1538 | * Code common to create, mkdir, and mknod. |
1529 | */ | 1539 | */ |
1530 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | 1540 | int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, |
1531 | struct nfs_fattr *fattr) | 1541 | struct nfs_fattr *fattr, |
1542 | struct nfs4_label *label) | ||
1532 | { | 1543 | { |
1533 | struct dentry *parent = dget_parent(dentry); | 1544 | struct dentry *parent = dget_parent(dentry); |
1534 | struct inode *dir = parent->d_inode; | 1545 | struct inode *dir = parent->d_inode; |
@@ -1541,18 +1552,18 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, | |||
1541 | if (dentry->d_inode) | 1552 | if (dentry->d_inode) |
1542 | goto out; | 1553 | goto out; |
1543 | if (fhandle->size == 0) { | 1554 | if (fhandle->size == 0) { |
1544 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); | 1555 | error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, NULL); |
1545 | if (error) | 1556 | if (error) |
1546 | goto out_error; | 1557 | goto out_error; |
1547 | } | 1558 | } |
1548 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1559 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1549 | if (!(fattr->valid & NFS_ATTR_FATTR)) { | 1560 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
1550 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 1561 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
1551 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); | 1562 | error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL); |
1552 | if (error < 0) | 1563 | if (error < 0) |
1553 | goto out_error; | 1564 | goto out_error; |
1554 | } | 1565 | } |
1555 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr); | 1566 | inode = nfs_fhget(dentry->d_sb, fhandle, fattr, label); |
1556 | error = PTR_ERR(inode); | 1567 | error = PTR_ERR(inode); |
1557 | if (IS_ERR(inode)) | 1568 | if (IS_ERR(inode)) |
1558 | goto out_error; | 1569 | goto out_error; |
@@ -1721,7 +1732,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1721 | dir->i_ino, dentry->d_name.name); | 1732 | dir->i_ino, dentry->d_name.name); |
1722 | 1733 | ||
1723 | spin_lock(&dentry->d_lock); | 1734 | spin_lock(&dentry->d_lock); |
1724 | if (dentry->d_count > 1) { | 1735 | if (d_count(dentry) > 1) { |
1725 | spin_unlock(&dentry->d_lock); | 1736 | spin_unlock(&dentry->d_lock); |
1726 | /* Start asynchronous writeout of the inode */ | 1737 | /* Start asynchronous writeout of the inode */ |
1727 | write_inode_now(dentry->d_inode, 0); | 1738 | write_inode_now(dentry->d_inode, 0); |
@@ -1759,7 +1770,6 @@ EXPORT_SYMBOL_GPL(nfs_unlink); | |||
1759 | */ | 1770 | */ |
1760 | int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | 1771 | int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) |
1761 | { | 1772 | { |
1762 | struct pagevec lru_pvec; | ||
1763 | struct page *page; | 1773 | struct page *page; |
1764 | char *kaddr; | 1774 | char *kaddr; |
1765 | struct iattr attr; | 1775 | struct iattr attr; |
@@ -1799,11 +1809,8 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1799 | * No big deal if we can't add this page to the page cache here. | 1809 | * No big deal if we can't add this page to the page cache here. |
1800 | * READLINK will get the missing page from the server if needed. | 1810 | * READLINK will get the missing page from the server if needed. |
1801 | */ | 1811 | */ |
1802 | pagevec_init(&lru_pvec, 0); | 1812 | if (!add_to_page_cache_lru(page, dentry->d_inode->i_mapping, 0, |
1803 | if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0, | ||
1804 | GFP_KERNEL)) { | 1813 | GFP_KERNEL)) { |
1805 | pagevec_add(&lru_pvec, page); | ||
1806 | pagevec_lru_add_file(&lru_pvec); | ||
1807 | SetPageUptodate(page); | 1814 | SetPageUptodate(page); |
1808 | unlock_page(page); | 1815 | unlock_page(page); |
1809 | } else | 1816 | } else |
@@ -1870,7 +1877,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1870 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", | 1877 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", |
1871 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1878 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1872 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1879 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1873 | new_dentry->d_count); | 1880 | d_count(new_dentry)); |
1874 | 1881 | ||
1875 | /* | 1882 | /* |
1876 | * For non-directories, check whether the target is busy and if so, | 1883 | * For non-directories, check whether the target is busy and if so, |
@@ -1888,7 +1895,7 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1888 | rehash = new_dentry; | 1895 | rehash = new_dentry; |
1889 | } | 1896 | } |
1890 | 1897 | ||
1891 | if (new_dentry->d_count > 2) { | 1898 | if (d_count(new_dentry) > 2) { |
1892 | int err; | 1899 | int err; |
1893 | 1900 | ||
1894 | /* copy the target dentry's name */ | 1901 | /* copy the target dentry's name */ |