Loading fs/nfs/direct.c +29 −30 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,6 @@ #define NFSDBG_FACILITY NFSDBG_VFS #define NFSDBG_FACILITY NFSDBG_VFS static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty); static kmem_cache_t *nfs_direct_cachep; static kmem_cache_t *nfs_direct_cachep; /* /* Loading Loading @@ -121,6 +120,18 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_ return -EINVAL; return -EINVAL; } } static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty) { int i; for (i = 0; i < npages; i++) { struct page *page = pages[i]; if (do_dirty && !PageCompound(page)) set_page_dirty_lock(page); page_cache_release(page); } kfree(pages); } static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) { { int result = -ENOMEM; int result = -ENOMEM; Loading @@ -138,31 +149,23 @@ static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t siz page_count, (rw == READ), 0, page_count, (rw == READ), 0, *pages, NULL); *pages, NULL); up_read(¤t->mm->mmap_sem); up_read(¤t->mm->mmap_sem); if (result != page_count) { /* /* * If we got fewer pages than expected from get_user_pages(), * If we got fewer pages than expected from * the user buffer runs off the end of a mapping; return EFAULT. * get_user_pages(), the user buffer runs off the * end of a mapping; return EFAULT. */ */ if (result >= 0 && result < page_count) { if (result >= 0) { nfs_free_user_pages(*pages, result, 0); nfs_free_user_pages(*pages, result, 0); *pages = NULL; result = -EFAULT; result = -EFAULT; } else kfree(*pages); *pages = NULL; } } } } return result; return result; } } static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty) { int i; for (i = 0; i < npages; i++) { struct page *page = pages[i]; if (do_dirty && !PageCompound(page)) set_page_dirty_lock(page); page_cache_release(page); } kfree(pages); } static inline struct nfs_direct_req *nfs_direct_req_alloc(void) static inline struct nfs_direct_req *nfs_direct_req_alloc(void) { { struct nfs_direct_req *dreq; struct nfs_direct_req *dreq; Loading Loading @@ -788,13 +791,11 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, if (retval) if (retval) goto out; goto out; page_count = nfs_get_user_pages(READ, (unsigned long) buf, retval = nfs_get_user_pages(READ, (unsigned long) buf, count, &pages); count, &pages); if (page_count < 0) { if (retval < 0) nfs_free_user_pages(pages, 0, 0); retval = page_count; goto out; goto out; } page_count = retval; retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos, retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos, pages, page_count); pages, page_count); Loading Loading @@ -862,13 +863,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t if (retval) if (retval) goto out; goto out; page_count = nfs_get_user_pages(WRITE, (unsigned long) buf, retval = nfs_get_user_pages(WRITE, (unsigned long) buf, count, &pages); count, &pages); if (page_count < 0) { if (retval < 0) nfs_free_user_pages(pages, 0, 0); retval = page_count; goto out; goto out; } page_count = retval; retval = nfs_direct_write(iocb, (unsigned long) buf, count, retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos, pages, page_count); pos, pages, page_count); Loading Loading
fs/nfs/direct.c +29 −30 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,6 @@ #define NFSDBG_FACILITY NFSDBG_VFS #define NFSDBG_FACILITY NFSDBG_VFS static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty); static kmem_cache_t *nfs_direct_cachep; static kmem_cache_t *nfs_direct_cachep; /* /* Loading Loading @@ -121,6 +120,18 @@ ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_ return -EINVAL; return -EINVAL; } } static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty) { int i; for (i = 0; i < npages; i++) { struct page *page = pages[i]; if (do_dirty && !PageCompound(page)) set_page_dirty_lock(page); page_cache_release(page); } kfree(pages); } static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t size, struct page ***pages) { { int result = -ENOMEM; int result = -ENOMEM; Loading @@ -138,31 +149,23 @@ static inline int nfs_get_user_pages(int rw, unsigned long user_addr, size_t siz page_count, (rw == READ), 0, page_count, (rw == READ), 0, *pages, NULL); *pages, NULL); up_read(¤t->mm->mmap_sem); up_read(¤t->mm->mmap_sem); if (result != page_count) { /* /* * If we got fewer pages than expected from get_user_pages(), * If we got fewer pages than expected from * the user buffer runs off the end of a mapping; return EFAULT. * get_user_pages(), the user buffer runs off the * end of a mapping; return EFAULT. */ */ if (result >= 0 && result < page_count) { if (result >= 0) { nfs_free_user_pages(*pages, result, 0); nfs_free_user_pages(*pages, result, 0); *pages = NULL; result = -EFAULT; result = -EFAULT; } else kfree(*pages); *pages = NULL; } } } } return result; return result; } } static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty) { int i; for (i = 0; i < npages; i++) { struct page *page = pages[i]; if (do_dirty && !PageCompound(page)) set_page_dirty_lock(page); page_cache_release(page); } kfree(pages); } static inline struct nfs_direct_req *nfs_direct_req_alloc(void) static inline struct nfs_direct_req *nfs_direct_req_alloc(void) { { struct nfs_direct_req *dreq; struct nfs_direct_req *dreq; Loading Loading @@ -788,13 +791,11 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, if (retval) if (retval) goto out; goto out; page_count = nfs_get_user_pages(READ, (unsigned long) buf, retval = nfs_get_user_pages(READ, (unsigned long) buf, count, &pages); count, &pages); if (page_count < 0) { if (retval < 0) nfs_free_user_pages(pages, 0, 0); retval = page_count; goto out; goto out; } page_count = retval; retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos, retval = nfs_direct_read(iocb, (unsigned long) buf, count, pos, pages, page_count); pages, page_count); Loading Loading @@ -862,13 +863,11 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t if (retval) if (retval) goto out; goto out; page_count = nfs_get_user_pages(WRITE, (unsigned long) buf, retval = nfs_get_user_pages(WRITE, (unsigned long) buf, count, &pages); count, &pages); if (page_count < 0) { if (retval < 0) nfs_free_user_pages(pages, 0, 0); retval = page_count; goto out; goto out; } page_count = retval; retval = nfs_direct_write(iocb, (unsigned long) buf, count, retval = nfs_direct_write(iocb, (unsigned long) buf, count, pos, pages, page_count); pos, pages, page_count); Loading