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

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

diff -urN linux-2.4.18/fs/coda/file.c linux-2.4.19/fs/coda/file.c
@@ -16,7 +16,6 @@
 #include <linux/errno.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
-#include <asm/segment.h>
 #include <linux/string.h>
 #include <asm/uaccess.h>
 
@@ -31,249 +30,247 @@
 int use_coda_close;
 
 static ssize_t
-coda_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+coda_file_read(struct file *coda_file, char *buf, size_t count, loff_t *ppos)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
-	ssize_t ret;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->read)
+	if (!host_file->f_op || !host_file->f_op->read)
 		return -EINVAL;
 
-	down(&inode->i_sem);
-	ret = cfile->f_op->read(cfile, buf, count, ppos);
-	UPDATE_ATIME(inode);
-	up(&inode->i_sem);
-
-	return ret;
+	return host_file->f_op->read(host_file, buf, count, ppos);
 }
 
 static ssize_t
-coda_file_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
+coda_file_write(struct file *coda_file, const char *buf, size_t count, loff_t *ppos)
 {
-	struct inode *cinode, *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
+	struct inode *coda_inode = coda_file->f_dentry->d_inode;
+	struct coda_file_info *cfi;
+	struct file *host_file;
 	ssize_t ret;
-	int flags;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->write)
+	if (!host_file->f_op || !host_file->f_op->write)
 		return -EINVAL;
 
-	cinode = cfile->f_dentry->d_inode;
-	down(&inode->i_sem);
-	flags = cfile->f_flags;
-        cfile->f_flags |= file->f_flags & (O_APPEND | O_SYNC);
-
-	ret = cfile->f_op->write(cfile, buf, count, ppos);
-
-	cfile->f_flags = flags;
-	inode->i_size = cinode->i_size;
-	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	up(&inode->i_sem);
+	down(&coda_inode->i_sem);
+
+	ret = host_file->f_op->write(host_file, buf, count, ppos);
+
+	coda_inode->i_size = host_file->f_dentry->d_inode->i_size;
+	coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
+	coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME;
+	up(&coda_inode->i_sem);
 
 	return ret;
 }
 
 static int
-coda_file_mmap(struct file *file, struct vm_area_struct *vma)
+coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
-	struct file *cfile;
-	int ret;
-
-	cfile = cii->c_container;
+	struct coda_file_info *cfi;
+	struct coda_inode_info *cii;
+	struct file *host_file;
+	struct inode *coda_inode, *host_inode;
 
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
-	if (!cfile->f_op || !cfile->f_op->mmap)
+	if (!host_file->f_op || !host_file->f_op->mmap)
 		return -ENODEV;
 
-	down(&inode->i_sem);
-	ret = cfile->f_op->mmap(cfile, vma);
-	UPDATE_ATIME(inode);
-	up(&inode->i_sem);
-
-	return ret;
+	coda_inode = coda_file->f_dentry->d_inode;
+	host_inode = host_file->f_dentry->d_inode;
+	if (coda_inode->i_mapping == &coda_inode->i_data)
+		coda_inode->i_mapping = host_inode->i_mapping;
+
+	/* only allow additional mmaps as long as userspace isn't changing
+	 * the container file on us! */
+	else if (coda_inode->i_mapping != host_inode->i_mapping)
+		return -EBUSY;
+
+	/* keep track of how often the coda_inode/host_file has been mmapped */
+	cii = ITOC(coda_inode);
+	cii->c_mapcount++;
+	cfi->cfi_mapcount++;
+ 
+	return host_file->f_op->mmap(host_file, vma);
 }
 
-int coda_open(struct inode *i, struct file *f)
+int coda_open(struct inode *coda_inode, struct file *coda_file)
 {
-	struct file *fh = NULL;
-	int error = 0;
-	unsigned short flags = f->f_flags & (~O_EXCL);
+	struct file *host_file = NULL;
+	int error;
+	unsigned short flags = coda_file->f_flags & (~O_EXCL);
 	unsigned short coda_flags = coda_flags_to_cflags(flags);
-	struct coda_cred *cred;
-	struct coda_inode_info *cii;
+	struct coda_file_info *cfi;
+	struct inode *host_inode;
 
-	lock_kernel();
 	coda_vfs_stat.open++;
 
-	CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
-	       f->f_dentry->d_inode->i_ino, atomic_read(&f->f_dentry->d_count), flags);
+	cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
+	if (!cfi) {
+		unlock_kernel();
+		return -ENOMEM;
+	}
 
