summaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-23 00:40:54 +0000
commit529c593ece216e4aaffd36bd940cb94f1fa63129 (patch)
tree78f1c0b805f5656aa7b0417a043c5346f700a2cf /fs/coda
parent0bd079751d25808d1972baee5c4eaa1db2227257 (diff)
Merge with 2.3.43. I did ignore all modifications to the qlogicisp.c
driver due to the Origin A64 hacks.
Diffstat (limited to 'fs/coda')
-rw-r--r--fs/coda/cnode.c119
-rw-r--r--fs/coda/coda_linux.c2
-rw-r--r--fs/coda/dir.c75
-rw-r--r--fs/coda/file.c146
-rw-r--r--fs/coda/inode.c21
-rw-r--r--fs/coda/pioctl.c18
-rw-r--r--fs/coda/psdev.c38
-rw-r--r--fs/coda/symlink.c4
-rw-r--r--fs/coda/sysctl.c7
-rw-r--r--fs/coda/upcall.c74
10 files changed, 226 insertions, 278 deletions
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index faa983e0f..88e954eeb 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -39,12 +39,62 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
inode->i_op = &coda_file_inode_operations;
else if (S_ISDIR(inode->i_mode))
inode->i_op = &coda_dir_inode_operations;
- else if (S_ISLNK(inode->i_mode))
- inode->i_op = &coda_symlink_inode_operations;
- else
+ else if (S_ISLNK(inode->i_mode)) {
+ inode->i_op = &page_symlink_inode_operations;
+ inode->i_data.a_ops = &coda_symlink_aops;
+ } else
init_special_inode(inode, inode->i_mode, attr->va_rdev);
}
+struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
+ struct coda_vattr * attr)
+{
+ struct inode *inode;
+ struct coda_sb_info *sbi= coda_sbp(sb);
+ struct coda_inode_info *cii;
+ ino_t ino = attr->va_fileid;
+
+ inode = iget(sb, ino);
+ if ( !inode ) {
+ CDEBUG(D_CNODE, "coda_iget: no inode\n");
+ return NULL;
+ }
+
+ /* check if the inode is already initialized */
+ cii = ITOC(inode);
+ if (cii->c_magic == CODA_CNODE_MAGIC)
+ goto out;
+
+ /* Initialize the Coda inode info structure */
+ memset(cii, 0, (int) sizeof(struct coda_inode_info));
+ cii->c_magic = CODA_CNODE_MAGIC;
+ cii->c_fid = *fid;
+ cii->c_flags = 0;
+ cii->c_vnode = inode;
+ INIT_LIST_HEAD(&(cii->c_cnhead));
+ INIT_LIST_HEAD(&(cii->c_volrootlist));
+
+ coda_fill_inode(inode, attr);
+
+ /* check if it is a weird fid (hashed fid != ino), f.i mountpoints
+ repair object, expanded local-global conflict trees, etc.
+ */
+ if ( coda_f2i(fid) == ino )
+ goto out;
+
+ /* check if we expect this weird fid */
+ if ( !coda_fid_is_weird(fid) )
+ printk("Coda: unknown weird fid: ino %ld, fid %s."
+ "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid));
+
+ /* add the inode to a global list so we can find it back later */
+ list_add(&cii->c_volrootlist, &sbi->sbi_volroothead);
+ CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n",
+ (long)ino, coda_f2s(&cii->c_fid));
+out:
+ return inode;
+}
+
/* this is effectively coda_iget:
- get attributes (might be cached)
- get the inode for the fid using vfs iget
@@ -54,16 +104,12 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
{
struct coda_inode_info *cnp;
- struct coda_sb_info *sbi= coda_sbp(sb);
struct coda_vattr attr;
int error;
- ino_t ino;
ENTRY;
- /*
- * We get inode numbers from Venus -- see venus source
- */
+ /* We get inode numbers from Venus -- see venus source */
error = venus_getattr(sb, fid, &attr);
if ( error ) {
@@ -74,53 +120,29 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
return error;
}
- ino = attr.va_fileid;
- *inode = iget(sb, ino);
- if ( !*inode ) {
- printk("coda_cnode_make: iget failed\n");
+ *inode = coda_iget(sb, fid, &attr);
+ if ( !(*inode) ) {
+ printk("coda_cnode_make: coda_iget failed\n");
return -ENOMEM;
}
cnp = ITOC(*inode);
- /* see if we've got it already */
- if ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
+ /* see if it is the right one (we might have an inode collision) */
+ if ( coda_fideq(fid, &cnp->c_fid) ) {
+ CDEBUG(D_DOWNCALL,
+ "Done making inode: ino %ld, count %d with %s\n",
+ (*inode)->i_ino, (*inode)->i_count,
+ coda_f2s(&cnp->c_fid));
+ EXIT;
return 0;
}
- /* not fresh: collision */
- if ( cnp->c_magic != 0 ) {
- printk("coda_cnode_make on initialized inode %ld, old %s new
-%s!\n",
+ /* collision */
+ printk("coda_cnode_make on initialized inode %ld, old %s new %s!\n",
(*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
iput(*inode);
- return -ENOENT;
- }
-
- memset(cnp, 0, (int) sizeof(struct coda_inode_info));
- cnp->c_fid = *fid;
- cnp->c_magic = CODA_CNODE_MAGIC;
- cnp->c_flags = 0;
- cnp->c_vnode = *inode;
- INIT_LIST_HEAD(&(cnp->c_cnhead));
- INIT_LIST_HEAD(&(cnp->c_volrootlist));
-
- /* fill in the inode attributes */
- if ( coda_f2i(fid) != ino ) {
- if ( !coda_fid_is_weird(fid) )
- printk("Coda: unknown weird fid: ino %ld, fid %s."
- "Tell Peter.\n", (long)ino, coda_f2s(&cnp->c_fid));
- list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
- CDEBUG(D_UPCALL, "Added %ld ,%s to volroothead\n",
- (long)ino, coda_f2s(&cnp->c_fid));
- }
-
- coda_fill_inode(*inode, &attr);
- CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
- (*inode)->i_ino, (*inode)->i_count,
- coda_f2s(&cnp->c_fid));
-
EXIT;
- return 0;
+ return -ENOENT;
}
@@ -183,11 +205,13 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
coda_f2s(&cii->c_fid), cii->c_vnode->i_ino);
if ( coda_fideq(&cii->c_fid, fid) ) {
inode = cii->c_vnode;
- CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino);
+ CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino);
if ( cii->c_magic != CODA_CNODE_MAGIC )
printk("%s: Bad magic in inode, tell Peter.\n",
__FUNCTION__);
- return cii->c_vnode;
+
+ iget(sb, inode->i_ino);
+ return inode;
}
}
@@ -224,7 +248,6 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
}
CDEBUG(D_INODE, "found %ld\n", inode->i_ino);
- iput(inode);
return inode;
}
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index 5f2f3c467..4a7bebb62 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -102,7 +102,6 @@ int coda_fid_is_weird(struct ViceFid *fid)
return 1;
return 0;
-
}
@@ -290,7 +289,6 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
vattr->va_ctime.tv_sec = iattr->ia_ctime;
vattr->va_ctime.tv_nsec = 0;
}
-
}
void print_vattr(struct coda_vattr *attr)
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 2a1a122c8..3eecd4a5a 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -77,26 +77,16 @@ struct inode_operations coda_dir_inode_operations =
coda_rename, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_permission, /* permission */
coda_revalidate_inode /* revalidate */
};
struct file_operations coda_dir_operations = {
- NULL, /* lseek */
- NULL, /* read -- bad */
- NULL, /* write */
- coda_readdir, /* readdir */
- NULL, /* select */
- NULL, /* ioctl */
- NULL, /* mmap */
- coda_open, /* open */
- NULL,
- coda_release, /* release */
- coda_fsync, /* fsync */
+ readdir: coda_readdir,
+ open: coda_open,
+ release: coda_release,
+ fsync: coda_fsync,
};
@@ -206,7 +196,6 @@ int coda_permission(struct inode *inode, int mask)
}
-
/* creation routines: create, mknod, mkdir, link, symlink */
static int coda_create(struct inode *dir, struct dentry *de, int mode)
@@ -267,7 +256,8 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
coda_vfs_stat.create++;
- CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",name, length, mode, rdev);
+ CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",
+ name, length, mode, rdev);
if (coda_isroot(dir) && coda_iscontrol(name, length))
return -EPERM;
@@ -528,7 +518,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
}
-
/* file operations for directories */
int coda_readdir(struct file *file, void *dirent, filldir_t filldir)
{
@@ -607,11 +596,11 @@ int coda_open(struct inode *i, struct file *f)
coda_load_creds(cred);
f->private_data = cred;
- if ( cnp->c_ovp ) {
+ if ( cnp->c_ovp )
iput(cnp->c_ovp);
- cnp->c_ovp = NULL;
- }
+
cnp->c_ovp = cont_inode;
+ i->i_mapping = cont_inode->i_mapping;
cnp->c_ocount++;
CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n",
@@ -626,7 +615,7 @@ int coda_open(struct inode *i, struct file *f)
int coda_release(struct inode *i, struct file *f)
{
struct coda_inode_info *cnp;
- int error;
+ int error = 0;
unsigned short flags = (f->f_flags) & (~O_EXCL);
unsigned short cflags = coda_flags_to_cflags(flags);
struct coda_cred *cred;
@@ -652,14 +641,17 @@ int coda_release(struct inode *i, struct file *f)
--cnp->c_ocount;
- if (flags & (O_WRONLY | O_RDWR)) {
+ if ( flags & (O_WRONLY | O_RDWR) )
--cnp->c_owrite;
- }
+ /* Venus closing a container file? don't bother making the upcall. */
+ if ( current->pid != coda_upc_comm.vc_pid ) {
error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
+ }
- CODA_FREE(cred, sizeof(*cred));
f->private_data = NULL;
+ if (cred)
+ CODA_FREE(cred, sizeof(*cred));
CDEBUG(D_FILE, "coda_release: result: %d\n", error);
return error;
@@ -857,19 +849,18 @@ int coda_revalidate_inode(struct dentry *dentry)
if ( cii->c_flags == 0 )
return 0;
- /* Venus closed the device .... */
- if ( cii->c_flags & C_DYING ) {
- make_bad_inode(inode);
- return -EIO;
- }
+ /* Venus accessing a container file, don't try to revalidate */
+ if ( current->pid == coda_upc_comm.vc_pid )
+ return 0;
+ /* Venus closed the device .... */
+ if ( cii->c_flags & C_DYING )
+ goto return_bad_inode;
if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
- if ( error ) {
- make_bad_inode(inode);
- return -EIO;
- }
+ if ( error )
+ goto return_bad_inode;
/* this inode may be lost if:
- it's ino changed
@@ -887,12 +878,9 @@ int coda_revalidate_inode(struct dentry *dentry)
}
/* the following can happen when a local fid is replaced
- with a global one, here we lose and declar the inode bad */
- if (inode->i_ino != old_ino) {
- make_bad_inode(inode);
- inode->i_mode = old_mode;
- return -EIO;
- }
+ with a global one, here we lose and declare the inode bad */
+ if (inode->i_ino != old_ino)
+ goto return_bad_inode;
if ( cii->c_flags )
coda_flag_inode_children(inode, C_FLUSH);
@@ -901,5 +889,14 @@ int coda_revalidate_inode(struct dentry *dentry)
}
return 0;
+
+return_bad_inode:
+ if ( cii->c_ovp ) {
+ iput(cii->c_ovp);
+ inode->i_mapping = &inode->i_data;
+ cii->c_ovp = NULL;
+ }
+ make_bad_inode(inode);
+ return -EIO;
}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 726bd18fd..82f661111 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -14,6 +14,7 @@
#include <linux/stat.h>
#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>
@@ -26,9 +27,6 @@
#include <linux/coda_proc.h>
/* file operations */
-static int coda_readpage(struct dentry *dentry, 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);
/* also exported from this file (used for dirs) */
@@ -47,57 +45,21 @@ struct inode_operations coda_file_inode_operations = {
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- coda_readpage, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_permission, /* permission */
coda_revalidate_inode /* 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 */
- NULL,
- coda_release, /* release */
- coda_fsync, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
+ read: generic_file_read,
+ write: generic_file_write,
+ mmap: coda_file_mmap,
+ open: coda_open,
+ release: coda_release,
+ fsync: coda_fsync,
};
-
-/* File file operations */
-static int coda_readpage(struct dentry * dentry, struct page * page)
-{
- struct inode *coda_inode = dentry->d_inode;
- struct dentry cont_dentry;
- struct coda_inode_info *cii;
-
- ENTRY;
- coda_vfs_stat.readpage++;
-
- cii = ITOC(coda_inode);
-
- if ( ! cii->c_ovp ) {
- printk("coda_readpage: no open inode for ino %ld, %s\n",
- coda_inode->i_ino, dentry->d_name.name);
- return -ENXIO;
- }
-
- cont_dentry.d_inode = cii->c_ovp;
-
- CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n",
- coda_inode->i_ino, cii->c_ovp->i_ino, page->index);
-
- block_read_full_page(&cont_dentry, page);
- EXIT;
- return 0;
-}
+
+/* File operations */
static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
{
@@ -115,89 +77,6 @@ static int coda_file_mmap(struct file * file, struct vm_area_struct * vma)
return res;
}
-static ssize_t coda_file_read(struct file *coda_file, char *buff,
- size_t count, loff_t *ppos)
-{
- struct coda_inode_info *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;
- coda_vfs_stat.file_read++;
-
- 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 %p result %d, count %ld, position: %d\n",
- cont_file.f_op, result, (long)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 coda_inode_info *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;
- coda_vfs_stat.file_write++;
-
- 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;
- }
-
- 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);
-
- if (result)
- cnp->c_flags |= C_VATTR;
-
- return result;
-}
-
int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
{
struct coda_inode_info *cnp;
@@ -213,12 +92,14 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
S_ISLNK(coda_inode->i_mode)))
return -EINVAL;
+ lock_kernel();
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");
+ unlock_kernel();
return -1;
}
@@ -235,6 +116,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry)
up(&cont_inode->i_sem);
coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
+ unlock_kernel();
return result;
}
/*
@@ -284,8 +166,8 @@ int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind)
*ind = iget(sbptr, ino);
if ( *ind == NULL ) {
- printk("coda_inode_grab: iget(dev: %d, ino: %ld)
- returns NULL.\n", dev, (long)ino);
+ printk("coda_inode_grab: iget(dev: %d, ino: %ld) "
+ "returns NULL.\n", dev, (long)ino);
return -ENOENT;
}
CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index e2f2931b1..b389b623e 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -52,7 +52,9 @@ struct super_operations coda_super_operations =
coda_put_super, /* put_super */
NULL, /* write_super */
coda_statfs, /* statfs */
- NULL /* remount_fs */
+ NULL, /* remount_fs */
+ NULL, /* no clear inode */
+ NULL /* umount attempt begin */
};
static struct super_block * coda_read_super(struct super_block *sb,
@@ -163,15 +165,16 @@ static void coda_read_inode(struct inode *inode)
return;
}
-static void coda_put_inode(struct inode *in)
+static void coda_put_inode(struct inode *inode)
{
ENTRY;
- CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count);
-
- if ( in->i_count == 1 )
- in->i_nlink = 0;
+ CDEBUG(D_INODE,"ino: %ld, count %d\n", inode->i_ino, inode->i_count);
+ if ( inode->i_count == 1 ) {
+ write_inode_now(inode);
+ inode->i_nlink = 0;
+ }
}
static void coda_delete_inode(struct inode *inode)
@@ -189,15 +192,17 @@ static void coda_delete_inode(struct inode *inode)
return;
}
-
- if ( ! list_empty(&cii->c_volrootlist) )
+ if ( ! list_empty(&cii->c_volrootlist) ) {
list_del(&cii->c_volrootlist);
+ INIT_LIST_HEAD(&cii->c_volrootlist);
+ }
open_inode = cii->c_ovp;
if ( open_inode ) {
CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",
open_inode->i_ino, open_inode->i_count);
cii->c_ovp = NULL;
+ inode->i_mapping = &inode->i_data;
iput(open_inode);
}
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index cec92b7f4..9a900a91a 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -46,26 +46,15 @@ struct inode_operations coda_ioctl_inode_operations =
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
NULL, /* truncate */
coda_ioctl_permission, /* permission */
NULL /* revalidate */
};
struct file_operations coda_ioctl_operations = {
- NULL, /* lseek - default should work for coda */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* select - default */
- coda_pioctl, /* ioctl */
- NULL, /* mmap */
- coda_ioctl_open, /* open */
- NULL,
- coda_ioctl_release, /* release */
- NULL, /* fsync */
+ ioctl: coda_pioctl,
+ open: coda_ioctl_open,
+ release: coda_ioctl_release,
};
/* the coda pioctl inode ops */
@@ -79,7 +68,6 @@ static int coda_ioctl_permission(struct inode *inode, int mask)
/* The pioctl file ops*/
int coda_ioctl_open(struct inode *i, struct file *f)
{
-
ENTRY;
CDEBUG(D_PIOCTL, "File inode number: %ld\n",
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 65aeee08e..07ba22335 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -76,6 +76,21 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
return mask;
}
+static int coda_psdev_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int data;
+
+ switch(cmd) {
+ case CIOC_KERNEL_VERSION:
+ data = CODA_KERNEL_VERSION;
+ return put_user(data, (int *) arg);
+ default:
+ return -ENOTTY;
+ }
+
+ return 0;
+}
/*
* Receive a message written by Venus to the psdev
@@ -246,7 +261,6 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
vcp->vc_inuse++;
MOD_INC_USE_COUNT;
-
if ( file->f_flags == O_RDWR ) {
vcp->vc_pid = current->pid;
vcp->vc_seq = 0;
@@ -262,7 +276,6 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
}
-
static int coda_psdev_release(struct inode * inode, struct file * file)
{
struct venus_comm *vcp = &coda_upc_comm;
@@ -298,6 +311,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
CODA_FREE(req, (u_int)sizeof(struct upc_req));
continue;
}
+ req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep);
}
@@ -305,6 +319,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
CDEBUG(D_PSDEV, "wake up processing clients\n");
while ( (lh = lh->next) != &vcp->vc_processing) {
req = list_entry(lh, struct upc_req, uc_chain);
+ req->uc_flags |= REQ_ABORT;
wake_up(&req->uc_sleep);
}
CDEBUG(D_PSDEV, "Done.\n");
@@ -315,19 +330,12 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
static struct file_operations coda_psdev_fops = {
- NULL, /* llseek */
- coda_psdev_read, /* read */
- coda_psdev_write, /* write */
- NULL, /* coda_psdev_readdir */
- coda_psdev_poll, /* poll */
- NULL, /* ioctl */
- NULL, /* coda_psdev_mmap */
- coda_psdev_open, /* open */
- NULL,
- coda_psdev_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL /* lock */
+ read: coda_psdev_read,
+ write: coda_psdev_write,
+ poll: coda_psdev_poll,
+ ioctl: coda_psdev_ioctl,
+ open: coda_psdev_open,
+ release: coda_psdev_release,
};
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index 872370cf9..d44d0f7c3 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -48,8 +48,6 @@ fail:
return error;
}
-struct inode_operations coda_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
+struct address_space_operations coda_symlink_aops = {
readpage: coda_symlink_filler
};
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 046153362..289f9417c 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -109,7 +109,8 @@ char *coda_upcall_names[] = {
"open_by_path", /* 31 */
"resolve ", /* 32 */
"reintegrate ", /* 33 */
- "statfs " /* 34 */
+ "statfs ", /* 34 */
+ "make_cinode " /* 35 */
};
@@ -214,8 +215,8 @@ unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pen
return 0;
time_avg = get_time_average( pentry );
- return
- sqr_root( (pentry->time_squared_sum / pentry->count) -
+
+ return sqr_root( (pentry->time_squared_sum / pentry->count) -
time_avg * time_avg );
}
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 9aecd8a6e..63586d05c 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -24,6 +24,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/fs.h>
+#include <linux/file.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
@@ -392,7 +393,7 @@ int venus_readlink(struct super_block *sb, struct ViceFid *fid,
if ( retlen > *length )
retlen = *length;
*length = retlen;
- result = (char *)outp + (int)outp->coda_readlink.data;
+ result = (char *)outp + (long)outp->coda_readlink.data;
memcpy(buffer, result, retlen);
*(buffer + retlen) = '\0';
}
@@ -541,7 +542,7 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
/* get the data out of user space */
- if ( copy_from_user((char*)inp + (int)inp->coda_ioctl.data,
+ if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
data->vi.in, data->vi.in_size) ) {
error = EINVAL;
goto exit;
@@ -567,7 +568,7 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
if ( error ) goto exit;
if (copy_to_user(data->vi.out,
- (char *)outp + (int)outp->coda_ioctl.data,
+ (char *)outp + (long)outp->coda_ioctl.data,
data->vi.out_size)) {
error = EINVAL;
goto exit;
@@ -630,7 +631,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
set_current_state(TASK_UNINTERRUPTIBLE);
/* got a reply */
- if ( vmp->uc_flags & REQ_WRITE )
+ if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
break;
if ( !coda_hard && signal_pending(current) ) {
@@ -660,7 +661,8 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
}
CDEBUG(D_SPECIAL, "begin: %ld.%06ld, elapsed: %ld.%06ld\n",
- begin.tv_sec, begin.tv_usec, end.tv_sec, end.tv_usec);
+ begin.tv_sec, (unsigned long)begin.tv_usec,
+ end.tv_sec, (unsigned long)end.tv_usec);
return ((end.tv_sec * 1000000) + end.tv_usec);
}
@@ -844,7 +846,6 @@ ENTRY;
int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
{
-
/* Handle invalidation requests. */
if ( !sb || !sb->s_root || !sb->s_root->d_inode) {
printk("coda_downcall: opcode %d, no sb!\n", opcode);
@@ -877,7 +878,8 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_ZAPDIR : {
struct inode *inode;
ViceFid *fid = &out->coda_zapdir.CodaFid;
- CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n",
+ coda_f2s(fid));
clstats(CODA_ZAPDIR);
inode = coda_fid_to_inode(fid, sb);
@@ -887,6 +889,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
coda_flag_inode_children(inode, C_PURGE);
CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
coda_flag_inode(inode, C_VATTR);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapdir: no inode\n");
@@ -897,11 +900,14 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
struct inode *inode;
struct ViceFid *fid = &out->coda_zapfile.CodaFid;
clstats(CODA_ZAPFILE);
- CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n",
+ coda_f2s(fid));
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n", inode->i_ino);
+ CDEBUG(D_DOWNCALL, "zapfile: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode(inode, C_VATTR);
+ iput(inode);
} else
CDEBUG(D_DOWNCALL, "zapfile: no inode\n");
return 0;
@@ -910,18 +916,61 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_PURGEFID : {
struct inode *inode;
ViceFid *fid = &out->coda_purgefid.CodaFid;
- CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
+ CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n",
+ coda_f2s(fid));
clstats(CODA_PURGEFID);
inode = coda_fid_to_inode(fid, sb);
if ( inode ) {
- CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
+ CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n",
+ inode->i_ino);
coda_flag_inode_children(inode, C_PURGE);
coda_purge_dentries(inode);
+ iput(inode);
}else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
return 0;
}
+ case CODA_MAKE_CINODE : {
+ struct inode *inode;
+ ViceFid *fid = &out->coda_make_cinode.CodaFid;
+ struct coda_vattr *attr = &out->coda_make_cinode.attr;
+ int fd = out->coda_make_cinode.fd;
+ struct file *file;
+ CDEBUG(D_DOWNCALL, "make_cinode: fid = %s, ino = %ld\n",
+ coda_f2s(fid), attr->va_fileid);
+
+ inode = coda_iget(sb, fid, attr);
+ if ( !inode ) {
+ CDEBUG(D_DOWNCALL, "make_cinode: no inode\n");
+ return -EINVAL;
+ }
+
+ file = fget(fd);
+ if ( !file ) {
+ CDEBUG(D_DOWNCALL, "make_cinode: no file\n");
+ iput(inode);
+ return -EINVAL;
+ }
+
+ inode->u.coda_i.c_ovp = file->f_dentry->d_inode;
+ inode->i_mapping = file->f_dentry->d_inode->i_mapping;
+ file->f_dentry->d_inode = inode;
+ file->f_op = &coda_file_operations;
+
+ /*
+ Unhash the dentry of the container file, as it is
+ still owned by the fs that stores the container
+ file. A more reliable solution would be to create
+ an new dentry owned by Coda, but that would require
+ knowledge of the internals of the dcache.
+ */
+ d_drop(file->f_dentry);
+
+ fput(file);
+ return 0;
+ }
+
case CODA_REPLACE : {
struct inode *inode;
ViceFid *oldfid = &out->coda_replace.OldFid;
@@ -932,6 +981,7 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
if ( inode ) {
CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
coda_replace_fid(inode, oldfid, newfid);
+ iput(inode);
}else
CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
@@ -941,5 +991,3 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
return 0;
}
-
-