diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-22 12:57:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-22 12:57:25 -0400 |
commit | ad746be96941ddd2fb31fad7a629de7912051c8d (patch) | |
tree | c94cc4d13d7595973c72e95dc093ef5404cb3b43 /fs | |
parent | 467e9e51d07d43d32a1dd8b6ead2351e28fff084 (diff) | |
parent | 086600430493e04b802bee6e5b3ce0458e4eb77f (diff) |
Merge tag 'nfs-for-3.6-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust:
- NFSv3 mounts need to fail if the FSINFO rpc call fails
- Ensure that the NFS commit cache gets torn down when we unload the
NFS module.
- Fix memory scribble issues when interrupting a LAYOUTGET rpc call
- Fix NFSv4 legacy idmapper regressions
- Fix issues with the NFSv4 getacl command
- Fix a regression when using the legacy "mount -t nfs4"
* tag 'nfs-for-3.6-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
NFSv3: Ensure that do_proc_get_root() reports errors correctly
NFSv4: Ensure that nfs4_alloc_client cleans up on error.
NFS: return -ENOKEY when the upcall fails to map the name
NFS: Clear key construction data if the idmap upcall fails
NFSv4: Don't use private xdr_stream fields in decode_getacl
NFSv4: Fix the acl cache size calculation
NFSv4: Fix pointer arithmetic in decode_getacl
NFS: Alias the nfs module to nfs4
NFS: Fix a regression when loading the NFS v4 module
NFSv4.1: Remove a bogus BUG_ON() in nfs4_layoutreturn_done
pnfs-obj: Better IO pattern in case of unaligned offset
NFS41: add pg_layout_private to nfs_pageio_descriptor
pnfs: nfs4_proc_layoutget returns void
pnfs: defer release of pages in layoutget
nfs: tear down caches in nfs_init_writepagecache when allocation fails
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/Makefile | 18 | ||||
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 62 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 76 | ||||
-rw-r--r-- | fs/nfs/nfs4super.c | 15 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 26 | ||||
-rw-r--r-- | fs/nfs/objlayout/objio_osd.c | 55 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 39 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 2 | ||||
-rw-r--r-- | fs/nfs/super.c | 39 | ||||
-rw-r--r-- | fs/nfs/write.c | 15 |
15 files changed, 239 insertions, 119 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index 8bf3a3f6925a..b7db60897f91 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile | |||
@@ -12,19 +12,19 @@ nfs-$(CONFIG_ROOT_NFS) += nfsroot.o | |||
12 | nfs-$(CONFIG_SYSCTL) += sysctl.o | 12 | nfs-$(CONFIG_SYSCTL) += sysctl.o |
13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o | 13 | nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o |
14 | 14 | ||
15 | obj-$(CONFIG_NFS_V2) += nfs2.o | 15 | obj-$(CONFIG_NFS_V2) += nfsv2.o |
16 | nfs2-y := nfs2super.o proc.o nfs2xdr.o | 16 | nfsv2-y := nfs2super.o proc.o nfs2xdr.o |
17 | 17 | ||
18 | obj-$(CONFIG_NFS_V3) += nfs3.o | 18 | obj-$(CONFIG_NFS_V3) += nfsv3.o |
19 | nfs3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o | 19 | nfsv3-y := nfs3super.o nfs3client.o nfs3proc.o nfs3xdr.o |
20 | nfs3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o | 20 | nfsv3-$(CONFIG_NFS_V3_ACL) += nfs3acl.o |
21 | 21 | ||
22 | obj-$(CONFIG_NFS_V4) += nfs4.o | 22 | obj-$(CONFIG_NFS_V4) += nfsv4.o |
23 | nfs4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ | 23 | nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ |
24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ | 24 | delegation.o idmap.o callback.o callback_xdr.o callback_proc.o \ |
25 | nfs4namespace.o nfs4getroot.o nfs4client.o | 25 | nfs4namespace.o nfs4getroot.o nfs4client.o |
26 | nfs4-$(CONFIG_SYSCTL) += nfs4sysctl.o | 26 | nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o |
27 | nfs4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o | 27 | nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o |
28 | 28 | ||
29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o | 29 | obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o |
30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o | 30 | nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 9fc0d9dfc91b..99694442b93f 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -105,7 +105,7 @@ struct nfs_subversion *get_nfs_version(unsigned int version) | |||
105 | 105 | ||
106 | if (IS_ERR(nfs)) { | 106 | if (IS_ERR(nfs)) { |
107 | mutex_lock(&nfs_version_mutex); | 107 | mutex_lock(&nfs_version_mutex); |
108 | request_module("nfs%d", version); | 108 | request_module("nfsv%d", version); |
109 | nfs = find_nfs_version(version); | 109 | nfs = find_nfs_version(version); |
110 | mutex_unlock(&nfs_version_mutex); | 110 | mutex_unlock(&nfs_version_mutex); |
111 | } | 111 | } |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b701358c39c3..a850079467d8 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -61,6 +61,12 @@ struct idmap { | |||
61 | struct mutex idmap_mutex; | 61 | struct mutex idmap_mutex; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct idmap_legacy_upcalldata { | ||
65 | struct rpc_pipe_msg pipe_msg; | ||
66 | struct idmap_msg idmap_msg; | ||
67 | struct idmap *idmap; | ||
68 | }; | ||
69 | |||
64 | /** | 70 | /** |
65 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields | 71 | * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields |
66 | * @fattr: fully initialised struct nfs_fattr | 72 | * @fattr: fully initialised struct nfs_fattr |
@@ -324,6 +330,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, | |||
324 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, | 330 | ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, |
325 | name, namelen, type, data, | 331 | name, namelen, type, data, |
326 | data_size, idmap); | 332 | data_size, idmap); |
333 | idmap->idmap_key_cons = NULL; | ||
327 | mutex_unlock(&idmap->idmap_mutex); | 334 | mutex_unlock(&idmap->idmap_mutex); |
328 | } | 335 | } |
329 | return ret; | 336 | return ret; |
@@ -380,11 +387,13 @@ static const match_table_t nfs_idmap_tokens = { | |||
380 | static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); | 387 | static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); |
381 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, | 388 | static ssize_t idmap_pipe_downcall(struct file *, const char __user *, |
382 | size_t); | 389 | size_t); |
390 | static void idmap_release_pipe(struct inode *); | ||
383 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); | 391 | static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); |
384 | 392 | ||
385 | static const struct rpc_pipe_ops idmap_upcall_ops = { | 393 | static const struct rpc_pipe_ops idmap_upcall_ops = { |
386 | .upcall = rpc_pipe_generic_upcall, | 394 | .upcall = rpc_pipe_generic_upcall, |
387 | .downcall = idmap_pipe_downcall, | 395 | .downcall = idmap_pipe_downcall, |
396 | .release_pipe = idmap_release_pipe, | ||
388 | .destroy_msg = idmap_pipe_destroy_msg, | 397 | .destroy_msg = idmap_pipe_destroy_msg, |
389 | }; | 398 | }; |
390 | 399 | ||
@@ -616,7 +625,8 @@ void nfs_idmap_quit(void) | |||
616 | nfs_idmap_quit_keyring(); | 625 | nfs_idmap_quit_keyring(); |
617 | } | 626 | } |
618 | 627 | ||
619 | static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, | 628 | static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, |
629 | struct idmap_msg *im, | ||
620 | struct rpc_pipe_msg *msg) | 630 | struct rpc_pipe_msg *msg) |
621 | { | 631 | { |
622 | substring_t substr; | 632 | substring_t substr; |
@@ -659,6 +669,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
659 | const char *op, | 669 | const char *op, |
660 | void *aux) | 670 | void *aux) |
661 | { | 671 | { |
672 | struct idmap_legacy_upcalldata *data; | ||
662 | struct rpc_pipe_msg *msg; | 673 | struct rpc_pipe_msg *msg; |
663 | struct idmap_msg *im; | 674 | struct idmap_msg *im; |
664 | struct idmap *idmap = (struct idmap *)aux; | 675 | struct idmap *idmap = (struct idmap *)aux; |
@@ -666,15 +677,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
666 | int ret = -ENOMEM; | 677 | int ret = -ENOMEM; |
667 | 678 | ||
668 | /* msg and im are freed in idmap_pipe_destroy_msg */ | 679 | /* msg and im are freed in idmap_pipe_destroy_msg */ |
669 | msg = kmalloc(sizeof(*msg), GFP_KERNEL); | 680 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
670 | if (!msg) | 681 | if (!data) |
671 | goto out0; | ||
672 | |||
673 | im = kmalloc(sizeof(*im), GFP_KERNEL); | ||
674 | if (!im) | ||
675 | goto out1; | 682 | goto out1; |
676 | 683 | ||
677 | ret = nfs_idmap_prepare_message(key->description, im, msg); | 684 | msg = &data->pipe_msg; |
685 | im = &data->idmap_msg; | ||
686 | data->idmap = idmap; | ||
687 | |||
688 | ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); | ||
678 | if (ret < 0) | 689 | if (ret < 0) |
679 | goto out2; | 690 | goto out2; |
680 | 691 | ||
@@ -683,15 +694,15 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, | |||
683 | 694 | ||
684 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); | 695 | ret = rpc_queue_upcall(idmap->idmap_pipe, msg); |
685 | if (ret < 0) | 696 | if (ret < 0) |
686 | goto out2; | 697 | goto out3; |
687 | 698 | ||
688 | return ret; | 699 | return ret; |
689 | 700 | ||
701 | out3: | ||
702 | idmap->idmap_key_cons = NULL; | ||
690 | out2: | 703 | out2: |
691 | kfree(im); | 704 | kfree(data); |
692 | out1: | 705 | out1: |
693 | kfree(msg); | ||
694 | out0: | ||
695 | complete_request_key(cons, ret); | 706 | complete_request_key(cons, ret); |
696 | return ret; | 707 | return ret; |
697 | } | 708 | } |
@@ -749,9 +760,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
749 | } | 760 | } |
750 | 761 | ||
751 | if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { | 762 | if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { |
752 | ret = mlen; | 763 | ret = -ENOKEY; |
753 | complete_request_key(cons, -ENOKEY); | 764 | goto out; |
754 | goto out_incomplete; | ||
755 | } | 765 | } |
756 | 766 | ||
757 | namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); | 767 | namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); |
@@ -768,16 +778,32 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
768 | 778 | ||
769 | out: | 779 | out: |
770 | complete_request_key(cons, ret); | 780 | complete_request_key(cons, ret); |
771 | out_incomplete: | ||
772 | return ret; | 781 | return ret; |
773 | } | 782 | } |
774 | 783 | ||
775 | static void | 784 | static void |
776 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) | 785 | idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) |
777 | { | 786 | { |
787 | struct idmap_legacy_upcalldata *data = container_of(msg, | ||
788 | struct idmap_legacy_upcalldata, | ||
789 | pipe_msg); | ||
790 | struct idmap *idmap = data->idmap; | ||
791 | struct key_construction *cons; | ||
792 | if (msg->errno) { | ||
793 | cons = ACCESS_ONCE(idmap->idmap_key_cons); | ||
794 | idmap->idmap_key_cons = NULL; | ||
795 | complete_request_key(cons, msg->errno); | ||
796 | } | ||
778 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ | 797 | /* Free memory allocated in nfs_idmap_legacy_upcall() */ |
779 | kfree(msg->data); | 798 | kfree(data); |
780 | kfree(msg); | 799 | } |
800 | |||
801 | static void | ||
802 | idmap_release_pipe(struct inode *inode) | ||
803 | { | ||
804 | struct rpc_inode *rpci = RPC_I(inode); | ||
805 | struct idmap *idmap = (struct idmap *)rpci->private; | ||
806 | idmap->idmap_key_cons = NULL; | ||
781 | } | 807 | } |
782 | 808 | ||
783 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) | 809 | int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 0952c791df36..d6b3b5f2d779 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, | |||
69 | nfs_fattr_init(info->fattr); | 69 | nfs_fattr_init(info->fattr); |
70 | status = rpc_call_sync(client, &msg, 0); | 70 | status = rpc_call_sync(client, &msg, 0); |
71 | dprintk("%s: reply fsinfo: %d\n", __func__, status); | 71 | dprintk("%s: reply fsinfo: %d\n", __func__, status); |
72 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { | 72 | if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { |
73 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; | 73 | msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; |
74 | msg.rpc_resp = info->fattr; | 74 | msg.rpc_resp = info->fattr; |
75 | status = rpc_call_sync(client, &msg, 0); | 75 | status = rpc_call_sync(client, &msg, 0); |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 3b950dd81e81..da0618aeeadb 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -205,6 +205,9 @@ extern const struct dentry_operations nfs4_dentry_operations; | |||
205 | int nfs_atomic_open(struct inode *, struct dentry *, struct file *, | 205 | int nfs_atomic_open(struct inode *, struct dentry *, struct file *, |
206 | unsigned, umode_t, int *); | 206 | unsigned, umode_t, int *); |
207 | 207 | ||
208 | /* super.c */ | ||
209 | extern struct file_system_type nfs4_fs_type; | ||
210 | |||
208 | /* nfs4namespace.c */ | 211 | /* nfs4namespace.c */ |
209 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); | 212 | rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); |
210 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); | 213 | struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *); |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index cbcdfaf32505..24eb663f8ed5 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -74,7 +74,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) | |||
74 | return clp; | 74 | return clp; |
75 | 75 | ||
76 | error: | 76 | error: |
77 | kfree(clp); | 77 | nfs_free_client(clp); |
78 | return ERR_PTR(err); | 78 | return ERR_PTR(err); |
79 | } | 79 | } |
80 | 80 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a99a8d948721..635274140b18 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3737,9 +3737,10 @@ out: | |||
3737 | static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) | 3737 | static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len) |
3738 | { | 3738 | { |
3739 | struct nfs4_cached_acl *acl; | 3739 | struct nfs4_cached_acl *acl; |
3740 | size_t buflen = sizeof(*acl) + acl_len; | ||
3740 | 3741 | ||
3741 | if (pages && acl_len <= PAGE_SIZE) { | 3742 | if (pages && buflen <= PAGE_SIZE) { |
3742 | acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL); | 3743 | acl = kmalloc(buflen, GFP_KERNEL); |
3743 | if (acl == NULL) | 3744 | if (acl == NULL) |
3744 | goto out; | 3745 | goto out; |
3745 | acl->cached = 1; | 3746 | acl->cached = 1; |
@@ -3819,7 +3820,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3819 | if (ret) | 3820 | if (ret) |
3820 | goto out_free; | 3821 | goto out_free; |
3821 | 3822 | ||
3822 | acl_len = res.acl_len - res.acl_data_offset; | 3823 | acl_len = res.acl_len; |
3823 | if (acl_len > args.acl_len) | 3824 | if (acl_len > args.acl_len) |
3824 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); | 3825 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); |
3825 | else | 3826 | else |
@@ -6223,11 +6224,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
6223 | dprintk("<-- %s\n", __func__); | 6224 | dprintk("<-- %s\n", __func__); |
6224 | } | 6225 | } |
6225 | 6226 | ||
6227 | static size_t max_response_pages(struct nfs_server *server) | ||
6228 | { | ||
6229 | u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
6230 | return nfs_page_array_len(0, max_resp_sz); | ||
6231 | } | ||
6232 | |||
6233 | static void nfs4_free_pages(struct page **pages, size_t size) | ||
6234 | { | ||
6235 | int i; | ||
6236 | |||
6237 | if (!pages) | ||
6238 | return; | ||
6239 | |||
6240 | for (i = 0; i < size; i++) { | ||
6241 | if (!pages[i]) | ||
6242 | break; | ||
6243 | __free_page(pages[i]); | ||
6244 | } | ||
6245 | kfree(pages); | ||
6246 | } | ||
6247 | |||
6248 | static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) | ||
6249 | { | ||
6250 | struct page **pages; | ||
6251 | int i; | ||
6252 | |||
6253 | pages = kcalloc(size, sizeof(struct page *), gfp_flags); | ||
6254 | if (!pages) { | ||
6255 | dprintk("%s: can't alloc array of %zu pages\n", __func__, size); | ||
6256 | return NULL; | ||
6257 | } | ||
6258 | |||
6259 | for (i = 0; i < size; i++) { | ||
6260 | pages[i] = alloc_page(gfp_flags); | ||
6261 | if (!pages[i]) { | ||
6262 | dprintk("%s: failed to allocate page\n", __func__); | ||
6263 | nfs4_free_pages(pages, size); | ||
6264 | return NULL; | ||
6265 | } | ||
6266 | } | ||
6267 | |||
6268 | return pages; | ||
6269 | } | ||
6270 | |||
6226 | static void nfs4_layoutget_release(void *calldata) | 6271 | static void nfs4_layoutget_release(void *calldata) |
6227 | { | 6272 | { |
6228 | struct nfs4_layoutget *lgp = calldata; | 6273 | struct nfs4_layoutget *lgp = calldata; |
6274 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | ||
6275 | size_t max_pages = max_response_pages(server); | ||
6229 | 6276 | ||
6230 | dprintk("--> %s\n", __func__); | 6277 | dprintk("--> %s\n", __func__); |
6278 | nfs4_free_pages(lgp->args.layout.pages, max_pages); | ||
6231 | put_nfs_open_context(lgp->args.ctx); | 6279 | put_nfs_open_context(lgp->args.ctx); |
6232 | kfree(calldata); | 6280 | kfree(calldata); |
6233 | dprintk("<-- %s\n", __func__); | 6281 | dprintk("<-- %s\n", __func__); |
@@ -6239,9 +6287,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { | |||
6239 | .rpc_release = nfs4_layoutget_release, | 6287 | .rpc_release = nfs4_layoutget_release, |
6240 | }; | 6288 | }; |
6241 | 6289 | ||
6242 | int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | 6290 | void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) |
6243 | { | 6291 | { |
6244 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6292 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
6293 | size_t max_pages = max_response_pages(server); | ||
6245 | struct rpc_task *task; | 6294 | struct rpc_task *task; |
6246 | struct rpc_message msg = { | 6295 | struct rpc_message msg = { |
6247 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6296 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
@@ -6259,12 +6308,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6259 | 6308 | ||
6260 | dprintk("--> %s\n", __func__); | 6309 | dprintk("--> %s\n", __func__); |
6261 | 6310 | ||
6311 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | ||
6312 | if (!lgp->args.layout.pages) { | ||
6313 | nfs4_layoutget_release(lgp); | ||
6314 | return; | ||
6315 | } | ||
6316 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | ||
6317 | |||
6262 | lgp->res.layoutp = &lgp->args.layout; | 6318 | lgp->res.layoutp = &lgp->args.layout; |
6263 | lgp->res.seq_res.sr_slot = NULL; | 6319 | lgp->res.seq_res.sr_slot = NULL; |
6264 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 6320 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6265 | task = rpc_run_task(&task_setup_data); | 6321 | task = rpc_run_task(&task_setup_data); |
6266 | if (IS_ERR(task)) | 6322 | if (IS_ERR(task)) |
6267 | return PTR_ERR(task); | 6323 | return; |
6268 | status = nfs4_wait_for_completion_rpc_task(task); | 6324 | status = nfs4_wait_for_completion_rpc_task(task); |
6269 | if (status == 0) | 6325 | if (status == 0) |
6270 | status = task->tk_status; | 6326 | status = task->tk_status; |
@@ -6272,7 +6328,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6272 | status = pnfs_layout_process(lgp); | 6328 | status = pnfs_layout_process(lgp); |
6273 | rpc_put_task(task); | 6329 | rpc_put_task(task); |
6274 | dprintk("<-- %s status=%d\n", __func__, status); | 6330 | dprintk("<-- %s status=%d\n", __func__, status); |
6275 | return status; | 6331 | return; |
6276 | } | 6332 | } |
6277 | 6333 | ||
6278 | static void | 6334 | static void |
@@ -6304,12 +6360,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6304 | return; | 6360 | return; |
6305 | } | 6361 | } |
6306 | spin_lock(&lo->plh_inode->i_lock); | 6362 | spin_lock(&lo->plh_inode->i_lock); |
6307 | if (task->tk_status == 0) { | 6363 | if (task->tk_status == 0 && lrp->res.lrs_present) |
6308 | if (lrp->res.lrs_present) { | 6364 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
6309 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | ||
6310 | } else | ||
6311 | BUG_ON(!list_empty(&lo->plh_segs)); | ||
6312 | } | ||
6313 | lo->plh_block_lgets--; | 6365 | lo->plh_block_lgets--; |
6314 | spin_unlock(&lo->plh_inode->i_lock); | 6366 | spin_unlock(&lo->plh_inode->i_lock); |
6315 | dprintk("<-- %s\n", __func__); | 6367 | dprintk("<-- %s\n", __func__); |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 12a31a9dbcdd..bd61221ad2c5 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -23,14 +23,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, | |||
23 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, | 23 | static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type, |
24 | int flags, const char *dev_name, void *raw_data); | 24 | int flags, const char *dev_name, void *raw_data); |
25 | 25 | ||
26 | static struct file_system_type nfs4_fs_type = { | ||
27 | .owner = THIS_MODULE, | ||
28 | .name = "nfs4", | ||
29 | .mount = nfs_fs_mount, | ||
30 | .kill_sb = nfs_kill_super, | ||
31 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
32 | }; | ||
33 | |||
34 | static struct file_system_type nfs4_remote_fs_type = { | 26 | static struct file_system_type nfs4_remote_fs_type = { |
35 | .owner = THIS_MODULE, | 27 | .owner = THIS_MODULE, |
36 | .name = "nfs4", | 28 | .name = "nfs4", |
@@ -344,14 +336,8 @@ static int __init init_nfs_v4(void) | |||
344 | if (err) | 336 | if (err) |
345 | goto out1; | 337 | goto out1; |
346 | 338 | ||
347 | err = register_filesystem(&nfs4_fs_type); | ||
348 | if (err < 0) | ||
349 | goto out2; | ||
350 | |||
351 | register_nfs_version(&nfs_v4); | 339 | register_nfs_version(&nfs_v4); |
352 | return 0; | 340 | return 0; |
353 | out2: | ||
354 | nfs4_unregister_sysctl(); | ||
355 | out1: | 341 | out1: |
356 | nfs_idmap_quit(); | 342 | nfs_idmap_quit(); |
357 | out: | 343 | out: |
@@ -361,7 +347,6 @@ out: | |||
361 | static void __exit exit_nfs_v4(void) | 347 | static void __exit exit_nfs_v4(void) |
362 | { | 348 | { |
363 | unregister_nfs_version(&nfs_v4); | 349 | unregister_nfs_version(&nfs_v4); |
364 | unregister_filesystem(&nfs4_fs_type); | ||
365 | nfs4_unregister_sysctl(); | 350 | nfs4_unregister_sysctl(); |
366 | nfs_idmap_quit(); | 351 | nfs_idmap_quit(); |
367 | } | 352 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index ca13483edd60..1bfbd67c556d 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -5045,22 +5045,19 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5045 | struct nfs_getaclres *res) | 5045 | struct nfs_getaclres *res) |
5046 | { | 5046 | { |
5047 | unsigned int savep; | 5047 | unsigned int savep; |
5048 | __be32 *bm_p; | ||
5049 | uint32_t attrlen, | 5048 | uint32_t attrlen, |
5050 | bitmap[3] = {0}; | 5049 | bitmap[3] = {0}; |
5051 | int status; | 5050 | int status; |
5052 | size_t page_len = xdr->buf->page_len; | 5051 | unsigned int pg_offset; |
5053 | 5052 | ||
5054 | res->acl_len = 0; | 5053 | res->acl_len = 0; |
5055 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) | 5054 | if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0) |
5056 | goto out; | 5055 | goto out; |
5057 | 5056 | ||
5058 | bm_p = xdr->p; | 5057 | xdr_enter_page(xdr, xdr->buf->page_len); |
5059 | res->acl_data_offset = be32_to_cpup(bm_p) + 2; | 5058 | |
5060 | res->acl_data_offset <<= 2; | 5059 | /* Calculate the offset of the page data */ |
5061 | /* Check if the acl data starts beyond the allocated buffer */ | 5060 | pg_offset = xdr->buf->head[0].iov_len; |
5062 | if (res->acl_data_offset > page_len) | ||
5063 | return -ERANGE; | ||
5064 | 5061 | ||
5065 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) | 5062 | if ((status = decode_attr_bitmap(xdr, bitmap)) != 0) |
5066 | goto out; | 5063 | goto out; |
@@ -5074,23 +5071,20 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
5074 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words | 5071 | /* The bitmap (xdr len + bitmaps) and the attr xdr len words |
5075 | * are stored with the acl data to handle the problem of | 5072 | * are stored with the acl data to handle the problem of |
5076 | * variable length bitmaps.*/ | 5073 | * variable length bitmaps.*/ |
5077 | xdr->p = bm_p; | 5074 | res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset; |
5078 | 5075 | ||
5079 | /* We ignore &savep and don't do consistency checks on | 5076 | /* We ignore &savep and don't do consistency checks on |
5080 | * the attr length. Let userspace figure it out.... */ | 5077 | * the attr length. Let userspace figure it out.... */ |
5081 | attrlen += res->acl_data_offset; | 5078 | res->acl_len = attrlen; |
5082 | if (attrlen > page_len) { | 5079 | if (attrlen > (xdr->nwords << 2)) { |
5083 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | 5080 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { |
5084 | /* getxattr interface called with a NULL buf */ | 5081 | /* getxattr interface called with a NULL buf */ |
5085 | res->acl_len = attrlen; | ||
5086 | goto out; | 5082 | goto out; |
5087 | } | 5083 | } |
5088 | dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", | 5084 | dprintk("NFS: acl reply: attrlen %u > page_len %u\n", |
5089 | attrlen, page_len); | 5085 | attrlen, xdr->nwords << 2); |
5090 | return -EINVAL; | 5086 | return -EINVAL; |
5091 | } | 5087 | } |
5092 | xdr_read_pages(xdr, attrlen); | ||
5093 | res->acl_len = attrlen; | ||
5094 | } else | 5088 | } else |
5095 | status = -EOPNOTSUPP; | 5089 | status = -EOPNOTSUPP; |
5096 | 5090 | ||
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index f50d3e8d6f22..ea6d111b03e9 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
@@ -570,17 +570,66 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
570 | return false; | 570 | return false; |
571 | 571 | ||
572 | return pgio->pg_count + req->wb_bytes <= | 572 | return pgio->pg_count + req->wb_bytes <= |
573 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | 573 | (unsigned long)pgio->pg_layout_private; |
574 | } | ||
575 | |||
576 | void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
577 | { | ||
578 | pnfs_generic_pg_init_read(pgio, req); | ||
579 | if (unlikely(pgio->pg_lseg == NULL)) | ||
580 | return; /* Not pNFS */ | ||
581 | |||
582 | pgio->pg_layout_private = (void *) | ||
583 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | ||
584 | } | ||
585 | |||
586 | static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, | ||
587 | unsigned long *stripe_end) | ||
588 | { | ||
589 | u32 stripe_off; | ||
590 | unsigned stripe_size; | ||
591 | |||
592 | if (layout->raid_algorithm == PNFS_OSD_RAID_0) | ||
593 | return true; | ||
594 | |||
595 | stripe_size = layout->stripe_unit * | ||
596 | (layout->group_width - layout->parity); | ||
597 | |||
598 | div_u64_rem(offset, stripe_size, &stripe_off); | ||
599 | if (!stripe_off) | ||
600 | return true; | ||
601 | |||
602 | *stripe_end = stripe_size - stripe_off; | ||
603 | return false; | ||
604 | } | ||
605 | |||
606 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | ||
607 | { | ||
608 | unsigned long stripe_end = 0; | ||
609 | |||
610 | pnfs_generic_pg_init_write(pgio, req); | ||
611 | if (unlikely(pgio->pg_lseg == NULL)) | ||
612 | return; /* Not pNFS */ | ||
613 | |||
614 | if (req->wb_offset || | ||
615 | !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE, | ||
616 | &OBJIO_LSEG(pgio->pg_lseg)->layout, | ||
617 | &stripe_end)) { | ||
618 | pgio->pg_layout_private = (void *)stripe_end; | ||
619 | } else { | ||
620 | pgio->pg_layout_private = (void *) | ||
621 | OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length; | ||
622 | } | ||
574 | } | 623 | } |
575 | 624 | ||
576 | static const struct nfs_pageio_ops objio_pg_read_ops = { | 625 | static const struct nfs_pageio_ops objio_pg_read_ops = { |
577 | .pg_init = pnfs_generic_pg_init_read, | 626 | .pg_init = objio_init_read, |
578 | .pg_test = objio_pg_test, | 627 | .pg_test = objio_pg_test, |
579 | .pg_doio = pnfs_generic_pg_readpages, | 628 | .pg_doio = pnfs_generic_pg_readpages, |
580 | }; | 629 | }; |
581 | 630 | ||
582 | static const struct nfs_pageio_ops objio_pg_write_ops = { | 631 | static const struct nfs_pageio_ops objio_pg_write_ops = { |
583 | .pg_init = pnfs_generic_pg_init_write, | 632 | .pg_init = objio_init_write, |
584 | .pg_test = objio_pg_test, | 633 | .pg_test = objio_pg_test, |
585 | .pg_doio = pnfs_generic_pg_writepages, | 634 | .pg_doio = pnfs_generic_pg_writepages, |
586 | }; | 635 | }; |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 1a6732ed04a4..311a79681e2b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -49,6 +49,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, | |||
49 | hdr->io_start = req_offset(hdr->req); | 49 | hdr->io_start = req_offset(hdr->req); |
50 | hdr->good_bytes = desc->pg_count; | 50 | hdr->good_bytes = desc->pg_count; |
51 | hdr->dreq = desc->pg_dreq; | 51 | hdr->dreq = desc->pg_dreq; |
52 | hdr->layout_private = desc->pg_layout_private; | ||
52 | hdr->release = release; | 53 | hdr->release = release; |
53 | hdr->completion_ops = desc->pg_completion_ops; | 54 | hdr->completion_ops = desc->pg_completion_ops; |
54 | if (hdr->completion_ops->init_hdr) | 55 | if (hdr->completion_ops->init_hdr) |
@@ -268,6 +269,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
268 | desc->pg_error = 0; | 269 | desc->pg_error = 0; |
269 | desc->pg_lseg = NULL; | 270 | desc->pg_lseg = NULL; |
270 | desc->pg_dreq = NULL; | 271 | desc->pg_dreq = NULL; |
272 | desc->pg_layout_private = NULL; | ||
271 | } | 273 | } |
272 | EXPORT_SYMBOL_GPL(nfs_pageio_init); | 274 | EXPORT_SYMBOL_GPL(nfs_pageio_init); |
273 | 275 | ||
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 76875bfcf19c..2e00feacd4be 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -583,9 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
583 | struct nfs_server *server = NFS_SERVER(ino); | 583 | struct nfs_server *server = NFS_SERVER(ino); |
584 | struct nfs4_layoutget *lgp; | 584 | struct nfs4_layoutget *lgp; |
585 | struct pnfs_layout_segment *lseg = NULL; | 585 | struct pnfs_layout_segment *lseg = NULL; |
586 | struct page **pages = NULL; | ||
587 | int i; | ||
588 | u32 max_resp_sz, max_pages; | ||
589 | 586 | ||
590 | dprintk("--> %s\n", __func__); | 587 | dprintk("--> %s\n", __func__); |
591 | 588 | ||
@@ -594,20 +591,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
594 | if (lgp == NULL) | 591 | if (lgp == NULL) |
595 | return NULL; | 592 | return NULL; |
596 | 593 | ||
597 | /* allocate pages for xdr post processing */ | ||
598 | max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
599 | max_pages = nfs_page_array_len(0, max_resp_sz); | ||
600 | |||
601 | pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); | ||
602 | if (!pages) | ||
603 | goto out_err_free; | ||
604 | |||
605 | for (i = 0; i < max_pages; i++) { | ||
606 | pages[i] = alloc_page(gfp_flags); | ||
607 | if (!pages[i]) | ||
608 | goto out_err_free; | ||
609 | } | ||
610 | |||
611 | lgp->args.minlength = PAGE_CACHE_SIZE; | 594 | lgp->args.minlength = PAGE_CACHE_SIZE; |
612 | if (lgp->args.minlength > range->length) | 595 | if (lgp->args.minlength > range->length) |
613 | lgp->args.minlength = range->length; | 596 | lgp->args.minlength = range->length; |
@@ -616,39 +599,19 @@ send_layoutget(struct pnfs_layout_hdr *lo, | |||
616 | lgp->args.type = server->pnfs_curr_ld->id; | 599 | lgp->args.type = server->pnfs_curr_ld->id; |
617 | lgp->args.inode = ino; | 600 | lgp->args.inode = ino; |
618 | lgp->args.ctx = get_nfs_open_context(ctx); | 601 | lgp->args.ctx = get_nfs_open_context(ctx); |
619 | lgp->args.layout.pages = pages; | ||
620 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | ||
621 | lgp->lsegpp = &lseg; | 602 | lgp->lsegpp = &lseg; |
622 | lgp->gfp_flags = gfp_flags; | 603 | lgp->gfp_flags = gfp_flags; |
623 | 604 | ||
624 | /* Synchronously retrieve layout information from server and | 605 | /* Synchronously retrieve layout information from server and |
625 | * store in lseg. | 606 | * store in lseg. |
626 | */ | 607 | */ |
627 | nfs4_proc_layoutget(lgp); | 608 | nfs4_proc_layoutget(lgp, gfp_flags); |
628 | if (!lseg) { | 609 | if (!lseg) { |
629 | /* remember that LAYOUTGET failed and suspend trying */ | 610 | /* remember that LAYOUTGET failed and suspend trying */ |
630 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); | 611 | set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); |
631 | } | 612 | } |
632 | 613 | ||
633 | /* free xdr pages */ | ||
634 | for (i = 0; i < max_pages; i++) | ||
635 | __free_page(pages[i]); | ||
636 | kfree(pages); | ||
637 | |||
638 | return lseg; | 614 | return lseg; |
639 | |||
640 | out_err_free: | ||
641 | /* free any allocated xdr pages, lgp as it's not used */ | ||
642 | if (pages) { | ||
643 | for (i = 0; i < max_pages; i++) { | ||
644 | if (!pages[i]) | ||
645 | break; | ||
646 | __free_page(pages[i]); | ||
647 | } | ||
648 | kfree(pages); | ||
649 | } | ||
650 | kfree(lgp); | ||
651 | return NULL; | ||
652 | } | 615 | } |
653 | 616 | ||
654 | /* | 617 | /* |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2c6c80503ba4..745aa1b39e7c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, | |||
172 | struct pnfs_devicelist *devlist); | 172 | struct pnfs_devicelist *devlist); |
173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, | 173 | extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, |
174 | struct pnfs_device *dev); | 174 | struct pnfs_device *dev); |
175 | extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); | 175 | extern void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); |
176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); | 176 | extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); |
177 | 177 | ||
178 | /* pnfs.c */ | 178 | /* pnfs.c */ |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ac6a3c55dce4..239aff7338eb 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -319,6 +319,34 @@ EXPORT_SYMBOL_GPL(nfs_sops); | |||
319 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); | 319 | static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *); |
320 | static int nfs4_validate_mount_data(void *options, | 320 | static int nfs4_validate_mount_data(void *options, |
321 | struct nfs_parsed_mount_data *args, const char *dev_name); | 321 | struct nfs_parsed_mount_data *args, const char *dev_name); |
322 | |||
323 | struct file_system_type nfs4_fs_type = { | ||
324 | .owner = THIS_MODULE, | ||
325 | .name = "nfs4", | ||
326 | .mount = nfs_fs_mount, | ||
327 | .kill_sb = nfs_kill_super, | ||
328 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | ||
329 | }; | ||
330 | EXPORT_SYMBOL_GPL(nfs4_fs_type); | ||
331 | |||
332 | static int __init register_nfs4_fs(void) | ||
333 | { | ||
334 | return register_filesystem(&nfs4_fs_type); | ||
335 | } | ||
336 | |||
337 | static void unregister_nfs4_fs(void) | ||
338 | { | ||
339 | unregister_filesystem(&nfs4_fs_type); | ||
340 | } | ||
341 | #else | ||
342 | static int __init register_nfs4_fs(void) | ||
343 | { | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static void unregister_nfs4_fs(void) | ||
348 | { | ||
349 | } | ||
322 | #endif | 350 | #endif |
323 | 351 | ||
324 | static struct shrinker acl_shrinker = { | 352 | static struct shrinker acl_shrinker = { |
@@ -337,12 +365,18 @@ int __init register_nfs_fs(void) | |||
337 | if (ret < 0) | 365 | if (ret < 0) |
338 | goto error_0; | 366 | goto error_0; |
339 | 367 | ||
340 | ret = nfs_register_sysctl(); | 368 | ret = register_nfs4_fs(); |
341 | if (ret < 0) | 369 | if (ret < 0) |
342 | goto error_1; | 370 | goto error_1; |
371 | |||
372 | ret = nfs_register_sysctl(); | ||
373 | if (ret < 0) | ||
374 | goto error_2; | ||
343 | register_shrinker(&acl_shrinker); | 375 | register_shrinker(&acl_shrinker); |
344 | return 0; | 376 | return 0; |
345 | 377 | ||
378 | error_2: | ||
379 | unregister_nfs4_fs(); | ||
346 | error_1: | 380 | error_1: |
347 | unregister_filesystem(&nfs_fs_type); | 381 | unregister_filesystem(&nfs_fs_type); |
348 | error_0: | 382 | error_0: |
@@ -356,6 +390,7 @@ void __exit unregister_nfs_fs(void) | |||
356 | { | 390 | { |
357 | unregister_shrinker(&acl_shrinker); | 391 | unregister_shrinker(&acl_shrinker); |
358 | nfs_unregister_sysctl(); | 392 | nfs_unregister_sysctl(); |
393 | unregister_nfs4_fs(); | ||
359 | unregister_filesystem(&nfs_fs_type); | 394 | unregister_filesystem(&nfs_fs_type); |
360 | } | 395 | } |
361 | 396 | ||
@@ -2645,4 +2680,6 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " | |||
2645 | module_param(send_implementation_id, ushort, 0644); | 2680 | module_param(send_implementation_id, ushort, 0644); |
2646 | MODULE_PARM_DESC(send_implementation_id, | 2681 | MODULE_PARM_DESC(send_implementation_id, |
2647 | "Send implementation ID with NFSv4.1 exchange_id"); | 2682 | "Send implementation ID with NFSv4.1 exchange_id"); |
2683 | MODULE_ALIAS("nfs4"); | ||
2684 | |||
2648 | #endif /* CONFIG_NFS_V4 */ | 2685 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5829d0ce7cfb..e3b55372726c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1814,19 +1814,19 @@ int __init nfs_init_writepagecache(void) | |||
1814 | nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, | 1814 | nfs_wdata_mempool = mempool_create_slab_pool(MIN_POOL_WRITE, |
1815 | nfs_wdata_cachep); | 1815 | nfs_wdata_cachep); |
1816 | if (nfs_wdata_mempool == NULL) | 1816 | if (nfs_wdata_mempool == NULL) |
1817 | return -ENOMEM; | 1817 | goto out_destroy_write_cache; |
1818 | 1818 | ||
1819 | nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", | 1819 | nfs_cdata_cachep = kmem_cache_create("nfs_commit_data", |
1820 | sizeof(struct nfs_commit_data), | 1820 | sizeof(struct nfs_commit_data), |
1821 | 0, SLAB_HWCACHE_ALIGN, | 1821 | 0, SLAB_HWCACHE_ALIGN, |
1822 | NULL); | 1822 | NULL); |
1823 | if (nfs_cdata_cachep == NULL) | 1823 | if (nfs_cdata_cachep == NULL) |
1824 | return -ENOMEM; | 1824 | goto out_destroy_write_mempool; |
1825 | 1825 | ||
1826 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, | 1826 | nfs_commit_mempool = mempool_create_slab_pool(MIN_POOL_COMMIT, |
1827 | nfs_wdata_cachep); | 1827 | nfs_wdata_cachep); |
1828 | if (nfs_commit_mempool == NULL) | 1828 | if (nfs_commit_mempool == NULL) |
1829 | return -ENOMEM; | 1829 | goto out_destroy_commit_cache; |
1830 | 1830 | ||
1831 | /* | 1831 | /* |
1832 | * NFS congestion size, scale with available memory. | 1832 | * NFS congestion size, scale with available memory. |
@@ -1849,11 +1849,20 @@ int __init nfs_init_writepagecache(void) | |||
1849 | nfs_congestion_kb = 256*1024; | 1849 | nfs_congestion_kb = 256*1024; |
1850 | 1850 | ||
1851 | return 0; | 1851 | return 0; |
1852 | |||
1853 | out_destroy_commit_cache: | ||
1854 | kmem_cache_destroy(nfs_cdata_cachep); | ||
1855 | out_destroy_write_mempool: | ||
1856 | mempool_destroy(nfs_wdata_mempool); | ||
1857 | out_destroy_write_cache: | ||
1858 | kmem_cache_destroy(nfs_wdata_cachep); | ||
1859 | return -ENOMEM; | ||
1852 | } | 1860 | } |
1853 | 1861 | ||
1854 | void nfs_destroy_writepagecache(void) | 1862 | void nfs_destroy_writepagecache(void) |
1855 | { | 1863 | { |
1856 | mempool_destroy(nfs_commit_mempool); | 1864 | mempool_destroy(nfs_commit_mempool); |
1865 | kmem_cache_destroy(nfs_cdata_cachep); | ||
1857 | mempool_destroy(nfs_wdata_mempool); | 1866 | mempool_destroy(nfs_wdata_mempool); |
1858 | kmem_cache_destroy(nfs_wdata_cachep); | 1867 | kmem_cache_destroy(nfs_wdata_cachep); |
1859 | } | 1868 | } |