| @@ -59,6 +59,17 @@ void pnfs_generic_commit_release(void *calldata) · 58 unmodified lines |
| 59 | 59 | } |
| 60 | 60 | EXPORT_SYMBOL_GPL(pnfs_generic_commit_release); |
| 61 | 61 | |
| 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 | + |
| 62 | 73 | /* The generic layer is about to remove the req from the commit list. |
| 63 | 74 | * If this will make the bucket empty, it will need to put the lseg reference. |
| 64 | 75 | * Note this must be called holding nfsi->commit_mutex |
| @@ -78,8 +89,7 @@ pnfs_generic_clear_request_commit(struct nfs_page *req, · 13 unmodified lines |
| 78 | 89 | bucket = list_first_entry(&req->wb_list, |
| 79 | 90 | struct pnfs_commit_bucket, |
| 80 | 91 | written); |
| 81 | | − freeme = bucket->wlseg; |
| 82 | | − bucket->wlseg = NULL; |
| 92 | + freeme = pnfs_free_bucket_lseg(bucket); |
| 83 | 93 | } |
| 84 | 94 | out: |
| 85 | 95 | nfs_request_remove_commit_list(req, cinfo); |
| @@ -103,8 +113,7 @@ pnfs_alloc_commit_array(size_t n, gfp_t gfp_flags) · 17 unmodified lines |
| 103 | 113 | for (b = &p->buckets[0]; n != 0; b++, n--) { |
| 104 | 114 | INIT_LIST_HEAD(&b->written); |
| 105 | 115 | INIT_LIST_HEAD(&b->committing); |
| 106 | | − b->wlseg = NULL; |
| 107 | | − b->clseg = NULL; |
| 116 | + b->lseg = NULL; |
| 108 | 117 | b->direct_verf.committed = NFS_INVALID_STABLE_HOW; |
| 109 | 118 | } |
| 110 | 119 | return p; |
| @@ -246,12 +255,6 @@ pnfs_bucket_scan_ds_commit_list(struct pnfs_commit_bucket *bucket, · 135 unmodified lines |
| 246 | 255 | if (ret) { |
| 247 | 256 | cinfo->ds->nwritten -= ret; |
| 248 | 257 | cinfo->ds->ncommitting += ret; |
| 249 | | − if (bucket->clseg == NULL) |
| 250 | | − bucket->clseg = pnfs_get_lseg(bucket->wlseg); |
| 251 | | − if (list_empty(src)) { |
| 252 | | − pnfs_put_lseg(bucket->wlseg); |
| 253 | | − bucket->wlseg = NULL; |
| 254 | | − } |
| 255 | 258 | } |
| 256 | 259 | return ret; |
| 257 | 260 | } |
| @@ -317,9 +320,8 @@ restart: · 59 unmodified lines |
| 317 | 320 | if (!nwritten) |
| 318 | 321 | continue; |
| 319 | 322 | ret += nwritten; |
| 320 | | − if (list_empty(&b->written)) { |
| 321 | | − freeme = b->wlseg; |
| 322 | | − b->wlseg = NULL; |
| 323 | + freeme = pnfs_free_bucket_lseg(b); |
| 324 | + if (freeme) { |
| 323 | 325 | pnfs_put_lseg(freeme); |
| 324 | 326 | goto restart; |
| 325 | 327 | } |
| @@ -405,15 +407,12 @@ pnfs_bucket_get_committing(struct list_head *head, · 79 unmodified lines |
| 405 | 407 | struct pnfs_commit_bucket *bucket, |
| 406 | 408 | struct nfs_commit_info *cinfo) |
| 407 | 409 | { |
| 408 | | − struct pnfs_layout_segment *freeme; |
| 409 | 410 | struct list_head *pos; |
| 410 | 411 | |
| 411 | 412 | list_for_each(pos, &bucket->committing) |
| 412 | 413 | cinfo->ds->ncommitting--; |
| 413 | 414 | list_splice_init(&bucket->committing, head); |
| 414 | | − freeme = bucket->clseg; |
| 415 | | − bucket->clseg = NULL; |
| 416 | | − return freeme; |
| 415 | + return pnfs_free_bucket_lseg(bucket); |
| 417 | 416 | } |
| 418 | 417 | |
| 419 | 418 | static struct nfs_commit_data * |
| @@ -425,6 +424,8 @@ pnfs_bucket_fetch_commitdata(struct pnfs_commit_bucket *bucket, · 5 unmodified lines |
| 425 | 424 | if (!data) |
| 426 | 425 | return NULL; |
| 427 | 426 | data->lseg = pnfs_bucket_get_committing(&data->pages, bucket, cinfo); |
| 427 | + if (!data->lseg) |
| 428 | + data->lseg = pnfs_get_lseg(bucket->lseg); |
| 428 | 429 | return data; |
| 429 | 430 | } |
| 430 | 431 | |
| @@ -1182,8 +1183,8 @@ pnfs_layout_mark_request_commit(struct nfs_page *req, · 751 unmodified lines |
| 1182 | 1183 | * off due to a rewrite, in which case it will be done in |
| 1183 | 1184 | * pnfs_common_clear_request_commit |
| 1184 | 1185 | */ |
| 1185 | | − WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL); |
| 1186 | | − buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg); |
| 1186 | + if (!buckets[ds_commit_idx].lseg) |
| 1187 | + buckets[ds_commit_idx].lseg = pnfs_get_lseg(lseg); |
| 1187 | 1188 | } |
| 1188 | 1189 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); |
| 1189 | 1190 | cinfo->ds->nwritten++; |