Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSv4/flexfiles: fix to allocate mirror->dss before use

Move mirror_array's dss_count initialization and dss allocation to
ff_layout_alloc_mirror(), just before the loop that initializes each
nfs4_ff_layout_ds_stripe's nfs_file_localio.

Also handle NULL return from kcalloc() and remove one level of indent
in ff_layout_alloc_mirror().

This commit fixes dangling nfsd_serv refcount issues seen when using
NFS LOCALIO and then attempting to stop the NFSD service.

Fixes: 20b1d75fb840 ("NFSv4/flexfiles: Add support for striped layouts")
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>

authored by

Mike Snitzer and committed by
Anna Schumaker
8db4a1d1 3a866087

+21 -14
+21 -14
fs/nfs/flexfilelayout/flexfilelayout.c
··· 270 270 mirror->layout = NULL; 271 271 } 272 272 273 - static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags) 273 + static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(u32 dss_count, 274 + gfp_t gfp_flags) 274 275 { 275 276 struct nfs4_ff_layout_mirror *mirror; 276 - u32 dss_id; 277 277 278 278 mirror = kzalloc(sizeof(*mirror), gfp_flags); 279 - if (mirror != NULL) { 280 - spin_lock_init(&mirror->lock); 281 - refcount_set(&mirror->ref, 1); 282 - INIT_LIST_HEAD(&mirror->mirrors); 283 - for (dss_id = 0; dss_id < mirror->dss_count; dss_id++) 284 - nfs_localio_file_init(&mirror->dss[dss_id].nfl); 279 + if (mirror == NULL) 280 + return NULL; 281 + 282 + spin_lock_init(&mirror->lock); 283 + refcount_set(&mirror->ref, 1); 284 + INIT_LIST_HEAD(&mirror->mirrors); 285 + 286 + mirror->dss_count = dss_count; 287 + mirror->dss = 288 + kcalloc(dss_count, sizeof(struct nfs4_ff_layout_ds_stripe), 289 + gfp_flags); 290 + if (mirror->dss == NULL) { 291 + kfree(mirror); 292 + return NULL; 285 293 } 294 + 295 + for (u32 dss_id = 0; dss_id < mirror->dss_count; dss_id++) 296 + nfs_localio_file_init(&mirror->dss[dss_id].nfl); 297 + 286 298 return mirror; 287 299 } 288 300 ··· 519 507 if (dss_count > 1 && stripe_unit == 0) 520 508 goto out_err_free; 521 509 522 - fls->mirror_array[i] = ff_layout_alloc_mirror(gfp_flags); 510 + fls->mirror_array[i] = ff_layout_alloc_mirror(dss_count, gfp_flags); 523 511 if (fls->mirror_array[i] == NULL) { 524 512 rc = -ENOMEM; 525 513 goto out_err_free; 526 514 } 527 - 528 - fls->mirror_array[i]->dss_count = dss_count; 529 - fls->mirror_array[i]->dss = 530 - kcalloc(dss_count, sizeof(struct nfs4_ff_layout_ds_stripe), 531 - gfp_flags); 532 515 533 516 for (dss_id = 0; dss_id < dss_count; dss_id++) { 534 517 dss_info = &fls->mirror_array[i]->dss[dss_id];