Commit b4655acd authored by Linus Torvalds's avatar Linus Torvalds

Merge home.transmeta.com:/home/torvalds/v2.5/coda

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 77a32d76 dbd82204
...@@ -85,6 +85,7 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, ...@@ -85,6 +85,7 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
cii = ITOC(inode); cii = ITOC(inode);
/* we still need to set i_ino for things like stat(2) */ /* we still need to set i_ino for things like stat(2) */
inode->i_ino = hash; inode->i_ino = hash;
cii->c_mapcount = 0;
list_add(&cii->c_cilist, &sbi->sbi_cihead); list_add(&cii->c_cilist, &sbi->sbi_cihead);
unlock_new_inode(inode); unlock_new_inode(inode);
} }
......
...@@ -29,21 +29,7 @@ int coda_fake_statfs; ...@@ -29,21 +29,7 @@ int coda_fake_statfs;
char * coda_f2s(ViceFid *f) char * coda_f2s(ViceFid *f)
{ {
static char s[60]; static char s[60];
if ( f ) { sprintf(s, "(%-#lx.%-#lx.%-#lx)", f->Volume, f->Vnode, f->Unique);
sprintf(s, "(%-#lx,%-#lx,%-#lx)",
f->Volume, f->Vnode, f->Unique);
}
return s;
}
/* print another fid */
char * coda_f2s2(ViceFid *f)
{
static char s[60];
if ( f ) {
sprintf(s, "(%-#lx,%-#lx,%-#lx)",
f->Volume, f->Vnode, f->Unique);
}
return s; return s;
} }
......
...@@ -49,40 +49,42 @@ static int coda_dentry_revalidate(struct dentry *de, int); ...@@ -49,40 +49,42 @@ static int coda_dentry_revalidate(struct dentry *de, int);
static int coda_dentry_delete(struct dentry *); static int coda_dentry_delete(struct dentry *);
/* support routines */ /* support routines */
static int coda_venus_readdir(struct file *filp, filldir_t filldir, void *dirent); static int coda_venus_readdir(struct file *filp, filldir_t filldir,
void *dirent, struct dentry *dir);
int coda_fsync(struct file *, struct dentry *dentry, int datasync); int coda_fsync(struct file *, struct dentry *dentry, int datasync);
int coda_hasmknod; int coda_hasmknod;
struct dentry_operations coda_dentry_operations = struct dentry_operations coda_dentry_operations =
{ {
d_revalidate: coda_dentry_revalidate, .d_revalidate = coda_dentry_revalidate,
d_delete: coda_dentry_delete, .d_delete = coda_dentry_delete,
}; };
struct inode_operations coda_dir_inode_operations = struct inode_operations coda_dir_inode_operations =
{ {
create: coda_create, .create = coda_create,
lookup: coda_lookup, .lookup = coda_lookup,
link: coda_link, .link = coda_link,
unlink: coda_unlink, .unlink = coda_unlink,
symlink: coda_symlink, .symlink = coda_symlink,
mkdir: coda_mkdir, .mkdir = coda_mkdir,
rmdir: coda_rmdir, .rmdir = coda_rmdir,
mknod: coda_mknod, .mknod = coda_mknod,
rename: coda_rename, .rename = coda_rename,
permission: coda_permission, .permission = coda_permission,
getattr: coda_getattr, .getattr = coda_getattr,
setattr: coda_setattr, .setattr = coda_setattr,
}; };
struct file_operations coda_dir_operations = { struct file_operations coda_dir_operations = {
read: generic_read_dir, .llseek = generic_file_llseek,
readdir: coda_readdir, .read = generic_read_dir,
open: coda_open, .readdir = coda_readdir,
flush: coda_flush, .open = coda_open,
release: coda_release, .flush = coda_flush,
fsync: coda_fsync, .release = coda_release,
.fsync = coda_fsync,
}; };
...@@ -475,70 +477,99 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, ...@@ -475,70 +477,99 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
/* file operations for directories */ /* file operations for directories */
int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir) int coda_readdir(struct file *coda_file, void *dirent, filldir_t filldir)
{ {
int result = 0;
struct dentry *coda_dentry = coda_file->f_dentry; struct dentry *coda_dentry = coda_file->f_dentry;
struct inode *coda_inode = coda_dentry->d_inode; struct coda_file_info *cfi;
struct coda_inode_info *cii = ITOC(coda_inode); struct file *host_file;
struct file *host_file = cii->c_container; struct inode *host_inode;
int ret;
BUG_ON(!host_file); cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
coda_vfs_stat.readdir++; coda_vfs_stat.readdir++;
/* Access to both host and coda f_pos fields is serialized on the host_inode = host_file->f_dentry->d_inode;
* coda_file->f_dentry->d_inode->i_sem which has already been taken by down(&host_inode->i_sem);
* vfs_readdir. Userspace shouldn't 'play' with the container file as
* long as the file is held open. */
host_file->f_pos = coda_file->f_pos; host_file->f_pos = coda_file->f_pos;
if ( !host_file->f_op->readdir ) if (!host_file->f_op->readdir) {
/* Venus: we must read Venus dirents from the file */ /* Venus: we must read Venus dirents from the file */
result = coda_venus_readdir(host_file, filldir, dirent); ret = coda_venus_readdir(host_file, filldir, dirent, coda_dentry);
else } else {
/* potemkin case: we were handed a directory inode */ /* potemkin case: we were handed a directory inode. */
result = vfs_readdir(host_file, filldir, dirent); /* Yuk, we can't call vfs_readdir because we are already
* holding the inode semaphore. */
ret = -ENOTDIR;
if (!host_file->f_op || !host_file->f_op->readdir)
goto out;
ret = -ENOENT;
if (!IS_DEADDIR(host_inode))
ret = host_file->f_op->readdir(host_file, filldir, dirent);
}
out:
coda_file->f_pos = host_file->f_pos; coda_file->f_pos = host_file->f_pos;
return result; up(&host_inode->i_sem);
return ret;
} }
static inline unsigned int CDT2DT(unsigned char cdt) static inline unsigned int CDT2DT(unsigned char cdt)
{ {
unsigned int dt; unsigned int dt;
switch(cdt) { switch(cdt) {
case CDT_UNKNOWN: dt = DT_UNKNOWN; break; case CDT_UNKNOWN: dt = DT_UNKNOWN; break;
case CDT_FIFO: dt = DT_FIFO; break; case CDT_FIFO: dt = DT_FIFO; break;
case CDT_CHR: dt = DT_CHR; break; case CDT_CHR: dt = DT_CHR; break;
case CDT_DIR: dt = DT_DIR; break; case CDT_DIR: dt = DT_DIR; break;
case CDT_BLK: dt = DT_BLK; break; case CDT_BLK: dt = DT_BLK; break;
case CDT_REG: dt = DT_REG; break; case CDT_REG: dt = DT_REG; break;
case CDT_LNK: dt = DT_LNK; break; case CDT_LNK: dt = DT_LNK; break;
case CDT_SOCK: dt = DT_SOCK; break; case CDT_SOCK: dt = DT_SOCK; break;
case CDT_WHT: dt = DT_WHT; break; case CDT_WHT: dt = DT_WHT; break;
default: dt = DT_UNKNOWN; break; default: dt = DT_UNKNOWN; break;
} }
return dt; return dt;
} }
/* support routines */ /* support routines */
static int coda_venus_readdir(struct file *filp, filldir_t filldir, static int coda_venus_readdir(struct file *filp, filldir_t filldir,
void *getdent) void *dirent, struct dentry *dir)
{ {
int result = 0; /* # of entries returned */ int result = 0; /* # of entries returned */
struct venus_dirent *vdir; struct venus_dirent *vdir;
unsigned long vdir_size = unsigned long vdir_size =
(unsigned long)(&((struct venus_dirent *)0)->d_name); (unsigned long)(&((struct venus_dirent *)0)->d_name);
int ret; unsigned int type;
struct qstr name;
ino_t ino;
int ret, i;
vdir = (struct venus_dirent *)kmalloc(sizeof(*vdir), GFP_KERNEL); vdir = (struct venus_dirent *)kmalloc(sizeof(*vdir), GFP_KERNEL);
if (!vdir) return -ENOMEM; if (!vdir) return -ENOMEM;
while(1) { i = filp->f_pos;
/* we use this routine to read the file into our buffer */ switch(i) {
ret = kernel_read(filp, filp->f_pos, (char *)vdir, case 0:
ret = filldir(dirent, ".", 1, 0, dir->d_inode->i_ino, DT_DIR);
if (ret < 0) break;
result++;
filp->f_pos++;
/* fallthrough */
case 1:
ret = filldir(dirent, "..", 2, 1, dir->d_parent->d_inode->i_ino, DT_DIR);
if (ret < 0) break;
result++;
filp->f_pos++;
/* fallthrough */
default:
while (1) {
/* read entries from the directory file */
ret = kernel_read(filp, filp->f_pos - 2, (char *)vdir,
sizeof(*vdir)); sizeof(*vdir));
if (ret < 0) { if (ret < 0) {
printk("coda_venus_readdir: read dir failed %d\n", ret); printk("coda_venus_readdir: read dir failed %d\n", ret);
...@@ -548,35 +579,51 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir, ...@@ -548,35 +579,51 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
/* catch truncated reads */ /* catch truncated reads */
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) { if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
printk("coda_venus_readdir: short read: %ld\n", printk("coda_venus_readdir: short read: %ld\n",
filp->f_dentry->d_inode->i_ino); filp->f_dentry->d_inode->i_ino);
ret = -EBADF; ret = -EBADF;
break; break;
} }
/* validate whether the directory file actually makes sense */ /* validate whether the directory file actually makes sense */
if (vdir->d_reclen < vdir_size + vdir->d_namlen || if (vdir->d_reclen < vdir_size + vdir->d_namlen ||
vdir->d_namlen > CODA_MAXNAMLEN) { vdir->d_namlen > CODA_MAXNAMLEN) {
printk("coda_venus_readdir: Invalid directory: %ld\n", printk("coda_venus_readdir: Invalid dir: %ld\n",
filp->f_dentry->d_inode->i_ino); filp->f_dentry->d_inode->i_ino);
ret = -EBADF; ret = -EBADF;
break; break;
} }
name.len = vdir->d_namlen;
name.name = vdir->d_name;
/* Make sure we skip '.' and '..', we already got those */
if (name.name[0] == '.' && (name.len == 1 ||
(vdir->d_name[1] == '.' && name.len == 2)))
vdir->d_fileno = name.len = 0;
/* skip null entries */ /* skip null entries */
if (vdir->d_fileno) { if (vdir->d_fileno && name.len) {
unsigned int d_type = CDT2DT(vdir->d_type); /* try to look up this entry in the dcache, that way
ret = filldir(getdent, vdir->d_name, vdir->d_namlen, * userspace doesn't have to worry about breaking
filp->f_pos, vdir->d_fileno, d_type); * getcwd by having mismatched inode numbers for
/* failure means no space for filling in this round */ * internal volume mountpoints. */
if (ret < 0) break; ino = find_inode_number(dir, &name);
result++; if (!ino) ino = vdir->d_fileno;
type = CDT2DT(vdir->d_type);
ret = filldir(dirent, name.name, name.len, filp->f_pos,
ino, type);
/* failure means no space for filling in this round */
if (ret < 0) break;
result++;
} }
/* we'll always have progress because d_reclen is unsigned and /* we'll always have progress because d_reclen is unsigned and
* we've already established it is non-zero. */ * we've already established it is non-zero. */
filp->f_pos += vdir->d_reclen; filp->f_pos += vdir->d_reclen;
} }
}
kfree(vdir); kfree(vdir);
return result ? result : ret; return result ? result : ret;
} }
/* called when a cache lookup succeeds */ /* called when a cache lookup succeeds */
...@@ -660,7 +707,7 @@ int coda_revalidate_inode(struct dentry *dentry) ...@@ -660,7 +707,7 @@ int coda_revalidate_inode(struct dentry *dentry)
if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
if ( error ) if ( error )
goto return_bad_inode; goto return_bad;
/* this inode may be lost if: /* this inode may be lost if:
- it's ino changed - it's ino changed
...@@ -679,7 +726,7 @@ int coda_revalidate_inode(struct dentry *dentry) ...@@ -679,7 +726,7 @@ int coda_revalidate_inode(struct dentry *dentry)
/* the following can happen when a local fid is replaced /* the following can happen when a local fid is replaced
with a global one, here we lose and declare the inode bad */ with a global one, here we lose and declare the inode bad */
if (inode->i_ino != old_ino) if (inode->i_ino != old_ino)
goto return_bad_inode; goto return_bad;
coda_flag_inode_children(inode, C_FLUSH); coda_flag_inode_children(inode, C_FLUSH);
cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
...@@ -689,13 +736,7 @@ int coda_revalidate_inode(struct dentry *dentry) ...@@ -689,13 +736,7 @@ int coda_revalidate_inode(struct dentry *dentry)
unlock_kernel(); unlock_kernel();
return 0; return 0;
return_bad_inode: return_bad:
inode->i_mapping = &inode->i_data;
if (cii->c_container) {
fput(cii->c_container);
cii->c_container = NULL;
}
make_bad_inode(inode);
unlock_kernel(); unlock_kernel();
return -EIO; return -EIO;
} }
......
...@@ -29,143 +29,152 @@ ...@@ -29,143 +29,152 @@
int use_coda_close; int use_coda_close;
static ssize_t 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_file_info *cfi;
struct coda_inode_info *cii = ITOC(inode); struct file *host_file;
struct file *cfile;
cfile = cii->c_container; cfi = CODA_FTOC(coda_file);
if (!cfile) BUG(); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
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; return -EINVAL;
return cfile->f_op->read(cfile, buf, count, ppos); return host_file->f_op->read(host_file, buf, count, ppos);
} }
static ssize_t 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 inode *host_inode, *coda_inode = coda_file->f_dentry->d_inode;
struct coda_inode_info *cii = ITOC(inode); struct coda_file_info *cfi;
struct file *cfile; struct file *host_file;
ssize_t ret; ssize_t ret;
int flags;
cfile = cii->c_container; cfi = CODA_FTOC(coda_file);
if (!cfile) BUG(); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
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; return -EINVAL;
cinode = cfile->f_dentry->d_inode; host_inode = host_file->f_dentry->d_inode;
down(&inode->i_sem); down(&coda_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); ret = host_file->f_op->write(host_file, buf, count, ppos);
cfile->f_flags = flags; coda_inode->i_size = host_inode->i_size;
inode->i_size = cinode->i_size; coda_inode->i_blocks = (coda_inode->i_size + 511) >> 9;
inode->i_mtime = inode->i_ctime = CURRENT_TIME; coda_inode->i_mtime = coda_inode->i_ctime = CURRENT_TIME;
up(&inode->i_sem); up(&coda_inode->i_sem);
return ret; return ret;
} }
static int 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_file_info *cfi;
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii;
struct file *cfile; struct file *host_file;
struct inode *coda_inode, *host_inode;
cfile = cii->c_container;
if (!cfile) BUG(); cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
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; return -ENODEV;
return cfile->f_op->mmap(cfile, vma); 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; struct file *host_file = NULL;
int error = 0; int error;
unsigned short flags = f->f_flags & (~O_EXCL); unsigned short flags = coda_file->f_flags & (~O_EXCL);
unsigned short coda_flags = coda_flags_to_cflags(flags); unsigned short coda_flags = coda_flags_to_cflags(flags);
struct coda_cred *cred; struct coda_file_info *cfi;
struct coda_inode_info *cii;
lock_kernel();
coda_vfs_stat.open++; coda_vfs_stat.open++;
error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &fh); cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL);
if (error || !fh) { if (!cfi) {
unlock_kernel(); unlock_kernel();
return error; return -ENOMEM;
} }
/* coda_upcall returns filehandle of container file object */ lock_kernel();
cii = ITOC(i);
if (cii->c_container)
fput(cii->c_container);
cii->c_contcount++; error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
cii->c_container = fh; &host_file);
i->i_mapping = &cii->c_container->f_dentry->d_inode->i_data; if (error || !host_file) {
kfree(cfi);
unlock_kernel();
return error;
}
cred = kmalloc(sizeof(struct coda_cred), GFP_KERNEL); host_file->f_flags |= coda_file->f_flags & (O_APPEND | O_SYNC);
/* If the allocation failed, we'll just muddle on. This actually works cfi->cfi_magic = CODA_MAGIC;
* fine for normal cases. (i.e. when open credentials are the same as cfi->cfi_mapcount = 0;
* close credentials) */ cfi->cfi_container = host_file;
if (cred) { coda_load_creds(&cfi->cfi_cred);
coda_load_creds(cred);
f->private_data = cred; BUG_ON(coda_file->private_data != NULL);
} coda_file->private_data = cfi;
unlock_kernel(); unlock_kernel();
return 0; return 0;
} }
int coda_flush(struct file *coda_file)
int coda_flush(struct file *file)
{ {
unsigned short flags = (file->f_flags) & (~O_EXCL); unsigned short flags = coda_file->f_flags & ~O_EXCL;
unsigned short cflags; unsigned short coda_flags = coda_flags_to_cflags(flags);
struct coda_inode_info *cii; struct coda_file_info *cfi;
struct file *cfile; struct inode *coda_inode;
struct inode *cinode, *inode;
int err = 0, fcnt; int err = 0, fcnt;
coda_vfs_stat.flush++; coda_vfs_stat.flush++;
/* last close semantics */
fcnt = file_count(coda_file);
if (fcnt > 1) return 0;
/* No need to make an upcall when we have not made any modifications /* No need to make an upcall when we have not made any modifications
* to the file */ * to the file */
if ((file->f_flags & O_ACCMODE) == O_RDONLY) if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
return 0; return 0;
if (use_coda_close) if (use_coda_close)
return 0; return 0;
fcnt = file_count(file); cfi = CODA_FTOC(coda_file);
if (fcnt > 1) return 0; BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
cflags = coda_flags_to_cflags(flags); coda_inode = coda_file->f_dentry->d_inode;
inode = file->f_dentry->d_inode; err = venus_store(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
cii = ITOC(inode); &cfi->cfi_cred);
cfile = cii->c_container;
if (!cfile) BUG();
cinode = cfile->f_dentry->d_inode;
err = venus_store(inode->i_sb, coda_i2f(inode), cflags,
(struct coda_cred *)file->private_data);
if (err == -EOPNOTSUPP) { if (err == -EOPNOTSUPP) {
use_coda_close = 1; use_coda_close = 1;
err = 0; err = 0;
...@@ -174,79 +183,81 @@ int coda_flush(struct file *file) ...@@ -174,79 +183,81 @@ int coda_flush(struct file *file)
return 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 flags = (coda_file->f_flags) & (~O_EXCL);
unsigned short cflags = coda_flags_to_cflags(flags); unsigned short coda_flags = coda_flags_to_cflags(flags);
struct coda_file_info *cfi;
struct coda_inode_info *cii; struct coda_inode_info *cii;
struct file *cfile; struct inode *host_inode;
int err = 0; int err = 0;
lock_kernel(); lock_kernel();
coda_vfs_stat.release++; coda_vfs_stat.release++;
if (!use_coda_close) { 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) { if (err == -EOPNOTSUPP) {
use_coda_close = 1; use_coda_close = 1;
err = 0; err = 0;
} }
} }
cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
if (use_coda_close) if (use_coda_close)
err = venus_close(i->i_sb, coda_i2f(i), cflags, err = venus_close(coda_inode->i_sb, coda_i2f(coda_inode),
(struct coda_cred *)f->private_data); coda_flags, &cfi->cfi_cred);
cii = ITOC(i); host_inode = cfi->cfi_container->f_dentry->d_inode;
cfile = cii->c_container; cii = ITOC(coda_inode);
if (!cfile) BUG();
if (--cii->c_contcount) { /* did we mmap this file? */
unlock_kernel(); if (coda_inode->i_mapping == &host_inode->i_data) {
return err; 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(cfi->cfi_container);
fput(cfile); kfree(coda_file->private_data);
cii->c_container = NULL; coda_file->private_data = NULL;
if (f->private_data) {
kfree(f->private_data);
f->private_data = NULL;
}
unlock_kernel(); unlock_kernel();
return err; 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 file *host_file;
struct dentry *cdentry; struct dentry *host_dentry;
struct inode *cinode, *inode = dentry->d_inode; struct inode *host_inode, *coda_inode = coda_dentry->d_inode;
struct coda_inode_info *cii = ITOC(inode); struct coda_file_info *cfi;
int err = 0; int err = 0;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
S_ISLNK(inode->i_mode))) S_ISLNK(coda_inode->i_mode)))
return -EINVAL; return -EINVAL;
cfile = cii->c_container; cfi = CODA_FTOC(coda_file);
if (!cfile) BUG(); BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
host_file = cfi->cfi_container;
coda_vfs_stat.fsync++; coda_vfs_stat.fsync++;
if (cfile->f_op && cfile->f_op->fsync) { if (host_file->f_op && host_file->f_op->fsync) {
cdentry = cfile->f_dentry; host_dentry = host_file->f_dentry;
cinode = cdentry->d_inode; host_inode = host_dentry->d_inode;
down(&cinode->i_sem); down(&host_inode->i_sem);
err = cfile->f_op->fsync(cfile, cdentry, datasync); err = host_file->f_op->fsync(host_file, host_dentry, datasync);
up(&cinode->i_sem); up(&host_inode->i_sem);
} }
if ( !err && !datasync ) { if ( !err && !datasync ) {
lock_kernel(); lock_kernel();
err = venus_fsync(inode->i_sb, coda_i2f(inode)); err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
unlock_kernel(); unlock_kernel();
} }
...@@ -254,13 +265,13 @@ int coda_fsync(struct file *file, struct dentry *dentry, int datasync) ...@@ -254,13 +265,13 @@ int coda_fsync(struct file *file, struct dentry *dentry, int datasync)
} }
struct file_operations coda_file_operations = { struct file_operations coda_file_operations = {
llseek: generic_file_llseek, .llseek = generic_file_llseek,
read: coda_file_read, .read = coda_file_read,
write: coda_file_write, .write = coda_file_write,
mmap: coda_file_mmap, .mmap = coda_file_mmap,
open: coda_open, .open = coda_open,
flush: coda_flush, .flush = coda_flush,
release: coda_release, .release = coda_release,
fsync: coda_fsync, .fsync = coda_fsync,
}; };
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
* Copyright (C) Carnegie Mellon University * Copyright (C) Carnegie Mellon University
*/ */
#define __NO_VERSION__
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -47,8 +46,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb) ...@@ -47,8 +46,6 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
memset(&ei->c_fid, 0, sizeof(struct ViceFid)); memset(&ei->c_fid, 0, sizeof(struct ViceFid));
ei->c_flags = 0; ei->c_flags = 0;
INIT_LIST_HEAD(&ei->c_cilist); INIT_LIST_HEAD(&ei->c_cilist);
ei->c_container = NULL;
ei->c_contcount = 0;
memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred)); memset(&ei->c_cached_cred, 0, sizeof(struct coda_cred));
ei->c_cached_perm = 0; ei->c_cached_perm = 0;
return &ei->vfs_inode; return &ei->vfs_inode;
...@@ -88,11 +85,11 @@ void coda_destroy_inodecache(void) ...@@ -88,11 +85,11 @@ void coda_destroy_inodecache(void)
/* exported operations */ /* exported operations */
struct super_operations coda_super_operations = struct super_operations coda_super_operations =
{ {
alloc_inode: coda_alloc_inode, .alloc_inode = coda_alloc_inode,
destroy_inode: coda_destroy_inode, .destroy_inode = coda_destroy_inode,
clear_inode: coda_clear_inode, .clear_inode = coda_clear_inode,
put_super: coda_put_super, .put_super = coda_put_super,
statfs: coda_statfs, .statfs = coda_statfs,
}; };
static int get_device_index(struct coda_mount_data *data) static int get_device_index(struct coda_mount_data *data)
...@@ -230,10 +227,7 @@ static void coda_clear_inode(struct inode *inode) ...@@ -230,10 +227,7 @@ static void coda_clear_inode(struct inode *inode)
{ {
struct coda_inode_info *cii = ITOC(inode); struct coda_inode_info *cii = ITOC(inode);
if (cii->c_container) BUG(); list_del_init(&cii->c_cilist);
list_del_init(&cii->c_cilist);
inode->i_mapping = &inode->i_data;
coda_cache_clear_inode(inode); coda_cache_clear_inode(inode);
} }
...@@ -248,16 +242,16 @@ int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat ...@@ -248,16 +242,16 @@ int coda_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
int coda_setattr(struct dentry *de, struct iattr *iattr) int coda_setattr(struct dentry *de, struct iattr *iattr)
{ {
struct inode *inode = de->d_inode; struct inode *inode = de->d_inode;
struct coda_vattr vattr; struct coda_vattr vattr;
int error; int error;
lock_kernel(); lock_kernel();
memset(&vattr, 0, sizeof(vattr)); memset(&vattr, 0, sizeof(vattr));
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
coda_iattr_to_vattr(iattr, &vattr); coda_iattr_to_vattr(iattr, &vattr);
vattr.va_type = C_VNON; /* cannot set type */ vattr.va_type = C_VNON; /* cannot set type */
/* Venus is responsible for truncating the container-file!!! */ /* Venus is responsible for truncating the container-file!!! */
error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr); error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
...@@ -273,9 +267,9 @@ int coda_setattr(struct dentry *de, struct iattr *iattr) ...@@ -273,9 +267,9 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
} }
struct inode_operations coda_file_inode_operations = { struct inode_operations coda_file_inode_operations = {
permission: coda_permission, .permission = coda_permission,
getattr: coda_getattr, .getattr = coda_getattr,
setattr: coda_setattr, .setattr = coda_setattr,
}; };
static int coda_statfs(struct super_block *sb, struct statfs *buf) static int coda_statfs(struct super_block *sb, struct statfs *buf)
...@@ -314,8 +308,9 @@ static struct super_block *coda_get_sb(struct file_system_type *fs_type, ...@@ -314,8 +308,9 @@ static struct super_block *coda_get_sb(struct file_system_type *fs_type,
} }
struct file_system_type coda_fs_type = { struct file_system_type coda_fs_type = {
owner: THIS_MODULE, .owner = THIS_MODULE,
name: "coda", .name = "coda",
get_sb: coda_get_sb, .get_sb = coda_get_sb,
kill_sb: kill_anon_super, .kill_sb = kill_anon_super,
}; };
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h> #include <linux/string.h>
#define __NO_VERSION__
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -32,13 +31,13 @@ static int coda_pioctl(struct inode * inode, struct file * filp, ...@@ -32,13 +31,13 @@ static int coda_pioctl(struct inode * inode, struct file * filp,
/* exported from this file */ /* exported from this file */
struct inode_operations coda_ioctl_inode_operations = struct inode_operations coda_ioctl_inode_operations =
{ {
permission: coda_ioctl_permission, .permission = coda_ioctl_permission,
setattr: coda_setattr, .setattr = coda_setattr,
}; };
struct file_operations coda_ioctl_operations = { struct file_operations coda_ioctl_operations = {
owner: THIS_MODULE, .owner = THIS_MODULE,
ioctl: coda_pioctl, .ioctl = coda_pioctl,
}; };
/* the coda pioctl inode ops */ /* the coda pioctl inode ops */
......
...@@ -51,5 +51,5 @@ static int coda_symlink_filler(struct file *file, struct page *page) ...@@ -51,5 +51,5 @@ static int coda_symlink_filler(struct file *file, struct page *page)
} }
struct address_space_operations coda_symlink_aops = { struct address_space_operations coda_symlink_aops = {
readpage: coda_symlink_filler .readpage = coda_symlink_filler,
}; };
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <asm/bitops.h> #include <asm/bitops.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#define __NO_VERSION__
#include <linux/module.h> #include <linux/module.h>
#include <linux/coda.h> #include <linux/coda.h>
...@@ -39,7 +38,6 @@ static struct ctl_table_header *fs_table_header; ...@@ -39,7 +38,6 @@ static struct ctl_table_header *fs_table_header;
#define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */ #define CODA_TIMEOUT 3 /* timeout on upcalls to become intrble */
#define CODA_HARD 5 /* mount type "hard" or "soft" */ #define CODA_HARD 5 /* mount type "hard" or "soft" */
#define CODA_VFS 6 /* vfs statistics */ #define CODA_VFS 6 /* vfs statistics */
#define CODA_UPCALL 7 /* upcall statistics */
#define CODA_CACHE_INV 9 /* cache invalidation statistics */ #define CODA_CACHE_INV 9 /* cache invalidation statistics */
#define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */ #define CODA_FAKE_STATFS 10 /* don't query venus for actual cache usage */
...@@ -47,7 +45,6 @@ static ctl_table coda_table[] = { ...@@ -47,7 +45,6 @@ static ctl_table coda_table[] = {
{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec}, {CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec}, {CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
{CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats}, {CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
{CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats},
{CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats}, {CODA_CACHE_INV, "cache_inv_stats", NULL, 0, 0644, NULL, &do_reset_coda_cache_inv_stats},
{CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec}, {CODA_FAKE_STATFS, "fake_statfs", &coda_fake_statfs, sizeof(int), 0600, NULL, &proc_dointvec},
{ 0 } { 0 }
...@@ -60,152 +57,17 @@ static ctl_table fs_table[] = { ...@@ -60,152 +57,17 @@ static ctl_table fs_table[] = {
struct coda_vfs_stats coda_vfs_stat; struct coda_vfs_stats coda_vfs_stat;
struct coda_cache_inv_stats coda_cache_inv_stat; struct coda_cache_inv_stats coda_cache_inv_stat;
struct coda_upcall_stats_entry coda_upcall_stat[CODA_NCALLS];
struct coda_upcallstats coda_callstats;
int coda_upcall_timestamping = 0;
/* keep this in sync with coda.h! */
char *coda_upcall_names[] = {
"totals ", /* 0 */
"- ", /* 1 */
"root ", /* 2 */
"open_by_fd ", /* 3 */
"open ", /* 4 */
"close ", /* 5 */
"ioctl ", /* 6 */
"getattr ", /* 7 */
"setattr ", /* 8 */
"access ", /* 9 */
"lookup ", /* 10 */
"create ", /* 11 */
"remove ", /* 12 */
"link ", /* 13 */
"rename ", /* 14 */
"mkdir ", /* 15 */
"rmdir ", /* 16 */
"readdir ", /* 17 */
"symlink ", /* 18 */
"readlink ", /* 19 */
"fsync ", /* 20 */
"- ", /* 21 */
"vget ", /* 22 */
"signal ", /* 23 */
"replace ", /* 24 */
"flush ", /* 25 */
"purgeuser ", /* 26 */
"zapfile ", /* 27 */
"zapdir ", /* 28 */
"- ", /* 29 */
"purgefid ", /* 30 */
"open_by_path", /* 31 */
"resolve ", /* 32 */
"reintegrate ", /* 33 */
"statfs ", /* 34 */
"store ", /* 35 */
"release " /* 36 */
};
void reset_coda_vfs_stats( void ) void reset_coda_vfs_stats( void )
{ {
memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) ); memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
} }
void reset_coda_upcall_stats( void )
{
memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
}
void reset_coda_cache_inv_stats( void ) void reset_coda_cache_inv_stats( void )
{ {
memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) ); memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
} }
void do_time_stats( struct coda_upcall_stats_entry * pentry,
unsigned long runtime )
{
unsigned long time = runtime; /* time in us */
if ( pentry->count == 0 ) {
pentry->time_sum = pentry->time_squared_sum = 0;
}
pentry->count++;
pentry->time_sum += time;
pentry->time_squared_sum += time*time;
}
void coda_upcall_stats(int opcode, long unsigned runtime)
{
struct coda_upcall_stats_entry * pentry;
if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
printk("Nasty opcode %d passed to coda_upcall_stats\n",
opcode);
return;
}
pentry = &coda_upcall_stat[opcode];
do_time_stats(pentry, runtime);
/* fill in the totals */
pentry = &coda_upcall_stat[0];
do_time_stats(pentry, runtime);
}
unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
{
return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
}
static inline unsigned long absolute( unsigned long x )
{
return x >= 0 ? x : -x;
}
static unsigned long sqr_root( unsigned long x )
{
unsigned long y = x, r;
int n_bit = 0;
if ( x == 0 )
return 0;
if ( x < 0)
x = -x;
while ( y ) {
y >>= 1;
n_bit++;
}
r = 1 << (n_bit/2);
while ( 1 ) {
r = (r + x/r)/2;
if ( r*r <= x && x < (r+1)*(r+1) )
break;
}
return r;
}
unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
{
unsigned long time_avg;
if ( pentry->count <= 1 )
return 0;
time_avg = get_time_average( pentry );
return sqr_root( (pentry->time_squared_sum / pentry->count) -
time_avg * time_avg );
}
int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
void * buffer, size_t * lenp ) void * buffer, size_t * lenp )
{ {
...@@ -220,27 +82,6 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, ...@@ -220,27 +82,6 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
return 0; return 0;
} }
int do_reset_coda_upcall_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp )
{
if ( write ) {
if (*lenp > 0) {
char c;
if (get_user(c, (char *)buffer))
return -EFAULT;
coda_upcall_timestamping = (c == '1');
}
reset_coda_upcall_stats();
filp->f_pos += *lenp;
} else {
*lenp = 0;
}
return 0;
}
int do_reset_coda_cache_inv_stats( ctl_table * table, int write, int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
struct file * filp, void * buffer, struct file * filp, void * buffer,
size_t * lenp ) size_t * lenp )
...@@ -317,52 +158,6 @@ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, ...@@ -317,52 +158,6 @@ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
return len; return len;
} }
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
int length)
{
int len=0;
int i;
off_t begin;
off_t pos = 0;
char tmpbuf[80];
int tmplen = 0;
/* this works as long as we are below 1024 characters! */
if ( offset < 80 )
len += sprintf( buffer,"%-79s\n", "Coda upcall statistics");
if ( offset < 160)
len += sprintf( buffer + len,"%-79s\n", "======================");
if ( offset < 240)
len += sprintf( buffer + len,"%-79s\n", "upcall count avg time(us) std deviation(us)");
if ( offset < 320)
len += sprintf( buffer + len,"%-79s\n", "------ ----- ------------ -----------------");
pos = 320;
for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
tmplen += sprintf(tmpbuf,"%s %9d %10ld %10ld",
coda_upcall_names[i],
coda_upcall_stat[i].count,
get_time_average(&coda_upcall_stat[i]),
coda_upcall_stat[i].time_squared_sum);
pos += 80;
if ( pos < offset )
continue;
len += sprintf(buffer + len, "%-79s\n", tmpbuf);
if ( len >= length )
break;
}
begin = len- (pos - offset);
*start = buffer + begin;
len -= begin;
if ( len > length )
len = length;
if ( len < 0 )
len = 0;
return len;
}
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
int length) int length)
{ {
...@@ -421,9 +216,7 @@ struct proc_dir_entry* proc_fs_coda; ...@@ -421,9 +216,7 @@ struct proc_dir_entry* proc_fs_coda;
void coda_sysctl_init() void coda_sysctl_init()
{ {
memset(&coda_callstats, 0, sizeof(coda_callstats));
reset_coda_vfs_stats(); reset_coda_vfs_stats();
reset_coda_upcall_stats();
reset_coda_cache_inv_stats(); reset_coda_cache_inv_stats();
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
...@@ -431,7 +224,6 @@ void coda_sysctl_init() ...@@ -431,7 +224,6 @@ void coda_sysctl_init()
if (proc_fs_coda) { if (proc_fs_coda) {
proc_fs_coda->owner = THIS_MODULE; proc_fs_coda->owner = THIS_MODULE;
coda_proc_create("vfs_stats", coda_vfs_stats_get_info); coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info); coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
} }
#endif #endif
...@@ -454,7 +246,6 @@ void coda_sysctl_clean() ...@@ -454,7 +246,6 @@ void coda_sysctl_clean()
#if CONFIG_PROC_FS #if CONFIG_PROC_FS
remove_proc_entry("cache_inv_stats", proc_fs_coda); remove_proc_entry("cache_inv_stats", proc_fs_coda);
remove_proc_entry("upcall_stats", proc_fs_coda);
remove_proc_entry("vfs_stats", proc_fs_coda); remove_proc_entry("vfs_stats", proc_fs_coda);
remove_proc_entry("coda", proc_root_fs); remove_proc_entry("coda", proc_root_fs);
#endif #endif
......
...@@ -171,10 +171,7 @@ int venus_store(struct super_block *sb, struct ViceFid *fid, int flags, ...@@ -171,10 +171,7 @@ int venus_store(struct super_block *sb, struct ViceFid *fid, int flags,
insize = SIZE(store); insize = SIZE(store);
UPARG(CODA_STORE); UPARG(CODA_STORE);
if ( cred ) { memcpy(&(inp->ih.cred), cred, sizeof(*cred));
memcpy(&(inp->ih.cred), cred, sizeof(*cred));
} else
printk("CODA: store without valid file creds.\n");
inp->coda_store.VFid = *fid; inp->coda_store.VFid = *fid;
inp->coda_store.flags = flags; inp->coda_store.flags = flags;
...@@ -213,10 +210,7 @@ int venus_close(struct super_block *sb, struct ViceFid *fid, int flags, ...@@ -213,10 +210,7 @@ int venus_close(struct super_block *sb, struct ViceFid *fid, int flags,
insize = SIZE(release); insize = SIZE(release);
UPARG(CODA_CLOSE); UPARG(CODA_CLOSE);
if ( cred ) { memcpy(&(inp->ih.cred), cred, sizeof(*cred));
memcpy(&(inp->ih.cred), cred, sizeof(*cred));
} else
printk("CODA: close without valid file creds.\n");
inp->coda_close.VFid = *fid; inp->coda_close.VFid = *fid;
inp->coda_close.flags = flags; inp->coda_close.flags = flags;
...@@ -620,17 +614,13 @@ int venus_statfs(struct super_block *sb, struct statfs *sfs) ...@@ -620,17 +614,13 @@ int venus_statfs(struct super_block *sb, struct statfs *sfs)
* *
*/ */
static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp, static inline void coda_waitfor_upcall(struct upc_req *vmp,
struct venus_comm *vcommp) struct venus_comm *vcommp)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
struct timeval begin = { 0, 0 }, end = { 0, 0 };
vmp->uc_posttime = jiffies; vmp->uc_posttime = jiffies;
if (coda_upcall_timestamping)
do_gettimeofday(&begin);
add_wait_queue(&vmp->uc_sleep, &wait); add_wait_queue(&vmp->uc_sleep, &wait);
for (;;) { for (;;) {
if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE ) if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE )
...@@ -661,17 +651,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp, ...@@ -661,17 +651,7 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp,
remove_wait_queue(&vmp->uc_sleep, &wait); remove_wait_queue(&vmp->uc_sleep, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
if (coda_upcall_timestamping && begin.tv_sec != 0) { return;
do_gettimeofday(&end);
if (end.tv_usec < begin.tv_usec) {
end.tv_usec += 1000000; end.tv_sec--;
}
end.tv_sec -= begin.tv_sec;
end.tv_usec -= begin.tv_usec;
}
return ((end.tv_sec * 1000000) + end.tv_usec);
} }
...@@ -689,7 +669,6 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -689,7 +669,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
int inSize, int *outSize, int inSize, int *outSize,
union inputArgs *buffer) union inputArgs *buffer)
{ {
unsigned long runtime;
struct venus_comm *vcommp; struct venus_comm *vcommp;
union outputArgs *out; union outputArgs *out;
struct upc_req *req; struct upc_req *req;
...@@ -732,8 +711,7 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -732,8 +711,7 @@ static int coda_upcall(struct coda_sb_info *sbi,
* ENODEV. */ * ENODEV. */
/* Go to sleep. Wake up on signals only after the timeout. */ /* Go to sleep. Wake up on signals only after the timeout. */
runtime = coda_waitfor_upcall(req, vcommp); coda_waitfor_upcall(req, vcommp);
coda_upcall_stats(((union inputArgs *)buffer)->ih.opcode, runtime);
if (vcommp->vc_inuse) { /* i.e. Venus is still alive */ if (vcommp->vc_inuse) { /* i.e. Venus is still alive */
/* Op went through, interrupt or not... */ /* Op went through, interrupt or not... */
...@@ -794,8 +772,6 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -794,8 +772,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
exit: exit:
upc_free(req); upc_free(req);
if (error)
badclstats();
return error; return error;
} }
...@@ -842,7 +818,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -842,7 +818,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
switch (opcode) { switch (opcode) {
case CODA_FLUSH : { case CODA_FLUSH : {
clstats(CODA_FLUSH);
coda_cache_clear_all(sb, NULL); coda_cache_clear_all(sb, NULL);
shrink_dcache_sb(sb); shrink_dcache_sb(sb);
coda_flag_inode(sb->s_root->d_inode, C_FLUSH); coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
...@@ -855,7 +830,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -855,7 +830,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
printk("PURGEUSER: null cred!\n"); printk("PURGEUSER: null cred!\n");
return 0; return 0;
} }
clstats(CODA_PURGEUSER);
coda_cache_clear_all(sb, cred); coda_cache_clear_all(sb, cred);
return(0); return(0);
} }
...@@ -863,7 +837,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -863,7 +837,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_ZAPDIR : { case CODA_ZAPDIR : {
struct inode *inode; struct inode *inode;
ViceFid *fid = &out->coda_zapdir.CodaFid; ViceFid *fid = &out->coda_zapdir.CodaFid;
clstats(CODA_ZAPDIR);
inode = coda_fid_to_inode(fid, sb); inode = coda_fid_to_inode(fid, sb);
if (inode) { if (inode) {
...@@ -878,7 +851,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -878,7 +851,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_ZAPFILE : { case CODA_ZAPFILE : {
struct inode *inode; struct inode *inode;
struct ViceFid *fid = &out->coda_zapfile.CodaFid; struct ViceFid *fid = &out->coda_zapfile.CodaFid;
clstats(CODA_ZAPFILE);
inode = coda_fid_to_inode(fid, sb); inode = coda_fid_to_inode(fid, sb);
if ( inode ) { if ( inode ) {
coda_flag_inode(inode, C_VATTR); coda_flag_inode(inode, C_VATTR);
...@@ -890,7 +862,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -890,7 +862,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
case CODA_PURGEFID : { case CODA_PURGEFID : {
struct inode *inode; struct inode *inode;
ViceFid *fid = &out->coda_purgefid.CodaFid; ViceFid *fid = &out->coda_purgefid.CodaFid;
clstats(CODA_PURGEFID);
inode = coda_fid_to_inode(fid, sb); inode = coda_fid_to_inode(fid, sb);
if ( inode ) { if ( inode ) {
coda_flag_inode_children(inode, C_PURGE); coda_flag_inode_children(inode, C_PURGE);
...@@ -908,7 +879,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) ...@@ -908,7 +879,6 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
struct inode *inode; struct inode *inode;
ViceFid *oldfid = &out->coda_replace.OldFid; ViceFid *oldfid = &out->coda_replace.OldFid;
ViceFid *newfid = &out->coda_replace.NewFid; ViceFid *newfid = &out->coda_replace.NewFid;
clstats(CODA_REPLACE);
inode = coda_fid_to_inode(oldfid, sb); inode = coda_fid_to_inode(oldfid, sb);
if ( inode ) { if ( inode ) {
coda_replace_fid(inode, oldfid, newfid); coda_replace_fid(inode, oldfid, newfid);
......
...@@ -20,13 +20,25 @@ struct coda_inode_info { ...@@ -20,13 +20,25 @@ struct coda_inode_info {
struct ViceFid c_fid; /* Coda identifier */ struct ViceFid c_fid; /* Coda identifier */
u_short c_flags; /* flags (see below) */ u_short c_flags; /* flags (see below) */
struct list_head c_cilist; /* list of all coda inodes */ struct list_head c_cilist; /* list of all coda inodes */
struct file *c_container; /* container file for this cnode */ unsigned int c_mapcount; /* nr of times this inode is mapped */
unsigned int c_contcount; /* refcount for container file */
struct coda_cred c_cached_cred; /* credentials of cached perms */ struct coda_cred c_cached_cred; /* credentials of cached perms */
unsigned int c_cached_perm; /* cached access permissions */ unsigned int c_cached_perm; /* cached access permissions */
struct inode vfs_inode; struct inode vfs_inode;
}; };
/*
* coda fs file private data
*/
#define CODA_MAGIC 0xC0DAC0DA
struct coda_file_info {
int cfi_magic; /* magic number */
struct file *cfi_container; /* container file for this cnode */
unsigned int cfi_mapcount; /* nr of times this file is mapped */
struct coda_cred cfi_cred; /* credentials of opener */
};
#define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data))
/* flags */ /* flags */
#define C_VATTR 0x1 /* Validity of vattr in inode */ #define C_VATTR 0x1 /* Validity of vattr in inode */
#define C_FLUSH 0x2 /* used after a flush */ #define C_FLUSH 0x2 /* used after a flush */
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/coda_fs_i.h>
/* operations */ /* operations */
extern struct inode_operations coda_dir_inode_operations; extern struct inode_operations coda_dir_inode_operations;
...@@ -45,7 +46,6 @@ int coda_setattr(struct dentry *, struct iattr *); ...@@ -45,7 +46,6 @@ int coda_setattr(struct dentry *, struct iattr *);
int coda_isnullfid(ViceFid *fid); int coda_isnullfid(ViceFid *fid);
/* global variables */ /* global variables */
extern int coda_access_cache;
extern int coda_fake_statfs; extern int coda_fake_statfs;
/* this file: heloers */ /* this file: heloers */
...@@ -53,7 +53,6 @@ static __inline__ struct ViceFid *coda_i2f(struct inode *); ...@@ -53,7 +53,6 @@ static __inline__ struct ViceFid *coda_i2f(struct inode *);
static __inline__ char *coda_i2s(struct inode *); static __inline__ char *coda_i2s(struct inode *);
static __inline__ void coda_flag_inode(struct inode *, int flag); static __inline__ void coda_flag_inode(struct inode *, int flag);
char *coda_f2s(ViceFid *f); char *coda_f2s(ViceFid *f);
char *coda_f2s2(ViceFid *f);
int coda_isroot(struct inode *i); int coda_isroot(struct inode *i);
int coda_iscontrol(const char *name, size_t length); int coda_iscontrol(const char *name, size_t length);
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
void coda_sysctl_init(void); void coda_sysctl_init(void);
void coda_sysctl_clean(void); void coda_sysctl_clean(void);
void coda_upcall_stats(int opcode, unsigned long jiffies);
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/coda_fs_i.h> #include <linux/coda_fs_i.h>
...@@ -23,13 +22,11 @@ void coda_upcall_stats(int opcode, unsigned long jiffies); ...@@ -23,13 +22,11 @@ void coda_upcall_stats(int opcode, unsigned long jiffies);
/* these four files are presented to show the result of the statistics: /* these four files are presented to show the result of the statistics:
* *
* /proc/fs/coda/vfs_stats * /proc/fs/coda/vfs_stats
* upcall_stats
* cache_inv_stats * cache_inv_stats
* *
* these four files are presented to reset the statistics to 0: * these four files are presented to reset the statistics to 0:
* *
* /proc/sys/coda/vfs_stats * /proc/sys/coda/vfs_stats
* upcall_stats
* cache_inv_stats * cache_inv_stats
*/ */
...@@ -61,13 +58,6 @@ struct coda_vfs_stats ...@@ -61,13 +58,6 @@ struct coda_vfs_stats
int readlink; int readlink;
}; };
struct coda_upcall_stats_entry
{
int count;
unsigned long time_sum;
unsigned long time_squared_sum;
};
/* cache invalidation statistics */ /* cache invalidation statistics */
struct coda_cache_inv_stats struct coda_cache_inv_stats
{ {
...@@ -83,31 +73,16 @@ struct coda_cache_inv_stats ...@@ -83,31 +73,16 @@ struct coda_cache_inv_stats
/* these global variables hold the actual statistics data */ /* these global variables hold the actual statistics data */
extern struct coda_vfs_stats coda_vfs_stat; extern struct coda_vfs_stats coda_vfs_stat;
extern struct coda_cache_inv_stats coda_cache_inv_stat; extern struct coda_cache_inv_stats coda_cache_inv_stat;
extern int coda_upcall_timestamping;
/* reset statistics to 0 */ /* reset statistics to 0 */
void reset_coda_vfs_stats( void ); void reset_coda_vfs_stats( void );
void reset_coda_upcall_stats( void );
void reset_coda_cache_inv_stats( void ); void reset_coda_cache_inv_stats( void );
/* some utitlities to make it easier for you to do statistics for time */
void do_time_stats( struct coda_upcall_stats_entry * pentry,
unsigned long jiffy );
/*
double get_time_average( const struct coda_upcall_stats_entry * pentry );
double get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
*/
unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry );
unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry );
/* like coda_dointvec, these functions are to be registered in the ctl_table /* like coda_dointvec, these functions are to be registered in the ctl_table
* data structure for /proc/sys/... files * data structure for /proc/sys/... files
*/ */
int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp, int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
void * buffer, size_t * lenp ); void * buffer, size_t * lenp );
int do_reset_coda_upcall_stats( ctl_table * table, int write,
struct file * filp, void * buffer,
size_t * lenp );
int do_reset_coda_cache_inv_stats( ctl_table * table, int write, int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
struct file * filp, void * buffer, struct file * filp, void * buffer,
size_t * lenp ); size_t * lenp );
...@@ -115,8 +90,6 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write, ...@@ -115,8 +90,6 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
/* these functions are called to form the content of /proc/fs/coda/... files */ /* these functions are called to form the content of /proc/fs/coda/... files */
int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset, int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
int length); int length);
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
int length);
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset, int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
int length); int length);
......
...@@ -98,27 +98,7 @@ struct upc_req { ...@@ -98,27 +98,7 @@ struct upc_req {
/* /*
* Statistics * Statistics
*/ */
struct coda_upcallstats {
int ncalls; /* client requests */
int nbadcalls; /* upcall failures */
int reqs[CODA_NCALLS]; /* count of each request */
} ;
extern struct coda_upcallstats coda_callstats;
extern struct venus_comm coda_comms[]; extern struct venus_comm coda_comms[];
static inline void clstats(int opcode)
{
coda_callstats.ncalls++;
if ( (0 <= opcode) && (opcode <= CODA_NCALLS) )
coda_callstats.reqs[opcode]++;
else
printk("clstats called with bad opcode %d\n", opcode);
}
static inline void badclstats(void)
{
coda_callstats.nbadcalls++;
}
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment