diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/Makefile | 18 | ||||
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/file.c | 4 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 62 | ||||
-rw-r--r-- | fs/nfs/inode.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4file.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 127 | ||||
-rw-r--r-- | fs/nfs/nfs4super.c | 15 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 41 | ||||
-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 | 41 | ||||
-rw-r--r-- | fs/nfs/write.c | 15 |
18 files changed, 278 insertions, 160 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/file.c b/fs/nfs/file.c index 75d6d0a3d32e..6a7fcab7ecb3 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -287,10 +287,12 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
287 | struct inode *inode = file->f_path.dentry->d_inode; | 287 | struct inode *inode = file->f_path.dentry->d_inode; |
288 | 288 | ||
289 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 289 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
290 | if (ret != 0) | ||
291 | goto out; | ||
290 | mutex_lock(&inode->i_mutex); | 292 | mutex_lock(&inode->i_mutex); |
291 | ret = nfs_file_fsync_commit(file, start, end, datasync); | 293 | ret = nfs_file_fsync_commit(file, start, end, datasync); |
292 | mutex_unlock(&inode->i_mutex); | 294 | mutex_unlock(&inode->i_mutex); |
293 | 295 | out: | |
294 | return ret; | 296 | return ret; |
295 | } | 297 | } |
296 | 298 | ||
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/inode.c b/fs/nfs/inode.c index c6e895f0fbf3..9b47610338f5 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
154 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 154 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
155 | nfsi->attrtimeo_timestamp = jiffies; | 155 | nfsi->attrtimeo_timestamp = jiffies; |
156 | 156 | ||
157 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | 157 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
158 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) | 158 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) |
159 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 159 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
160 | else | 160 | else |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 0952c791df36..69322096c325 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); |
@@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
643 | u64 cookie, struct page **pages, unsigned int count, int plus) | 643 | u64 cookie, struct page **pages, unsigned int count, int plus) |
644 | { | 644 | { |
645 | struct inode *dir = dentry->d_inode; | 645 | struct inode *dir = dentry->d_inode; |
646 | __be32 *verf = NFS_COOKIEVERF(dir); | 646 | __be32 *verf = NFS_I(dir)->cookieverf; |
647 | struct nfs3_readdirargs arg = { | 647 | struct nfs3_readdirargs arg = { |
648 | .fh = NFS_FH(dir), | 648 | .fh = NFS_FH(dir), |
649 | .cookie = cookie, | 649 | .cookie = cookie, |
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/nfs4file.c b/fs/nfs/nfs4file.c index acb65e7887f8..eb5eb8eef4d3 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
@@ -96,13 +96,15 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) | |||
96 | struct inode *inode = file->f_path.dentry->d_inode; | 96 | struct inode *inode = file->f_path.dentry->d_inode; |
97 | 97 | ||
98 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | 98 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
99 | if (ret != 0) | ||
100 | goto out; | ||
99 | mutex_lock(&inode->i_mutex); | 101 | mutex_lock(&inode->i_mutex); |
100 | ret = nfs_file_fsync_commit(file, start, end, datasync); | 102 | ret = nfs_file_fsync_commit(file, start, end, datasync); |
101 | if (!ret && !datasync) | 103 | if (!ret && !datasync) |
102 | /* application has asked for meta-data sync */ | 104 | /* application has asked for meta-data sync */ |
103 | ret = pnfs_layoutcommit_inode(inode, true); | 105 | ret = pnfs_layoutcommit_inode(inode, true); |
104 | mutex_unlock(&inode->i_mutex); | 106 | mutex_unlock(&inode->i_mutex); |
105 | 107 | out: | |
106 | return ret; | 108 | return ret; |
107 | } | 109 | } |
108 | 110 | ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index a99a8d948721..1e50326d00dd 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3215 | dentry->d_parent->d_name.name, | 3215 | dentry->d_parent->d_name.name, |
3216 | dentry->d_name.name, | 3216 | dentry->d_name.name, |
3217 | (unsigned long long)cookie); | 3217 | (unsigned long long)cookie); |
3218 | nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); | 3218 | nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); |
3219 | res.pgbase = args.pgbase; | 3219 | res.pgbase = args.pgbase; |
3220 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); | 3220 | status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); |
3221 | if (status >= 0) { | 3221 | if (status >= 0) { |
3222 | memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); | 3222 | memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); |
3223 | status += args.pgbase; | 3223 | status += args.pgbase; |
3224 | } | 3224 | } |
3225 | 3225 | ||
@@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server) | |||
3653 | && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); | 3653 | && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); |
3654 | } | 3654 | } |
3655 | 3655 | ||
3656 | /* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that | 3656 | /* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that |
3657 | * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on | 3657 | * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on |
3658 | * the stack. | 3658 | * the stack. |
3659 | */ | 3659 | */ |
3660 | #define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT) | 3660 | #define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE) |
3661 | 3661 | ||
3662 | static int buf_to_pages_noslab(const void *buf, size_t buflen, | 3662 | static int buf_to_pages_noslab(const void *buf, size_t buflen, |
3663 | struct page **pages, unsigned int *pgbase) | 3663 | struct page **pages, unsigned int *pgbase) |
@@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen, | |||
3668 | spages = pages; | 3668 | spages = pages; |
3669 | 3669 | ||
3670 | do { | 3670 | do { |
3671 | len = min_t(size_t, PAGE_CACHE_SIZE, buflen); | 3671 | len = min_t(size_t, PAGE_SIZE, buflen); |
3672 | newpage = alloc_page(GFP_KERNEL); | 3672 | newpage = alloc_page(GFP_KERNEL); |
3673 | 3673 | ||
3674 | if (newpage == NULL) | 3674 | if (newpage == NULL) |
@@ -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 (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; |
@@ -3781,17 +3782,15 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3781 | .rpc_argp = &args, | 3782 | .rpc_argp = &args, |
3782 | .rpc_resp = &res, | 3783 | .rpc_resp = &res, |
3783 | }; | 3784 | }; |
3784 | int ret = -ENOMEM, npages, i; | 3785 | unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); |
3785 | size_t acl_len = 0; | 3786 | int ret = -ENOMEM, i; |
3786 | 3787 | ||
3787 | npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
3788 | /* As long as we're doing a round trip to the server anyway, | 3788 | /* As long as we're doing a round trip to the server anyway, |
3789 | * let's be prepared for a page of acl data. */ | 3789 | * let's be prepared for a page of acl data. */ |
3790 | if (npages == 0) | 3790 | if (npages == 0) |
3791 | npages = 1; | 3791 | npages = 1; |
3792 | 3792 | if (npages > ARRAY_SIZE(pages)) | |
3793 | /* Add an extra page to handle the bitmap returned */ | 3793 | return -ERANGE; |
3794 | npages++; | ||
3795 | 3794 | ||
3796 | for (i = 0; i < npages; i++) { | 3795 | for (i = 0; i < npages; i++) { |
3797 | pages[i] = alloc_page(GFP_KERNEL); | 3796 | pages[i] = alloc_page(GFP_KERNEL); |
@@ -3807,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3807 | args.acl_len = npages * PAGE_SIZE; | 3806 | args.acl_len = npages * PAGE_SIZE; |
3808 | args.acl_pgbase = 0; | 3807 | args.acl_pgbase = 0; |
3809 | 3808 | ||
3810 | /* Let decode_getfacl know not to fail if the ACL data is larger than | ||
3811 | * the page we send as a guess */ | ||
3812 | if (buf == NULL) | ||
3813 | res.acl_flags |= NFS4_ACL_LEN_REQUEST; | ||
3814 | |||
3815 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", | 3809 | dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n", |
3816 | __func__, buf, buflen, npages, args.acl_len); | 3810 | __func__, buf, buflen, npages, args.acl_len); |
3817 | ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), | 3811 | ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode), |
@@ -3819,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu | |||
3819 | if (ret) | 3813 | if (ret) |
3820 | goto out_free; | 3814 | goto out_free; |
3821 | 3815 | ||
3822 | acl_len = res.acl_len - res.acl_data_offset; | 3816 | /* Handle the case where the passed-in buffer is too short */ |
3823 | if (acl_len > args.acl_len) | 3817 | if (res.acl_flags & NFS4_ACL_TRUNC) { |
3824 | nfs4_write_cached_acl(inode, NULL, 0, acl_len); | 3818 | /* Did the user only issue a request for the acl length? */ |
3825 | else | 3819 | if (buf == NULL) |
3826 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, | 3820 | goto out_ok; |
3827 | acl_len); | ||
3828 | if (buf) { | ||
3829 | ret = -ERANGE; | 3821 | ret = -ERANGE; |
3830 | if (acl_len > buflen) | 3822 | goto out_free; |
3831 | goto out_free; | ||
3832 | _copy_from_pages(buf, pages, res.acl_data_offset, | ||
3833 | acl_len); | ||
3834 | } | 3823 | } |
3835 | ret = acl_len; | 3824 | nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len); |
3825 | if (buf) | ||
3826 | _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len); | ||
3827 | out_ok: | ||
3828 | ret = res.acl_len; | ||
3836 | out_free: | 3829 | out_free: |
3837 | for (i = 0; i < npages; i++) | 3830 | for (i = 0; i < npages; i++) |
3838 | if (pages[i]) | 3831 | if (pages[i]) |
@@ -3890,10 +3883,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl | |||
3890 | .rpc_argp = &arg, | 3883 | .rpc_argp = &arg, |
3891 | .rpc_resp = &res, | 3884 | .rpc_resp = &res, |
3892 | }; | 3885 | }; |
3886 | unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); | ||
3893 | int ret, i; | 3887 | int ret, i; |
3894 | 3888 | ||
3895 | if (!nfs4_server_supports_acls(server)) | 3889 | if (!nfs4_server_supports_acls(server)) |
3896 | return -EOPNOTSUPP; | 3890 | return -EOPNOTSUPP; |
3891 | if (npages > ARRAY_SIZE(pages)) | ||
3892 | return -ERANGE; | ||
3897 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 3893 | i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
3898 | if (i < 0) | 3894 | if (i < 0) |
3899 | return i; | 3895 | return i; |
@@ -6223,11 +6219,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
6223 | dprintk("<-- %s\n", __func__); | 6219 | dprintk("<-- %s\n", __func__); |
6224 | } | 6220 | } |
6225 | 6221 | ||
6222 | static size_t max_response_pages(struct nfs_server *server) | ||
6223 | { | ||
6224 | u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; | ||
6225 | return nfs_page_array_len(0, max_resp_sz); | ||
6226 | } | ||
6227 | |||
6228 | static void nfs4_free_pages(struct page **pages, size_t size) | ||
6229 | { | ||
6230 | int i; | ||
6231 | |||
6232 | if (!pages) | ||
6233 | return; | ||
6234 | |||
6235 | for (i = 0; i < size; i++) { | ||
6236 | if (!pages[i]) | ||
6237 | break; | ||
6238 | __free_page(pages[i]); | ||
6239 | } | ||
6240 | kfree(pages); | ||
6241 | } | ||
6242 | |||
6243 | static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) | ||
6244 | { | ||
6245 | struct page **pages; | ||
6246 | int i; | ||
6247 | |||
6248 | pages = kcalloc(size, sizeof(struct page *), gfp_flags); | ||
6249 | if (!pages) { | ||
6250 | dprintk("%s: can't alloc array of %zu pages\n", __func__, size); | ||
6251 | return NULL; | ||
6252 | } | ||
6253 | |||
6254 | for (i = 0; i < size; i++) { | ||
6255 | pages[i] = alloc_page(gfp_flags); | ||
6256 | if (!pages[i]) { | ||
6257 | dprintk("%s: failed to allocate page\n", __func__); | ||
6258 | nfs4_free_pages(pages, size); | ||
6259 | return NULL; | ||
6260 | } | ||
6261 | } | ||
6262 | |||
6263 | return pages; | ||
6264 | } | ||
6265 | |||
6226 | static void nfs4_layoutget_release(void *calldata) | 6266 | static void nfs4_layoutget_release(void *calldata) |
6227 | { | 6267 | { |
6228 | struct nfs4_layoutget *lgp = calldata; | 6268 | struct nfs4_layoutget *lgp = calldata; |
6269 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | ||
6270 | size_t max_pages = max_response_pages(server); | ||
6229 | 6271 | ||
6230 | dprintk("--> %s\n", __func__); | 6272 | dprintk("--> %s\n", __func__); |
6273 | nfs4_free_pages(lgp->args.layout.pages, max_pages); | ||
6231 | put_nfs_open_context(lgp->args.ctx); | 6274 | put_nfs_open_context(lgp->args.ctx); |
6232 | kfree(calldata); | 6275 | kfree(calldata); |
6233 | dprintk("<-- %s\n", __func__); | 6276 | dprintk("<-- %s\n", __func__); |
@@ -6239,9 +6282,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { | |||
6239 | .rpc_release = nfs4_layoutget_release, | 6282 | .rpc_release = nfs4_layoutget_release, |
6240 | }; | 6283 | }; |
6241 | 6284 | ||
6242 | int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | 6285 | void nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) |
6243 | { | 6286 | { |
6244 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); | 6287 | struct nfs_server *server = NFS_SERVER(lgp->args.inode); |
6288 | size_t max_pages = max_response_pages(server); | ||
6245 | struct rpc_task *task; | 6289 | struct rpc_task *task; |
6246 | struct rpc_message msg = { | 6290 | struct rpc_message msg = { |
6247 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], | 6291 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], |
@@ -6259,12 +6303,19 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6259 | 6303 | ||
6260 | dprintk("--> %s\n", __func__); | 6304 | dprintk("--> %s\n", __func__); |
6261 | 6305 | ||
6306 | lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); | ||
6307 | if (!lgp->args.layout.pages) { | ||
6308 | nfs4_layoutget_release(lgp); | ||
6309 | return; | ||
6310 | } | ||
6311 | lgp->args.layout.pglen = max_pages * PAGE_SIZE; | ||
6312 | |||
6262 | lgp->res.layoutp = &lgp->args.layout; | 6313 | lgp->res.layoutp = &lgp->args.layout; |
6263 | lgp->res.seq_res.sr_slot = NULL; | 6314 | lgp->res.seq_res.sr_slot = NULL; |
6264 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); | 6315 | nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); |
6265 | task = rpc_run_task(&task_setup_data); | 6316 | task = rpc_run_task(&task_setup_data); |
6266 | if (IS_ERR(task)) | 6317 | if (IS_ERR(task)) |
6267 | return PTR_ERR(task); | 6318 | return; |
6268 | status = nfs4_wait_for_completion_rpc_task(task); | 6319 | status = nfs4_wait_for_completion_rpc_task(task); |
6269 | if (status == 0) | 6320 | if (status == 0) |
6270 | status = task->tk_status; | 6321 | status = task->tk_status; |
@@ -6272,7 +6323,7 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) | |||
6272 | status = pnfs_layout_process(lgp); | 6323 | status = pnfs_layout_process(lgp); |
6273 | rpc_put_task(task); | 6324 | rpc_put_task(task); |
6274 | dprintk("<-- %s status=%d\n", __func__, status); | 6325 | dprintk("<-- %s status=%d\n", __func__, status); |
6275 | return status; | 6326 | return; |
6276 | } | 6327 | } |
6277 | 6328 | ||
6278 | static void | 6329 | static void |
@@ -6304,12 +6355,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
6304 | return; | 6355 | return; |
6305 | } | 6356 | } |
6306 | spin_lock(&lo->plh_inode->i_lock); | 6357 | spin_lock(&lo->plh_inode->i_lock); |
6307 | if (task->tk_status == 0) { | 6358 | if (task->tk_status == 0 && lrp->res.lrs_present) |
6308 | if (lrp->res.lrs_present) { | 6359 | 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--; | 6360 | lo->plh_block_lgets--; |
6314 | spin_unlock(&lo->plh_inode->i_lock); | 6361 | spin_unlock(&lo->plh_inode->i_lock); |
6315 | dprintk("<-- %s\n", __func__); | 6362 | 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..8dba6bd48557 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,16 @@ 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 | |||
5079 | /* We ignore &savep and don't do consistency checks on | ||
5080 | * the attr length. Let userspace figure it out.... */ | ||
5081 | attrlen += res->acl_data_offset; | ||
5082 | if (attrlen > page_len) { | ||
5083 | if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { | ||
5084 | /* getxattr interface called with a NULL buf */ | ||
5085 | res->acl_len = attrlen; | ||
5086 | goto out; | ||
5087 | } | ||
5088 | dprintk("NFS: acl reply: attrlen %u > page_len %zu\n", | ||
5089 | attrlen, page_len); | ||
5090 | return -EINVAL; | ||
5091 | } | ||
5092 | xdr_read_pages(xdr, attrlen); | ||
5093 | res->acl_len = attrlen; | 5075 | res->acl_len = attrlen; |
5076 | |||
5077 | /* Check for receive buffer overflow */ | ||
5078 | if (res->acl_len > (xdr->nwords << 2) || | ||
5079 | res->acl_len + res->acl_data_offset > xdr->buf->page_len) { | ||
5080 | res->acl_flags |= NFS4_ACL_TRUNC; | ||
5081 | dprintk("NFS: acl reply: attrlen %u > page_len %u\n", | ||
5082 | attrlen, xdr->nwords << 2); | ||
5083 | } | ||
5094 | } else | 5084 | } else |
5095 | status = -EOPNOTSUPP; | 5085 | status = -EOPNOTSUPP; |
5096 | 5086 | ||
@@ -6235,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6235 | status = decode_open(xdr, res); | 6225 | status = decode_open(xdr, res); |
6236 | if (status) | 6226 | if (status) |
6237 | goto out; | 6227 | goto out; |
6238 | if (decode_getfh(xdr, &res->fh) != 0) | 6228 | status = decode_getfh(xdr, &res->fh); |
6229 | if (status) | ||
6239 | goto out; | 6230 | goto out; |
6240 | decode_getfattr(xdr, res->f_attr, res->server); | 6231 | decode_getfattr(xdr, res->f_attr, res->server); |
6241 | out: | 6232 | out: |
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..b8eda700584b 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 | ||
@@ -1832,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options, | |||
1832 | 1867 | ||
1833 | memcpy(sap, &data->addr, sizeof(data->addr)); | 1868 | memcpy(sap, &data->addr, sizeof(data->addr)); |
1834 | args->nfs_server.addrlen = sizeof(data->addr); | 1869 | args->nfs_server.addrlen = sizeof(data->addr); |
1870 | args->nfs_server.port = ntohs(data->addr.sin_port); | ||
1835 | if (!nfs_verify_server_address(sap)) | 1871 | if (!nfs_verify_server_address(sap)) |
1836 | goto out_no_address; | 1872 | goto out_no_address; |
1837 | 1873 | ||
@@ -2529,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options, | |||
2529 | return -EFAULT; | 2565 | return -EFAULT; |
2530 | if (!nfs_verify_server_address(sap)) | 2566 | if (!nfs_verify_server_address(sap)) |
2531 | goto out_no_address; | 2567 | goto out_no_address; |
2568 | args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); | ||
2532 | 2569 | ||
2533 | if (data->auth_flavourlen) { | 2570 | if (data->auth_flavourlen) { |
2534 | if (data->auth_flavourlen > 1) | 2571 | if (data->auth_flavourlen > 1) |
@@ -2645,4 +2682,6 @@ MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " | |||
2645 | module_param(send_implementation_id, ushort, 0644); | 2682 | module_param(send_implementation_id, ushort, 0644); |
2646 | MODULE_PARM_DESC(send_implementation_id, | 2683 | MODULE_PARM_DESC(send_implementation_id, |
2647 | "Send implementation ID with NFSv4.1 exchange_id"); | 2684 | "Send implementation ID with NFSv4.1 exchange_id"); |
2685 | MODULE_ALIAS("nfs4"); | ||
2686 | |||
2648 | #endif /* CONFIG_NFS_V4 */ | 2687 | #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 | } |