Skip to content

Commit c21443c

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
NFSv4: Fix a reboot recovery race when opening a file
If the server reboots after it has replied to our OPEN, but before we call nfs4_opendata_to_nfs4_state(), then the reboot recovery thread will not see a stateid for this open, and so will fail to recover it. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 65b62a2 commit c21443c

File tree

1 file changed

+38
-12
lines changed

1 file changed

+38
-12
lines changed

fs/nfs/nfs4proc.c

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,43 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
18481848
sattr->ia_valid |= ATTR_MTIME;
18491849
}
18501850

1851+
static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
1852+
fmode_t fmode,
1853+
int flags,
1854+
struct nfs4_state **res)
1855+
{
1856+
struct nfs4_state_owner *sp = opendata->owner;
1857+
struct nfs_server *server = sp->so_server;
1858+
struct nfs4_state *state;
1859+
unsigned int seq;
1860+
int ret;
1861+
1862+
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
1863+
1864+
ret = _nfs4_proc_open(opendata);
1865+
if (ret != 0)
1866+
goto out;
1867+
1868+
state = nfs4_opendata_to_nfs4_state(opendata);
1869+
ret = PTR_ERR(state);
1870+
if (IS_ERR(state))
1871+
goto out;
1872+
if (server->caps & NFS_CAP_POSIX_LOCK)
1873+
set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
1874+
1875+
ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags);
1876+
if (ret != 0)
1877+
goto out;
1878+
1879+
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq)) {
1880+
nfs4_schedule_stateid_recovery(server, state);
1881+
nfs4_wait_clnt_recover(server->nfs_client);
1882+
}
1883+
*res = state;
1884+
out:
1885+
return ret;
1886+
}
1887+
18511888
/*
18521889
* Returns a referenced nfs4_state
18531890
*/
@@ -1892,18 +1929,7 @@ static int _nfs4_do_open(struct inode *dir,
18921929
if (dentry->d_inode != NULL)
18931930
opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
18941931

1895-
status = _nfs4_proc_open(opendata);
1896-
if (status != 0)
1897-
goto err_opendata_put;
1898-
1899-
state = nfs4_opendata_to_nfs4_state(opendata);
1900-
status = PTR_ERR(state);
1901-
if (IS_ERR(state))
1902-
goto err_opendata_put;
1903-
if (server->caps & NFS_CAP_POSIX_LOCK)
1904-
set_bit(NFS_STATE_POSIX_LOCKS, &state->flags);
1905-
1906-
status = nfs4_opendata_access(cred, opendata, state, fmode, flags);
1932+
status = _nfs4_open_and_get_state(opendata, fmode, flags, &state);
19071933
if (status != 0)
19081934
goto err_opendata_put;
19091935

0 commit comments

Comments
 (0)