@@ -346,26 +346,62 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
346
346
/* Return true if layoutreturn is needed */
347
347
static bool
348
348
pnfs_layout_need_return (struct pnfs_layout_hdr * lo ,
349
- struct pnfs_layout_segment * lseg ,
350
- nfs4_stateid * stateid , enum pnfs_iomode * iomode )
349
+ struct pnfs_layout_segment * lseg )
351
350
{
352
351
struct pnfs_layout_segment * s ;
353
352
354
353
if (!test_bit (NFS_LSEG_LAYOUTRETURN , & lseg -> pls_flags ))
355
354
return false;
356
355
357
356
list_for_each_entry (s , & lo -> plh_segs , pls_list )
358
- if (test_bit (NFS_LSEG_LAYOUTRETURN , & lseg -> pls_flags ))
357
+ if (s != lseg && test_bit (NFS_LSEG_LAYOUTRETURN , & s -> pls_flags ))
359
358
return false;
360
359
361
- * stateid = lo -> plh_stateid ;
362
- * iomode = lo -> plh_return_iomode ;
363
- /* decreased in pnfs_send_layoutreturn() */
364
- lo -> plh_block_lgets ++ ;
365
- lo -> plh_return_iomode = 0 ;
366
360
return true;
367
361
}
368
362
363
+ static void pnfs_layoutreturn_free_lseg (struct work_struct * work )
364
+ {
365
+ struct pnfs_layout_segment * lseg ;
366
+ struct pnfs_layout_hdr * lo ;
367
+ struct inode * inode ;
368
+
369
+ lseg = container_of (work , struct pnfs_layout_segment , pls_work );
370
+ WARN_ON (atomic_read (& lseg -> pls_refcount ));
371
+ lo = lseg -> pls_layout ;
372
+ inode = lo -> plh_inode ;
373
+
374
+ spin_lock (& inode -> i_lock );
375
+ if (pnfs_layout_need_return (lo , lseg )) {
376
+ nfs4_stateid stateid ;
377
+ enum pnfs_iomode iomode ;
378
+
379
+ stateid = lo -> plh_stateid ;
380
+ iomode = lo -> plh_return_iomode ;
381
+ /* decreased in pnfs_send_layoutreturn() */
382
+ lo -> plh_block_lgets ++ ;
383
+ lo -> plh_return_iomode = 0 ;
384
+ spin_unlock (& inode -> i_lock );
385
+
386
+ pnfs_send_layoutreturn (lo , stateid , iomode , true);
387
+ spin_lock (& inode -> i_lock );
388
+ } else
389
+ /* match pnfs_get_layout_hdr #2 in pnfs_put_lseg */
390
+ pnfs_put_layout_hdr (lo );
391
+ pnfs_layout_remove_lseg (lo , lseg );
392
+ spin_unlock (& inode -> i_lock );
393
+ pnfs_free_lseg (lseg );
394
+ /* match pnfs_get_layout_hdr #1 in pnfs_put_lseg */
395
+ pnfs_put_layout_hdr (lo );
396
+ }
397
+
398
+ static void
399
+ pnfs_layoutreturn_free_lseg_async (struct pnfs_layout_segment * lseg )
400
+ {
401
+ INIT_WORK (& lseg -> pls_work , pnfs_layoutreturn_free_lseg );
402
+ queue_work (nfsiod_workqueue , & lseg -> pls_work );
403
+ }
404
+
369
405
void
370
406
pnfs_put_lseg (struct pnfs_layout_segment * lseg )
371
407
{
@@ -381,21 +417,18 @@ pnfs_put_lseg(struct pnfs_layout_segment *lseg)
381
417
lo = lseg -> pls_layout ;
382
418
inode = lo -> plh_inode ;
383
419
if (atomic_dec_and_lock (& lseg -> pls_refcount , & inode -> i_lock )) {
384
- bool need_return ;
385
- nfs4_stateid stateid ;
386
- enum pnfs_iomode iomode ;
387
-
388
420
pnfs_get_layout_hdr (lo );
389
- pnfs_layout_remove_lseg ( lo , lseg );
390
- need_return = pnfs_layout_need_return ( lo , lseg ,
391
- & stateid , & iomode );
392
- spin_unlock ( & inode -> i_lock );
393
- pnfs_free_lseg (lseg );
394
- if ( need_return )
395
- pnfs_send_layoutreturn (lo , stateid , iomode ,
396
- true );
397
- else
421
+ if ( pnfs_layout_need_return ( lo , lseg )) {
422
+ spin_unlock ( & inode -> i_lock );
423
+ /* hdr reference dropped in nfs4_layoutreturn_release */
424
+ pnfs_get_layout_hdr ( lo );
425
+ pnfs_layoutreturn_free_lseg_async (lseg );
426
+ } else {
427
+ pnfs_layout_remove_lseg (lo , lseg );
428
+ spin_unlock ( & inode -> i_lock );
429
+ pnfs_free_lseg ( lseg );
398
430
pnfs_put_layout_hdr (lo );
431
+ }
399
432
}
400
433
}
401
434
EXPORT_SYMBOL_GPL (pnfs_put_lseg );
@@ -1059,8 +1092,7 @@ bool pnfs_roc(struct inode *ino)
1059
1092
}
1060
1093
spin_unlock (& ino -> i_lock );
1061
1094
if (layoutreturn )
1062
- pnfs_send_layoutreturn (lo , stateid , IOMODE_ANY , 0 ,
1063
- NFS4_MAX_UINT64 , true);
1095
+ pnfs_send_layoutreturn (lo , stateid , IOMODE_ANY , true);
1064
1096
return false;
1065
1097
}
1066
1098
@@ -1127,8 +1159,7 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier, struct rpc_task *task)
1127
1159
spin_unlock (& ino -> i_lock );
1128
1160
if (layoutreturn ) {
1129
1161
rpc_sleep_on (& NFS_SERVER (ino )-> roc_rpcwaitq , task , NULL );
1130
- pnfs_send_layoutreturn (lo , stateid , IOMODE_ANY , 0 ,
1131
- NFS4_MAX_UINT64 , false);
1162
+ pnfs_send_layoutreturn (lo , stateid , IOMODE_ANY , false);
1132
1163
}
1133
1164
return found ;
1134
1165
}
0 commit comments