-	error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &fh); 
-	if (error || !fh) {
-	        CDEBUG(D_FILE, "coda_open: venus_open result %d\n", error);
+	lock_kernel();
+
+	error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+			   &host_file); 
+	if (error || !host_file) {
+		kfree(cfi);
 		unlock_kernel();
 		return error;
 	}
 
-	/* coda_upcall returns filehandle of container file object */
-	cii = ITOC(i);
-	if (cii->c_container)
-		fput(cii->c_container);
-
-	cii->c_contcount++;
-	cii->c_container = fh;
-	i->i_mapping = &cii->c_container->f_dentry->d_inode->i_data;
-
-	cred = kmalloc(sizeof(struct coda_cred), GFP_KERNEL);
-
-	/* If the allocation failed, we'll just muddle on. This actually works
-	 * fine for normal cases. (i.e. when open credentials are the same as
-	 * close credentials) */
-	if (cred) {
-		coda_load_creds(cred);
-		f->private_data = cred;
+	host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);
+
+	cfi->cfi_magic = CODA_MAGIC;
+	cfi->cfi_mapcount = 0;
+	cfi->cfi_container = host_file;
+	coda_load_creds(&cfi->cfi_cred);
+
+	host_inode = host_file->f_dentry->d_inode;
+	if (coda_inode->i_mapping == &coda_inode->i_data)
+		coda_inode->i_mapping = host_inode->i_mapping;
+
+	else if (coda_inode->i_mapping != host_inode->i_mapping) {
+		/* This is not a good thing, it doesn't happen with 'venus'
+		 * Coda's own userspace daemon, but others might not provide
+		 * the same guarantees. Still looking for the real fix. */
+		printk("coda_open: changed mapping\n");
+		coda_inode->i_mapping = host_inode->i_mapping;
 	}
 
-	CDEBUG(D_FILE, "result %d, coda i->i_count is %d, cii->contcount is %d for ino %ld\n", 
-	       error, atomic_read(&i->i_count), cii->c_contcount, i->i_ino);
-	CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", 
-	       fh->f_dentry->d_inode->i_ino,
-	       atomic_read(&fh->f_dentry->d_inode->i_count),
-               fh->f_dentry->d_inode->i_op);
+	if (coda_file->private_data != NULL) BUG();
+	coda_file->private_data = cfi;
+
 	unlock_kernel();
 	return 0;
 }
 
-
-int coda_flush(struct file *file)
+int coda_flush(struct file *coda_file)
 {
-	unsigned short flags = (file->f_flags) & (~O_EXCL);
-	unsigned short cflags;
-	struct coda_inode_info *cii;
-	struct file *cfile;
-	struct inode *cinode, *inode;
+	unsigned short flags = coda_file->f_flags & ~O_EXCL;
+	unsigned short coda_flags = coda_flags_to_cflags(flags);
+	struct coda_file_info *cfi;
+	struct inode *coda_inode;
 	int err = 0, fcnt;
 
 	coda_vfs_stat.flush++;
 
 	/* No need to make an upcall when we have not made any modifications
 	 * to the file */
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+	if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
 		return 0;
 
 	if (use_coda_close)
 		return 0;
 
-	fcnt = file_count(file);
+	fcnt = file_count(coda_file);
 	if (fcnt > 1) return 0;
 
-	cflags = coda_flags_to_cflags(flags);
+	coda_inode = coda_file->f_dentry->d_inode;
 
-	inode = file->f_dentry->d_inode;
-	cii = ITOC(inode);
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
 
-	cinode = cfile->f_dentry->d_inode;
+	err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
+			  &cfi->cfi_cred);
 
-	CDEBUG(D_FILE, "FLUSH coda (file %p ct %d)\n", file, fcnt);
-
-	err = venus_store(inode->i_sb, coda_i2f(inode), cflags,
-                          (struct coda_cred *)file->private_data);
 	if (err == -EOPNOTSUPP) {
 		use_coda_close = 1;
 		err = 0;
 	}
 
