patch-2.1.70 linux/fs/coda/file.c

Next file: linux/fs/coda/inode.c
Previous file: linux/fs/coda/dir.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.69/linux/fs/coda/file.c linux/fs/coda/file.c
@@ -0,0 +1,251 @@
+/*
+ * File operations for Coda.
+ * Original version: (C) 1996 Peter Braam 
+ * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
+ *
+ * Carnegie Mellon encourages users of this code to contribute improvements
+ * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/locks.h>
+#include <asm/segment.h>
+#include <linux/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/coda_namecache.h>
+#include <linux/coda.h>
+#include <linux/coda_linux.h>
+#include <linux/coda_cnode.h>
+#include <linux/coda_psdev.h>
+
+/* file operations */
+static int coda_readpage(struct inode * inode, struct page * page);
+static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
+static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
+static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
+
+/* exported from this file */
+struct inode_operations coda_file_inode_operations = {
+	&coda_file_operations,	/* default file operations */
+	NULL,			/* create */
+	NULL,		        /* lookup */
+	NULL,			/* link */
+	NULL,		        /* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,		/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	coda_readpage,    	/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+        coda_permission,        /* permission */
+	NULL,                   /* smap */
+	NULL,                   /* update page */
+        NULL                    /* revalidate */
+};
+
+struct file_operations coda_file_operations = {
+	NULL,		        /* lseek - default should work for coda */
+	coda_file_read,         /* read */
+	coda_file_write,        /* write */
+	NULL,          		/* readdir */
+	NULL,			/* select - default */
+	NULL,		        /* ioctl */
+	coda_file_mmap,         /* mmap */
+	coda_open,              /* open */
+	coda_release,           /* release */
+	NULL,		        /* fsync */
+};
+
+/*  File file operations */
+static int coda_readpage(struct inode * inode, struct page * page)
+{
+        struct inode *open_inode;
+        struct cnode *cnp;
+
+        ENTRY;
+        
+        cnp = ITOC(inode);
+        CHECK_CNODE(cnp);
+
+        if ( ! cnp->c_ovp ) {
+            printk("coda_readpage: no open inode for ino %ld\n", inode->i_ino);
+                return -ENXIO;
+        }
+
+        open_inode = cnp->c_ovp;
+
+        CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n", inode->i_ino, open_inode->i_ino, page->offset);
+
+        generic_readpage(open_inode, page);
+        EXIT;
+        return 0;
+}
+
+static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
+{
+        struct cnode *cnp;
+	cnp = ITOC(file->f_dentry->d_inode);
+	cnp->c_mmcount++;
+  
+	return generic_file_mmap(file, vma);
+}
+
+static ssize_t coda_file_read(struct file *coda_file, char *buff, 
+			   size_t count, loff_t *ppos)
+{
+        struct cnode *cnp;
+	struct inode *coda_inode = coda_file->f_dentry->d_inode;
+        struct inode *cont_inode = NULL;
+        struct file  cont_file;
+	struct dentry cont_dentry;
+        int result = 0;
+
+        ENTRY;
+
+        cnp = ITOC(coda_inode);
+        CHECK_CNODE(cnp);
+	
+        cont_inode = cnp->c_ovp;
+        if ( cont_inode == NULL ) {
+                printk("coda_file_read: cached inode is 0!\n");
+                return -1;
+        }
+
+        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
+			      &cont_file, &cont_dentry);
+
+        if (!cont_file.f_op || ! cont_file.f_op->read) { 
+                printk( "container file has no read in file operations.\n");
+                return -1;
+        }
+
+        result = cont_file.f_op->read(&cont_file , buff, count, 
+				      &(cont_file.f_pos));
+
+        CDEBUG(D_FILE, "ops at %x result %d, count %d, position: %d\n", 
+	       (int)cont_file.f_op, result, count, (int)cont_file.f_pos);
+
+        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
+        return result;
+}
+
+
+static ssize_t coda_file_write(struct file *coda_file, const char *buff, 
+			    size_t count, loff_t *ppos)
+{
+        struct cnode *cnp;
+	struct inode *coda_inode = coda_file->f_dentry->d_inode;
+        struct inode *cont_inode = NULL;
+        struct file  cont_file;
+	struct dentry cont_dentry;
+        int result = 0;
+
+        ENTRY;
+
+        cnp = ITOC(coda_inode);
+        CHECK_CNODE(cnp);
+
+        cont_inode = cnp->c_ovp;
+        if ( cont_inode == NULL ) {
+                printk("coda_file_write: cached inode is 0!\n");
+                return -1; 
+        }
+
+        coda_prepare_openfile(coda_inode, coda_file, cont_inode, 
+			      &cont_file, &cont_dentry);
+
+        if (!cont_file.f_op || !cont_file.f_op->write) {
+                printk("coda_file_write: container file has no file ops.\n");
+                return -1;
+        }
+
+        cnp->c_flags &= ~C_VATTR;
+
+	down(&cont_inode->i_sem);
+        result = cont_file.f_op->write(&cont_file , buff, count, 
+				       &(cont_file.f_pos));
+	up(&cont_inode->i_sem);
+        coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
+
+        return result;
+}
+
+
+
+/* 
+ * support routines
+ */
+
+/* instantiate the container file and dentry object to do io */                
+void coda_prepare_openfile(struct inode *i, struct file *coda_file, 
+			   struct inode *cont_inode, struct file *cont_file,
+			   struct dentry *cont_dentry)
+{
+        cont_file->f_pos = coda_file->f_pos;
+        cont_file->f_mode = coda_file->f_mode;
+        cont_file->f_flags = coda_file->f_flags;
+        cont_file->f_count  = coda_file->f_count;
+        cont_file->f_owner  = coda_file->f_owner;
+	cont_file->f_op = cont_inode->i_op->default_file_ops;
+	cont_file->f_dentry = cont_dentry;
+        cont_file->f_dentry->d_inode = cont_inode;
+        return ;
+}
+
+/* update the Coda file & inode after I/O */
+void coda_restore_codafile(struct inode *coda_inode, struct file *coda_file, 
+			   struct inode *open_inode, struct file *open_file)
+{
+        coda_file->f_pos = open_file->f_pos;
+	/* XXX what about setting the mtime here too? */
+	coda_inode->i_mtime = open_inode->i_mtime;
+	coda_inode->i_size = open_inode->i_size;
+        return;
+}
+
+/* grab the ext2 inode of the container file */
+int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind)
+{
+        struct super_block *sbptr;
+
+        sbptr = coda_find_super(dev);
+
+        if ( !sbptr ) {
+                printk("coda_inode_grab: coda_find_super returns NULL.\n");
+                return -ENXIO;
+        }
+                
+        *ind = NULL;
+        *ind = iget(sbptr, ino);
+
+        if ( *ind == NULL ) {
+                printk("coda_inode_grab: iget(dev: %d, ino: %ld) 
+                       returns NULL.\n", dev, ino);
+                return -ENOENT;
+        }
+	CDEBUG(D_FILE, "ino: %ld, ops at %x\n", ino, (int)(*ind)->i_op);
+        return 0;
+}
+
+struct super_block *coda_find_super(kdev_t device)
+{
+        struct super_block *super;
+
+        for (super = super_blocks + 0; super < super_blocks + NR_SUPER ; 
+	     super++) {
+                if (super->s_dev == device) 
+                        return super;
+        }
+        return NULL;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov