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 |
