aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-02-07 14:26:21 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-02-11 15:33:14 -0500
commitc21443c2c792cd9b463646d982b0fe48aa6feb0f (patch)
treec2d7f04beead6499390b5fffd842c76e248781da /fs/nfs
parent65b62a29f719e937b5be1df472287f4c61e53ac6 (diff)
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 <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d51227371c67..7cbf7aa6c634 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1848,6 +1848,43 @@ static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct
1848 sattr->ia_valid |= ATTR_MTIME; 1848 sattr->ia_valid |= ATTR_MTIME;
1849} 1849}
1850 1850
1851static 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;
1884out:
1885 return ret;
1886}
1887
1851/* 1888/*
1852 * Returns a referenced nfs4_state 1889 * Returns a referenced nfs4_state
1853 */ 1890 */
@@ -1892,18 +1929,7 @@ static int _nfs4_do_open(struct inode *dir,
1892 if (dentry->d_inode != NULL) 1929 if (dentry->d_inode != NULL)
1893 opendata->state = nfs4_get_open_state(dentry->d_inode, sp); 1930 opendata->state = nfs4_get_open_state(dentry->d_inode, sp);
1894 1931
1895 status = _nfs4_proc_open(opendata); 1932 status = _nfs4_open_and_get_state(opendata, fmode, flags, &state);
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);
1907 if (status != 0) 1933 if (status != 0)
1908 goto err_opendata_put; 1934 goto err_opendata_put;
1909 1935