diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-23 00:40:54 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-23 00:40:54 +0000 |
commit | 529c593ece216e4aaffd36bd940cb94f1fa63129 (patch) | |
tree | 78f1c0b805f5656aa7b0417a043c5346f700a2cf /fs/coda | |
parent | 0bd079751d25808d1972baee5c4eaa1db2227257 (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.c | 119 | ||||
-rw-r--r-- | fs/coda/coda_linux.c | 2 | ||||
-rw-r--r-- | fs/coda/dir.c | 75 | ||||
-rw-r--r-- | fs/coda/file.c | 146 | ||||
-rw-r--r-- | fs/coda/inode.c | 21 | ||||
-rw-r--r-- | fs/coda/pioctl.c | 18 | ||||
-rw-r--r-- | fs/coda/psdev.c | 38 | ||||
-rw-r--r-- | fs/coda/symlink.c | 4 | ||||
-rw-r--r-- | fs/coda/sysctl.c | 7 | ||||
-rw-r--r-- | fs/coda/upcall.c | 74 |
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; } - - |