patch-2.3.7 linux/fs/fifo.c

Next file: linux/fs/hfs/dir_nat.c
Previous file: linux/fs/ext2/truncate.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.6/linux/fs/fifo.c linux/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 <linux/mm.h>
+#include <linux/malloc.h>
 
 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 @@
 	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 @@
 	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;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)