aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/callback.c2
-rw-r--r--fs/nfs/dns_resolve.c5
-rw-r--r--fs/nfs/inode.c5
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/mount_clnt.c2
-rw-r--r--fs/nfs/namespace.c19
-rw-r--r--fs/nfs/nfs4filelayout.c21
-rw-r--r--fs/nfs/nfs4filelayout.h1
-rw-r--r--fs/nfs/nfs4filelayoutdev.c22
-rw-r--r--fs/nfs/nfs4getroot.c1
-rw-r--r--fs/nfs/nfs4namespace.c3
-rw-r--r--fs/nfs/nfs4proc.c46
-rw-r--r--fs/nfs/objlayout/objio_osd.c6
-rw-r--r--fs/nfs/pnfs.c4
-rw-r--r--fs/nfs/pnfs.h1
-rw-r--r--fs/nfs/super.c51
-rw-r--r--fs/nfs/unlink.c2
17 files changed, 131 insertions, 66 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 9a521fb39869..5088b57b078a 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
241 svc_exit_thread(cb_info->rqst); 241 svc_exit_thread(cb_info->rqst);
242 cb_info->rqst = NULL; 242 cb_info->rqst = NULL;
243 cb_info->task = NULL; 243 cb_info->task = NULL;
244 return PTR_ERR(cb_info->task); 244 return ret;
245 } 245 }
246 dprintk("nfs_callback_up: service started\n"); 246 dprintk("nfs_callback_up: service started\n");
247 return 0; 247 return 0;
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index 31c26c4dcc23..ca4b11ec87a2 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
217{ 217{
218 char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; 218 char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
219 struct nfs_dns_ent key, *item; 219 struct nfs_dns_ent key, *item;
220 unsigned long ttl; 220 unsigned int ttl;
221 ssize_t len; 221 ssize_t len;
222 int ret = -EINVAL; 222 int ret = -EINVAL;
223 223
@@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
240 key.namelen = len; 240 key.namelen = len;
241 memset(&key.h, 0, sizeof(key.h)); 241 memset(&key.h, 0, sizeof(key.h));
242 242
243 ttl = get_expiry(&buf); 243 if (get_uint(&buf, &ttl) < 0)
244 goto out;
244 if (ttl == 0) 245 if (ttl == 0)
245 goto out; 246 goto out;
246 key.h.expiry_time = ttl + seconds_since_boot(); 247 key.h.expiry_time = ttl + seconds_since_boot();
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5c7325c5c5e6..6fa01aea2488 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
685 if (ctx->cred != NULL) 685 if (ctx->cred != NULL)
686 put_rpccred(ctx->cred); 686 put_rpccred(ctx->cred);
687 dput(ctx->dentry); 687 dput(ctx->dentry);
688 nfs_sb_deactive(sb); 688 if (is_sync)
689 nfs_sb_deactive(sb);
690 else
691 nfs_sb_deactive_async(sb);
689 kfree(ctx->mdsthreshold); 692 kfree(ctx->mdsthreshold);
690 kfree(ctx); 693 kfree(ctx);
691} 694}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 59b133c5d652..05521cadac2e 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
351extern void __exit unregister_nfs_fs(void); 351extern void __exit unregister_nfs_fs(void);
352extern void nfs_sb_active(struct super_block *sb); 352extern void nfs_sb_active(struct super_block *sb);
353extern void nfs_sb_deactive(struct super_block *sb); 353extern void nfs_sb_deactive(struct super_block *sb);
354extern void nfs_sb_deactive_async(struct super_block *sb);
354 355
355/* namespace.c */ 356/* namespace.c */
357#define NFS_PATH_CANONICAL 1
356extern char *nfs_path(char **p, struct dentry *dentry, 358extern char *nfs_path(char **p, struct dentry *dentry,
357 char *buffer, ssize_t buflen); 359 char *buffer, ssize_t buflen, unsigned flags);
358extern struct vfsmount *nfs_d_automount(struct path *path); 360extern struct vfsmount *nfs_d_automount(struct path *path);
359struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, 361struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
360 struct nfs_fh *, struct nfs_fattr *); 362 struct nfs_fh *, struct nfs_fattr *);
@@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
498 char *buffer, ssize_t buflen) 500 char *buffer, ssize_t buflen)
499{ 501{
500 char *dummy; 502 char *dummy;
501 return nfs_path(&dummy, dentry, buffer, buflen); 503 return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
502} 504}
503 505
504/* 506/*
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 8e65c7f1f87c..015f71f8f62c 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
181 else 181 else
182 msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; 182 msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
183 183
184 status = rpc_call_sync(mnt_clnt, &msg, 0); 184 status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
185 rpc_shutdown_client(mnt_clnt); 185 rpc_shutdown_client(mnt_clnt);
186 186
187 if (status < 0) 187 if (status < 0)
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 655925373b91..dd057bc6b65b 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
33 * @dentry - pointer to dentry 33 * @dentry - pointer to dentry
34 * @buffer - result buffer 34 * @buffer - result buffer
35 * @buflen - length of buffer 35 * @buflen - length of buffer
36 * @flags - options (see below)
36 * 37 *
37 * Helper function for constructing the server pathname 38 * Helper function for constructing the server pathname
38 * by arbitrary hashed dentry. 39 * by arbitrary hashed dentry.
@@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
40 * This is mainly for use in figuring out the path on the 41 * This is mainly for use in figuring out the path on the
41 * server side when automounting on top of an existing partition 42 * server side when automounting on top of an existing partition
42 * and in generating /proc/mounts and friends. 43 * and in generating /proc/mounts and friends.
44 *
45 * Supported flags:
46 * NFS_PATH_CANONICAL: ensure there is exactly one slash after
47 * the original device (export) name
48 * (if unset, the original name is returned verbatim)
43 */ 49 */
44char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) 50char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
51 unsigned flags)
45{ 52{
46 char *end; 53 char *end;
47 int namelen; 54 int namelen;
@@ -74,7 +81,7 @@ rename_retry:
74 rcu_read_unlock(); 81 rcu_read_unlock();
75 goto rename_retry; 82 goto rename_retry;
76 } 83 }
77 if (*end != '/') { 84 if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
78 if (--buflen < 0) { 85 if (--buflen < 0) {
79 spin_unlock(&dentry->d_lock); 86 spin_unlock(&dentry->d_lock);
80 rcu_read_unlock(); 87 rcu_read_unlock();
@@ -91,9 +98,11 @@ rename_retry:
91 return end; 98 return end;
92 } 99 }
93 namelen = strlen(base); 100 namelen = strlen(base);
94 /* Strip off excess slashes in base string */ 101 if (flags & NFS_PATH_CANONICAL) {
95 while (namelen > 0 && base[namelen - 1] == '/') 102 /* Strip off excess slashes in base string */
96 namelen--; 103 while (namelen > 0 && base[namelen - 1] == '/')
104 namelen--;
105 }
97 buflen -= namelen; 106 buflen -= namelen;
98 if (buflen < 0) { 107 if (buflen < 0) {
99 spin_unlock(&dentry->d_lock); 108 spin_unlock(&dentry->d_lock);
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 52d847212066..2e45fd9c02a3 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data)
122 } 122 }
123} 123}
124 124
125static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
126{
127 if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
128 return;
129 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
130 pnfs_return_layout(inode);
131}
132
125static int filelayout_async_handle_error(struct rpc_task *task, 133static int filelayout_async_handle_error(struct rpc_task *task,
126 struct nfs4_state *state, 134 struct nfs4_state *state,
127 struct nfs_client *clp, 135 struct nfs_client *clp,
128 struct pnfs_layout_segment *lseg) 136 struct pnfs_layout_segment *lseg)
129{ 137{
130 struct inode *inode = lseg->pls_layout->plh_inode; 138 struct pnfs_layout_hdr *lo = lseg->pls_layout;
139 struct inode *inode = lo->plh_inode;
131 struct nfs_server *mds_server = NFS_SERVER(inode); 140 struct nfs_server *mds_server = NFS_SERVER(inode);
132 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); 141 struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
133 struct nfs_client *mds_client = mds_server->nfs_client; 142 struct nfs_client *mds_client = mds_server->nfs_client;
@@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
204 dprintk("%s DS connection error %d\n", __func__, 213 dprintk("%s DS connection error %d\n", __func__,
205 task->tk_status); 214 task->tk_status);
206 nfs4_mark_deviceid_unavailable(devid); 215 nfs4_mark_deviceid_unavailable(devid);
207 clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); 216 set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
208 _pnfs_return_layout(inode);
209 rpc_wake_up(&tbl->slot_tbl_waitq); 217 rpc_wake_up(&tbl->slot_tbl_waitq);
210 nfs4_ds_disconnect(clp);
211 /* fall through */ 218 /* fall through */
212 default: 219 default:
213reset: 220reset:
@@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data)
331static void filelayout_read_release(void *data) 338static void filelayout_read_release(void *data)
332{ 339{
333 struct nfs_read_data *rdata = data; 340 struct nfs_read_data *rdata = data;
341 struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;
334 342
343 filelayout_fenceme(lo->plh_inode, lo);
335 nfs_put_client(rdata->ds_clp); 344 nfs_put_client(rdata->ds_clp);
336 rdata->header->mds_ops->rpc_release(data); 345 rdata->header->mds_ops->rpc_release(data);
337} 346}
@@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data)
429static void filelayout_write_release(void *data) 438static void filelayout_write_release(void *data)
430{ 439{
431 struct nfs_write_data *wdata = data; 440 struct nfs_write_data *wdata = data;
441 struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;
432 442
443 filelayout_fenceme(lo->plh_inode, lo);
433 nfs_put_client(wdata->ds_clp); 444 nfs_put_client(wdata->ds_clp);
434 wdata->header->mds_ops->rpc_release(data); 445 wdata->header->mds_ops->rpc_release(data);
435} 446}
@@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
739 goto out_err; 750 goto out_err;
740 751
741 if (fl->num_fh > 0) { 752 if (fl->num_fh > 0) {
742 fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), 753 fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
743 gfp_flags); 754 gfp_flags);
744 if (!fl->fh_array) 755 if (!fl->fh_array)
745 goto out_err; 756 goto out_err;
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index dca47d786710..8c07241fe52b 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
149extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); 149extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
150struct nfs4_file_layout_dsaddr * 150struct nfs4_file_layout_dsaddr *
151filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); 151filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
152void nfs4_ds_disconnect(struct nfs_client *clp);
153 152
154#endif /* FS_NFS_NFS4FILELAYOUT_H */ 153#endif /* FS_NFS_NFS4FILELAYOUT_H */
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 3336d5eaf879..a8eaa9b7bb0f 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -149,28 +149,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
149} 149}
150 150
151/* 151/*
152 * Lookup DS by nfs_client pointer. Zero data server client pointer
153 */
154void nfs4_ds_disconnect(struct nfs_client *clp)
155{
156 struct nfs4_pnfs_ds *ds;
157 struct nfs_client *found = NULL;
158
159 dprintk("%s clp %p\n", __func__, clp);
160 spin_lock(&nfs4_ds_cache_lock);
161 list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
162 if (ds->ds_clp && ds->ds_clp == clp) {
163 found = ds->ds_clp;
164 ds->ds_clp = NULL;
165 }
166 spin_unlock(&nfs4_ds_cache_lock);
167 if (found) {
168 set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
169 nfs_put_client(clp);
170 }
171}
172
173/*
174 * Create an rpc connection to the nfs4_pnfs_ds data server 152 * Create an rpc connection to the nfs4_pnfs_ds data server
175 * Currently only supports IPv4 and IPv6 addresses 153 * Currently only supports IPv4 and IPv6 addresses
176 */ 154 */
diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c
index 6a83780e0ce6..549462e5b9b0 100644
--- a/fs/nfs/nfs4getroot.c
+++ b/fs/nfs/nfs4getroot.c
@@ -5,6 +5,7 @@
5 5
6#include <linux/nfs_fs.h> 6#include <linux/nfs_fs.h>
7#include "nfs4_fs.h" 7#include "nfs4_fs.h"
8#include "internal.h"
8 9
9#define NFSDBG_FACILITY NFSDBG_CLIENT 10#define NFSDBG_FACILITY NFSDBG_CLIENT
10 11
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 79fbb61ce202..1e09eb78543b 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
81static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) 81static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
82{ 82{
83 char *limit; 83 char *limit;
84 char *path = nfs_path(&limit, dentry, buffer, buflen); 84 char *path = nfs_path(&limit, dentry, buffer, buflen,
85 NFS_PATH_CANONICAL);
85 if (!IS_ERR(path)) { 86 if (!IS_ERR(path)) {
86 char *path_component = nfs_path_component(path, limit); 87 char *path_component = nfs_path_component(path, limit);
87 if (path_component) 88 if (path_component)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 68b21d81b7ac..5eec4429970c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
339 dprintk("%s ERROR: %d Reset session\n", __func__, 339 dprintk("%s ERROR: %d Reset session\n", __func__,
340 errorcode); 340 errorcode);
341 nfs4_schedule_session_recovery(clp->cl_session, errorcode); 341 nfs4_schedule_session_recovery(clp->cl_session, errorcode);
342 exception->retry = 1; 342 goto wait_on_recovery;
343 break;
344#endif /* defined(CONFIG_NFS_V4_1) */ 343#endif /* defined(CONFIG_NFS_V4_1) */
345 case -NFS4ERR_FILE_OPEN: 344 case -NFS4ERR_FILE_OPEN:
346 if (exception->timeout > HZ) { 345 if (exception->timeout > HZ) {
@@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
1572 data->timestamp = jiffies; 1571 data->timestamp = jiffies;
1573 if (nfs4_setup_sequence(data->o_arg.server, 1572 if (nfs4_setup_sequence(data->o_arg.server,
1574 &data->o_arg.seq_args, 1573 &data->o_arg.seq_args,
1575 &data->o_res.seq_res, task)) 1574 &data->o_res.seq_res,
1576 return; 1575 task) != 0)
1577 rpc_call_start(task); 1576 nfs_release_seqid(data->o_arg.seqid);
1577 else
1578 rpc_call_start(task);
1578 return; 1579 return;
1579unlock_no_action: 1580unlock_no_action:
1580 rcu_read_unlock(); 1581 rcu_read_unlock();
@@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
1748 1749
1749 /* even though OPEN succeeded, access is denied. Close the file */ 1750 /* even though OPEN succeeded, access is denied. Close the file */
1750 nfs4_close_state(state, fmode); 1751 nfs4_close_state(state, fmode);
1751 return -NFS4ERR_ACCESS; 1752 return -EACCES;
1752} 1753}
1753 1754
1754/* 1755/*
@@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
2196 nfs4_put_open_state(calldata->state); 2197 nfs4_put_open_state(calldata->state);
2197 nfs_free_seqid(calldata->arg.seqid); 2198 nfs_free_seqid(calldata->arg.seqid);
2198 nfs4_put_state_owner(sp); 2199 nfs4_put_state_owner(sp);
2199 nfs_sb_deactive(sb); 2200 nfs_sb_deactive_async(sb);
2200 kfree(calldata); 2201 kfree(calldata);
2201} 2202}
2202 2203
@@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
2296 if (nfs4_setup_sequence(NFS_SERVER(inode), 2297 if (nfs4_setup_sequence(NFS_SERVER(inode),
2297 &calldata->arg.seq_args, 2298 &calldata->arg.seq_args,
2298 &calldata->res.seq_res, 2299 &calldata->res.seq_res,
2299 task)) 2300 task) != 0)
2300 goto out; 2301 nfs_release_seqid(calldata->arg.seqid);
2301 rpc_call_start(task); 2302 else
2303 rpc_call_start(task);
2302out: 2304out:
2303 dprintk("%s: done!\n", __func__); 2305 dprintk("%s: done!\n", __func__);
2304} 2306}
@@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
4529 if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) 4531 if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
4530 rpc_restart_call_prepare(task); 4532 rpc_restart_call_prepare(task);
4531 } 4533 }
4534 nfs_release_seqid(calldata->arg.seqid);
4532} 4535}
4533 4536
4534static void nfs4_locku_prepare(struct rpc_task *task, void *data) 4537static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
4545 calldata->timestamp = jiffies; 4548 calldata->timestamp = jiffies;
4546 if (nfs4_setup_sequence(calldata->server, 4549 if (nfs4_setup_sequence(calldata->server,
4547 &calldata->arg.seq_args, 4550 &calldata->arg.seq_args,
4548 &calldata->res.seq_res, task)) 4551 &calldata->res.seq_res,
4549 return; 4552 task) != 0)
4550 rpc_call_start(task); 4553 nfs_release_seqid(calldata->arg.seqid);
4554 else
4555 rpc_call_start(task);
4551} 4556}
4552 4557
4553static const struct rpc_call_ops nfs4_locku_ops = { 4558static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
4692 /* Do we need to do an open_to_lock_owner? */ 4697 /* Do we need to do an open_to_lock_owner? */
4693 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { 4698 if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
4694 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) 4699 if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
4695 return; 4700 goto out_release_lock_seqid;
4696 data->arg.open_stateid = &state->stateid; 4701 data->arg.open_stateid = &state->stateid;
4697 data->arg.new_lock_owner = 1; 4702 data->arg.new_lock_owner = 1;
4698 data->res.open_seqid = data->arg.open_seqid; 4703 data->res.open_seqid = data->arg.open_seqid;
@@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
4701 data->timestamp = jiffies; 4706 data->timestamp = jiffies;
4702 if (nfs4_setup_sequence(data->server, 4707 if (nfs4_setup_sequence(data->server,
4703 &data->arg.seq_args, 4708 &data->arg.seq_args,
4704 &data->res.seq_res, task)) 4709 &data->res.seq_res,
4710 task) == 0) {
4711 rpc_call_start(task);
4705 return; 4712 return;
4706 rpc_call_start(task); 4713 }
4707 dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); 4714 nfs_release_seqid(data->arg.open_seqid);
4715out_release_lock_seqid:
4716 nfs_release_seqid(data->arg.lock_seqid);
4717 dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
4708} 4718}
4709 4719
4710static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) 4720static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
@@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
5667 tbl->slots = new; 5677 tbl->slots = new;
5668 tbl->max_slots = max_slots; 5678 tbl->max_slots = max_slots;
5669 } 5679 }
5670 tbl->highest_used_slotid = -1; /* no slot is currently used */ 5680 tbl->highest_used_slotid = NFS4_NO_SLOT;
5671 for (i = 0; i < tbl->max_slots; i++) 5681 for (i = 0; i < tbl->max_slots; i++)
5672 tbl->slots[i].seq_nr = ivalue; 5682 tbl->slots[i].seq_nr = ivalue;
5673 spin_unlock(&tbl->slot_tbl_lock); 5683 spin_unlock(&tbl->slot_tbl_lock);
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index be731e6b7b9c..c6f990656f89 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir)
369 kfree(objios); 369 kfree(objios);
370} 370}
371 371
372enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) 372static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
373{ 373{
374 switch (oep) { 374 switch (oep) {
375 case OSD_ERR_PRI_NO_ERROR: 375 case OSD_ERR_PRI_NO_ERROR:
@@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
574 (unsigned long)pgio->pg_layout_private; 574 (unsigned long)pgio->pg_layout_private;
575} 575}
576 576
577void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 577static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
578{ 578{
579 pnfs_generic_pg_init_read(pgio, req); 579 pnfs_generic_pg_init_read(pgio, req);
580 if (unlikely(pgio->pg_lseg == NULL)) 580 if (unlikely(pgio->pg_lseg == NULL))
@@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
604 return false; 604 return false;
605} 605}
606 606
607void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) 607static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
608{ 608{
609 unsigned long stripe_end = 0; 609 unsigned long stripe_end = 0;
610 u64 wb_size; 610 u64 wb_size;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index fe624c91bd00..2878f97bd78d 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
925 if (likely(nfsi->layout == NULL)) { /* Won the race? */ 925 if (likely(nfsi->layout == NULL)) { /* Won the race? */
926 nfsi->layout = new; 926 nfsi->layout = new;
927 return new; 927 return new;
928 } 928 } else if (new != NULL)
929 pnfs_free_layout_hdr(new); 929 pnfs_free_layout_hdr(new);
930out_existing: 930out_existing:
931 pnfs_get_layout_hdr(nfsi->layout); 931 pnfs_get_layout_hdr(nfsi->layout);
932 return nfsi->layout; 932 return nfsi->layout;
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 2d722dba1111..dbf7bba52da0 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -62,6 +62,7 @@ enum {
62 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ 62 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
63 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ 63 NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */
64 NFS_LAYOUT_ROC, /* some lseg had roc bit set */ 64 NFS_LAYOUT_ROC, /* some lseg had roc bit set */
65 NFS_LAYOUT_RETURN, /* Return this layout ASAP */
65}; 66};
66 67
67enum layoutdriver_policy_flags { 68enum layoutdriver_policy_flags {
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index e831bce49766..652d3f7176a9 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -54,6 +54,7 @@
54#include <linux/parser.h> 54#include <linux/parser.h>
55#include <linux/nsproxy.h> 55#include <linux/nsproxy.h>
56#include <linux/rcupdate.h> 56#include <linux/rcupdate.h>
57#include <linux/kthread.h>
57 58
58#include <asm/uaccess.h> 59#include <asm/uaccess.h>
59 60
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
415} 416}
416EXPORT_SYMBOL_GPL(nfs_sb_deactive); 417EXPORT_SYMBOL_GPL(nfs_sb_deactive);
417 418
419static int nfs_deactivate_super_async_work(void *ptr)
420{
421 struct super_block *sb = ptr;
422
423 deactivate_super(sb);
424 module_put_and_exit(0);
425 return 0;
426}
427
428/*
429 * same effect as deactivate_super, but will do final unmount in kthread
430 * context
431 */
432static void nfs_deactivate_super_async(struct super_block *sb)
433{
434 struct task_struct *task;
435 char buf[INET6_ADDRSTRLEN + 1];
436 struct nfs_server *server = NFS_SB(sb);
437 struct nfs_client *clp = server->nfs_client;
438
439 if (!atomic_add_unless(&sb->s_active, -1, 1)) {
440 rcu_read_lock();
441 snprintf(buf, sizeof(buf),
442 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
443 rcu_read_unlock();
444
445 __module_get(THIS_MODULE);
446 task = kthread_run(nfs_deactivate_super_async_work, sb,
447 "%s-deactivate-super", buf);
448 if (IS_ERR(task)) {
449 pr_err("%s: kthread_run: %ld\n",
450 __func__, PTR_ERR(task));
451 /* make synchronous call and hope for the best */
452 deactivate_super(sb);
453 module_put(THIS_MODULE);
454 }
455 }
456}
457
458void nfs_sb_deactive_async(struct super_block *sb)
459{
460 struct nfs_server *server = NFS_SB(sb);
461
462 if (atomic_dec_and_test(&server->active))
463 nfs_deactivate_super_async(sb);
464}
465EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
466
418/* 467/*
419 * Deliver file system statistics to userspace 468 * Deliver file system statistics to userspace
420 */ 469 */
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
771 int err = 0; 820 int err = 0;
772 if (!page) 821 if (!page)
773 return -ENOMEM; 822 return -ENOMEM;
774 devname = nfs_path(&dummy, root, page, PAGE_SIZE); 823 devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
775 if (IS_ERR(devname)) 824 if (IS_ERR(devname))
776 err = PTR_ERR(devname); 825 err = PTR_ERR(devname);
777 else 826 else
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 13cea637eff8..3f79c77153b8 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
95 95
96 nfs_dec_sillycount(data->dir); 96 nfs_dec_sillycount(data->dir);
97 nfs_free_unlinkdata(data); 97 nfs_free_unlinkdata(data);
98 nfs_sb_deactive(sb); 98 nfs_sb_deactive_async(sb);
99} 99}
100 100
101static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) 101static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)