@@ -1427,14 +1427,26 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
14271427 kfree (copy );
14281428}
14291429
1430+ static void release_copy_files (struct nfsd4_copy * copy );
1431+
14301432static void nfsd4_stop_copy (struct nfsd4_copy * copy )
14311433{
14321434 trace_nfsd_copy_async_cancel (copy );
14331435 if (!test_and_set_bit (NFSD4_COPY_F_STOPPED , & copy -> cp_flags )) {
14341436 kthread_stop (copy -> copy_task );
1435- copy -> nfserr = nfs_ok ;
1437+ if (!test_bit (NFSD4_COPY_F_CB_ERROR , & copy -> cp_flags ))
1438+ copy -> nfserr = nfs_ok ;
14361439 set_bit (NFSD4_COPY_F_COMPLETED , & copy -> cp_flags );
14371440 }
1441+
1442+ /*
1443+ * The copy was removed from async_copies before this function
1444+ * was called, so the reaper cannot clean it up. Release files
1445+ * here regardless of who won the STOPPED race. If the thread
1446+ * set STOPPED, it has finished using the files. If STOPPED
1447+ * was set here, kthread_stop() waited for the thread to exit.
1448+ */
1449+ release_copy_files (copy );
14381450 nfs4_put_copy (copy );
14391451}
14401452
@@ -1462,6 +1474,72 @@ void nfsd4_shutdown_copy(struct nfs4_client *clp)
14621474 while ((copy = nfsd4_unhash_copy (clp )) != NULL )
14631475 nfsd4_stop_copy (copy );
14641476}
1477+
1478+ static bool nfsd4_copy_on_sb (const struct nfsd4_copy * copy ,
1479+ const struct super_block * sb )
1480+ {
1481+ if (copy -> nf_src &&
1482+ file_inode (copy -> nf_src -> nf_file )-> i_sb == sb )
1483+ return true;
1484+ if (copy -> nf_dst &&
1485+ file_inode (copy -> nf_dst -> nf_file )-> i_sb == sb )
1486+ return true;
1487+ return false;
1488+ }
1489+
1490+ /**
1491+ * nfsd4_cancel_copy_by_sb - cancel async copy operations on @sb
1492+ * @net: net namespace containing the copy operations
1493+ * @sb: targeted superblock
1494+ */
1495+ void nfsd4_cancel_copy_by_sb (struct net * net , struct super_block * sb )
1496+ {
1497+ struct nfsd_net * nn = net_generic (net , nfsd_net_id );
1498+ struct nfsd4_copy * copy , * tmp ;
1499+ struct nfs4_client * clp ;
1500+ unsigned int idhashval ;
1501+ LIST_HEAD (to_cancel );
1502+
1503+ spin_lock (& nn -> client_lock );
1504+ for (idhashval = 0 ; idhashval < CLIENT_HASH_SIZE ; idhashval ++ ) {
1505+ struct list_head * head = & nn -> conf_id_hashtbl [idhashval ];
1506+
1507+ list_for_each_entry (clp , head , cl_idhash ) {
1508+ spin_lock (& clp -> async_lock );
1509+ list_for_each_entry_safe (copy , tmp ,
1510+ & clp -> async_copies , copies ) {
1511+ if (nfsd4_copy_on_sb (copy , sb )) {
1512+ refcount_inc (& copy -> refcount );
1513+ /*
1514+ * Hold a reference on the client while
1515+ * nfsd4_stop_copy() runs. Unlike
1516+ * nfsd4_unhash_copy(), cp_clp is not
1517+ * NULLed here because nfsd4_send_cb_offload()
1518+ * needs a valid client to send CB_OFFLOAD.
1519+ * That function takes its own reference to
1520+ * survive callback flight.
1521+ */
1522+ kref_get (& clp -> cl_nfsdfs .cl_ref );
1523+ copy -> nfserr = nfserr_admin_revoked ;
1524+ set_bit (NFSD4_COPY_F_CB_ERROR ,
1525+ & copy -> cp_flags );
1526+ list_move (& copy -> copies , & to_cancel );
1527+ }
1528+ }
1529+ spin_unlock (& clp -> async_lock );
1530+ }
1531+ }
1532+ spin_unlock (& nn -> client_lock );
1533+
1534+ list_for_each_entry_safe (copy , tmp , & to_cancel , copies ) {
1535+ struct nfs4_client * clp = copy -> cp_clp ;
1536+
1537+ list_del_init (& copy -> copies );
1538+ nfsd4_stop_copy (copy );
1539+ nfsd4_put_client (clp );
1540+ }
1541+ }
1542+
14651543#ifdef CONFIG_NFSD_V4_2_INTER_SSC
14661544
14671545extern struct file * nfs42_ssc_open (struct vfsmount * ss_mnt ,
@@ -1751,6 +1829,7 @@ static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
17511829 container_of (cbo , struct nfsd4_copy , cp_cb_offload );
17521830
17531831 set_bit (NFSD4_COPY_F_OFFLOAD_DONE , & copy -> cp_flags );
1832+ nfsd4_put_client (cb -> cb_clp );
17541833}
17551834
17561835static int nfsd4_cb_offload_done (struct nfsd4_callback * cb ,
@@ -1870,10 +1949,14 @@ static void dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
18701949
18711950static void release_copy_files (struct nfsd4_copy * copy )
18721951{
1873- if (copy -> nf_src )
1952+ if (copy -> nf_src ) {
18741953 nfsd_file_put (copy -> nf_src );
1875- if (copy -> nf_dst )
1954+ copy -> nf_src = NULL ;
1955+ }
1956+ if (copy -> nf_dst ) {
18761957 nfsd_file_put (copy -> nf_dst );
1958+ copy -> nf_dst = NULL ;
1959+ }
18771960}
18781961
18791962static void cleanup_async_copy (struct nfsd4_copy * copy )
@@ -1892,18 +1975,34 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)
18921975static void nfsd4_send_cb_offload (struct nfsd4_copy * copy )
18931976{
18941977 struct nfsd4_cb_offload * cbo = & copy -> cp_cb_offload ;
1978+ struct nfs4_client * clp = copy -> cp_clp ;
1979+
1980+ /*
1981+ * cp_clp is NULL when called via nfsd4_shutdown_copy() during
1982+ * client destruction. Skip the callback; the client is gone.
1983+ */
1984+ if (!clp ) {
1985+ set_bit (NFSD4_COPY_F_OFFLOAD_DONE , & copy -> cp_flags );
1986+ return ;
1987+ }
18951988
18961989 memcpy (& cbo -> co_res , & copy -> cp_res , sizeof (copy -> cp_res ));
18971990 memcpy (& cbo -> co_fh , & copy -> fh , sizeof (copy -> fh ));
18981991 cbo -> co_nfserr = copy -> nfserr ;
18991992 cbo -> co_retries = 5 ;
19001993
1901- nfsd4_init_cb (& cbo -> co_cb , copy -> cp_clp , & nfsd4_cb_offload_ops ,
1994+ /*
1995+ * Hold a reference on the client while the callback is in flight.
1996+ * Released in nfsd4_cb_offload_release().
1997+ */
1998+ kref_get (& clp -> cl_nfsdfs .cl_ref );
1999+
2000+ nfsd4_init_cb (& cbo -> co_cb , clp , & nfsd4_cb_offload_ops ,
19022001 NFSPROC4_CLNT_CB_OFFLOAD );
19032002 nfsd41_cb_referring_call (& cbo -> co_cb , & cbo -> co_referring_sessionid ,
19042003 cbo -> co_referring_slotid ,
19052004 cbo -> co_referring_seqno );
1906- trace_nfsd_cb_offload (copy -> cp_clp , & cbo -> co_res .cb_stateid ,
2005+ trace_nfsd_cb_offload (clp , & cbo -> co_res .cb_stateid ,
19072006 & cbo -> co_fh , copy -> cp_count , copy -> nfserr );
19082007 nfsd4_try_run_cb (& cbo -> co_cb );
19092008}
@@ -1918,6 +2017,7 @@ static void nfsd4_send_cb_offload(struct nfsd4_copy *copy)
19182017static int nfsd4_do_async_copy (void * data )
19192018{
19202019 struct nfsd4_copy * copy = (struct nfsd4_copy * )data ;
2020+ __be32 nfserr = nfs_ok ;
19212021
19222022 trace_nfsd_copy_async (copy );
19232023 if (nfsd4_ssc_is_inter (copy )) {
@@ -1928,23 +2028,25 @@ static int nfsd4_do_async_copy(void *data)
19282028 if (IS_ERR (filp )) {
19292029 switch (PTR_ERR (filp )) {
19302030 case - EBADF :
1931- copy -> nfserr = nfserr_wrong_type ;
2031+ nfserr = nfserr_wrong_type ;
19322032 break ;
19332033 default :
1934- copy -> nfserr = nfserr_offload_denied ;
2034+ nfserr = nfserr_offload_denied ;
19352035 }
19362036 /* ss_mnt will be unmounted by the laundromat */
19372037 goto do_callback ;
19382038 }
1939- copy -> nfserr = nfsd4_do_copy (copy , filp , copy -> nf_dst -> nf_file ,
1940- false);
2039+ nfserr = nfsd4_do_copy (copy , filp , copy -> nf_dst -> nf_file ,
2040+ false);
19412041 nfsd4_cleanup_inter_ssc (copy -> ss_nsui , filp , copy -> nf_dst );
19422042 } else {
1943- copy -> nfserr = nfsd4_do_copy (copy , copy -> nf_src -> nf_file ,
1944- copy -> nf_dst -> nf_file , false);
2043+ nfserr = nfsd4_do_copy (copy , copy -> nf_src -> nf_file ,
2044+ copy -> nf_dst -> nf_file , false);
19452045 }
19462046
19472047do_callback :
2048+ if (!test_bit (NFSD4_COPY_F_CB_ERROR , & copy -> cp_flags ))
2049+ copy -> nfserr = nfserr ;
19482050 /* The kthread exits forthwith. Ensure that a subsequent
19492051 * OFFLOAD_CANCEL won't try to kill it again. */
19502052 set_bit (NFSD4_COPY_F_STOPPED , & copy -> cp_flags );
0 commit comments