diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-09-08 12:48:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-08 13:22:51 -0400 |
commit | e9f7bee1df223dcf83743b46cb06c08d95497ec0 (patch) | |
tree | 67beae4733ef0286645112a52623c81c8f8a19a9 /include/linux | |
parent | 016eb4a0ed06a3677d67a584da901f0e9a63c666 (diff) |
[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>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/nfs_fs.h | 6 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 4 |
2 files changed, 5 insertions, 5 deletions
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 247434553ae8..530b1e6173b1 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -427,7 +427,7 @@ extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); | |||
427 | extern void nfs_writedata_release(void *); | 427 | extern void nfs_writedata_release(void *); |
428 | 428 | ||
429 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 429 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
430 | struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount); | 430 | struct nfs_write_data *nfs_commit_alloc(void); |
431 | void nfs_commit_free(struct nfs_write_data *p); | 431 | void nfs_commit_free(struct nfs_write_data *p); |
432 | #endif | 432 | #endif |
433 | 433 | ||
@@ -478,7 +478,7 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page) | |||
478 | /* | 478 | /* |
479 | * Allocate nfs_write_data structures | 479 | * Allocate nfs_write_data structures |
480 | */ | 480 | */ |
481 | extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); | 481 | extern struct nfs_write_data *nfs_writedata_alloc(size_t len); |
482 | 482 | ||
483 | /* | 483 | /* |
484 | * linux/fs/nfs/read.c | 484 | * linux/fs/nfs/read.c |
@@ -492,7 +492,7 @@ extern void nfs_readdata_release(void *data); | |||
492 | /* | 492 | /* |
493 | * Allocate nfs_read_data structures | 493 | * Allocate nfs_read_data structures |
494 | */ | 494 | */ |
495 | extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); | 495 | extern struct nfs_read_data *nfs_readdata_alloc(size_t len); |
496 | 496 | ||
497 | /* | 497 | /* |
498 | * linux/fs/nfs3proc.c | 498 | * linux/fs/nfs3proc.c |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index db9cbf68e12b..41e5a19199e9 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -729,7 +729,7 @@ struct nfs_read_data { | |||
729 | struct list_head pages; /* Coalesced read requests */ | 729 | struct list_head pages; /* Coalesced read requests */ |
730 | struct nfs_page *req; /* multi ops per nfs_page */ | 730 | struct nfs_page *req; /* multi ops per nfs_page */ |
731 | struct page **pagevec; | 731 | struct page **pagevec; |
732 | unsigned int npages; /* active pages in pagevec */ | 732 | unsigned int npages; /* Max length of pagevec */ |
733 | struct nfs_readargs args; | 733 | struct nfs_readargs args; |
734 | struct nfs_readres res; | 734 | struct nfs_readres res; |
735 | #ifdef CONFIG_NFS_V4 | 735 | #ifdef CONFIG_NFS_V4 |
@@ -748,7 +748,7 @@ struct nfs_write_data { | |||
748 | struct list_head pages; /* Coalesced requests we wish to flush */ | 748 | struct list_head pages; /* Coalesced requests we wish to flush */ |
749 | struct nfs_page *req; /* multi ops per nfs_page */ | 749 | struct nfs_page *req; /* multi ops per nfs_page */ |
750 | struct page **pagevec; | 750 | struct page **pagevec; |
751 | unsigned int npages; /* active pages in pagevec */ | 751 | unsigned int npages; /* Max length of pagevec */ |
752 | struct nfs_writeargs args; /* argument struct */ | 752 | struct nfs_writeargs args; /* argument struct */ |
753 | struct nfs_writeres res; /* result struct */ | 753 | struct nfs_writeres res; /* result struct */ |
754 | #ifdef CONFIG_NFS_V4 | 754 | #ifdef CONFIG_NFS_V4 |