diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/callback.c | 2 | ||||
-rw-r--r-- | fs/nfs/dns_resolve.c | 5 | ||||
-rw-r--r-- | fs/nfs/inode.c | 5 | ||||
-rw-r--r-- | fs/nfs/internal.h | 6 | ||||
-rw-r--r-- | fs/nfs/mount_clnt.c | 2 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 19 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 21 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 22 | ||||
-rw-r--r-- | fs/nfs/nfs4getroot.c | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4namespace.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 46 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 6 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 1 | ||||
-rw-r--r-- | fs/nfs/super.c | 51 | ||||
-rw-r--r-- | fs/nfs/unlink.c | 2 |
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); | |||
351 | extern void __exit unregister_nfs_fs(void); | 351 | extern void __exit unregister_nfs_fs(void); |
352 | extern void nfs_sb_active(struct super_block *sb); | 352 | extern void nfs_sb_active(struct super_block *sb); |
353 | extern void nfs_sb_deactive(struct super_block *sb); | 353 | extern void nfs_sb_deactive(struct super_block *sb); |
354 | extern void nfs_sb_deactive_async(struct super_block *sb); | ||
354 | 355 | ||
355 | /* namespace.c */ | 356 | /* namespace.c */ |
357 | #define NFS_PATH_CANONICAL 1 | ||
356 | extern char *nfs_path(char **p, struct dentry *dentry, | 358 | extern char *nfs_path(char **p, struct dentry *dentry, |
357 | char *buffer, ssize_t buflen); | 359 | char *buffer, ssize_t buflen, unsigned flags); |
358 | extern struct vfsmount *nfs_d_automount(struct path *path); | 360 | extern struct vfsmount *nfs_d_automount(struct path *path); |
359 | struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *, | 361 | struct 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 | */ |
44 | char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) | 50 | char *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 | ||
125 | static 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 | |||
125 | static int filelayout_async_handle_error(struct rpc_task *task, | 133 | static 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: |
213 | reset: | 220 | reset: |
@@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data) | |||
331 | static void filelayout_read_release(void *data) | 338 | static 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) | |||
429 | static void filelayout_write_release(void *data) | 438 | static 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); | |||
149 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 149 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
150 | struct nfs4_file_layout_dsaddr * | 150 | struct nfs4_file_layout_dsaddr * |
151 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); | 151 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); |
152 | void 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 | */ | ||
154 | void 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) | |||
81 | static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) | 81 | static 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; |
1579 | unlock_no_action: | 1580 | unlock_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); | ||
2302 | out: | 2304 | out: |
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 | ||
4534 | static void nfs4_locku_prepare(struct rpc_task *task, void *data) | 4537 | static 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 | ||
4553 | static const struct rpc_call_ops nfs4_locku_ops = { | 4558 | static 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); |
4715 | out_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 | ||
4710 | static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) | 4720 | static 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 | ||
372 | enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) | 372 | static 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 | ||
577 | void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 577 | static 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 | ||
607 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 607 | static 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); |
930 | out_existing: | 930 | out_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 | ||
67 | enum layoutdriver_policy_flags { | 68 | enum 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 | } |
416 | EXPORT_SYMBOL_GPL(nfs_sb_deactive); | 417 | EXPORT_SYMBOL_GPL(nfs_sb_deactive); |
417 | 418 | ||
419 | static 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 | */ | ||
432 | static 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 | |||
458 | void 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 | } | ||
465 | EXPORT_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 | ||
101 | static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) | 101 | static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) |