diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/delegation.c | 6 | ||||
-rw-r--r-- | fs/nfs/direct.c | 36 | ||||
-rw-r--r-- | fs/nfs/file.c | 19 | ||||
-rw-r--r-- | fs/nfs/mount_clnt.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 9 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 16 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 8 |
7 files changed, 58 insertions, 40 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index b9c3c43cea1d..98e8e35c4408 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -24,8 +24,6 @@ | |||
24 | 24 | ||
25 | static void nfs_do_free_delegation(struct nfs_delegation *delegation) | 25 | static void nfs_do_free_delegation(struct nfs_delegation *delegation) |
26 | { | 26 | { |
27 | if (delegation->cred) | ||
28 | put_rpccred(delegation->cred); | ||
29 | kfree(delegation); | 27 | kfree(delegation); |
30 | } | 28 | } |
31 | 29 | ||
@@ -38,6 +36,10 @@ static void nfs_free_delegation_callback(struct rcu_head *head) | |||
38 | 36 | ||
39 | static void nfs_free_delegation(struct nfs_delegation *delegation) | 37 | static void nfs_free_delegation(struct nfs_delegation *delegation) |
40 | { | 38 | { |
39 | if (delegation->cred) { | ||
40 | put_rpccred(delegation->cred); | ||
41 | delegation->cred = NULL; | ||
42 | } | ||
41 | call_rcu(&delegation->rcu, nfs_free_delegation_callback); | 43 | call_rcu(&delegation->rcu, nfs_free_delegation_callback); |
42 | } | 44 | } |
43 | 45 | ||
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 064a80961677..e0e9d49773bd 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -407,15 +407,18 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
407 | pos += vec->iov_len; | 407 | pos += vec->iov_len; |
408 | } | 408 | } |
409 | 409 | ||
410 | /* | ||
411 | * If no bytes were started, return the error, and let the | ||
412 | * generic layer handle the completion. | ||
413 | */ | ||
414 | if (requested_bytes == 0) { | ||
415 | nfs_direct_req_release(dreq); | ||
416 | return result < 0 ? result : -EIO; | ||
417 | } | ||
418 | |||
410 | if (put_dreq(dreq)) | 419 | if (put_dreq(dreq)) |
411 | nfs_direct_complete(dreq); | 420 | nfs_direct_complete(dreq); |
412 | 421 | return 0; | |
413 | if (requested_bytes != 0) | ||
414 | return 0; | ||
415 | |||
416 | if (result < 0) | ||
417 | return result; | ||
418 | return -EIO; | ||
419 | } | 422 | } |
420 | 423 | ||
421 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | 424 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
@@ -841,15 +844,18 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
841 | pos += vec->iov_len; | 844 | pos += vec->iov_len; |
842 | } | 845 | } |
843 | 846 | ||
847 | /* | ||
848 | * If no bytes were started, return the error, and let the | ||
849 | * generic layer handle the completion. | ||
850 | */ | ||
851 | if (requested_bytes == 0) { | ||
852 | nfs_direct_req_release(dreq); | ||
853 | return result < 0 ? result : -EIO; | ||
854 | } | ||
855 | |||
844 | if (put_dreq(dreq)) | 856 | if (put_dreq(dreq)) |
845 | nfs_direct_write_complete(dreq, dreq->inode); | 857 | nfs_direct_write_complete(dreq, dreq->inode); |
846 | 858 | return 0; | |
847 | if (requested_bytes != 0) | ||
848 | return 0; | ||
849 | |||
850 | if (result < 0) | ||
851 | return result; | ||
852 | return -EIO; | ||
853 | } | 859 | } |
854 | 860 | ||
855 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | 861 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, |
@@ -873,7 +879,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
873 | dreq->inode = inode; | 879 | dreq->inode = inode; |
874 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 880 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
875 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | 881 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); |
876 | if (dreq->l_ctx != NULL) | 882 | if (dreq->l_ctx == NULL) |
877 | goto out_release; | 883 | goto out_release; |
878 | if (!is_sync_kiocb(iocb)) | 884 | if (!is_sync_kiocb(iocb)) |
879 | dreq->iocb = iocb; | 885 | dreq->iocb = iocb; |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 05bf3c0dc751..22a185b328ef 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -551,7 +551,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
551 | struct file *filp = vma->vm_file; | 551 | struct file *filp = vma->vm_file; |
552 | struct dentry *dentry = filp->f_path.dentry; | 552 | struct dentry *dentry = filp->f_path.dentry; |
553 | unsigned pagelen; | 553 | unsigned pagelen; |
554 | int ret = -EINVAL; | 554 | int ret = VM_FAULT_NOPAGE; |
555 | struct address_space *mapping; | 555 | struct address_space *mapping; |
556 | 556 | ||
557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", | 557 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", |
@@ -567,21 +567,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
567 | if (mapping != dentry->d_inode->i_mapping) | 567 | if (mapping != dentry->d_inode->i_mapping) |
568 | goto out_unlock; | 568 | goto out_unlock; |
569 | 569 | ||
570 | ret = 0; | ||
571 | pagelen = nfs_page_length(page); | 570 | pagelen = nfs_page_length(page); |
572 | if (pagelen == 0) | 571 | if (pagelen == 0) |
573 | goto out_unlock; | 572 | goto out_unlock; |
574 | 573 | ||
575 | ret = nfs_flush_incompatible(filp, page); | 574 | ret = VM_FAULT_LOCKED; |
576 | if (ret != 0) | 575 | if (nfs_flush_incompatible(filp, page) == 0 && |
577 | goto out_unlock; | 576 | nfs_updatepage(filp, page, 0, pagelen) == 0) |
577 | goto out; | ||
578 | 578 | ||
579 | ret = nfs_updatepage(filp, page, 0, pagelen); | 579 | ret = VM_FAULT_SIGBUS; |
580 | out_unlock: | 580 | out_unlock: |
581 | if (!ret) | ||
582 | return VM_FAULT_LOCKED; | ||
583 | unlock_page(page); | 581 | unlock_page(page); |
584 | return VM_FAULT_SIGBUS; | 582 | out: |
583 | return ret; | ||
585 | } | 584 | } |
586 | 585 | ||
587 | static const struct vm_operations_struct nfs_file_vm_ops = { | 586 | static const struct vm_operations_struct nfs_file_vm_ops = { |
@@ -688,6 +687,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
688 | { | 687 | { |
689 | struct inode *inode = filp->f_mapping->host; | 688 | struct inode *inode = filp->f_mapping->host; |
690 | int status = 0; | 689 | int status = 0; |
690 | unsigned int saved_type = fl->fl_type; | ||
691 | 691 | ||
692 | /* Try local locking first */ | 692 | /* Try local locking first */ |
693 | posix_test_lock(filp, fl); | 693 | posix_test_lock(filp, fl); |
@@ -695,6 +695,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | |||
695 | /* found a conflict */ | 695 | /* found a conflict */ |
696 | goto out; | 696 | goto out; |
697 | } | 697 | } |
698 | fl->fl_type = saved_type; | ||
698 | 699 | ||
699 | if (nfs_have_delegation(inode, FMODE_READ)) | 700 | if (nfs_have_delegation(inode, FMODE_READ)) |
700 | goto out_noconflict; | 701 | goto out_noconflict; |
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 59047f8d7d72..3dde50c093b5 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c | |||
@@ -503,13 +503,13 @@ static struct rpc_procinfo mnt3_procedures[] = { | |||
503 | 503 | ||
504 | static struct rpc_version mnt_version1 = { | 504 | static struct rpc_version mnt_version1 = { |
505 | .number = 1, | 505 | .number = 1, |
506 | .nrprocs = 2, | 506 | .nrprocs = ARRAY_SIZE(mnt_procedures), |
507 | .procs = mnt_procedures, | 507 | .procs = mnt_procedures, |
508 | }; | 508 | }; |
509 | 509 | ||
510 | static struct rpc_version mnt_version3 = { | 510 | static struct rpc_version mnt_version3 = { |
511 | .number = 3, | 511 | .number = 3, |
512 | .nrprocs = 2, | 512 | .nrprocs = ARRAY_SIZE(mnt3_procedures), |
513 | .procs = mnt3_procedures, | 513 | .procs = mnt3_procedures, |
514 | }; | 514 | }; |
515 | 515 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 089da5b5d20a..74aa54e1712e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -255,9 +255,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
255 | nfs4_state_mark_reclaim_nograce(clp, state); | 255 | nfs4_state_mark_reclaim_nograce(clp, state); |
256 | goto do_state_recovery; | 256 | goto do_state_recovery; |
257 | case -NFS4ERR_STALE_STATEID: | 257 | case -NFS4ERR_STALE_STATEID: |
258 | if (state == NULL) | ||
259 | break; | ||
260 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
261 | case -NFS4ERR_STALE_CLIENTID: | 258 | case -NFS4ERR_STALE_CLIENTID: |
262 | case -NFS4ERR_EXPIRED: | 259 | case -NFS4ERR_EXPIRED: |
263 | goto do_state_recovery; | 260 | goto do_state_recovery; |
@@ -1120,6 +1117,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1120 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 1117 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
1121 | smp_rmb(); | 1118 | smp_rmb(); |
1122 | if (state->n_rdwr != 0) { | 1119 | if (state->n_rdwr != 0) { |
1120 | clear_bit(NFS_O_RDWR_STATE, &state->flags); | ||
1123 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); | 1121 | ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate); |
1124 | if (ret != 0) | 1122 | if (ret != 0) |
1125 | return ret; | 1123 | return ret; |
@@ -1127,6 +1125,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1127 | return -ESTALE; | 1125 | return -ESTALE; |
1128 | } | 1126 | } |
1129 | if (state->n_wronly != 0) { | 1127 | if (state->n_wronly != 0) { |
1128 | clear_bit(NFS_O_WRONLY_STATE, &state->flags); | ||
1130 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); | 1129 | ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate); |
1131 | if (ret != 0) | 1130 | if (ret != 0) |
1132 | return ret; | 1131 | return ret; |
@@ -1134,6 +1133,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state * | |||
1134 | return -ESTALE; | 1133 | return -ESTALE; |
1135 | } | 1134 | } |
1136 | if (state->n_rdonly != 0) { | 1135 | if (state->n_rdonly != 0) { |
1136 | clear_bit(NFS_O_RDONLY_STATE, &state->flags); | ||
1137 | ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); | 1137 | ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate); |
1138 | if (ret != 0) | 1138 | if (ret != 0) |
1139 | return ret; | 1139 | return ret; |
@@ -3490,9 +3490,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3490 | nfs4_state_mark_reclaim_nograce(clp, state); | 3490 | nfs4_state_mark_reclaim_nograce(clp, state); |
3491 | goto do_state_recovery; | 3491 | goto do_state_recovery; |
3492 | case -NFS4ERR_STALE_STATEID: | 3492 | case -NFS4ERR_STALE_STATEID: |
3493 | if (state == NULL) | ||
3494 | break; | ||
3495 | nfs4_state_mark_reclaim_reboot(clp, state); | ||
3496 | case -NFS4ERR_STALE_CLIENTID: | 3493 | case -NFS4ERR_STALE_CLIENTID: |
3497 | case -NFS4ERR_EXPIRED: | 3494 | case -NFS4ERR_EXPIRED: |
3498 | goto do_state_recovery; | 3495 | goto do_state_recovery; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 3e2f19b04c06..940cf7c070af 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1138,16 +1138,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp, | |||
1138 | (void)ops->reclaim_complete(clp); | 1138 | (void)ops->reclaim_complete(clp); |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | 1141 | static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp) |
1142 | { | 1142 | { |
1143 | struct nfs4_state_owner *sp; | 1143 | struct nfs4_state_owner *sp; |
1144 | struct rb_node *pos; | 1144 | struct rb_node *pos; |
1145 | struct nfs4_state *state; | 1145 | struct nfs4_state *state; |
1146 | 1146 | ||
1147 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1147 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
1148 | return; | 1148 | return 0; |
1149 | |||
1150 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | ||
1151 | 1149 | ||
1152 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { | 1150 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { |
1153 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); | 1151 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); |
@@ -1161,6 +1159,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | |||
1161 | } | 1159 | } |
1162 | 1160 | ||
1163 | nfs_delegation_reap_unclaimed(clp); | 1161 | nfs_delegation_reap_unclaimed(clp); |
1162 | return 1; | ||
1163 | } | ||
1164 | |||
1165 | static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | ||
1166 | { | ||
1167 | if (!nfs4_state_clear_reclaim_reboot(clp)) | ||
1168 | return; | ||
1169 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); | ||
1164 | } | 1170 | } |
1165 | 1171 | ||
1166 | static void nfs_delegation_clear_all(struct nfs_client *clp) | 1172 | static void nfs_delegation_clear_all(struct nfs_client *clp) |
@@ -1187,7 +1193,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) | |||
1187 | case -NFS4ERR_STALE_CLIENTID: | 1193 | case -NFS4ERR_STALE_CLIENTID: |
1188 | case -NFS4ERR_LEASE_MOVED: | 1194 | case -NFS4ERR_LEASE_MOVED: |
1189 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 1195 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
1190 | nfs4_state_end_reclaim_reboot(clp); | 1196 | nfs4_state_clear_reclaim_reboot(clp); |
1191 | nfs4_state_start_reclaim_reboot(clp); | 1197 | nfs4_state_start_reclaim_reboot(clp); |
1192 | break; | 1198 | break; |
1193 | case -NFS4ERR_EXPIRED: | 1199 | case -NFS4ERR_EXPIRED: |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 919490232e17..137b549e63db 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -65,6 +65,13 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
65 | if (req == NULL) | 65 | if (req == NULL) |
66 | return ERR_PTR(-ENOMEM); | 66 | return ERR_PTR(-ENOMEM); |
67 | 67 | ||
68 | /* get lock context early so we can deal with alloc failures */ | ||
69 | req->wb_lock_context = nfs_get_lock_context(ctx); | ||
70 | if (req->wb_lock_context == NULL) { | ||
71 | nfs_page_free(req); | ||
72 | return ERR_PTR(-ENOMEM); | ||
73 | } | ||
74 | |||
68 | /* Initialize the request struct. Initially, we assume a | 75 | /* Initialize the request struct. Initially, we assume a |
69 | * long write-back delay. This will be adjusted in | 76 | * long write-back delay. This will be adjusted in |
70 | * update_nfs_request below if the region is not locked. */ | 77 | * update_nfs_request below if the region is not locked. */ |
@@ -79,7 +86,6 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
79 | req->wb_pgbase = offset; | 86 | req->wb_pgbase = offset; |
80 | req->wb_bytes = count; | 87 | req->wb_bytes = count; |
81 | req->wb_context = get_nfs_open_context(ctx); | 88 | req->wb_context = get_nfs_open_context(ctx); |
82 | req->wb_lock_context = nfs_get_lock_context(ctx); | ||
83 | kref_init(&req->wb_kref); | 89 | kref_init(&req->wb_kref); |
84 | return req; | 90 | return req; |
85 | } | 91 | } |