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
- Lines: 396
- Date:
Fri Aug 2 17:39:45 2002
- Orig file:
linux-2.4.18/fs/coda/file.c
- Orig date:
Mon Feb 25 11:38:08 2002
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)