summaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-09-28 22:25:29 +0000
commit0ae8dceaebe3659ee0c3352c08125f403e77ebca (patch)
tree5085c389f09da78182b899d19fe1068b619a69dd /fs/coda
parent273767781288c35c9d679e908672b9996cda4c34 (diff)
Merge with 2.3.10.
Diffstat (limited to 'fs/coda')
-rw-r--r--fs/coda/cache.c2
-rw-r--r--fs/coda/cnode.c29
-rw-r--r--fs/coda/coda_linux.c2
-rw-r--r--fs/coda/dir.c8
-rw-r--r--fs/coda/inode.c36
-rw-r--r--fs/coda/sysctl.c50
-rw-r--r--fs/coda/upcall.c48
7 files changed, 129 insertions, 46 deletions
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index 1c3b11199..d3412e52c 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -326,8 +326,8 @@ void coda_flag_inode_children(struct inode *inode, int flag)
while ( alias != &inode->i_dentry ) {
alias_de = list_entry(alias, struct dentry, d_alias);
coda_flag_children(alias_de, flag);
- shrink_dcache_parent(alias_de);
alias = alias->next;
+ shrink_dcache_parent(alias_de);
}
}
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index dd1e03f5f..ffae7746f 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -14,6 +14,17 @@
extern int coda_debug;
extern int coda_print_entry;
+inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
+{
+ if (fid1->Vnode != fid2->Vnode)
+ return 0;
+ if (fid1->Volume != fid2->Volume)
+ return 0;
+ if (fid1->Unique != fid2->Unique)
+ return 0;
+ return 1;
+}
+
/* cnode.c */
static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
{
@@ -71,8 +82,14 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
}
cnp = ITOC(*inode);
- if ( cnp->c_magic != 0 ) {
- printk("coda_cnode make on initialized inode %ld, old %s new
+ /* see if we've got it already */
+ if ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
+ return 0;
+ }
+
+ /* not fresh: collision */
+ if ( cnp->c_magic != 0 ) {
+ 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);
@@ -106,14 +123,6 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
return 0;
}
-inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
-{
- int eq;
- eq = ( (fid1->Vnode == fid2->Vnode) &&
- (fid1->Volume == fid2->Volume) &&
- (fid1->Unique == fid2->Unique) );
- return eq;
-}
void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
struct ViceFid *newfid)
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index f684f3a78..5f2f3c467 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -215,6 +215,8 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_ctime.tv_sec != -1)
inode->i_ctime = attr->va_ctime.tv_sec;
}
+
+
/*
* BSD sets attributes that need not be modified to -1.
* Linux uses the valid field to indicate what should be
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 4313edb69..10b1cb171 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -800,6 +800,10 @@ static int coda_dentry_revalidate(struct dentry *de, int flags)
shrink_dcache_parent(de);
+ /* propagate for a flush */
+ if (cii->c_flags & C_FLUSH)
+ coda_flag_inode_children(inode, C_FLUSH);
+
if (de->d_count > 1) {
/* pretend it's valid, but don't change the flags */
CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
@@ -807,10 +811,6 @@ static int coda_dentry_revalidate(struct dentry *de, int flags)
return 1;
}
- /* propagate for a flush */
- if (cii->c_flags & C_FLUSH)
- coda_flag_inode_children(inode, C_FLUSH);
-
/* clear the flags. */
cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 49359f260..604e906a2 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -22,8 +22,6 @@
#include <asm/uaccess.h>
#include <linux/fs.h>
-#include <linux/stat.h>
-#include <asm/uaccess.h>
#include <linux/vmalloc.h>
#include <asm/segment.h>
@@ -75,6 +73,9 @@ static struct super_block * coda_read_super(struct super_block *sb,
if ( sbi->sbi_sb ) {
printk("Already mounted\n");
+ unlock_super(sb);
+ EXIT;
+ MOD_DEC_USE_COUNT;
return NULL;
}
@@ -98,7 +99,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
printk("coda_read_super: coda_get_rootfid failed with %d\n",
error);
sb->s_dev = 0;
- unlock_super(sb);
goto error;
}
printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
@@ -108,7 +108,6 @@ static struct super_block * coda_read_super(struct super_block *sb,
if ( error || !root ) {
printk("Failure of coda_cnode_make for root: error %d\n", error);
sb->s_dev = 0;
- unlock_super(sb);
goto error;
}
@@ -121,6 +120,7 @@ static struct super_block * coda_read_super(struct super_block *sb,
return sb;
error:
+ unlock_super(sb);
EXIT;
MOD_DEC_USE_COUNT;
if (sbi) {
@@ -145,7 +145,6 @@ static void coda_put_super(struct super_block *sb)
sb->s_dev = 0;
coda_cache_clear_all(sb);
sb_info = coda_sbp(sb);
-/* sb_info->sbi_vcomm->vc_inuse = 0; You can not do this: psdev_release would see usagecount == 0 and would refuse to decrease MOD_USE_COUNT --pavel */
coda_super_info.sbi_sb = NULL;
printk("Coda: Bye bye.\n");
memset(sb_info, 0, sizeof(* sb_info));
@@ -209,7 +208,7 @@ static void coda_delete_inode(struct inode *inode)
EXIT;
}
-static int coda_notify_change(struct dentry *de, struct iattr *iattr)
+static int coda_notify_change(struct dentry *de, struct iattr *iattr)
{
struct inode *inode = de->d_inode;
struct coda_inode_info *cii;
@@ -238,21 +237,32 @@ static int coda_notify_change(struct dentry *de, struct iattr *iattr)
return error;
}
-/* we need _something_ for this routine. Let's mimic AFS */
static int coda_statfs(struct super_block *sb, struct statfs *buf,
int bufsiz)
{
struct statfs tmp;
+ int error;
+
+ memset(&tmp, 0, sizeof(struct statfs));
+
+ error = venus_statfs(sb, &tmp);
+ if (error) {
+ /* fake something like AFS does */
+ tmp.f_blocks = 9000000;
+ tmp.f_bfree = 9000000;
+ tmp.f_bavail = 9000000;
+ tmp.f_files = 9000000;
+ tmp.f_ffree = 9000000;
+ }
+
+ /* and fill in the rest */
tmp.f_type = CODA_SUPER_MAGIC;
tmp.f_bsize = 1024;
- tmp.f_blocks = 9000000;
- tmp.f_bfree = 9000000;
- tmp.f_bavail = 9000000 ;
- tmp.f_files = 9000000;
- tmp.f_ffree = 9000000;
- tmp.f_namelen = 0;
+ tmp.f_namelen = CODA_MAXNAMLEN;
+
copy_to_user(buf, &tmp, bufsiz);
+
return 0;
}
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 79a4c7ebb..e35174e5c 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -71,6 +71,7 @@ struct coda_permission_stats coda_permission_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[] = {
@@ -103,9 +104,12 @@ char *coda_upcall_names[] = {
"purgeuser ", /* 26 */
"zapfile ", /* 27 */
"zapdir ", /* 28 */
- "zapvnode ", /* 28 */
+ "noop2 ", /* 29 */
"purgefid ", /* 30 */
- "open_by_path" /* 31 */
+ "open_by_path", /* 31 */
+ "resolve ", /* 32 */
+ "reintegrate ", /* 33 */
+ "statfs " /* 34 */
};
@@ -133,8 +137,7 @@ void reset_coda_cache_inv_stats( void )
void do_time_stats( struct coda_upcall_stats_entry * pentry,
unsigned long runtime )
{
-
- unsigned long time = runtime * 1000 /HZ; /* time in ms */
+ unsigned long time = runtime; /* time in us */
CDEBUG(D_SPECIAL, "time: %ld\n", time);
if ( pentry->count == 0 ) {
@@ -221,9 +224,12 @@ int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
{
if ( write ) {
reset_coda_vfs_stats();
+
+ filp->f_pos += *lenp;
+ } else {
+ *lenp = 0;
}
-
- *lenp = 0;
+
return 0;
}
@@ -232,10 +238,19 @@ int do_reset_coda_upcall_stats( ctl_table * table, int write,
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;
}
-
- *lenp = 0;
+
return 0;
}
@@ -245,9 +260,12 @@ int do_reset_coda_permission_stats( ctl_table * table, int write,
{
if ( write ) {
reset_coda_permission_stats();
+
+ filp->f_pos += *lenp;
+ } else {
+ *lenp = 0;
}
-
- *lenp = 0;
+
return 0;
}
@@ -257,9 +275,12 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
{
if ( write ) {
reset_coda_cache_inv_stats();
+
+ filp->f_pos += *lenp;
+ } else {
+ *lenp = 0;
}
- *lenp = 0;
return 0;
}
@@ -347,12 +368,12 @@ int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
if ( offset < 160)
len += sprintf( buffer + len,"%-79s\n", "======================");
if ( offset < 240)
- len += sprintf( buffer + len,"%-79s\n", "upcall\t\t count\tavg time(ms)\tstd deviation(ms)");
+ len += sprintf( buffer + len,"%-79s\n", "upcall count avg time(us) std deviation(us)");
if ( offset < 320)
- len += sprintf( buffer + len,"%-79s\n", "------\t\t -----\t------------\t-----------------");
+ len += sprintf( buffer + len,"%-79s\n", "------ ----- ------------ -----------------");
pos = 320;
for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
- tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%10ld",
+ tmplen += sprintf(tmpbuf,"%s %9d %10ld %10ld",
coda_upcall_names[i],
coda_upcall_stat[i].count,
get_time_average(&coda_upcall_stat[i]),
@@ -499,6 +520,7 @@ static void coda_proc_modcount(struct inode *inode, int fill)
MOD_INC_USE_COUNT;
else
MOD_DEC_USE_COUNT;
+
}
#endif
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index a0c1092b2..62fd62e35 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -580,6 +580,33 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
return error;
}
+int venus_statfs(struct super_block *sb, struct statfs *sfs)
+{
+ union inputArgs *inp;
+ union outputArgs *outp;
+ int insize, outsize, error;
+
+ insize = max(INSIZE(statfs), OUTSIZE(statfs));
+ UPARG(CODA_STATFS);
+
+ error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+
+ if (!error) {
+ sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
+ sfs->f_bfree = outp->coda_statfs.stat.f_bfree;
+ sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
+ sfs->f_files = outp->coda_statfs.stat.f_files;
+ sfs->f_ffree = outp->coda_statfs.stat.f_ffree;
+ } else {
+ printk("coda_statfs: Venus returns: %d\n", error);
+ }
+
+ if (inp) CODA_FREE(inp, insize);
+ CDEBUG(D_INODE, " result %d\n",error);
+ EXIT;
+ return error;
+}
+
/*
* coda_upcall and coda_downcall routines.
*
@@ -588,10 +615,12 @@ int venus_pioctl(struct super_block *sb, struct ViceFid *fid,
static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
{
DECLARE_WAITQUEUE(wait, current);
- unsigned long posttime;
+ struct timeval begin = { 0, 0 }, end = { 0, 0 };
vmp->uc_posttime = jiffies;
- posttime = jiffies;
+
+ if (coda_upcall_timestamping)
+ do_gettimeofday(&begin);
add_wait_queue(&vmp->uc_sleep, &wait);
for (;;) {
@@ -620,9 +649,20 @@ static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
remove_wait_queue(&vmp->uc_sleep, &wait);
current->state = TASK_RUNNING;
- CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n", posttime, jiffies-posttime);
- return (jiffies - posttime);
+ if (coda_upcall_timestamping && begin.tv_sec != 0) {
+ 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;
+ }
+
+ CDEBUG(D_SPECIAL, "begin: %ld.%06ld, elapsed: %ld.%06ld\n",
+ begin.tv_sec, begin.tv_usec, end.tv_sec, end.tv_usec);
+ return ((end.tv_sec * 1000000) + end.tv_usec);
}