aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback_proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r--fs/nfs/callback_proc.c52
1 files changed, 45 insertions, 7 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 807eb6ef4f91..f0939d097406 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -83,8 +83,11 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
83 83
84 res = htonl(NFS4ERR_BADHANDLE); 84 res = htonl(NFS4ERR_BADHANDLE);
85 inode = nfs_delegation_find_inode(cps->clp, &args->fh); 85 inode = nfs_delegation_find_inode(cps->clp, &args->fh);
86 if (inode == NULL) 86 if (inode == NULL) {
87 trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
88 &args->stateid, -ntohl(res));
87 goto out; 89 goto out;
90 }
88 /* Set up a helper thread to actually return the delegation */ 91 /* Set up a helper thread to actually return the delegation */
89 switch (nfs_async_inode_return_delegation(inode, &args->stateid)) { 92 switch (nfs_async_inode_return_delegation(inode, &args->stateid)) {
90 case 0: 93 case 0:
@@ -96,7 +99,8 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy,
96 default: 99 default:
97 res = htonl(NFS4ERR_RESOURCE); 100 res = htonl(NFS4ERR_RESOURCE);
98 } 101 }
99 trace_nfs4_recall_delegation(inode, -ntohl(res)); 102 trace_nfs4_cb_recall(cps->clp, &args->fh, inode,
103 &args->stateid, -ntohl(res));
100 iput(inode); 104 iput(inode);
101out: 105out:
102 dprintk("%s: exit with status = %d\n", __func__, ntohl(res)); 106 dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
@@ -160,6 +164,22 @@ static struct pnfs_layout_hdr * get_layout_by_fh(struct nfs_client *clp,
160 return lo; 164 return lo;
161} 165}
162 166
167/*
168 * Enforce RFC5661 section 12.5.5.2.1. (Layout Recall and Return Sequencing)
169 */
170static bool pnfs_check_stateid_sequence(struct pnfs_layout_hdr *lo,
171 const nfs4_stateid *new)
172{
173 u32 oldseq, newseq;
174
175 oldseq = be32_to_cpu(lo->plh_stateid.seqid);
176 newseq = be32_to_cpu(new->seqid);
177
178 if (newseq > oldseq + 1)
179 return false;
180 return true;
181}
182
163static u32 initiate_file_draining(struct nfs_client *clp, 183static u32 initiate_file_draining(struct nfs_client *clp,
164 struct cb_layoutrecallargs *args) 184 struct cb_layoutrecallargs *args)
165{ 185{
@@ -169,34 +189,52 @@ static u32 initiate_file_draining(struct nfs_client *clp,
169 LIST_HEAD(free_me_list); 189 LIST_HEAD(free_me_list);
170 190
171 lo = get_layout_by_fh(clp, &args->cbl_fh, &args->cbl_stateid); 191 lo = get_layout_by_fh(clp, &args->cbl_fh, &args->cbl_stateid);
172 if (!lo) 192 if (!lo) {
193 trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, NULL,
194 &args->cbl_stateid, -rv);
173 goto out; 195 goto out;
196 }
174 197
175 ino = lo->plh_inode; 198 ino = lo->plh_inode;
176 199
177 spin_lock(&ino->i_lock); 200 spin_lock(&ino->i_lock);
201 if (!pnfs_check_stateid_sequence(lo, &args->cbl_stateid)) {
202 rv = NFS4ERR_DELAY;
203 goto unlock;
204 }
178 pnfs_set_layout_stateid(lo, &args->cbl_stateid, true); 205 pnfs_set_layout_stateid(lo, &args->cbl_stateid, true);
179 spin_unlock(&ino->i_lock); 206 spin_unlock(&ino->i_lock);
180 207
181 pnfs_layoutcommit_inode(ino, false); 208 pnfs_layoutcommit_inode(ino, false);
182 209
183 spin_lock(&ino->i_lock); 210 spin_lock(&ino->i_lock);
184 if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) || 211 /*
185 pnfs_mark_matching_lsegs_invalid(lo, &free_me_list, 212 * Enforce RFC5661 Section 12.5.5.2.1.5 (Bulk Recall and Return)
186 &args->cbl_range)) { 213 */
214 if (test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
187 rv = NFS4ERR_DELAY; 215 rv = NFS4ERR_DELAY;
188 goto unlock; 216 goto unlock;
189 } 217 }
190 218
219 if (pnfs_mark_matching_lsegs_return(lo, &free_me_list,
220 &args->cbl_range)) {
221 rv = NFS4_OK;
222 goto unlock;
223 }
224
191 if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) { 225 if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
192 NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, 226 NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo,
193 &args->cbl_range); 227 &args->cbl_range);
194 } 228 }
229 pnfs_mark_layout_returned_if_empty(lo);
195unlock: 230unlock:
196 spin_unlock(&ino->i_lock); 231 spin_unlock(&ino->i_lock);
197 pnfs_free_lseg_list(&free_me_list); 232 pnfs_free_lseg_list(&free_me_list);
233 /* Free all lsegs that are attached to commit buckets */
234 nfs_commit_inode(ino, 0);
198 pnfs_put_layout_hdr(lo); 235 pnfs_put_layout_hdr(lo);
199 trace_nfs4_cb_layoutrecall_inode(clp, &args->cbl_fh, ino, -rv); 236 trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
237 &args->cbl_stateid, -rv);
200 iput(ino); 238 iput(ino);
201out: 239out:
202 return rv; 240 return rv;