[PATCH] NFS: large non-page-aligned direct I/O clobbers memory
The logic in nfs_direct_read_schedule and nfs_direct_write_schedule can allow data->npages to be one larger than rpages. This causes a page pointer to be written beyond the end of the pagevec in nfs_read_data (or nfs_write_data). Fix this by making nfs_(read|write)_alloc() calculate the size of the pagevec array, and initialise data->npages. Also get rid of the redundant argument to nfs_commit_alloc(). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
016eb4a0ed
commit
e9f7bee1df
@@ -427,7 +427,7 @@ extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
|
||||
extern void nfs_writedata_release(void *);
|
||||
|
||||
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
|
||||
struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount);
|
||||
struct nfs_write_data *nfs_commit_alloc(void);
|
||||
void nfs_commit_free(struct nfs_write_data *p);
|
||||
#endif
|
||||
|
||||
@@ -478,7 +478,7 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page)
|
||||
/*
|
||||
* Allocate nfs_write_data structures
|
||||
*/
|
||||
extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount);
|
||||
extern struct nfs_write_data *nfs_writedata_alloc(size_t len);
|
||||
|
||||
/*
|
||||
* linux/fs/nfs/read.c
|
||||
@@ -492,7 +492,7 @@ extern void nfs_readdata_release(void *data);
|
||||
/*
|
||||
* Allocate nfs_read_data structures
|
||||
*/
|
||||
extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount);
|
||||
extern struct nfs_read_data *nfs_readdata_alloc(size_t len);
|
||||
|
||||
/*
|
||||
* linux/fs/nfs3proc.c
|
||||
|
||||
@@ -729,7 +729,7 @@ struct nfs_read_data {
|
||||
struct list_head pages; /* Coalesced read requests */
|
||||
struct nfs_page *req; /* multi ops per nfs_page */
|
||||
struct page **pagevec;
|
||||
unsigned int npages; /* active pages in pagevec */
|
||||
unsigned int npages; /* Max length of pagevec */
|
||||
struct nfs_readargs args;
|
||||
struct nfs_readres res;
|
||||
#ifdef CONFIG_NFS_V4
|
||||
@@ -748,7 +748,7 @@ struct nfs_write_data {
|
||||
struct list_head pages; /* Coalesced requests we wish to flush */
|
||||
struct nfs_page *req; /* multi ops per nfs_page */
|
||||
struct page **pagevec;
|
||||
unsigned int npages; /* active pages in pagevec */
|
||||
unsigned int npages; /* Max length of pagevec */
|
||||
struct nfs_writeargs args; /* argument struct */
|
||||
struct nfs_writeres res; /* result struct */
|
||||
#ifdef CONFIG_NFS_V4
|
||||
|
||||
Reference in New Issue
Block a user