patch-2.2.17 linux/fs/coda/dir.c
Next file: linux/fs/coda/file.c
Previous file: linux/fs/coda/cnode.c
Back to the patch index
Back to the overall index
- Lines: 376
- Date:
Mon Sep 4 18:39:22 2000
- Orig file:
v2.2.16/fs/coda/dir.c
- Orig date:
Mon Sep 4 18:37:09 2000
diff -u --recursive --new-file v2.2.16/fs/coda/dir.c linux/fs/coda/dir.c
@@ -37,8 +37,8 @@
const char *symname);
static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);
static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);
-static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
- struct inode *new_inode, struct dentry *new_dentry);
+static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry);
/* dir file-ops */
static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
@@ -52,7 +52,6 @@
filldir_t filldir);
int coda_fsync(struct file *, struct dentry *dentry);
-int coda_crossvol_rename = 0;
int coda_hasmknod = 0;
struct dentry_operations coda_dentry_operations =
@@ -111,9 +110,9 @@
{
struct coda_inode_info *dircnp;
struct inode *res_inode = NULL;
- struct ViceFid resfid;
+ struct ViceFid resfid = {0,0,0};
int dropme = 0; /* to indicate entry should not be cached */
- int type;
+ int type = 0;
int error = 0;
const char *name = entry->d_name.name;
size_t length = entry->d_name.len;
@@ -137,6 +136,7 @@
CDEBUG(D_SPECIAL,
"Lookup on CTL object; dir ino %ld, count %d\n",
dir->i_ino, dir->i_count);
+ dropme = 1;
goto exit;
}
@@ -151,9 +151,14 @@
coda_f2s(&resfid));
dropme = 1;
}
+
error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
- if (error)
- return ERR_PTR(error);
+ if (error) return ERR_PTR(error);
+
+ /* make sure we drop unexpected non-hashable fids */
+ if (coda_f2i(&resfid) != res_inode->i_ino &&
+ !coda_fid_is_weird(&resfid))
+ dropme = 1;
} else if (error != -ENOENT) {
CDEBUG(D_INODE, "error for %s(%*s)%d\n",
coda_f2s(&dircnp->c_fid), (int)length, name, error);
@@ -168,7 +173,7 @@
d_add(entry, res_inode);
if ( dropme ) {
d_drop(entry);
- ITOC(res_inode)->c_flags |= C_VATTR;
+ coda_flag_inode(res_inode, C_VATTR);
}
EXIT;
return NULL;
@@ -184,9 +189,8 @@
coda_vfs_stat.permission++;
coda_permission_stat.count++;
- if ( mask == 0 ) {
+ if ( mask == 0 )
return 0;
- }
if ( coda_access_cache == 1 ) {
if ( coda_cache_check(inode, mask) ) {
@@ -203,17 +207,29 @@
CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n",
coda_f2s(&(cp->c_fid)), inode->i_ino, mask, error);
- if ( error == 0 ) {
+ if (!error)
coda_cache_enter(inode, mask);
- }
return error;
}
-
+static inline void coda_dir_changed(struct inode *dir, int link)
+{
+#ifdef REQUERY_VENUS_FOR_MTIME
+ /* invalidate the directory cnode's attributes to refetch the
+ * attributes from venus next time the inode is referenced */
+ coda_flag_inode(dir, C_VATTR);
+#else
+ /* optimistically we can also act as if our nose bleeds. The
+ * granularity of the mtime is coarse anyways so we might actually be
+ * right most of the time. Note: we only do this for directories. */
+ dir->i_mtime = CURRENT_TIME;
+#endif
+ if (link)
+ dir->i_nlink += link;
+}
/* creation routines: create, mknod, mkdir, link, symlink */
-
static int coda_create(struct inode *dir, struct dentry *de, int mode)
{
int error=0;
@@ -252,10 +268,10 @@
}
/* invalidate the directory cnode's attributes */
- dircnp->c_flags |= C_VATTR;
+ coda_dir_changed(dir, 0);
d_instantiate(de, result);
return 0;
-}
+}
static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev)
{
@@ -297,7 +313,7 @@
}
/* invalidate the directory cnode's attributes */
- dircnp->c_flags |= C_VATTR;
+ coda_dir_changed(dir, 0);
d_instantiate(de, result);
return 0;
}
@@ -344,8 +360,7 @@
}
/* invalidate the directory cnode's attributes */
- dircnp->c_flags |= C_VATTR;
- dir->i_nlink++;
+ coda_dir_changed(dir, 1);
d_instantiate(de, inode);
return 0;
}
@@ -375,16 +390,17 @@
error = venus_link(dir_inode->i_sb,&(cnp->c_fid), &(dir_cnp->c_fid),
(const char *)name, len);
- if ( ! error ) {
- dir_cnp->c_flags |= C_VATTR;
- ++inode->i_count;
- d_instantiate(de, inode);
- inode->i_nlink++;
- } else {
+ if (error) {
d_drop(de);
- return error;
+ goto out;
}
+ coda_dir_changed(dir_inode, 0);
+ inode->i_count++;
+ d_instantiate(de, inode);
+ inode->i_nlink++;
+
+out:
CDEBUG(D_INODE, "link result %d\n",error);
EXIT;
return(error);
@@ -421,9 +437,8 @@
symname, symlen);
/* mtime is no good anymore */
- if ( !error ) {
- dir_cnp->c_flags |= C_VATTR;
- }
+ if ( !error )
+ coda_dir_changed(dir_inode, 0);
CDEBUG(D_INODE, "in symlink result %d\n",error);
EXIT;
@@ -451,7 +466,7 @@
}
/* cache management: mtime has changed, ask Venus */
- dircnp->c_flags |= C_VATTR;
+ coda_dir_changed(dir, 0);
de->d_inode->i_nlink--;
d_delete(de);
@@ -479,8 +494,9 @@
return error;
}
- if (de->d_inode->i_nlink)
- de->d_inode->i_nlink --;
+ coda_dir_changed(dir, -1);
+ de->d_inode->i_nlink--;
+ d_delete(de);
return 0;
}
@@ -493,7 +509,6 @@
const char *new_name = new_dentry->d_name.name;
int old_length = old_dentry->d_name.len;
int new_length = new_dentry->d_name.len;
- struct inode *new_inode = new_dentry->d_inode;
struct coda_inode_info *new_cnp, *old_cnp;
int error;
@@ -508,28 +523,29 @@
old_name, old_length, (long)strlen(old_name), new_name, new_length,
(long)strlen(new_name),old_dentry->d_count, new_dentry->d_count);
- /* the C library will do unlink/create etc */
- if ( coda_crossvol_rename == 0 &&
- old_cnp->c_fid.Volume != new_cnp->c_fid.Volume )
- return -EXDEV;
-
error = venus_rename(old_dir->i_sb, &(old_cnp->c_fid),
&(new_cnp->c_fid), old_length, new_length,
(const char *) old_name, (const char *)new_name);
- if ( error ) {
- CDEBUG(D_INODE, "returned error %d\n", error);
- return error;
+ if ( !error ) {
+ if ( new_dentry->d_inode ) {
+ if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
+ old_dir->i_nlink--;
+ new_dir->i_nlink++;
+ }
+ coda_flag_inode(new_dentry->d_inode, C_VATTR);
+ }
+
+ /* coda_flag_inode(old_dir, C_VATTR); */
+ /* coda_flag_inode(new_dir, C_VATTR); */
+ old_dir->i_mtime = new_dir->i_mtime = CURRENT_TIME;
}
- coda_flag_inode(new_inode, C_VATTR);
- coda_flag_inode(old_dir, C_VATTR);
- coda_flag_inode(new_dir, C_VATTR);
CDEBUG(D_INODE, "result %d\n", error);
EXIT;
- return 0;
+ return error;
}
@@ -589,7 +605,6 @@
cnp = ITOC(i);
-
error = venus_open(i->i_sb, &(cnp->c_fid), coda_flags, &ino, &dev);
if (error) {
CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",
@@ -617,7 +632,7 @@
cnp->c_ovp = NULL;
}
cnp->c_ovp = cont_inode;
- cnp->c_ocount++;
+ cnp->c_contcount++;
CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n",
error, i->i_count, i->i_ino);
@@ -642,24 +657,16 @@
cred = (struct coda_cred *)f->private_data;
cnp =ITOC(i);
- CHECK_CNODE(cnp);
CDEBUG(D_FILE,
- "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n",
- i->i_ino, i->i_count, (cnp->c_ovp ? cnp->c_ovp->i_ino : 0),
+ "RELEASE coda (ino %ld, ct %d, ref %d) cache (ino %ld, ct %d)\n",
+ i->i_ino, i->i_count, cnp->c_contcount,
+ (cnp->c_ovp ? cnp->c_ovp->i_ino : 0),
(cnp->c_ovp ? cnp->c_ovp->i_count : -99));
-
- /* even when c_ocount=0 we cannot put c_ovp to
- * NULL since the file may be mmapped.
- * See code in inode.c (coda_put_inode) for
- * further handling of close.
- */
-
- --cnp->c_ocount;
-
- if (flags & (O_WRONLY | O_RDWR)) {
- --cnp->c_owrite;
- }
+ if (--cnp->c_contcount == 0) {
+ iput(cnp->c_ovp);
+ cnp->c_ovp = NULL;
+ }
error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
@@ -780,7 +787,6 @@
/* called when a cache lookup succeeds */
static int coda_dentry_revalidate(struct dentry *de, int flags)
{
- int valid = 1;
struct inode *inode = de->d_inode;
struct coda_inode_info *cii;
ENTRY;
@@ -788,14 +794,14 @@
if (!inode)
return 1;
- cii = ITOC(de->d_inode);
if (coda_isroot(inode))
return 1;
if (is_bad_inode(inode))
return 0;
+ cii = ITOC(de->d_inode);
if (! (cii->c_flags & (C_PURGE | C_FLUSH)) )
- return valid;
+ return 1;
shrink_dcache_parent(de);
@@ -825,9 +831,9 @@
int flags;
if (!dentry->d_inode)
- return ;
+ return;
- flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
+ flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
if (is_bad_inode(dentry->d_inode) || flags) {
CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -862,19 +868,10 @@
if ( cii->c_flags == 0 )
return 0;
- /* Venus closed the device .... */
- if ( cii->c_flags & C_DYING ) {
- make_bad_inode(inode);
- return -EIO;
- }
-
-
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);
+ if ( error )
return -EIO;
- }
/* this inode may be lost if:
- it's ino changed
@@ -885,17 +882,15 @@
old_ino = inode->i_ino;
coda_vattr_to_iattr(inode, &attr);
-
if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
printk("Coda: inode %ld, fid %s changed type!\n",
inode->i_ino, coda_f2s(&(cii->c_fid)));
}
/* the following can happen when a local fid is replaced
- with a global one, here we lose and declar the inode bad */
+ with a global one, here we lose and declare the inode bad */
if (inode->i_ino != old_ino) {
make_bad_inode(inode);
- inode->i_mode = old_mode;
return -EIO;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)