Re: 2.6.6-rc3-mm2 (4KSTACK)

Andrew Morton
2004-05-07T19:58:54Z

"Martin J. Bligh" <mbligh@aracnet.com> wrote:
>
> 2 nfs_writepage_sync is a known stack-abuser ;-) 1632 bytes on PPC64 at least
> (from Anton's data). Maybe it's that struct nfs_write_data ?

(from Anton's data). Maybe it's that struct nfs_write_data ?

diff -puN fs/nfs/write.c~nfs_writepage_sync-stack-reduction fs/nfs/write.c
--- 25/fs/nfs/write.c~nfs_writepage_sync-stack-reduction 2004-05-07 12:36:51.648098192 -0700
+++ 25-akpm/fs/nfs/write.c 2004-05-07 12:39:41.320304096 -0700
@@ -179,7 +179,13 @@ static int nfs_writepage_sync(struct fil
{
unsigned int wsize = NFS_SERVER(inode)->wsize;
int result, written = 0;
- struct nfs_write_data wdata = {
+ struct nfs_write_data *wdata;
+
+ wdata = kmalloc(sizeof(*wdata), GFP_NOFS);
+ if (!wdata)
+ return -ENOMEM;
+
+ *wdata = (struct nfs_write_data) {
.flags = how,
.cred = NULL,
.inode = inode,
@@ -192,8 +198,8 @@ static int nfs_writepage_sync(struct fil
.count = wsize,
},
.res = {
- .fattr = &wdata.fattr,
- .verf = &wdata.verf,
+ .fattr = &wdata->fattr,
+ .verf = &wdata->verf,
},
};

@@ -205,22 +211,22 @@ static int nfs_writepage_sync(struct fil
nfs_begin_data_update(inode);
do {
if (count < wsize)
- wdata.args.count = count;
- wdata.args.offset = page_offset(page) + wdata.args.pgbase;
+ wdata->args.count = count;
+ wdata->args.offset = page_offset(page) + wdata->args.pgbase;

- result = NFS_PROTO(inode)->write(&wdata, file);
+ result = NFS_PROTO(inode)->write(wdata, file);

if (result < 0) {
/* Must mark the page invalid after I/O error */
ClearPageUptodate(page);
goto io_error;
}
- if (result < wdata.args.count)
+ if (result < wdata->args.count)
printk(KERN_WARNING "NFS: short write, count=%u, result=%d\n",
- wdata.args.count, result);
+ wdata->args.count, result);

- wdata.args.offset += result;
- wdata.args.pgbase += result;
+ wdata->args.offset += result;
+ wdata->args.pgbase += result;
written += result;
count -= result;
} while (count);
@@ -234,9 +240,10 @@ static int nfs_writepage_sync(struct fil

io_error:
nfs_end_data_update_defer(inode);
- if (wdata.cred)
- put_rpccred(wdata.cred);
+ if (wdata->cred)
+ put_rpccred(wdata->cred);

+ kfree(wdata);
return written ? written : result;
}

_