aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c59
1 files changed, 29 insertions, 30 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index b4bbf6d75923..58830429e42a 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -59,7 +59,6 @@
59 59
60#define NFSDBG_FACILITY NFSDBG_VFS 60#define NFSDBG_FACILITY NFSDBG_VFS
61 61
62static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty);
63static kmem_cache_t *nfs_direct_cachep; 62static kmem_cache_t *nfs_direct_cachep;
64 63
65/* 64/*
@@ -121,6 +120,18 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_
121 return -EINVAL; 120 return -EINVAL;
122} 121}
123 122
123static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
124{
125 int i;
126 for (i = 0; i < npages; i++) {
127 struct page *page = pages[i];
128 if (do_dirty && !PageCompound(page))
129 set_page_dirty_lock(page);
130 page_cache_release(page);
131 }
132 kfree(pages);
133}
134
124static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) 135static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages)
125{ 136{
126 int result = -ENOMEM; 137 int result = -ENOMEM;
@@ -138,31 +149,23 @@ static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t siz
138 page_count, (rw == READ), 0, 149 page_count, (rw == READ), 0,
139 *pages, NULL); 150 *pages, NULL);
140 up_read(&current->mm->mmap_sem); 151 up_read(&current->mm->mmap_sem);
141 /* 152 if (result != page_count) {
142 * If we got fewer pages than expected from get_user_pages(), 153 /*
143 * the user buffer runs off the end of a mapping; return EFAULT. 154 * If we got fewer pages than expected from
144 */ 155 * get_user_pages(), the user buffer runs off the
145 if (result >= 0 && result < page_count) { 156 * end of a mapping; return EFAULT.
146 nfs_free_user_pages(*pages, result, 0); 157 */
158 if (result >= 0) {
159 nfs_free_user_pages(*pages, result, 0);
160 result = -EFAULT;
161 } else
162 kfree(*pages);
147 *pages = NULL; 163 *pages = NULL;
148 result = -EFAULT;
149 } 164 }
150 } 165 }
151 return result; 166 return result;
152} 167}
153 168
154static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty)
155{
156 int i;
157 for (i = 0; i < npages; i++) {
158 struct page *page = pages[i];
159 if (do_dirty && !PageCompound(page))
160 set_page_dirty_lock(page);
161 page_cache_release(page);
162 }
163 kfree(pages);
164}
165
166static inline struct nfs_direct_req *nfs_direct_req_alloc(void) 169static inline struct nfs_direct_req *nfs_direct_req_alloc(void)
167{ 170{
168 struct nfs_direct_req *dreq; 171 struct nfs_direct_req *dreq;
@@ -788,13 +791,11 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count,
788 if (retval) 791 if (retval)
789 goto out; 792 goto out;
790 793
791 page_count = nfs_get_user_pages(READ, (unsigned long) buf, 794 retval = nfs_get_user_pages(READ, (unsigned long) buf,
792 count, &pages); 795 count, &pages);
793 if (page_count < 0) { 796 if (retval < 0)
794 nfs_free_user_pages(pages, 0, 0);
795 retval = page_count;
796 goto out; 797 goto out;
797 } 798 page_count = retval;
798 799
799 retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos, 800 retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos,
800 pages, page_count); 801 pages, page_count);
@@ -862,13 +863,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t
862 if (retval) 863 if (retval)
863 goto out; 864 goto out;
864 865
865 page_count = nfs_get_user_pages(WRITE, (unsigned long) buf, 866 retval = nfs_get_user_pages(WRITE, (unsigned long) buf,
866 count, &pages); 867 count, &pages);
867 if (page_count < 0) { 868 if (retval < 0)
868 nfs_free_user_pages(pages, 0, 0);
869 retval = page_count;
870 goto out; 869 goto out;
871 } 870 page_count = retval;
872 871
873 retval = nfs_direct_write(iocb, (unsigned long) buf, count, 872 retval = nfs_direct_write(iocb, (unsigned long) buf, count,
874 pos, pages, page_count); 873 pos, pages, page_count);