@@ -1740,6 +1740,17 @@ static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
17401740 TASK_UNINTERRUPTIBLE );
17411741}
17421742
1743+ static void nfs_layoutget_begin (struct pnfs_layout_hdr * lo )
1744+ {
1745+ atomic_inc (& lo -> plh_outstanding );
1746+ }
1747+
1748+ static void nfs_layoutget_end (struct pnfs_layout_hdr * lo )
1749+ {
1750+ if (atomic_dec_and_test (& lo -> plh_outstanding ))
1751+ wake_up_var (& lo -> plh_outstanding );
1752+ }
1753+
17431754static void pnfs_clear_first_layoutget (struct pnfs_layout_hdr * lo )
17441755{
17451756 unsigned long * bitlock = & lo -> plh_flags ;
@@ -1839,6 +1850,21 @@ pnfs_update_layout(struct inode *ino,
18391850 goto out_unlock ;
18401851 }
18411852
1853+ /*
1854+ * If the layout segment list is empty, but there are outstanding
1855+ * layoutget calls, then they might be subject to a layoutrecall.
1856+ */
1857+ if (list_empty (& lo -> plh_segs ) &&
1858+ atomic_read (& lo -> plh_outstanding ) != 0 ) {
1859+ spin_unlock (& ino -> i_lock );
1860+ if (wait_var_event_killable (& lo -> plh_outstanding ,
1861+ atomic_read (& lo -> plh_outstanding ) == 0
1862+ || !list_empty (& lo -> plh_segs )))
1863+ goto out_put_layout_hdr ;
1864+ pnfs_put_layout_hdr (lo );
1865+ goto lookup_again ;
1866+ }
1867+
18421868 lseg = pnfs_find_lseg (lo , & arg , strict_iomode );
18431869 if (lseg ) {
18441870 trace_pnfs_update_layout (ino , pos , count , iomode , lo , lseg ,
@@ -1912,7 +1938,7 @@ pnfs_update_layout(struct inode *ino,
19121938 PNFS_UPDATE_LAYOUT_BLOCKED );
19131939 goto out_unlock ;
19141940 }
1915- atomic_inc ( & lo -> plh_outstanding );
1941+ nfs_layoutget_begin ( lo );
19161942 spin_unlock (& ino -> i_lock );
19171943
19181944 _add_to_server_list (lo , server );
@@ -1929,14 +1955,14 @@ pnfs_update_layout(struct inode *ino,
19291955 if (!lgp ) {
19301956 trace_pnfs_update_layout (ino , pos , count , iomode , lo , NULL ,
19311957 PNFS_UPDATE_LAYOUT_NOMEM );
1932- atomic_dec ( & lo -> plh_outstanding );
1958+ nfs_layoutget_end ( lo );
19331959 goto out_put_layout_hdr ;
19341960 }
19351961
19361962 lseg = nfs4_proc_layoutget (lgp , & timeout );
19371963 trace_pnfs_update_layout (ino , pos , count , iomode , lo , lseg ,
19381964 PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET );
1939- atomic_dec ( & lo -> plh_outstanding );
1965+ nfs_layoutget_end ( lo );
19401966 if (IS_ERR (lseg )) {
19411967 switch (PTR_ERR (lseg )) {
19421968 case - EBUSY :
@@ -2031,7 +2057,7 @@ _pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
20312057 goto out_unlock ;
20322058 if (test_and_set_bit (NFS_LAYOUT_FIRST_LAYOUTGET , & lo -> plh_flags ))
20332059 goto out_unlock ;
2034- atomic_inc ( & lo -> plh_outstanding );
2060+ nfs_layoutget_begin ( lo );
20352061 spin_unlock (& ino -> i_lock );
20362062 _add_to_server_list (lo , NFS_SERVER (ino ));
20372063 return lo ;
@@ -2172,8 +2198,8 @@ void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
21722198 struct inode * inode = lgp -> args .inode ;
21732199 if (inode ) {
21742200 struct pnfs_layout_hdr * lo = NFS_I (inode )-> layout ;
2175- atomic_dec (& lo -> plh_outstanding );
21762201 pnfs_clear_first_layoutget (lo );
2202+ nfs_layoutget_end (lo );
21772203 }
21782204 pnfs_layoutget_free (lgp );
21792205 }
0 commit comments