From 51d3b7814cdccef9188240fe0cbd8d97ff2c7470 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 22 Jun 1999 23:05:57 +0000 Subject: Merge with Linux 2.3.7. WARNING: 2.3.7 is known to eat filesystems for breakfast and little children for lunch, so if you try this on your machine make backups first ... --- fs/fifo.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 20 deletions(-) (limited to 'fs/fifo.c') diff --git a/fs/fifo.c b/fs/fifo.c index 5117d3a6e..e18183fc9 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -2,14 +2,45 @@ * linux/fs/fifo.c * * written by Paul H. Hargrove + * + * Fixes: + * 10-06-1999, AV: fixed OOM handling in fifo_open(), moved + * initialization there, switched to external + * allocation of pipe_inode_info. */ #include +#include static int fifo_open(struct inode * inode,struct file * filp) { int retval = 0; - unsigned long page; + unsigned long page = 0; + struct pipe_inode_info *info, *tmp = NULL; + + if (inode->i_pipe) + goto got_it; + tmp = kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL); + if (inode->i_pipe) + goto got_it; + if (!tmp) + goto oom; + page = __get_free_page(GFP_KERNEL); + if (inode->i_pipe) + goto got_it; + if (!page) + goto oom; + inode->i_pipe = tmp; + PIPE_LOCK(*inode) = 0; + PIPE_START(*inode) = PIPE_LEN(*inode) = 0; + PIPE_BASE(*inode) = (char *) page; + PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; + PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; + init_waitqueue_head(&PIPE_WAIT(*inode)); + tmp = NULL; /* no need to free it */ + page = 0; + +got_it: switch( filp->f_mode ) { @@ -94,19 +125,26 @@ static int fifo_open(struct inode * inode,struct file * filp) default: retval = -EINVAL; } - if (retval || PIPE_BASE(*inode)) - return retval; - page = __get_free_page(GFP_KERNEL); - if (PIPE_BASE(*inode)) { + if (retval) + goto cleanup; +out: + if (tmp) + kfree(tmp); + if (page) free_page(page); - return 0; + return retval; + +cleanup: + if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) { + info = inode->i_pipe; + inode->i_pipe = NULL; + free_page((unsigned long)info->base); + kfree(info); } - if (!page) - return -ENOMEM; - PIPE_LOCK(*inode) = 0; - PIPE_START(*inode) = PIPE_LEN(*inode) = 0; - PIPE_BASE(*inode) = (char *) page; - return 0; + goto out; +oom: + retval = -ENOMEM; + goto out; } /* @@ -141,20 +179,20 @@ struct inode_operations fifo_inode_operations = { NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ + NULL, /* bmap */ NULL, /* readpage */ NULL, /* writepage */ - NULL, /* bmap */ + NULL, /* flushpage */ NULL, /* truncate */ - NULL /* permission */ + NULL, /* permission */ + NULL, /* smap */ + NULL /* revalidate */ }; + +/* Goner. Filesystems do not use it anymore. */ + void init_fifo(struct inode * inode) { inode->i_op = &fifo_inode_operations; - PIPE_LOCK(*inode) = 0; - PIPE_BASE(*inode) = NULL; - PIPE_START(*inode) = PIPE_LEN(*inode) = 0; - PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0; - init_waitqueue_head(&PIPE_WAIT(*inode)); - PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0; } -- cgit v1.2.3