diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-10-15 15:54:56 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-10-15 15:54:56 -0400 |
commit | 6925bac120097b823fc990c143b9789c21cc60b5 (patch) | |
tree | 0f92e1b22122fba623aeff4c271c16df673244eb /fs/nfs | |
parent | 04ab591808565f968d4406f6435090ad671ebdab (diff) | |
parent | 011935a0a710c20bb7ae63523b78856848db1926 (diff) |
Merge branch 'next'
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/client.c | 5 | ||||
-rw-r--r-- | fs/nfs/dir.c | 20 | ||||
-rw-r--r-- | fs/nfs/file.c | 18 | ||||
-rw-r--r-- | fs/nfs/inode.c | 183 | ||||
-rw-r--r-- | fs/nfs/internal.h | 25 | ||||
-rw-r--r-- | fs/nfs/mount_clnt.c | 3 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 20 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 105 | ||||
-rw-r--r-- | fs/nfs/proc.c | 10 | ||||
-rw-r--r-- | fs/nfs/super.c | 126 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 5 | ||||
-rw-r--r-- | fs/nfs/write.c | 3 |
14 files changed, 321 insertions, 211 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 5ee23e7058b3..7547600b6174 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -675,7 +675,7 @@ static int nfs_init_server(struct nfs_server *server, | |||
675 | server->nfs_client = clp; | 675 | server->nfs_client = clp; |
676 | 676 | ||
677 | /* Initialise the client representation from the mount data */ | 677 | /* Initialise the client representation from the mount data */ |
678 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 678 | server->flags = data->flags; |
679 | 679 | ||
680 | if (data->rsize) | 680 | if (data->rsize) |
681 | server->rsize = nfs_block_size(data->rsize, NULL); | 681 | server->rsize = nfs_block_size(data->rsize, NULL); |
@@ -850,7 +850,6 @@ static struct nfs_server *nfs_alloc_server(void) | |||
850 | INIT_LIST_HEAD(&server->client_link); | 850 | INIT_LIST_HEAD(&server->client_link); |
851 | INIT_LIST_HEAD(&server->master_link); | 851 | INIT_LIST_HEAD(&server->master_link); |
852 | 852 | ||
853 | init_waitqueue_head(&server->active_wq); | ||
854 | atomic_set(&server->active, 0); | 853 | atomic_set(&server->active, 0); |
855 | 854 | ||
856 | server->io_stats = nfs_alloc_iostats(); | 855 | server->io_stats = nfs_alloc_iostats(); |
@@ -1073,7 +1072,7 @@ static int nfs4_init_server(struct nfs_server *server, | |||
1073 | goto error; | 1072 | goto error; |
1074 | 1073 | ||
1075 | /* Initialise the client representation from the mount data */ | 1074 | /* Initialise the client representation from the mount data */ |
1076 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1075 | server->flags = data->flags; |
1077 | server->caps |= NFS_CAP_ATOMIC_OPEN; | 1076 | server->caps |= NFS_CAP_ATOMIC_OPEN; |
1078 | 1077 | ||
1079 | if (data->rsize) | 1078 | if (data->rsize) |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 74f92b717f78..2ab70d46ecbc 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -156,6 +156,7 @@ typedef struct { | |||
156 | decode_dirent_t decode; | 156 | decode_dirent_t decode; |
157 | int plus; | 157 | int plus; |
158 | unsigned long timestamp; | 158 | unsigned long timestamp; |
159 | unsigned long gencount; | ||
159 | int timestamp_valid; | 160 | int timestamp_valid; |
160 | } nfs_readdir_descriptor_t; | 161 | } nfs_readdir_descriptor_t; |
161 | 162 | ||
@@ -177,7 +178,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
177 | struct file *file = desc->file; | 178 | struct file *file = desc->file; |
178 | struct inode *inode = file->f_path.dentry->d_inode; | 179 | struct inode *inode = file->f_path.dentry->d_inode; |
179 | struct rpc_cred *cred = nfs_file_cred(file); | 180 | struct rpc_cred *cred = nfs_file_cred(file); |
180 | unsigned long timestamp; | 181 | unsigned long timestamp, gencount; |
181 | int error; | 182 | int error; |
182 | 183 | ||
183 | dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n", | 184 | dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n", |
@@ -186,6 +187,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
186 | 187 | ||
187 | again: | 188 | again: |
188 | timestamp = jiffies; | 189 | timestamp = jiffies; |
190 | gencount = nfs_inc_attr_generation_counter(); | ||
189 | error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page, | 191 | error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page, |
190 | NFS_SERVER(inode)->dtsize, desc->plus); | 192 | NFS_SERVER(inode)->dtsize, desc->plus); |
191 | if (error < 0) { | 193 | if (error < 0) { |
@@ -199,6 +201,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page) | |||
199 | goto error; | 201 | goto error; |
200 | } | 202 | } |
201 | desc->timestamp = timestamp; | 203 | desc->timestamp = timestamp; |
204 | desc->gencount = gencount; | ||
202 | desc->timestamp_valid = 1; | 205 | desc->timestamp_valid = 1; |
203 | SetPageUptodate(page); | 206 | SetPageUptodate(page); |
204 | /* Ensure consistent page alignment of the data. | 207 | /* Ensure consistent page alignment of the data. |
@@ -224,9 +227,10 @@ int dir_decode(nfs_readdir_descriptor_t *desc) | |||
224 | if (IS_ERR(p)) | 227 | if (IS_ERR(p)) |
225 | return PTR_ERR(p); | 228 | return PTR_ERR(p); |
226 | desc->ptr = p; | 229 | desc->ptr = p; |
227 | if (desc->timestamp_valid) | 230 | if (desc->timestamp_valid) { |
228 | desc->entry->fattr->time_start = desc->timestamp; | 231 | desc->entry->fattr->time_start = desc->timestamp; |
229 | else | 232 | desc->entry->fattr->gencount = desc->gencount; |
233 | } else | ||
230 | desc->entry->fattr->valid &= ~NFS_ATTR_FATTR; | 234 | desc->entry->fattr->valid &= ~NFS_ATTR_FATTR; |
231 | return 0; | 235 | return 0; |
232 | } | 236 | } |
@@ -471,7 +475,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
471 | struct rpc_cred *cred = nfs_file_cred(file); | 475 | struct rpc_cred *cred = nfs_file_cred(file); |
472 | struct page *page = NULL; | 476 | struct page *page = NULL; |
473 | int status; | 477 | int status; |
474 | unsigned long timestamp; | 478 | unsigned long timestamp, gencount; |
475 | 479 | ||
476 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", | 480 | dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n", |
477 | (unsigned long long)*desc->dir_cookie); | 481 | (unsigned long long)*desc->dir_cookie); |
@@ -482,6 +486,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
482 | goto out; | 486 | goto out; |
483 | } | 487 | } |
484 | timestamp = jiffies; | 488 | timestamp = jiffies; |
489 | gencount = nfs_inc_attr_generation_counter(); | ||
485 | status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, | 490 | status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, |
486 | *desc->dir_cookie, page, | 491 | *desc->dir_cookie, page, |
487 | NFS_SERVER(inode)->dtsize, | 492 | NFS_SERVER(inode)->dtsize, |
@@ -490,6 +495,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
490 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ | 495 | desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */ |
491 | if (status >= 0) { | 496 | if (status >= 0) { |
492 | desc->timestamp = timestamp; | 497 | desc->timestamp = timestamp; |
498 | desc->gencount = gencount; | ||
493 | desc->timestamp_valid = 1; | 499 | desc->timestamp_valid = 1; |
494 | if ((status = dir_decode(desc)) == 0) | 500 | if ((status = dir_decode(desc)) == 0) |
495 | desc->entry->prev_cookie = *desc->dir_cookie; | 501 | desc->entry->prev_cookie = *desc->dir_cookie; |
@@ -655,7 +661,7 @@ static int nfs_fsync_dir(struct file *filp, struct dentry *dentry, int datasync) | |||
655 | */ | 661 | */ |
656 | void nfs_force_lookup_revalidate(struct inode *dir) | 662 | void nfs_force_lookup_revalidate(struct inode *dir) |
657 | { | 663 | { |
658 | NFS_I(dir)->cache_change_attribute = jiffies; | 664 | NFS_I(dir)->cache_change_attribute++; |
659 | } | 665 | } |
660 | 666 | ||
661 | /* | 667 | /* |
@@ -667,6 +673,8 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry) | |||
667 | { | 673 | { |
668 | if (IS_ROOT(dentry)) | 674 | if (IS_ROOT(dentry)) |
669 | return 1; | 675 | return 1; |
676 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONE) | ||
677 | return 0; | ||
670 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) | 678 | if (!nfs_verify_change_attribute(dir, dentry->d_time)) |
671 | return 0; | 679 | return 0; |
672 | /* Revalidate nfsi->cache_change_attribute before we declare a match */ | 680 | /* Revalidate nfsi->cache_change_attribute before we declare a match */ |
@@ -750,6 +758,8 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry, | |||
750 | /* Don't revalidate a negative dentry if we're creating a new file */ | 758 | /* Don't revalidate a negative dentry if we're creating a new file */ |
751 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) | 759 | if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0) |
752 | return 0; | 760 | return 0; |
761 | if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG) | ||
762 | return 1; | ||
753 | return !nfs_check_verifier(dir, dentry); | 763 | return !nfs_check_verifier(dir, dentry); |
754 | } | 764 | } |
755 | 765 | ||
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 78460657f5cb..d319b49f8f06 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -188,13 +188,16 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
188 | /* origin == SEEK_END => we must revalidate the cached file length */ | 188 | /* origin == SEEK_END => we must revalidate the cached file length */ |
189 | if (origin == SEEK_END) { | 189 | if (origin == SEEK_END) { |
190 | struct inode *inode = filp->f_mapping->host; | 190 | struct inode *inode = filp->f_mapping->host; |
191 | |||
191 | int retval = nfs_revalidate_file_size(inode, filp); | 192 | int retval = nfs_revalidate_file_size(inode, filp); |
192 | if (retval < 0) | 193 | if (retval < 0) |
193 | return (loff_t)retval; | 194 | return (loff_t)retval; |
194 | } | 195 | |
195 | lock_kernel(); /* BKL needed? */ | 196 | spin_lock(&inode->i_lock); |
196 | loff = generic_file_llseek_unlocked(filp, offset, origin); | 197 | loff = generic_file_llseek_unlocked(filp, offset, origin); |
197 | unlock_kernel(); | 198 | spin_unlock(&inode->i_lock); |
199 | } else | ||
200 | loff = generic_file_llseek_unlocked(filp, offset, origin); | ||
198 | return loff; | 201 | return loff; |
199 | } | 202 | } |
200 | 203 | ||
@@ -699,13 +702,6 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
699 | filp->f_path.dentry->d_name.name, | 702 | filp->f_path.dentry->d_name.name, |
700 | fl->fl_type, fl->fl_flags); | 703 | fl->fl_type, fl->fl_flags); |
701 | 704 | ||
702 | /* | ||
703 | * No BSD flocks over NFS allowed. | ||
704 | * Note: we could try to fake a POSIX lock request here by | ||
705 | * using ((u32) filp | 0x80000000) or some such as the pid. | ||
706 | * Not sure whether that would be unique, though, or whether | ||
707 | * that would break in other places. | ||
708 | */ | ||
709 | if (!(fl->fl_flags & FL_FLOCK)) | 705 | if (!(fl->fl_flags & FL_FLOCK)) |
710 | return -ENOLCK; | 706 | return -ENOLCK; |
711 | 707 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 52daefa2f521..b9195c02a863 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -305,8 +305,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
305 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 305 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
306 | 306 | ||
307 | nfsi->read_cache_jiffies = fattr->time_start; | 307 | nfsi->read_cache_jiffies = fattr->time_start; |
308 | nfsi->last_updated = now; | 308 | nfsi->attr_gencount = fattr->gencount; |
309 | nfsi->cache_change_attribute = now; | ||
310 | inode->i_atime = fattr->atime; | 309 | inode->i_atime = fattr->atime; |
311 | inode->i_mtime = fattr->mtime; | 310 | inode->i_mtime = fattr->mtime; |
312 | inode->i_ctime = fattr->ctime; | 311 | inode->i_ctime = fattr->ctime; |
@@ -453,6 +452,7 @@ out_big: | |||
453 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 452 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) |
454 | { | 453 | { |
455 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 454 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
455 | spin_lock(&inode->i_lock); | ||
456 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 456 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
457 | int mode = attr->ia_mode & S_IALLUGO; | 457 | int mode = attr->ia_mode & S_IALLUGO; |
458 | mode |= inode->i_mode & ~S_IALLUGO; | 458 | mode |= inode->i_mode & ~S_IALLUGO; |
@@ -462,7 +462,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
462 | inode->i_uid = attr->ia_uid; | 462 | inode->i_uid = attr->ia_uid; |
463 | if ((attr->ia_valid & ATTR_GID) != 0) | 463 | if ((attr->ia_valid & ATTR_GID) != 0) |
464 | inode->i_gid = attr->ia_gid; | 464 | inode->i_gid = attr->ia_gid; |
465 | spin_lock(&inode->i_lock); | ||
466 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 465 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
467 | spin_unlock(&inode->i_lock); | 466 | spin_unlock(&inode->i_lock); |
468 | } | 467 | } |
@@ -472,37 +471,6 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | |||
472 | } | 471 | } |
473 | } | 472 | } |
474 | 473 | ||
475 | static int nfs_wait_schedule(void *word) | ||
476 | { | ||
477 | if (signal_pending(current)) | ||
478 | return -ERESTARTSYS; | ||
479 | schedule(); | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | /* | ||
484 | * Wait for the inode to get unlocked. | ||
485 | */ | ||
486 | static int nfs_wait_on_inode(struct inode *inode) | ||
487 | { | ||
488 | struct nfs_inode *nfsi = NFS_I(inode); | ||
489 | int error; | ||
490 | |||
491 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, | ||
492 | nfs_wait_schedule, TASK_KILLABLE); | ||
493 | |||
494 | return error; | ||
495 | } | ||
496 | |||
497 | static void nfs_wake_up_inode(struct inode *inode) | ||
498 | { | ||
499 | struct nfs_inode *nfsi = NFS_I(inode); | ||
500 | |||
501 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); | ||
502 | smp_mb__after_clear_bit(); | ||
503 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); | ||
504 | } | ||
505 | |||
506 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 474 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
507 | { | 475 | { |
508 | struct inode *inode = dentry->d_inode; | 476 | struct inode *inode = dentry->d_inode; |
@@ -697,20 +665,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
697 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 665 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
698 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 666 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
699 | 667 | ||
700 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | ||
701 | if (is_bad_inode(inode)) | 668 | if (is_bad_inode(inode)) |
702 | goto out_nowait; | 669 | goto out; |
703 | if (NFS_STALE(inode)) | 670 | if (NFS_STALE(inode)) |
704 | goto out_nowait; | ||
705 | |||
706 | status = nfs_wait_on_inode(inode); | ||
707 | if (status < 0) | ||
708 | goto out; | 671 | goto out; |
709 | 672 | ||
710 | status = -ESTALE; | ||
711 | if (NFS_STALE(inode)) | 673 | if (NFS_STALE(inode)) |
712 | goto out; | 674 | goto out; |
713 | 675 | ||
676 | nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE); | ||
714 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 677 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
715 | if (status != 0) { | 678 | if (status != 0) { |
716 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 679 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
@@ -724,16 +687,13 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
724 | goto out; | 687 | goto out; |
725 | } | 688 | } |
726 | 689 | ||
727 | spin_lock(&inode->i_lock); | 690 | status = nfs_refresh_inode(inode, &fattr); |
728 | status = nfs_update_inode(inode, &fattr); | ||
729 | if (status) { | 691 | if (status) { |
730 | spin_unlock(&inode->i_lock); | ||
731 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 692 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
732 | inode->i_sb->s_id, | 693 | inode->i_sb->s_id, |
733 | (long long)NFS_FILEID(inode), status); | 694 | (long long)NFS_FILEID(inode), status); |
734 | goto out; | 695 | goto out; |
735 | } | 696 | } |
736 | spin_unlock(&inode->i_lock); | ||
737 | 697 | ||
738 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 698 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
739 | nfs_zap_acl_cache(inode); | 699 | nfs_zap_acl_cache(inode); |
@@ -743,9 +703,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
743 | (long long)NFS_FILEID(inode)); | 703 | (long long)NFS_FILEID(inode)); |
744 | 704 | ||
745 | out: | 705 | out: |
746 | nfs_wake_up_inode(inode); | ||
747 | |||
748 | out_nowait: | ||
749 | return status; | 706 | return status; |
750 | } | 707 | } |
751 | 708 | ||
@@ -908,9 +865,6 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
908 | return -EIO; | 865 | return -EIO; |
909 | } | 866 | } |
910 | 867 | ||
911 | /* Do atomic weak cache consistency updates */ | ||
912 | nfs_wcc_update_inode(inode, fattr); | ||
913 | |||
914 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 868 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
915 | nfsi->change_attr != fattr->change_attr) | 869 | nfsi->change_attr != fattr->change_attr) |
916 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 870 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; |
@@ -939,15 +893,81 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
939 | 893 | ||
940 | if (invalid != 0) | 894 | if (invalid != 0) |
941 | nfsi->cache_validity |= invalid; | 895 | nfsi->cache_validity |= invalid; |
942 | else | ||
943 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR | ||
944 | | NFS_INO_INVALID_ATIME | ||
945 | | NFS_INO_REVAL_PAGECACHE); | ||
946 | 896 | ||
947 | nfsi->read_cache_jiffies = fattr->time_start; | 897 | nfsi->read_cache_jiffies = fattr->time_start; |
948 | return 0; | 898 | return 0; |
949 | } | 899 | } |
950 | 900 | ||
901 | static int nfs_ctime_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
902 | { | ||
903 | return timespec_compare(&fattr->ctime, &inode->i_ctime) > 0; | ||
904 | } | ||
905 | |||
906 | static int nfs_size_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
907 | { | ||
908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | ||
909 | } | ||
910 | |||
911 | static unsigned long nfs_attr_generation_counter; | ||
912 | |||
913 | static unsigned long nfs_read_attr_generation_counter(void) | ||
914 | { | ||
915 | smp_rmb(); | ||
916 | return nfs_attr_generation_counter; | ||
917 | } | ||
918 | |||
919 | unsigned long nfs_inc_attr_generation_counter(void) | ||
920 | { | ||
921 | unsigned long ret; | ||
922 | smp_rmb(); | ||
923 | ret = ++nfs_attr_generation_counter; | ||
924 | smp_wmb(); | ||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | void nfs_fattr_init(struct nfs_fattr *fattr) | ||
929 | { | ||
930 | fattr->valid = 0; | ||
931 | fattr->time_start = jiffies; | ||
932 | fattr->gencount = nfs_inc_attr_generation_counter(); | ||
933 | } | ||
934 | |||
935 | /** | ||
936 | * nfs_inode_attrs_need_update - check if the inode attributes need updating | ||
937 | * @inode - pointer to inode | ||
938 | * @fattr - attributes | ||
939 | * | ||
940 | * Attempt to divine whether or not an RPC call reply carrying stale | ||
941 | * attributes got scheduled after another call carrying updated ones. | ||
942 | * | ||
943 | * To do so, the function first assumes that a more recent ctime means | ||
944 | * that the attributes in fattr are newer, however it also attempt to | ||
945 | * catch the case where ctime either didn't change, or went backwards | ||
946 | * (if someone reset the clock on the server) by looking at whether | ||
947 | * or not this RPC call was started after the inode was last updated. | ||
948 | * Note also the check for wraparound of 'attr_gencount' | ||
949 | * | ||
950 | * The function returns 'true' if it thinks the attributes in 'fattr' are | ||
951 | * more recent than the ones cached in the inode. | ||
952 | * | ||
953 | */ | ||
954 | static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr) | ||
955 | { | ||
956 | const struct nfs_inode *nfsi = NFS_I(inode); | ||
957 | |||
958 | return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 || | ||
959 | nfs_ctime_need_update(inode, fattr) || | ||
960 | nfs_size_need_update(inode, fattr) || | ||
961 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | ||
962 | } | ||
963 | |||
964 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | ||
965 | { | ||
966 | if (nfs_inode_attrs_need_update(inode, fattr)) | ||
967 | return nfs_update_inode(inode, fattr); | ||
968 | return nfs_check_inode_attributes(inode, fattr); | ||
969 | } | ||
970 | |||
951 | /** | 971 | /** |
952 | * nfs_refresh_inode - try to update the inode attribute cache | 972 | * nfs_refresh_inode - try to update the inode attribute cache |
953 | * @inode - pointer to inode | 973 | * @inode - pointer to inode |
@@ -960,21 +980,28 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat | |||
960 | */ | 980 | */ |
961 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | 981 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) |
962 | { | 982 | { |
963 | struct nfs_inode *nfsi = NFS_I(inode); | ||
964 | int status; | 983 | int status; |
965 | 984 | ||
966 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 985 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
967 | return 0; | 986 | return 0; |
968 | spin_lock(&inode->i_lock); | 987 | spin_lock(&inode->i_lock); |
969 | if (time_after(fattr->time_start, nfsi->last_updated)) | 988 | status = nfs_refresh_inode_locked(inode, fattr); |
970 | status = nfs_update_inode(inode, fattr); | ||
971 | else | ||
972 | status = nfs_check_inode_attributes(inode, fattr); | ||
973 | |||
974 | spin_unlock(&inode->i_lock); | 989 | spin_unlock(&inode->i_lock); |
975 | return status; | 990 | return status; |
976 | } | 991 | } |
977 | 992 | ||
993 | static int nfs_post_op_update_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | ||
994 | { | ||
995 | struct nfs_inode *nfsi = NFS_I(inode); | ||
996 | |||
997 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | ||
998 | if (S_ISDIR(inode->i_mode)) | ||
999 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
1000 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | ||
1001 | return 0; | ||
1002 | return nfs_refresh_inode_locked(inode, fattr); | ||
1003 | } | ||
1004 | |||
978 | /** | 1005 | /** |
979 | * nfs_post_op_update_inode - try to update the inode attribute cache | 1006 | * nfs_post_op_update_inode - try to update the inode attribute cache |
980 | * @inode - pointer to inode | 1007 | * @inode - pointer to inode |
@@ -991,14 +1018,12 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
991 | */ | 1018 | */ |
992 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1019 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
993 | { | 1020 | { |
994 | struct nfs_inode *nfsi = NFS_I(inode); | 1021 | int status; |
995 | 1022 | ||
996 | spin_lock(&inode->i_lock); | 1023 | spin_lock(&inode->i_lock); |
997 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE; | 1024 | status = nfs_post_op_update_inode_locked(inode, fattr); |
998 | if (S_ISDIR(inode->i_mode)) | ||
999 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | ||
1000 | spin_unlock(&inode->i_lock); | 1025 | spin_unlock(&inode->i_lock); |
1001 | return nfs_refresh_inode(inode, fattr); | 1026 | return status; |
1002 | } | 1027 | } |
1003 | 1028 | ||
1004 | /** | 1029 | /** |
@@ -1014,6 +1039,15 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1014 | */ | 1039 | */ |
1015 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) | 1040 | int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fattr) |
1016 | { | 1041 | { |
1042 | int status; | ||
1043 | |||
1044 | spin_lock(&inode->i_lock); | ||
1045 | /* Don't do a WCC update if these attributes are already stale */ | ||
1046 | if ((fattr->valid & NFS_ATTR_FATTR) == 0 || | ||
1047 | !nfs_inode_attrs_need_update(inode, fattr)) { | ||
1048 | fattr->valid &= ~(NFS_ATTR_WCC_V4|NFS_ATTR_WCC); | ||
1049 | goto out_noforce; | ||
1050 | } | ||
1017 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1051 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
1018 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { | 1052 | (fattr->valid & NFS_ATTR_WCC_V4) == 0) { |
1019 | fattr->pre_change_attr = NFS_I(inode)->change_attr; | 1053 | fattr->pre_change_attr = NFS_I(inode)->change_attr; |
@@ -1026,7 +1060,10 @@ int nfs_post_op_update_inode_force_wcc(struct inode *inode, struct nfs_fattr *fa | |||
1026 | fattr->pre_size = i_size_read(inode); | 1060 | fattr->pre_size = i_size_read(inode); |
1027 | fattr->valid |= NFS_ATTR_WCC; | 1061 | fattr->valid |= NFS_ATTR_WCC; |
1028 | } | 1062 | } |
1029 | return nfs_post_op_update_inode(inode, fattr); | 1063 | out_noforce: |
1064 | status = nfs_post_op_update_inode_locked(inode, fattr); | ||
1065 | spin_unlock(&inode->i_lock); | ||
1066 | return status; | ||
1030 | } | 1067 | } |
1031 | 1068 | ||
1032 | /* | 1069 | /* |
@@ -1092,7 +1129,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1092 | } | 1129 | } |
1093 | /* If ctime has changed we should definitely clear access+acl caches */ | 1130 | /* If ctime has changed we should definitely clear access+acl caches */ |
1094 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) | 1131 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) |
1095 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1132 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1096 | } else if (nfsi->change_attr != fattr->change_attr) { | 1133 | } else if (nfsi->change_attr != fattr->change_attr) { |
1097 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1134 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1098 | inode->i_sb->s_id, inode->i_ino); | 1135 | inode->i_sb->s_id, inode->i_ino); |
@@ -1126,6 +1163,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1126 | inode->i_gid != fattr->gid) | 1163 | inode->i_gid != fattr->gid) |
1127 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1164 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1128 | 1165 | ||
1166 | if (inode->i_nlink != fattr->nlink) | ||
1167 | invalid |= NFS_INO_INVALID_ATTR; | ||
1168 | |||
1129 | inode->i_mode = fattr->mode; | 1169 | inode->i_mode = fattr->mode; |
1130 | inode->i_nlink = fattr->nlink; | 1170 | inode->i_nlink = fattr->nlink; |
1131 | inode->i_uid = fattr->uid; | 1171 | inode->i_uid = fattr->uid; |
@@ -1145,18 +1185,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1145 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1185 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1146 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1186 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1147 | nfsi->attrtimeo_timestamp = now; | 1187 | nfsi->attrtimeo_timestamp = now; |
1148 | nfsi->last_updated = now; | 1188 | nfsi->attr_gencount = nfs_inc_attr_generation_counter(); |
1149 | } else { | 1189 | } else { |
1150 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { | 1190 | if (!time_in_range(now, nfsi->attrtimeo_timestamp, nfsi->attrtimeo_timestamp + nfsi->attrtimeo)) { |
1151 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1191 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
1152 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1192 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
1153 | nfsi->attrtimeo_timestamp = now; | 1193 | nfsi->attrtimeo_timestamp = now; |
1154 | } | 1194 | } |
1155 | /* | ||
1156 | * Avoid jiffy wraparound issues with nfsi->last_updated | ||
1157 | */ | ||
1158 | if (!time_in_range(nfsi->last_updated, nfsi->read_cache_jiffies, now)) | ||
1159 | nfsi->last_updated = nfsi->read_cache_jiffies; | ||
1160 | } | 1195 | } |
1161 | invalid &= ~NFS_INO_INVALID_ATTR; | 1196 | invalid &= ~NFS_INO_INVALID_ATTR; |
1162 | /* Don't invalidate the data if we were to blame */ | 1197 | /* Don't invalidate the data if we were to blame */ |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 24241fcbb98d..d212ee41caf2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -153,6 +153,7 @@ extern void nfs4_clear_inode(struct inode *); | |||
153 | void nfs_zap_acl_cache(struct inode *inode); | 153 | void nfs_zap_acl_cache(struct inode *inode); |
154 | 154 | ||
155 | /* super.c */ | 155 | /* super.c */ |
156 | void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *); | ||
156 | extern struct file_system_type nfs_xdev_fs_type; | 157 | extern struct file_system_type nfs_xdev_fs_type; |
157 | #ifdef CONFIG_NFS_V4 | 158 | #ifdef CONFIG_NFS_V4 |
158 | extern struct file_system_type nfs4_xdev_fs_type; | 159 | extern struct file_system_type nfs4_xdev_fs_type; |
@@ -163,8 +164,8 @@ extern struct rpc_stat nfs_rpcstat; | |||
163 | 164 | ||
164 | extern int __init register_nfs_fs(void); | 165 | extern int __init register_nfs_fs(void); |
165 | extern void __exit unregister_nfs_fs(void); | 166 | extern void __exit unregister_nfs_fs(void); |
166 | extern void nfs_sb_active(struct nfs_server *server); | 167 | extern void nfs_sb_active(struct super_block *sb); |
167 | extern void nfs_sb_deactive(struct nfs_server *server); | 168 | extern void nfs_sb_deactive(struct super_block *sb); |
168 | 169 | ||
169 | /* namespace.c */ | 170 | /* namespace.c */ |
170 | extern char *nfs_path(const char *base, | 171 | extern char *nfs_path(const char *base, |
@@ -276,3 +277,23 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len) | |||
276 | PAGE_SIZE - 1) >> PAGE_SHIFT; | 277 | PAGE_SIZE - 1) >> PAGE_SHIFT; |
277 | } | 278 | } |
278 | 279 | ||
280 | #define IPV6_SCOPE_DELIMITER '%' | ||
281 | |||
282 | /* | ||
283 | * Set the port number in an address. Be agnostic about the address | ||
284 | * family. | ||
285 | */ | ||
286 | static inline void nfs_set_port(struct sockaddr *sap, unsigned short port) | ||
287 | { | ||
288 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
289 | struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap; | ||
290 | |||
291 | switch (sap->sa_family) { | ||
292 | case AF_INET: | ||
293 | ap->sin_port = htons(port); | ||
294 | break; | ||
295 | case AF_INET6: | ||
296 | ap6->sin6_port = htons(port); | ||
297 | break; | ||
298 | } | ||
299 | } | ||
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 779d2eb649c5..086a6830d785 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
15 | #include <linux/sunrpc/sched.h> | 15 | #include <linux/sunrpc/sched.h> |
16 | #include <linux/nfs_fs.h> | 16 | #include <linux/nfs_fs.h> |
17 | #include "internal.h" | ||
17 | 18 | ||
18 | #ifdef RPC_DEBUG | 19 | #ifdef RPC_DEBUG |
19 | # define NFSDBG_FACILITY NFSDBG_MOUNT | 20 | # define NFSDBG_FACILITY NFSDBG_MOUNT |
@@ -98,7 +99,7 @@ out_call_err: | |||
98 | 99 | ||
99 | out_mnt_err: | 100 | out_mnt_err: |
100 | dprintk("NFS: MNT server returned result %d\n", result.status); | 101 | dprintk("NFS: MNT server returned result %d\n", result.status); |
101 | status = -EACCES; | 102 | status = nfs_stat_to_errno(result.status); |
102 | goto out; | 103 | goto out; |
103 | } | 104 | } |
104 | 105 | ||
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 66df08dd1caf..64a288ee046d 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -105,7 +105,10 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
105 | 105 | ||
106 | dprintk("--> nfs_follow_mountpoint()\n"); | 106 | dprintk("--> nfs_follow_mountpoint()\n"); |
107 | 107 | ||
108 | BUG_ON(IS_ROOT(dentry)); | 108 | err = -ESTALE; |
109 | if (IS_ROOT(dentry)) | ||
110 | goto out_err; | ||
111 | |||
109 | dprintk("%s: enter\n", __func__); | 112 | dprintk("%s: enter\n", __func__); |
110 | dput(nd->path.dentry); | 113 | dput(nd->path.dentry); |
111 | nd->path.dentry = dget(dentry); | 114 | nd->path.dentry = dget(dentry); |
@@ -189,7 +192,7 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, | |||
189 | struct nfs_clone_mount *mountdata) | 192 | struct nfs_clone_mount *mountdata) |
190 | { | 193 | { |
191 | #ifdef CONFIG_NFS_V4 | 194 | #ifdef CONFIG_NFS_V4 |
192 | struct vfsmount *mnt = NULL; | 195 | struct vfsmount *mnt = ERR_PTR(-EINVAL); |
193 | switch (server->nfs_client->rpc_ops->version) { | 196 | switch (server->nfs_client->rpc_ops->version) { |
194 | case 2: | 197 | case 2: |
195 | case 3: | 198 | case 3: |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 423842f51ac9..cef62557c87d 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -229,6 +229,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
229 | 229 | ||
230 | dprintk("NFS call getacl\n"); | 230 | dprintk("NFS call getacl\n"); |
231 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL]; | 231 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_GETACL]; |
232 | nfs_fattr_init(&fattr); | ||
232 | status = rpc_call_sync(server->client_acl, &msg, 0); | 233 | status = rpc_call_sync(server->client_acl, &msg, 0); |
233 | dprintk("NFS reply getacl: %d\n", status); | 234 | dprintk("NFS reply getacl: %d\n", status); |
234 | 235 | ||
@@ -322,6 +323,7 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
322 | 323 | ||
323 | dprintk("NFS call setacl\n"); | 324 | dprintk("NFS call setacl\n"); |
324 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; | 325 | msg.rpc_proc = &server->client_acl->cl_procinfo[ACLPROC3_SETACL]; |
326 | nfs_fattr_init(&fattr); | ||
325 | status = rpc_call_sync(server->client_acl, &msg, 0); | 327 | status = rpc_call_sync(server->client_acl, &msg, 0); |
326 | nfs_access_zap_cache(inode); | 328 | nfs_access_zap_cache(inode); |
327 | nfs_zap_acl_cache(inode); | 329 | nfs_zap_acl_cache(inode); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 1e750e4574a9..c55be7a7679e 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -699,7 +699,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
699 | } | 699 | } |
700 | 700 | ||
701 | static int | 701 | static int |
702 | nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | 702 | do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle, |
703 | struct nfs_fsinfo *info) | 703 | struct nfs_fsinfo *info) |
704 | { | 704 | { |
705 | struct rpc_message msg = { | 705 | struct rpc_message msg = { |
@@ -711,11 +711,27 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
711 | 711 | ||
712 | dprintk("NFS call fsinfo\n"); | 712 | dprintk("NFS call fsinfo\n"); |
713 | nfs_fattr_init(info->fattr); | 713 | nfs_fattr_init(info->fattr); |
714 | status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | 714 | status = rpc_call_sync(client, &msg, 0); |
715 | dprintk("NFS reply fsinfo: %d\n", status); | 715 | dprintk("NFS reply fsinfo: %d\n", status); |
716 | return status; | 716 | return status; |
717 | } | 717 | } |
718 | 718 | ||
719 | /* | ||
720 | * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via | ||
721 | * nfs_create_server | ||
722 | */ | ||
723 | static int | ||
724 | nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | ||
725 | struct nfs_fsinfo *info) | ||
726 | { | ||
727 | int status; | ||
728 | |||
729 | status = do_proc_fsinfo(server->client, fhandle, info); | ||
730 | if (status && server->nfs_client->cl_rpcclient != server->client) | ||
731 | status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info); | ||
732 | return status; | ||
733 | } | ||
734 | |||
719 | static int | 735 | static int |
720 | nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | 736 | nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
721 | struct nfs_pathconf *info) | 737 | struct nfs_pathconf *info) |
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index b112857301f7..30befc39b3c6 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -93,21 +93,52 @@ static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, | |||
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* | 96 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, |
97 | * Check if the string represents a "valid" IPv4 address | 97 | char *page, char *page2, |
98 | */ | 98 | const struct nfs4_fs_location *location) |
99 | static inline int valid_ipaddr4(const char *buf) | ||
100 | { | 99 | { |
101 | int rc, count, in[4]; | 100 | struct vfsmount *mnt = ERR_PTR(-ENOENT); |
102 | 101 | char *mnt_path; | |
103 | rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); | 102 | int page2len; |
104 | if (rc != 4) | 103 | unsigned int s; |
105 | return -EINVAL; | 104 | |
106 | for (count = 0; count < 4; count++) { | 105 | mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); |
107 | if (in[count] > 255) | 106 | if (IS_ERR(mnt_path)) |
108 | return -EINVAL; | 107 | return mnt; |
108 | mountdata->mnt_path = mnt_path; | ||
109 | page2 += strlen(mnt_path) + 1; | ||
110 | page2len = PAGE_SIZE - strlen(mnt_path) - 1; | ||
111 | |||
112 | for (s = 0; s < location->nservers; s++) { | ||
113 | const struct nfs4_string *buf = &location->servers[s]; | ||
114 | struct sockaddr_storage addr; | ||
115 | |||
116 | if (buf->len <= 0 || buf->len >= PAGE_SIZE) | ||
117 | continue; | ||
118 | |||
119 | mountdata->addr = (struct sockaddr *)&addr; | ||
120 | |||
121 | if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len)) | ||
122 | continue; | ||
123 | nfs_parse_ip_address(buf->data, buf->len, | ||
124 | mountdata->addr, &mountdata->addrlen); | ||
125 | if (mountdata->addr->sa_family == AF_UNSPEC) | ||
126 | continue; | ||
127 | nfs_set_port(mountdata->addr, NFS_PORT); | ||
128 | |||
129 | strncpy(page2, buf->data, page2len); | ||
130 | page2[page2len] = '\0'; | ||
131 | mountdata->hostname = page2; | ||
132 | |||
133 | snprintf(page, PAGE_SIZE, "%s:%s", | ||
134 | mountdata->hostname, | ||
135 | mountdata->mnt_path); | ||
136 | |||
137 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, mountdata); | ||
138 | if (!IS_ERR(mnt)) | ||
139 | break; | ||
109 | } | 140 | } |
110 | return 0; | 141 | return mnt; |
111 | } | 142 | } |
112 | 143 | ||
113 | /** | 144 | /** |
@@ -128,7 +159,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
128 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, | 159 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, |
129 | }; | 160 | }; |
130 | char *page = NULL, *page2 = NULL; | 161 | char *page = NULL, *page2 = NULL; |
131 | unsigned int s; | ||
132 | int loc, error; | 162 | int loc, error; |
133 | 163 | ||
134 | if (locations == NULL || locations->nlocations <= 0) | 164 | if (locations == NULL || locations->nlocations <= 0) |
@@ -152,53 +182,16 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
152 | goto out; | 182 | goto out; |
153 | } | 183 | } |
154 | 184 | ||
155 | loc = 0; | 185 | for (loc = 0; loc < locations->nlocations; loc++) { |
156 | while (loc < locations->nlocations && IS_ERR(mnt)) { | ||
157 | const struct nfs4_fs_location *location = &locations->locations[loc]; | 186 | const struct nfs4_fs_location *location = &locations->locations[loc]; |
158 | char *mnt_path; | ||
159 | 187 | ||
160 | if (location == NULL || location->nservers <= 0 || | 188 | if (location == NULL || location->nservers <= 0 || |
161 | location->rootpath.ncomponents == 0) { | 189 | location->rootpath.ncomponents == 0) |
162 | loc++; | ||
163 | continue; | 190 | continue; |
164 | } | ||
165 | 191 | ||
166 | mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); | 192 | mnt = try_location(&mountdata, page, page2, location); |
167 | if (IS_ERR(mnt_path)) { | 193 | if (!IS_ERR(mnt)) |
168 | loc++; | 194 | break; |
169 | continue; | ||
170 | } | ||
171 | mountdata.mnt_path = mnt_path; | ||
172 | |||
173 | s = 0; | ||
174 | while (s < location->nservers) { | ||
175 | struct sockaddr_in addr = { | ||
176 | .sin_family = AF_INET, | ||
177 | .sin_port = htons(NFS_PORT), | ||
178 | }; | ||
179 | |||
180 | if (location->servers[s].len <= 0 || | ||
181 | valid_ipaddr4(location->servers[s].data) < 0) { | ||
182 | s++; | ||
183 | continue; | ||
184 | } | ||
185 | |||
186 | mountdata.hostname = location->servers[s].data; | ||
187 | addr.sin_addr.s_addr = in_aton(mountdata.hostname), | ||
188 | mountdata.addr = (struct sockaddr *)&addr; | ||
189 | mountdata.addrlen = sizeof(addr); | ||
190 | |||
191 | snprintf(page, PAGE_SIZE, "%s:%s", | ||
192 | mountdata.hostname, | ||
193 | mountdata.mnt_path); | ||
194 | |||
195 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata); | ||
196 | if (!IS_ERR(mnt)) { | ||
197 | break; | ||
198 | } | ||
199 | s++; | ||
200 | } | ||
201 | loc++; | ||
202 | } | 195 | } |
203 | 196 | ||
204 | out: | 197 | out: |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 4dbb84df1b68..193465210d7c 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -65,14 +65,20 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
65 | 65 | ||
66 | dprintk("%s: call getattr\n", __func__); | 66 | dprintk("%s: call getattr\n", __func__); |
67 | nfs_fattr_init(fattr); | 67 | nfs_fattr_init(fattr); |
68 | status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | 68 | status = rpc_call_sync(server->client, &msg, 0); |
69 | /* Retry with default authentication if different */ | ||
70 | if (status && server->nfs_client->cl_rpcclient != server->client) | ||
71 | status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | ||
69 | dprintk("%s: reply getattr: %d\n", __func__, status); | 72 | dprintk("%s: reply getattr: %d\n", __func__, status); |
70 | if (status) | 73 | if (status) |
71 | return status; | 74 | return status; |
72 | dprintk("%s: call statfs\n", __func__); | 75 | dprintk("%s: call statfs\n", __func__); |
73 | msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; | 76 | msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; |
74 | msg.rpc_resp = &fsinfo; | 77 | msg.rpc_resp = &fsinfo; |
75 | status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | 78 | status = rpc_call_sync(server->client, &msg, 0); |
79 | /* Retry with default authentication if different */ | ||
80 | if (status && server->nfs_client->cl_rpcclient != server->client) | ||
81 | status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); | ||
76 | dprintk("%s: reply statfs: %d\n", __func__, status); | 82 | dprintk("%s: reply statfs: %d\n", __func__, status); |
77 | if (status) | 83 | if (status) |
78 | return status; | 84 | return status; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ffb697416cb1..8b28b95c9e44 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -91,6 +91,7 @@ enum { | |||
91 | /* Mount options that take string arguments */ | 91 | /* Mount options that take string arguments */ |
92 | Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, | 92 | Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost, |
93 | Opt_addr, Opt_mountaddr, Opt_clientaddr, | 93 | Opt_addr, Opt_mountaddr, Opt_clientaddr, |
94 | Opt_lookupcache, | ||
94 | 95 | ||
95 | /* Special mount options */ | 96 | /* Special mount options */ |
96 | Opt_userspace, Opt_deprecated, Opt_sloppy, | 97 | Opt_userspace, Opt_deprecated, Opt_sloppy, |
@@ -154,6 +155,8 @@ static const match_table_t nfs_mount_option_tokens = { | |||
154 | { Opt_mounthost, "mounthost=%s" }, | 155 | { Opt_mounthost, "mounthost=%s" }, |
155 | { Opt_mountaddr, "mountaddr=%s" }, | 156 | { Opt_mountaddr, "mountaddr=%s" }, |
156 | 157 | ||
158 | { Opt_lookupcache, "lookupcache=%s" }, | ||
159 | |||
157 | { Opt_err, NULL } | 160 | { Opt_err, NULL } |
158 | }; | 161 | }; |
159 | 162 | ||
@@ -200,6 +203,22 @@ static const match_table_t nfs_secflavor_tokens = { | |||
200 | { Opt_sec_err, NULL } | 203 | { Opt_sec_err, NULL } |
201 | }; | 204 | }; |
202 | 205 | ||
206 | enum { | ||
207 | Opt_lookupcache_all, Opt_lookupcache_positive, | ||
208 | Opt_lookupcache_none, | ||
209 | |||
210 | Opt_lookupcache_err | ||
211 | }; | ||
212 | |||
213 | static match_table_t nfs_lookupcache_tokens = { | ||
214 | { Opt_lookupcache_all, "all" }, | ||
215 | { Opt_lookupcache_positive, "pos" }, | ||
216 | { Opt_lookupcache_positive, "positive" }, | ||
217 | { Opt_lookupcache_none, "none" }, | ||
218 | |||
219 | { Opt_lookupcache_err, NULL } | ||
220 | }; | ||
221 | |||
203 | 222 | ||
204 | static void nfs_umount_begin(struct super_block *); | 223 | static void nfs_umount_begin(struct super_block *); |
205 | static int nfs_statfs(struct dentry *, struct kstatfs *); | 224 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
@@ -209,7 +228,6 @@ static int nfs_get_sb(struct file_system_type *, int, const char *, void *, stru | |||
209 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, | 228 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, |
210 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 229 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
211 | static void nfs_kill_super(struct super_block *); | 230 | static void nfs_kill_super(struct super_block *); |
212 | static void nfs_put_super(struct super_block *); | ||
213 | static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | 231 | static int nfs_remount(struct super_block *sb, int *flags, char *raw_data); |
214 | 232 | ||
215 | static struct file_system_type nfs_fs_type = { | 233 | static struct file_system_type nfs_fs_type = { |
@@ -232,7 +250,6 @@ static const struct super_operations nfs_sops = { | |||
232 | .alloc_inode = nfs_alloc_inode, | 250 | .alloc_inode = nfs_alloc_inode, |
233 | .destroy_inode = nfs_destroy_inode, | 251 | .destroy_inode = nfs_destroy_inode, |
234 | .write_inode = nfs_write_inode, | 252 | .write_inode = nfs_write_inode, |
235 | .put_super = nfs_put_super, | ||
236 | .statfs = nfs_statfs, | 253 | .statfs = nfs_statfs, |
237 | .clear_inode = nfs_clear_inode, | 254 | .clear_inode = nfs_clear_inode, |
238 | .umount_begin = nfs_umount_begin, | 255 | .umount_begin = nfs_umount_begin, |
@@ -337,26 +354,20 @@ void __exit unregister_nfs_fs(void) | |||
337 | unregister_filesystem(&nfs_fs_type); | 354 | unregister_filesystem(&nfs_fs_type); |
338 | } | 355 | } |
339 | 356 | ||
340 | void nfs_sb_active(struct nfs_server *server) | 357 | void nfs_sb_active(struct super_block *sb) |
341 | { | 358 | { |
342 | atomic_inc(&server->active); | 359 | struct nfs_server *server = NFS_SB(sb); |
343 | } | ||
344 | 360 | ||
345 | void nfs_sb_deactive(struct nfs_server *server) | 361 | if (atomic_inc_return(&server->active) == 1) |
346 | { | 362 | atomic_inc(&sb->s_active); |
347 | if (atomic_dec_and_test(&server->active)) | ||
348 | wake_up(&server->active_wq); | ||
349 | } | 363 | } |
350 | 364 | ||
351 | static void nfs_put_super(struct super_block *sb) | 365 | void nfs_sb_deactive(struct super_block *sb) |
352 | { | 366 | { |
353 | struct nfs_server *server = NFS_SB(sb); | 367 | struct nfs_server *server = NFS_SB(sb); |
354 | /* | 368 | |
355 | * Make sure there are no outstanding ops to this server. | 369 | if (atomic_dec_and_test(&server->active)) |
356 | * If so, wait for them to finish before allowing the | 370 | deactivate_super(sb); |
357 | * unmount to continue. | ||
358 | */ | ||
359 | wait_event(server->active_wq, atomic_read(&server->active) == 0); | ||
360 | } | 371 | } |
361 | 372 | ||
362 | /* | 373 | /* |
@@ -664,25 +675,6 @@ static void nfs_umount_begin(struct super_block *sb) | |||
664 | } | 675 | } |
665 | 676 | ||
666 | /* | 677 | /* |
667 | * Set the port number in an address. Be agnostic about the address family. | ||
668 | */ | ||
669 | static void nfs_set_port(struct sockaddr *sap, unsigned short port) | ||
670 | { | ||
671 | switch (sap->sa_family) { | ||
672 | case AF_INET: { | ||
673 | struct sockaddr_in *ap = (struct sockaddr_in *)sap; | ||
674 | ap->sin_port = htons(port); | ||
675 | break; | ||
676 | } | ||
677 | case AF_INET6: { | ||
678 | struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; | ||
679 | ap->sin6_port = htons(port); | ||
680 | break; | ||
681 | } | ||
682 | } | ||
683 | } | ||
684 | |||
685 | /* | ||
686 | * Sanity-check a server address provided by the mount command. | 678 | * Sanity-check a server address provided by the mount command. |
687 | * | 679 | * |
688 | * Address family must be initialized, and address must not be | 680 | * Address family must be initialized, and address must not be |
@@ -724,20 +716,22 @@ static void nfs_parse_ipv4_address(char *string, size_t str_len, | |||
724 | *addr_len = 0; | 716 | *addr_len = 0; |
725 | } | 717 | } |
726 | 718 | ||
727 | #define IPV6_SCOPE_DELIMITER '%' | ||
728 | |||
729 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 719 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
730 | static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, | 720 | static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, |
731 | const char *delim, | 721 | const char *delim, |
732 | struct sockaddr_in6 *sin6) | 722 | struct sockaddr_in6 *sin6) |
733 | { | 723 | { |
734 | char *p; | 724 | char *p; |
735 | size_t len; | 725 | size_t len; |
736 | 726 | ||
737 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) | 727 | if ((string + str_len) == delim) |
738 | return ; | 728 | return 1; |
729 | |||
739 | if (*delim != IPV6_SCOPE_DELIMITER) | 730 | if (*delim != IPV6_SCOPE_DELIMITER) |
740 | return; | 731 | return 0; |
732 | |||
733 | if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)) | ||
734 | return 0; | ||
741 | 735 | ||
742 | len = (string + str_len) - delim - 1; | 736 | len = (string + str_len) - delim - 1; |
743 | p = kstrndup(delim + 1, len, GFP_KERNEL); | 737 | p = kstrndup(delim + 1, len, GFP_KERNEL); |
@@ -750,14 +744,20 @@ static void nfs_parse_ipv6_scope_id(const char *string, const size_t str_len, | |||
750 | scope_id = dev->ifindex; | 744 | scope_id = dev->ifindex; |
751 | dev_put(dev); | 745 | dev_put(dev); |
752 | } else { | 746 | } else { |
753 | /* scope_id is set to zero on error */ | 747 | if (strict_strtoul(p, 10, &scope_id) == 0) { |
754 | strict_strtoul(p, 10, &scope_id); | 748 | kfree(p); |
749 | return 0; | ||
750 | } | ||
755 | } | 751 | } |
756 | 752 | ||
757 | kfree(p); | 753 | kfree(p); |
754 | |||
758 | sin6->sin6_scope_id = scope_id; | 755 | sin6->sin6_scope_id = scope_id; |
759 | dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id); | 756 | dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id); |
757 | return 1; | ||
760 | } | 758 | } |
759 | |||
760 | return 0; | ||
761 | } | 761 | } |
762 | 762 | ||
763 | static void nfs_parse_ipv6_address(char *string, size_t str_len, | 763 | static void nfs_parse_ipv6_address(char *string, size_t str_len, |
@@ -773,9 +773,11 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len, | |||
773 | 773 | ||
774 | sin6->sin6_family = AF_INET6; | 774 | sin6->sin6_family = AF_INET6; |
775 | *addr_len = sizeof(*sin6); | 775 | *addr_len = sizeof(*sin6); |
776 | if (in6_pton(string, str_len, addr, IPV6_SCOPE_DELIMITER, &delim)) { | 776 | if (in6_pton(string, str_len, addr, |
777 | nfs_parse_ipv6_scope_id(string, str_len, delim, sin6); | 777 | IPV6_SCOPE_DELIMITER, &delim) != 0) { |
778 | return; | 778 | if (nfs_parse_ipv6_scope_id(string, str_len, |
779 | delim, sin6) != 0) | ||
780 | return; | ||
779 | } | 781 | } |
780 | } | 782 | } |
781 | 783 | ||
@@ -798,7 +800,7 @@ static void nfs_parse_ipv6_address(char *string, size_t str_len, | |||
798 | * If there is a problem constructing the new sockaddr, set the address | 800 | * If there is a problem constructing the new sockaddr, set the address |
799 | * family to AF_UNSPEC. | 801 | * family to AF_UNSPEC. |
800 | */ | 802 | */ |
801 | static void nfs_parse_ip_address(char *string, size_t str_len, | 803 | void nfs_parse_ip_address(char *string, size_t str_len, |
802 | struct sockaddr *sap, size_t *addr_len) | 804 | struct sockaddr *sap, size_t *addr_len) |
803 | { | 805 | { |
804 | unsigned int i, colons; | 806 | unsigned int i, colons; |
@@ -1258,6 +1260,30 @@ static int nfs_parse_mount_options(char *raw, | |||
1258 | &mnt->mount_server.addrlen); | 1260 | &mnt->mount_server.addrlen); |
1259 | kfree(string); | 1261 | kfree(string); |
1260 | break; | 1262 | break; |
1263 | case Opt_lookupcache: | ||
1264 | string = match_strdup(args); | ||
1265 | if (string == NULL) | ||
1266 | goto out_nomem; | ||
1267 | token = match_token(string, | ||
1268 | nfs_lookupcache_tokens, args); | ||
1269 | kfree(string); | ||
1270 | switch (token) { | ||
1271 | case Opt_lookupcache_all: | ||
1272 | mnt->flags &= ~(NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE); | ||
1273 | break; | ||
1274 | case Opt_lookupcache_positive: | ||
1275 | mnt->flags &= ~NFS_MOUNT_LOOKUP_CACHE_NONE; | ||
1276 | mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG; | ||
1277 | break; | ||
1278 | case Opt_lookupcache_none: | ||
1279 | mnt->flags |= NFS_MOUNT_LOOKUP_CACHE_NONEG|NFS_MOUNT_LOOKUP_CACHE_NONE; | ||
1280 | break; | ||
1281 | default: | ||
1282 | errors++; | ||
1283 | dfprintk(MOUNT, "NFS: invalid " | ||
1284 | "lookupcache argument\n"); | ||
1285 | }; | ||
1286 | break; | ||
1261 | 1287 | ||
1262 | /* | 1288 | /* |
1263 | * Special options | 1289 | * Special options |
@@ -1558,7 +1584,7 @@ static int nfs_validate_mount_data(void *options, | |||
1558 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | 1584 | * Translate to nfs_parsed_mount_data, which nfs_fill_super |
1559 | * can deal with. | 1585 | * can deal with. |
1560 | */ | 1586 | */ |
1561 | args->flags = data->flags; | 1587 | args->flags = data->flags & NFS_MOUNT_FLAGMASK; |
1562 | args->rsize = data->rsize; | 1588 | args->rsize = data->rsize; |
1563 | args->wsize = data->wsize; | 1589 | args->wsize = data->wsize; |
1564 | args->timeo = data->timeo; | 1590 | args->timeo = data->timeo; |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index f089e5839d7d..ecc295347775 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -99,7 +99,7 @@ static void nfs_async_unlink_release(void *calldata) | |||
99 | 99 | ||
100 | nfs_dec_sillycount(data->dir); | 100 | nfs_dec_sillycount(data->dir); |
101 | nfs_free_unlinkdata(data); | 101 | nfs_free_unlinkdata(data); |
102 | nfs_sb_deactive(NFS_SB(sb)); | 102 | nfs_sb_deactive(sb); |
103 | } | 103 | } |
104 | 104 | ||
105 | static const struct rpc_call_ops nfs_unlink_ops = { | 105 | static const struct rpc_call_ops nfs_unlink_ops = { |
@@ -118,6 +118,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
118 | .rpc_message = &msg, | 118 | .rpc_message = &msg, |
119 | .callback_ops = &nfs_unlink_ops, | 119 | .callback_ops = &nfs_unlink_ops, |
120 | .callback_data = data, | 120 | .callback_data = data, |
121 | .workqueue = nfsiod_workqueue, | ||
121 | .flags = RPC_TASK_ASYNC, | 122 | .flags = RPC_TASK_ASYNC, |
122 | }; | 123 | }; |
123 | struct rpc_task *task; | 124 | struct rpc_task *task; |
@@ -149,7 +150,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n | |||
149 | nfs_dec_sillycount(dir); | 150 | nfs_dec_sillycount(dir); |
150 | return 0; | 151 | return 0; |
151 | } | 152 | } |
152 | nfs_sb_active(NFS_SERVER(dir)); | 153 | nfs_sb_active(dir->i_sb); |
153 | data->args.fh = NFS_FH(dir); | 154 | data->args.fh = NFS_FH(dir); |
154 | nfs_fattr_init(&data->res.dir_attr); | 155 | nfs_fattr_init(&data->res.dir_attr); |
155 | 156 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 3229e217c773..9f9845859fc1 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1427,8 +1427,9 @@ static int nfs_write_mapping(struct address_space *mapping, int how) | |||
1427 | .bdi = mapping->backing_dev_info, | 1427 | .bdi = mapping->backing_dev_info, |
1428 | .sync_mode = WB_SYNC_NONE, | 1428 | .sync_mode = WB_SYNC_NONE, |
1429 | .nr_to_write = LONG_MAX, | 1429 | .nr_to_write = LONG_MAX, |
1430 | .range_start = 0, | ||
1431 | .range_end = LLONG_MAX, | ||
1430 | .for_writepages = 1, | 1432 | .for_writepages = 1, |
1431 | .range_cyclic = 1, | ||
1432 | }; | 1433 | }; |
1433 | int ret; | 1434 | int ret; |
1434 | 1435 | ||