hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/fs/nfs/pnfs_nfs.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Common NFS I/O operations for the pnfs file based
34 * layout drivers.
....@@ -58,6 +59,17 @@
5859 }
5960 EXPORT_SYMBOL_GPL(pnfs_generic_commit_release);
6061
62
+static struct pnfs_layout_segment *
63
+pnfs_free_bucket_lseg(struct pnfs_commit_bucket *bucket)
64
+{
65
+ if (list_empty(&bucket->committing) && list_empty(&bucket->written)) {
66
+ struct pnfs_layout_segment *freeme = bucket->lseg;
67
+ bucket->lseg = NULL;
68
+ return freeme;
69
+ }
70
+ return NULL;
71
+}
72
+
6173 /* The generic layer is about to remove the req from the commit list.
6274 * If this will make the bucket empty, it will need to put the lseg reference.
6375 * Note this must be called holding nfsi->commit_mutex
....@@ -66,30 +78,169 @@
6678 pnfs_generic_clear_request_commit(struct nfs_page *req,
6779 struct nfs_commit_info *cinfo)
6880 {
69
- struct pnfs_layout_segment *freeme = NULL;
81
+ struct pnfs_commit_bucket *bucket = NULL;
7082
7183 if (!test_and_clear_bit(PG_COMMIT_TO_DS, &req->wb_flags))
7284 goto out;
7385 cinfo->ds->nwritten--;
74
- if (list_is_singular(&req->wb_list)) {
75
- struct pnfs_commit_bucket *bucket;
76
-
86
+ if (list_is_singular(&req->wb_list))
7787 bucket = list_first_entry(&req->wb_list,
78
- struct pnfs_commit_bucket,
79
- written);
80
- freeme = bucket->wlseg;
81
- bucket->wlseg = NULL;
82
- }
88
+ struct pnfs_commit_bucket, written);
8389 out:
8490 nfs_request_remove_commit_list(req, cinfo);
85
- pnfs_put_lseg(freeme);
91
+ if (bucket)
92
+ pnfs_put_lseg(pnfs_free_bucket_lseg(bucket));
8693 }
8794 EXPORT_SYMBOL_GPL(pnfs_generic_clear_request_commit);
8895
96
+struct pnfs_commit_array *
97
+pnfs_alloc_commit_array(size_t n, gfp_t gfp_flags)
98
+{
99
+ struct pnfs_commit_array *p;
100
+ struct pnfs_commit_bucket *b;
101
+
102
+ p = kmalloc(struct_size(p, buckets, n), gfp_flags);
103
+ if (!p)
104
+ return NULL;
105
+ p->nbuckets = n;
106
+ INIT_LIST_HEAD(&p->cinfo_list);
107
+ INIT_LIST_HEAD(&p->lseg_list);
108
+ p->lseg = NULL;
109
+ for (b = &p->buckets[0]; n != 0; b++, n--) {
110
+ INIT_LIST_HEAD(&b->written);
111
+ INIT_LIST_HEAD(&b->committing);
112
+ b->lseg = NULL;
113
+ b->direct_verf.committed = NFS_INVALID_STABLE_HOW;
114
+ }
115
+ return p;
116
+}
117
+EXPORT_SYMBOL_GPL(pnfs_alloc_commit_array);
118
+
119
+void
120
+pnfs_free_commit_array(struct pnfs_commit_array *p)
121
+{
122
+ kfree_rcu(p, rcu);
123
+}
124
+EXPORT_SYMBOL_GPL(pnfs_free_commit_array);
125
+
126
+static struct pnfs_commit_array *
127
+pnfs_find_commit_array_by_lseg(struct pnfs_ds_commit_info *fl_cinfo,
128
+ struct pnfs_layout_segment *lseg)
129
+{
130
+ struct pnfs_commit_array *array;
131
+
132
+ list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
133
+ if (array->lseg == lseg)
134
+ return array;
135
+ }
136
+ return NULL;
137
+}
138
+
139
+struct pnfs_commit_array *
140
+pnfs_add_commit_array(struct pnfs_ds_commit_info *fl_cinfo,
141
+ struct pnfs_commit_array *new,
142
+ struct pnfs_layout_segment *lseg)
143
+{
144
+ struct pnfs_commit_array *array;
145
+
146
+ array = pnfs_find_commit_array_by_lseg(fl_cinfo, lseg);
147
+ if (array)
148
+ return array;
149
+ new->lseg = lseg;
150
+ refcount_set(&new->refcount, 1);
151
+ list_add_rcu(&new->cinfo_list, &fl_cinfo->commits);
152
+ list_add(&new->lseg_list, &lseg->pls_commits);
153
+ return new;
154
+}
155
+EXPORT_SYMBOL_GPL(pnfs_add_commit_array);
156
+
157
+static struct pnfs_commit_array *
158
+pnfs_lookup_commit_array(struct pnfs_ds_commit_info *fl_cinfo,
159
+ struct pnfs_layout_segment *lseg)
160
+{
161
+ struct pnfs_commit_array *array;
162
+
163
+ rcu_read_lock();
164
+ array = pnfs_find_commit_array_by_lseg(fl_cinfo, lseg);
165
+ if (!array) {
166
+ rcu_read_unlock();
167
+ fl_cinfo->ops->setup_ds_info(fl_cinfo, lseg);
168
+ rcu_read_lock();
169
+ array = pnfs_find_commit_array_by_lseg(fl_cinfo, lseg);
170
+ }
171
+ rcu_read_unlock();
172
+ return array;
173
+}
174
+
175
+static void
176
+pnfs_release_commit_array_locked(struct pnfs_commit_array *array)
177
+{
178
+ list_del_rcu(&array->cinfo_list);
179
+ list_del(&array->lseg_list);
180
+ pnfs_free_commit_array(array);
181
+}
182
+
183
+static void
184
+pnfs_put_commit_array_locked(struct pnfs_commit_array *array)
185
+{
186
+ if (refcount_dec_and_test(&array->refcount))
187
+ pnfs_release_commit_array_locked(array);
188
+}
189
+
190
+static void
191
+pnfs_put_commit_array(struct pnfs_commit_array *array, struct inode *inode)
192
+{
193
+ if (refcount_dec_and_lock(&array->refcount, &inode->i_lock)) {
194
+ pnfs_release_commit_array_locked(array);
195
+ spin_unlock(&inode->i_lock);
196
+ }
197
+}
198
+
199
+static struct pnfs_commit_array *
200
+pnfs_get_commit_array(struct pnfs_commit_array *array)
201
+{
202
+ if (refcount_inc_not_zero(&array->refcount))
203
+ return array;
204
+ return NULL;
205
+}
206
+
207
+static void
208
+pnfs_remove_and_free_commit_array(struct pnfs_commit_array *array)
209
+{
210
+ array->lseg = NULL;
211
+ list_del_init(&array->lseg_list);
212
+ pnfs_put_commit_array_locked(array);
213
+}
214
+
215
+void
216
+pnfs_generic_ds_cinfo_release_lseg(struct pnfs_ds_commit_info *fl_cinfo,
217
+ struct pnfs_layout_segment *lseg)
218
+{
219
+ struct pnfs_commit_array *array, *tmp;
220
+
221
+ list_for_each_entry_safe(array, tmp, &lseg->pls_commits, lseg_list)
222
+ pnfs_remove_and_free_commit_array(array);
223
+}
224
+EXPORT_SYMBOL_GPL(pnfs_generic_ds_cinfo_release_lseg);
225
+
226
+void
227
+pnfs_generic_ds_cinfo_destroy(struct pnfs_ds_commit_info *fl_cinfo)
228
+{
229
+ struct pnfs_commit_array *array, *tmp;
230
+
231
+ list_for_each_entry_safe(array, tmp, &fl_cinfo->commits, cinfo_list)
232
+ pnfs_remove_and_free_commit_array(array);
233
+}
234
+EXPORT_SYMBOL_GPL(pnfs_generic_ds_cinfo_destroy);
235
+
236
+/*
237
+ * Locks the nfs_page requests for commit and moves them to
238
+ * @bucket->committing.
239
+ */
89240 static int
90
-pnfs_generic_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
91
- struct nfs_commit_info *cinfo,
92
- int max)
241
+pnfs_bucket_scan_ds_commit_list(struct pnfs_commit_bucket *bucket,
242
+ struct nfs_commit_info *cinfo,
243
+ int max)
93244 {
94245 struct list_head *src = &bucket->written;
95246 struct list_head *dst = &bucket->committing;
....@@ -100,158 +251,255 @@
100251 if (ret) {
101252 cinfo->ds->nwritten -= ret;
102253 cinfo->ds->ncommitting += ret;
103
- if (bucket->clseg == NULL)
104
- bucket->clseg = pnfs_get_lseg(bucket->wlseg);
105
- if (list_empty(src)) {
106
- pnfs_put_lseg(bucket->wlseg);
107
- bucket->wlseg = NULL;
108
- }
109254 }
110255 return ret;
256
+}
257
+
258
+static int pnfs_bucket_scan_array(struct nfs_commit_info *cinfo,
259
+ struct pnfs_commit_bucket *buckets,
260
+ unsigned int nbuckets,
261
+ int max)
262
+{
263
+ unsigned int i;
264
+ int rv = 0, cnt;
265
+
266
+ for (i = 0; i < nbuckets && max != 0; i++) {
267
+ cnt = pnfs_bucket_scan_ds_commit_list(&buckets[i], cinfo, max);
268
+ rv += cnt;
269
+ max -= cnt;
270
+ }
271
+ return rv;
111272 }
112273
113274 /* Move reqs from written to committing lists, returning count
114275 * of number moved.
115276 */
116
-int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo,
117
- int max)
277
+int pnfs_generic_scan_commit_lists(struct nfs_commit_info *cinfo, int max)
118278 {
119
- int i, rv = 0, cnt;
279
+ struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
280
+ struct pnfs_commit_array *array;
281
+ int rv = 0, cnt;
120282
121
- lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
122
- for (i = 0; i < cinfo->ds->nbuckets && max != 0; i++) {
123
- cnt = pnfs_generic_scan_ds_commit_list(&cinfo->ds->buckets[i],
124
- cinfo, max);
125
- max -= cnt;
283
+ rcu_read_lock();
284
+ list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
285
+ if (!array->lseg || !pnfs_get_commit_array(array))
286
+ continue;
287
+ rcu_read_unlock();
288
+ cnt = pnfs_bucket_scan_array(cinfo, array->buckets,
289
+ array->nbuckets, max);
290
+ rcu_read_lock();
291
+ pnfs_put_commit_array(array, cinfo->inode);
126292 rv += cnt;
293
+ max -= cnt;
294
+ if (!max)
295
+ break;
127296 }
297
+ rcu_read_unlock();
128298 return rv;
129299 }
130300 EXPORT_SYMBOL_GPL(pnfs_generic_scan_commit_lists);
301
+
302
+static unsigned int
303
+pnfs_bucket_recover_commit_reqs(struct list_head *dst,
304
+ struct pnfs_commit_bucket *buckets,
305
+ unsigned int nbuckets,
306
+ struct nfs_commit_info *cinfo)
307
+{
308
+ struct pnfs_commit_bucket *b;
309
+ struct pnfs_layout_segment *freeme;
310
+ unsigned int nwritten, ret = 0;
311
+ unsigned int i;
312
+
313
+restart:
314
+ for (i = 0, b = buckets; i < nbuckets; i++, b++) {
315
+ nwritten = nfs_scan_commit_list(&b->written, dst, cinfo, 0);
316
+ if (!nwritten)
317
+ continue;
318
+ ret += nwritten;
319
+ freeme = pnfs_free_bucket_lseg(b);
320
+ if (freeme) {
321
+ pnfs_put_lseg(freeme);
322
+ goto restart;
323
+ }
324
+ }
325
+ return ret;
326
+}
131327
132328 /* Pull everything off the committing lists and dump into @dst. */
133329 void pnfs_generic_recover_commit_reqs(struct list_head *dst,
134330 struct nfs_commit_info *cinfo)
135331 {
136
- struct pnfs_commit_bucket *b;
137
- struct pnfs_layout_segment *freeme;
138
- int nwritten;
139
- int i;
332
+ struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
333
+ struct pnfs_commit_array *array;
334
+ unsigned int nwritten;
140335
141336 lockdep_assert_held(&NFS_I(cinfo->inode)->commit_mutex);
142
-restart:
143
- for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
144
- nwritten = nfs_scan_commit_list(&b->written, dst, cinfo, 0);
145
- if (!nwritten)
337
+ rcu_read_lock();
338
+ list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
339
+ if (!array->lseg || !pnfs_get_commit_array(array))
146340 continue;
147
- cinfo->ds->nwritten -= nwritten;
148
- if (list_empty(&b->written)) {
149
- freeme = b->wlseg;
150
- b->wlseg = NULL;
151
- pnfs_put_lseg(freeme);
152
- goto restart;
153
- }
341
+ rcu_read_unlock();
342
+ nwritten = pnfs_bucket_recover_commit_reqs(dst,
343
+ array->buckets,
344
+ array->nbuckets,
345
+ cinfo);
346
+ rcu_read_lock();
347
+ pnfs_put_commit_array(array, cinfo->inode);
348
+ fl_cinfo->nwritten -= nwritten;
154349 }
350
+ rcu_read_unlock();
155351 }
156352 EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs);
157353
158
-static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx)
354
+static struct nfs_page *
355
+pnfs_bucket_search_commit_reqs(struct pnfs_commit_bucket *buckets,
356
+ unsigned int nbuckets, struct page *page)
357
+{
358
+ struct nfs_page *req;
359
+ struct pnfs_commit_bucket *b;
360
+ unsigned int i;
361
+
362
+ /* Linearly search the commit lists for each bucket until a matching
363
+ * request is found */
364
+ for (i = 0, b = buckets; i < nbuckets; i++, b++) {
365
+ list_for_each_entry(req, &b->written, wb_list) {
366
+ if (req->wb_page == page)
367
+ return req->wb_head;
368
+ }
369
+ list_for_each_entry(req, &b->committing, wb_list) {
370
+ if (req->wb_page == page)
371
+ return req->wb_head;
372
+ }
373
+ }
374
+ return NULL;
375
+}
376
+
377
+/* pnfs_generic_search_commit_reqs - Search lists in @cinfo for the head reqest
378
+ * for @page
379
+ * @cinfo - commit info for current inode
380
+ * @page - page to search for matching head request
381
+ *
382
+ * Returns a the head request if one is found, otherwise returns NULL.
383
+ */
384
+struct nfs_page *
385
+pnfs_generic_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page)
159386 {
160387 struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
388
+ struct pnfs_commit_array *array;
389
+ struct nfs_page *req;
390
+
391
+ list_for_each_entry(array, &fl_cinfo->commits, cinfo_list) {
392
+ req = pnfs_bucket_search_commit_reqs(array->buckets,
393
+ array->nbuckets, page);
394
+ if (req)
395
+ return req;
396
+ }
397
+ return NULL;
398
+}
399
+EXPORT_SYMBOL_GPL(pnfs_generic_search_commit_reqs);
400
+
401
+static struct pnfs_layout_segment *
402
+pnfs_bucket_get_committing(struct list_head *head,
403
+ struct pnfs_commit_bucket *bucket,
404
+ struct nfs_commit_info *cinfo)
405
+{
406
+ struct pnfs_layout_segment *lseg;
407
+ struct list_head *pos;
408
+
409
+ list_for_each(pos, &bucket->committing)
410
+ cinfo->ds->ncommitting--;
411
+ list_splice_init(&bucket->committing, head);
412
+ lseg = pnfs_free_bucket_lseg(bucket);
413
+ if (!lseg)
414
+ lseg = pnfs_get_lseg(bucket->lseg);
415
+ return lseg;
416
+}
417
+
418
+static struct nfs_commit_data *
419
+pnfs_bucket_fetch_commitdata(struct pnfs_commit_bucket *bucket,
420
+ struct nfs_commit_info *cinfo)
421
+{
422
+ struct nfs_commit_data *data = nfs_commitdata_alloc();
423
+
424
+ if (!data)
425
+ return NULL;
426
+ data->lseg = pnfs_bucket_get_committing(&data->pages, bucket, cinfo);
427
+ return data;
428
+}
429
+
430
+static void pnfs_generic_retry_commit(struct pnfs_commit_bucket *buckets,
431
+ unsigned int nbuckets,
432
+ struct nfs_commit_info *cinfo,
433
+ unsigned int idx)
434
+{
161435 struct pnfs_commit_bucket *bucket;
162436 struct pnfs_layout_segment *freeme;
163
- struct list_head *pos;
164437 LIST_HEAD(pages);
165
- int i;
166438
167
- mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
168
- for (i = idx; i < fl_cinfo->nbuckets; i++) {
169
- bucket = &fl_cinfo->buckets[i];
439
+ for (bucket = buckets; idx < nbuckets; bucket++, idx++) {
170440 if (list_empty(&bucket->committing))
171441 continue;
172
- freeme = bucket->clseg;
173
- bucket->clseg = NULL;
174
- list_for_each(pos, &bucket->committing)
175
- cinfo->ds->ncommitting--;
176
- list_splice_init(&bucket->committing, &pages);
177
- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
178
- nfs_retry_commit(&pages, freeme, cinfo, i);
179
- pnfs_put_lseg(freeme);
180442 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
443
+ freeme = pnfs_bucket_get_committing(&pages, bucket, cinfo);
444
+ mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
445
+ nfs_retry_commit(&pages, freeme, cinfo, idx);
446
+ pnfs_put_lseg(freeme);
181447 }
182
- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
183448 }
184449
185450 static unsigned int
186
-pnfs_generic_alloc_ds_commits(struct nfs_commit_info *cinfo,
187
- struct list_head *list)
451
+pnfs_bucket_alloc_ds_commits(struct list_head *list,
452
+ struct pnfs_commit_bucket *buckets,
453
+ unsigned int nbuckets,
454
+ struct nfs_commit_info *cinfo)
188455 {
189
- struct pnfs_ds_commit_info *fl_cinfo;
190456 struct pnfs_commit_bucket *bucket;
191457 struct nfs_commit_data *data;
192
- int i;
458
+ unsigned int i;
193459 unsigned int nreq = 0;
194460
195
- fl_cinfo = cinfo->ds;
196
- bucket = fl_cinfo->buckets;
197
- for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) {
461
+ for (i = 0, bucket = buckets; i < nbuckets; i++, bucket++) {
198462 if (list_empty(&bucket->committing))
199463 continue;
200
- data = nfs_commitdata_alloc(false);
201
- if (!data)
202
- break;
203
- data->ds_commit_index = i;
204
- list_add(&data->pages, list);
205
- nreq++;
464
+ mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
465
+ if (!list_empty(&bucket->committing)) {
466
+ data = pnfs_bucket_fetch_commitdata(bucket, cinfo);
467
+ if (!data)
468
+ goto out_error;
469
+ data->ds_commit_index = i;
470
+ list_add_tail(&data->list, list);
471
+ nreq++;
472
+ }
473
+ mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
206474 }
207
-
475
+ return nreq;
476
+out_error:
477
+ mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
208478 /* Clean up on error */
209
- pnfs_generic_retry_commit(cinfo, i);
479
+ pnfs_generic_retry_commit(buckets, nbuckets, cinfo, i);
210480 return nreq;
211481 }
212482
213
-static inline
214
-void pnfs_fetch_commit_bucket_list(struct list_head *pages,
215
- struct nfs_commit_data *data,
216
- struct nfs_commit_info *cinfo)
483
+static unsigned int
484
+pnfs_alloc_ds_commits_list(struct list_head *list,
485
+ struct pnfs_ds_commit_info *fl_cinfo,
486
+ struct nfs_commit_info *cinfo)
217487 {
218
- struct pnfs_commit_bucket *bucket;
219
- struct list_head *pos;
488
+ struct pnfs_commit_array *array;
489
+ unsigned int ret = 0;
220490
221
- bucket = &cinfo->ds->buckets[data->ds_commit_index];
222
- mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
223
- list_for_each(pos, &bucket->committing)
224
- cinfo->ds->ncommitting--;
225
- list_splice_init(&bucket->committing, pages);
226
- data->lseg = bucket->clseg;
227
- bucket->clseg = NULL;
228
- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
229
-
230
-}
231
-
232
-/* Helper function for pnfs_generic_commit_pagelist to catch an empty
233
- * page list. This can happen when two commits race.
234
- *
235
- * This must be called instead of nfs_init_commit - call one or the other, but
236
- * not both!
237
- */
238
-static bool
239
-pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
240
- struct nfs_commit_data *data,
241
- struct nfs_commit_info *cinfo)
242
-{
243
- if (list_empty(pages)) {
244
- if (atomic_dec_and_test(&cinfo->mds->rpcs_out))
245
- wake_up_var(&cinfo->mds->rpcs_out);
246
- /* don't call nfs_commitdata_release - it tries to put
247
- * the open_context which is not acquired until nfs_init_commit
248
- * which has not been called on @data */
249
- WARN_ON_ONCE(data->context);
250
- nfs_commit_free(data);
251
- return true;
491
+ rcu_read_lock();
492
+ list_for_each_entry_rcu(array, &fl_cinfo->commits, cinfo_list) {
493
+ if (!array->lseg || !pnfs_get_commit_array(array))
494
+ continue;
495
+ rcu_read_unlock();
496
+ ret += pnfs_bucket_alloc_ds_commits(list, array->buckets,
497
+ array->nbuckets, cinfo);
498
+ rcu_read_lock();
499
+ pnfs_put_commit_array(array, cinfo->inode);
252500 }
253
-
254
- return false;
501
+ rcu_read_unlock();
502
+ return ret;
255503 }
256504
257505 /* This follows nfs_commit_list pretty closely */
....@@ -261,47 +509,37 @@
261509 int (*initiate_commit)(struct nfs_commit_data *data,
262510 int how))
263511 {
512
+ struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
264513 struct nfs_commit_data *data, *tmp;
265514 LIST_HEAD(list);
266515 unsigned int nreq = 0;
267516
268517 if (!list_empty(mds_pages)) {
269
- data = nfs_commitdata_alloc(true);
518
+ data = nfs_commitdata_alloc();
519
+ if (!data) {
520
+ nfs_retry_commit(mds_pages, NULL, cinfo, -1);
521
+ return -ENOMEM;
522
+ }
270523 data->ds_commit_index = -1;
271
- list_add(&data->pages, &list);
524
+ list_splice_init(mds_pages, &data->pages);
525
+ list_add_tail(&data->list, &list);
272526 nreq++;
273527 }
274528
275
- nreq += pnfs_generic_alloc_ds_commits(cinfo, &list);
276
-
529
+ nreq += pnfs_alloc_ds_commits_list(&list, fl_cinfo, cinfo);
277530 if (nreq == 0)
278531 goto out;
279532
280
- atomic_add(nreq, &cinfo->mds->rpcs_out);
281
-
282
- list_for_each_entry_safe(data, tmp, &list, pages) {
283
- list_del_init(&data->pages);
533
+ list_for_each_entry_safe(data, tmp, &list, list) {
534
+ list_del(&data->list);
284535 if (data->ds_commit_index < 0) {
285
- /* another commit raced with us */
286
- if (pnfs_generic_commit_cancel_empty_pagelist(mds_pages,
287
- data, cinfo))
288
- continue;
289
-
290
- nfs_init_commit(data, mds_pages, NULL, cinfo);
536
+ nfs_init_commit(data, NULL, NULL, cinfo);
291537 nfs_initiate_commit(NFS_CLIENT(inode), data,
292538 NFS_PROTO(data->inode),
293
- data->mds_ops, how, 0);
539
+ data->mds_ops, how,
540
+ RPC_TASK_CRED_NOREF);
294541 } else {
295
- LIST_HEAD(pages);
296
-
297
- pnfs_fetch_commit_bucket_list(&pages, data, cinfo);
298
-
299
- /* another commit raced with us */
300
- if (pnfs_generic_commit_cancel_empty_pagelist(&pages,
301
- data, cinfo))
302
- continue;
303
-
304
- nfs_init_commit(data, &pages, data->lseg, cinfo);
542
+ nfs_init_commit(data, NULL, data->lseg, cinfo);
305543 initiate_commit(data, how);
306544 }
307545 }
....@@ -622,11 +860,16 @@
622860 /* Add this address as an alias */
623861 rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
624862 rpc_clnt_test_and_add_xprt, NULL);
625
- } else
626
- clp = get_v3_ds_connect(mds_srv,
627
- (struct sockaddr *)&da->da_addr,
628
- da->da_addrlen, IPPROTO_TCP,
629
- timeo, retrans);
863
+ continue;
864
+ }
865
+ clp = get_v3_ds_connect(mds_srv,
866
+ (struct sockaddr *)&da->da_addr,
867
+ da->da_addrlen, IPPROTO_TCP,
868
+ timeo, retrans);
869
+ if (IS_ERR(clp))
870
+ continue;
871
+ clp->cl_rpcclient->cl_softerr = 0;
872
+ clp->cl_rpcclient->cl_softrtry = 0;
630873 }
631874
632875 if (IS_ERR(clp)) {
....@@ -682,7 +925,7 @@
682925 rpc_clnt_setup_test_and_add_xprt,
683926 &rpcdata);
684927 if (xprtdata.cred)
685
- put_rpccred(xprtdata.cred);
928
+ put_cred(xprtdata.cred);
686929 } else {
687930 clp = nfs4_set_ds_client(mds_srv,
688931 (struct sockaddr *)&da->da_addr,
....@@ -924,32 +1167,33 @@
9241167 u32 ds_commit_idx)
9251168 {
9261169 struct list_head *list;
927
- struct pnfs_commit_bucket *buckets;
1170
+ struct pnfs_commit_array *array;
1171
+ struct pnfs_commit_bucket *bucket;
9281172
9291173 mutex_lock(&NFS_I(cinfo->inode)->commit_mutex);
930
- buckets = cinfo->ds->buckets;
931
- list = &buckets[ds_commit_idx].written;
932
- if (list_empty(list)) {
933
- if (!pnfs_is_valid_lseg(lseg)) {
934
- mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
935
- cinfo->completion_ops->resched_write(cinfo, req);
936
- return;
937
- }
938
- /* Non-empty buckets hold a reference on the lseg. That ref
939
- * is normally transferred to the COMMIT call and released
940
- * there. It could also be released if the last req is pulled
941
- * off due to a rewrite, in which case it will be done in
942
- * pnfs_common_clear_request_commit
943
- */
944
- WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL);
945
- buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg);
946
- }
1174
+ array = pnfs_lookup_commit_array(cinfo->ds, lseg);
1175
+ if (!array || !pnfs_is_valid_lseg(lseg))
1176
+ goto out_resched;
1177
+ bucket = &array->buckets[ds_commit_idx];
1178
+ list = &bucket->written;
1179
+ /* Non-empty buckets hold a reference on the lseg. That ref
1180
+ * is normally transferred to the COMMIT call and released
1181
+ * there. It could also be released if the last req is pulled
1182
+ * off due to a rewrite, in which case it will be done in
1183
+ * pnfs_common_clear_request_commit
1184
+ */
1185
+ if (!bucket->lseg)
1186
+ bucket->lseg = pnfs_get_lseg(lseg);
9471187 set_bit(PG_COMMIT_TO_DS, &req->wb_flags);
9481188 cinfo->ds->nwritten++;
9491189
9501190 nfs_request_add_commit_list_locked(req, list, cinfo);
9511191 mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
9521192 nfs_mark_page_unstable(req->wb_page, cinfo);
1193
+ return;
1194
+out_resched:
1195
+ mutex_unlock(&NFS_I(cinfo->inode)->commit_mutex);
1196
+ cinfo->completion_ops->resched_write(cinfo, req);
9531197 }
9541198 EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit);
9551199