-	CDEBUG(D_FILE, "coda_flush: result: %d\n", err);
 	return err;
 }
 
-int coda_release(struct inode *i, struct file *f)
+int coda_release(struct inode *coda_inode, struct file *coda_file)
 {
-	unsigned short flags = (f->f_flags) & (~O_EXCL);
-	unsigned short cflags = coda_flags_to_cflags(flags);
+	unsigned short flags = (coda_file->f_flags) & (~O_EXCL);
+	unsigned short coda_flags = coda_flags_to_cflags(flags);
+	struct coda_file_info *cfi;
 	struct coda_inode_info *cii;
-	struct file *cfile;
+	struct inode *host_inode;
 	int err = 0;
 
 	lock_kernel();
 	coda_vfs_stat.release++;
  
 	if (!use_coda_close) {
-		err = venus_release(i->i_sb, coda_i2f(i), cflags);
+		err = venus_release(coda_inode->i_sb, coda_i2f(coda_inode),
+				    coda_flags);
 		if (err == -EOPNOTSUPP) {
 			use_coda_close = 1;
 			err = 0;
 		}
 	}
 
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+
 	if (use_coda_close)
-		err = venus_close(i->i_sb, coda_i2f(i), cflags,
-                                  (struct coda_cred *)f->private_data);
+		err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
+				  coda_flags, &cfi->cfi_cred);
 
-	cii = ITOC(i);
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	host_inode = cfi->cfi_container->f_dentry->d_inode;
+	cii = ITOC(coda_inode);
 
-	if (--cii->c_contcount) {
-		unlock_kernel();
-		return err;
+	/* did we mmap this file? */
+	if (coda_inode->i_mapping == &host_inode->i_data) {
+		cii->c_mapcount -= cfi->cfi_mapcount;
+		if (!cii->c_mapcount)
+			coda_inode->i_mapping = &coda_inode->i_data;
 	}
 
-	i->i_mapping = &i->i_data;
-	fput(cfile);
-	cii->c_container = NULL;
-
-	if (f->private_data) {
-		kfree(f->private_data);
-		f->private_data = NULL;
-	}
+	fput(cfi->cfi_container);
+
+	kfree(coda_file->private_data);
+	coda_file->private_data = NULL;
 
 	unlock_kernel();
 	return err;
 }
 
-int coda_fsync(struct file *file, struct dentry *dentry, int datasync)
+int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync)
 {
-	struct file *cfile;
-	struct dentry *cdentry;
-	struct inode *cinode, *inode = dentry->d_inode;
-	struct coda_inode_info *cii = ITOC(inode);
+	struct file *host_file;
+	struct dentry *host_dentry;
+	struct inode *host_inode, *coda_inode = coda_dentry->d_inode;
+	struct coda_file_info *cfi;
 	int err = 0;
 
-	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
-	      S_ISLNK(inode->i_mode)))
+	if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
+	      S_ISLNK(coda_inode->i_mode)))
 		return -EINVAL;
 
-	cfile = cii->c_container;
-	if (!cfile) BUG();
+	cfi = CODA_FTOC(coda_file);
+	if (!cfi || cfi->cfi_magic != CODA_MAGIC) BUG();
+	host_file = cfi->cfi_container;
 
 	coda_vfs_stat.fsync++;
 
-	if (cfile->f_op && cfile->f_op->fsync) {
-		cdentry = cfile->f_dentry;
-		cinode = cdentry->d_inode;
-		down(&cinode->i_sem);
-		err = cfile->f_op->fsync(cfile, cdentry, datasync);
-		up(&cinode->i_sem);
+	if (host_file->f_op && host_file->f_op->fsync) {
+		host_dentry = host_file->f_dentry;
+		host_inode = host_dentry->d_inode;
+		down(&host_inode->i_sem);
+		err = host_file->f_op->fsync(host_file, host_dentry, datasync);
+		up(&host_inode->i_sem);
 	}
 
 	if ( !err && !datasync ) {
 		lock_kernel();
-		err = venus_fsync(inode->i_sb, coda_i2f(inode));
+		err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
 		unlock_kernel();
 	}
 

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