diff options
Diffstat (limited to 'fs/nfs/nfs4session.c')
-rw-r--r-- | fs/nfs/nfs4session.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index 701170293ceb..066cfa101b41 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -217,11 +217,65 @@ static void nfs4_destroy_slot_tables(struct nfs4_session *session) | |||
217 | nfs4_shrink_slot_table(&session->bc_slot_table, 0); | 217 | nfs4_shrink_slot_table(&session->bc_slot_table, 0); |
218 | } | 218 | } |
219 | 219 | ||
220 | static bool nfs41_assign_slot(struct rpc_task *task, void *pslot) | ||
221 | { | ||
222 | struct nfs4_sequence_args *args = task->tk_msg.rpc_argp; | ||
223 | struct nfs4_sequence_res *res = task->tk_msg.rpc_resp; | ||
224 | struct nfs4_slot *slot = pslot; | ||
225 | struct nfs4_slot_table *tbl = slot->table; | ||
226 | |||
227 | if (nfs4_session_draining(tbl->session) && !args->sa_privileged) | ||
228 | return false; | ||
229 | slot->renewal_time = jiffies; | ||
230 | slot->generation = tbl->generation; | ||
231 | args->sa_slot = slot; | ||
232 | res->sr_slot = slot; | ||
233 | res->sr_status_flags = 0; | ||
234 | res->sr_status = 1; | ||
235 | return true; | ||
236 | } | ||
237 | |||
238 | static bool __nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
239 | struct nfs4_slot *slot) | ||
240 | { | ||
241 | if (rpc_wake_up_first(&tbl->slot_tbl_waitq, nfs41_assign_slot, slot)) | ||
242 | return true; | ||
243 | return false; | ||
244 | } | ||
245 | |||
246 | bool nfs41_wake_and_assign_slot(struct nfs4_slot_table *tbl, | ||
247 | struct nfs4_slot *slot) | ||
248 | { | ||
249 | if (slot->slot_nr > tbl->max_slotid) | ||
250 | return false; | ||
251 | return __nfs41_wake_and_assign_slot(tbl, slot); | ||
252 | } | ||
253 | |||
254 | static bool nfs41_try_wake_next_slot_table_entry(struct nfs4_slot_table *tbl) | ||
255 | { | ||
256 | struct nfs4_slot *slot = nfs4_alloc_slot(tbl); | ||
257 | if (!IS_ERR(slot)) { | ||
258 | bool ret = __nfs41_wake_and_assign_slot(tbl, slot); | ||
259 | if (ret) | ||
260 | return ret; | ||
261 | nfs4_free_slot(tbl, slot); | ||
262 | } | ||
263 | return false; | ||
264 | } | ||
265 | |||
266 | void nfs41_wake_slot_table(struct nfs4_slot_table *tbl) | ||
267 | { | ||
268 | for (;;) { | ||
269 | if (!nfs41_try_wake_next_slot_table_entry(tbl)) | ||
270 | break; | ||
271 | } | ||
272 | } | ||
273 | |||
220 | /* Update the client's idea of target_highest_slotid */ | 274 | /* Update the client's idea of target_highest_slotid */ |
221 | static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl, | 275 | static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl, |
222 | u32 target_highest_slotid) | 276 | u32 target_highest_slotid) |
223 | { | 277 | { |
224 | unsigned int max_slotid, i; | 278 | unsigned int max_slotid; |
225 | 279 | ||
226 | if (tbl->target_highest_slotid == target_highest_slotid) | 280 | if (tbl->target_highest_slotid == target_highest_slotid) |
227 | return; | 281 | return; |
@@ -229,9 +283,8 @@ static void nfs41_set_target_slotid_locked(struct nfs4_slot_table *tbl, | |||
229 | tbl->generation++; | 283 | tbl->generation++; |
230 | 284 | ||
231 | max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, tbl->target_highest_slotid); | 285 | max_slotid = min(NFS4_MAX_SLOT_TABLE - 1, tbl->target_highest_slotid); |
232 | for (i = tbl->max_slotid + 1; i <= max_slotid; i++) | ||
233 | rpc_wake_up_next(&tbl->slot_tbl_waitq); | ||
234 | tbl->max_slotid = max_slotid; | 286 | tbl->max_slotid = max_slotid; |
287 | nfs41_wake_slot_table(tbl); | ||
235 | } | 288 | } |
236 | 289 | ||
237 | void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, | 290 | void nfs41_set_target_slotid(struct nfs4_slot_table *tbl, |