patch-2.1.75 linux/fs/coda/dir.c
Next file: linux/fs/coda/file.c
Previous file: linux/fs/coda/coda_linux.c
Back to the patch index
Back to the overall index
- Lines: 444
- Date:
Sun Dec 21 14:45:14 1997
- Orig file:
v2.1.74/linux/fs/coda/dir.c
- Orig date:
Tue Dec 2 16:45:19 1997
diff -u --recursive --new-file v2.1.74/linux/fs/coda/dir.c linux/fs/coda/dir.c
@@ -1,5 +1,5 @@
/*
- * Direcotry operations for Coda filesystem
+ * Directory operations for Coda filesystem
* Original version: (C) 1996 P. Braam and M. Callahan
* Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University
*
@@ -22,7 +22,7 @@
#include <linux/coda_linux.h>
#include <linux/coda_psdev.h>
#include <linux/coda_cnode.h>
-#include <linux/coda_namecache.h>
+#include <linux/coda_cache.h>
/* dir inode-ops */
static int coda_create(struct inode *dir, struct dentry *new, int mode);
@@ -43,8 +43,15 @@
/* support routines */
static int coda_venus_readdir(struct file *filp, void *dirent,
filldir_t filldir);
+int coda_fsync(struct file *, struct dentry *dentry);
-
+struct dentry_operations coda_dentry_operations =
+{
+ NULL, /* revalidate */
+ NULL, /* hash */
+ NULL,
+ coda_dentry_delete
+};
struct inode_operations coda_dir_inode_operations =
{
@@ -80,7 +87,10 @@
NULL, /* mmap */
coda_open, /* open */
coda_release, /* release */
- NULL, /* fsync */
+ coda_fsync, /* fsync */
+ NULL,
+ NULL,
+ NULL
};
@@ -88,9 +98,10 @@
/* acces routines: lookup, readlink, permission */
static int coda_lookup(struct inode *dir, struct dentry *entry)
{
- struct cnode *dircnp, *savedcnp;
+ struct cnode *dircnp;
struct inode *res_inode = NULL;
struct ViceFid resfid;
+ int dropme = 0; /* to indicate entry should not be cached */
int type;
int error = 0;
const char *name = entry->d_name.name;
@@ -110,78 +121,56 @@
CHECK_CNODE(dircnp);
if ( length > CFS_MAXNAMLEN ) {
- printk("name too long: lookup, %s (%s)\n",
- coda_f2s(&dircnp->c_fid, str), name);
+ printk("name too long: lookup, %s (%*s)\n",
+ coda_f2s(&dircnp->c_fid, str), length, name);
return -ENAMETOOLONG;
}
- CDEBUG(D_INODE, "lookup: %s in %s\n", name,
+ CDEBUG(D_INODE, "lookup: %*s in %s\n", length, name,
coda_f2s(&dircnp->c_fid, str));
/* control object, create inode on the fly */
- if ( coda_isroot(dir) && (CFS_CONTROLLEN == length) &&
- (strncmp(name, CFS_CONTROL, CFS_CONTROLLEN) == 0) ) {
+ if (coda_isroot(dir) && coda_iscontrol(name, length)) {
error = coda_cnode_makectl(&res_inode, dir->i_sb);
CDEBUG(D_SPECIAL,
- "Lookup on CTL object; iput of ino %ld, count %d\n",
+ "Lookup on CTL object; dir ino %ld, count %d\n",
dir->i_ino, dir->i_count);
goto exit;
}
- /* do we have it already in name cache */
- if ( (savedcnp = cfsnc_lookup(dircnp, name, length)) != NULL ) {
- CHECK_CNODE(savedcnp);
- res_inode = CTOI(savedcnp);
- iget(res_inode->i_sb, res_inode->i_ino);
- CDEBUG(D_INODE, "cache hit for ino: %ld, count: %d!\n",
- res_inode->i_ino, res_inode->i_count);
- goto exit;
- }
- CDEBUG(D_INODE, "name not found in cache!\n");
-
- /* name not cached */
error = venus_lookup(dir->i_sb, &(dircnp->c_fid),
- (const char *)name, length, &type, &resfid);
+ (const char *)name, length, &type, &resfid);
res_inode = NULL;
- if (!error) {
+ if (!error || (error == -CFS_NOCACHE) ) {
+ if (error == -CFS_NOCACHE)
+ dropme = 1;
error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
if (error)
- return -EACCES;
- /* put the thing in the name cache */
- savedcnp = ITOC(res_inode);
- CHECK_CNODE(savedcnp);
- CDEBUG(D_INODE, "ABOUT to enter into cache.\n");
- cfsnc_enter(dircnp, name, length, savedcnp);
- CDEBUG(D_INODE, "entered in cache\n");
+ return -error;
} else if (error != -ENOENT) {
- CDEBUG(D_INODE, "error for %s(%s)%d\n",
- coda_f2s(&dircnp->c_fid, str), name, error);
+ CDEBUG(D_INODE, "error for %s(%*s)%d\n",
+ coda_f2s(&dircnp->c_fid, str), length, name, error);
return error;
}
- CDEBUG(D_INODE, "lookup: %s is (%s) type %d result %d\n",
- name, coda_f2s(&resfid, str), type, error);
-
- /* at last we have our inode number from Venus,
- now allocate storage for
- the cnode and do iget, and fill in the attributes */
-
+ CDEBUG(D_INODE, "lookup: %s is (%s) type %d result %d, dropme %d\n",
+ name, coda_f2s(&resfid, str), type, error, dropme);
exit:
entry->d_time = 0;
- entry->d_op = NULL;
+ entry->d_op = &coda_dentry_operations;
d_add(entry, res_inode);
+ if ( dropme )
+ d_drop(entry);
EXIT;
return 0;
}
-
int coda_permission(struct inode *inode, int mask)
{
struct cnode *cp;
int error;
- int mode = inode->i_mode;
char str[50];
ENTRY;
@@ -191,16 +180,10 @@
return 0;
}
- /* we should be able to trust what is in the mode
- although Venus should be told to return the
- correct modes to the kernel */
- if ( coda_access_cache == 1 ) {
- if (current->fsuid == inode->i_uid)
- mode >>= 6;
- else if (in_group_p(inode->i_gid))
- mode >>= 3;
- if (((mode & mask & 0007) == mask) )
- return 0;
+ if ( coda_access_cache == 1 ) {
+ if ( coda_cache_check(inode, mask) ) {
+ return 0;
+ }
}
cp = ITOC(inode);
@@ -212,6 +195,10 @@
CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n",
coda_f2s(&(cp->c_fid), str), inode->i_ino, mask, error);
+ if ( error == 0 ) {
+ coda_cache_enter(inode, mask);
+ }
+
return error;
}
@@ -235,6 +222,10 @@
printk("coda_create: inode is null or not a directory\n");
return -ENOENT;
}
+
+ if (coda_isroot(dir) && coda_iscontrol(name, length))
+ return -EPERM;
+
dircnp = ITOC(dir);
CHECK_CNODE(dircnp);
@@ -263,7 +254,7 @@
/* invalidate the directory cnode's attributes */
dircnp->c_flags &= ~C_VATTR;
- cfsnc_zapfid(&(dircnp->c_fid));
+/* cfsnc_zapfid(&(dircnp->c_fid)); */
d_instantiate(de, result);
return 0;
@@ -280,15 +271,18 @@
struct ViceFid newfid;
char fidstr[50];
+
if (!dir || !S_ISDIR(dir->i_mode)) {
printk("coda_mkdir: inode is NULL or not a directory\n");
return -ENOENT;
}
- dircnp = ITOC(dir);
- CHECK_CNODE(dircnp);
-
if ( len > CFS_MAXNAMLEN )
return -ENAMETOOLONG;
+ if (coda_isroot(dir) && coda_iscontrol(name, len))
+ return -EPERM;
+
+ dircnp = ITOC(dir);
+ CHECK_CNODE(dircnp);
CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n",
name, len, coda_f2s(&(dircnp->c_fid), fidstr), mode);
@@ -312,7 +306,7 @@
/* invalidate the directory cnode's attributes */
dircnp->c_flags &= ~C_VATTR;
- cfsnc_zapfid(&(dircnp->c_fid));
+/* cfsnc_zapfid(&(dircnp->c_fid)); */
dir->i_nlink++;
d_instantiate(de, inode);
@@ -330,6 +324,9 @@
ENTRY;
+ if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
+ return -EPERM;
+
dir_cnp = ITOC(dir_inode);
CHECK_CNODE(dir_cnp);
cnp = ITOC(inode);
@@ -350,8 +347,8 @@
if ( ! error ) {
dir_cnp->c_flags &= ~C_VATTR;
- cfsnc_zapfid(&(dir_cnp->c_fid));
- cfsnc_zapfid(&(cnp->c_fid));
+/* cfsnc_zapfid(&(dir_cnp->c_fid)); */
+/* cfsnc_zapfid(&(cnp->c_fid)); */
inode->i_nlink++;
d_instantiate(de, inode);
@@ -362,9 +359,8 @@
}
-static int
-coda_symlink(struct inode *dir_inode, struct dentry *de,
- const char *symname)
+static int coda_symlink(struct inode *dir_inode, struct dentry *de,
+ const char *symname)
{
const char *name = de->d_name.name;
int len = de->d_name.len;
@@ -374,23 +370,23 @@
ENTRY;
- error = -ENAMETOOLONG;
- if ( len > CFS_MAXNAMLEN ) {
- return error;
- }
+ if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
+ return -EPERM;
+
+ if ( len > CFS_MAXNAMLEN )
+ return -ENAMETOOLONG;
symlen = strlen(symname);
- if ( symlen > CFS_MAXNAMLEN ) {
- return error;
- }
+ if ( symlen > CFS_MAXPATHLEN )
+ return -ENAMETOOLONG;
+
CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
error = venus_symlink(dir_inode->i_sb, &(dir_cnp->c_fid), name, len,
symname, symlen);
- if ( !error ) {
- d_drop(de);
- }
+ if ( !error )
+ d_drop(de);
CDEBUG(D_INODE, "in symlink result %d\n",error);
EXIT;
@@ -416,7 +412,7 @@
coda_f2s(&(dircnp->c_fid), fidstr), dir->i_ino);
/* this file should no longer be in the namecache! */
- cfsnc_zapfile(dircnp, (const char *)name, len);
+/* cfsnc_zapfile(dircnp, (const char *)name, len); */
error = venus_remove(dir->i_sb, &(dircnp->c_fid), name, len);
@@ -427,7 +423,7 @@
/* cache management */
dircnp->c_flags &= ~C_VATTR;
- cfsnc_zapfid(&(dircnp->c_fid));
+/* cfsnc_zapfid(&(dircnp->c_fid)); */
de->d_inode->i_nlink--;
d_delete(de);
@@ -452,8 +448,15 @@
if (len > CFS_MAXNAMLEN)
return -ENAMETOOLONG;
- /* this directory name should no longer be in the namecache */
- cfsnc_zapfile(dircnp, (const char *)name, len);
+ error = -EBUSY;
+ if (de->d_count > 1) {
+ /* Attempt to shrink child dentries ... */
+ shrink_dcache_parent(de);
+ if (de->d_count > 1)
+ return error;
+ }
+ /* Drop the dentry to force a new lookup */
+ d_drop(de);
error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
@@ -462,9 +465,6 @@
return error;
}
- dircnp->c_flags &= ~C_VATTR;
- cfsnc_zapfid(&(dircnp->c_fid));
-
dir->i_nlink--;
d_delete(de);
@@ -496,8 +496,8 @@
}
/* the old file should go from the namecache */
- cfsnc_zapfile(old_cnp, (const char *)old_name, old_length);
- cfsnc_zapfile(new_cnp, (const char *)new_name, new_length);
+/* cfsnc_zapfile(old_cnp, (const char *)old_name, old_length); */
+/* cfsnc_zapfile(new_cnp, (const char *)new_name, new_length); */
/* cross directory moves */
if (new_dir != old_dir &&
@@ -585,19 +585,17 @@
int error = 0;
struct inode *cont_inode = NULL;
unsigned short flags = f->f_flags;
+ unsigned short coda_flags = coda_flags_to_cflags(flags);
ENTRY;
CDEBUG(D_SPECIAL, "OPEN inode number: %ld, flags %o.\n",
f->f_dentry->d_inode->i_ino, flags);
- if ( flags & O_CREAT ) {
- flags &= ~O_EXCL; /* taken care of by coda_create ?? */
- }
cnp = ITOC(i);
CHECK_CNODE(cnp);
- error = venus_open(i->i_sb, &(cnp->c_fid), flags, &ino, &dev);
+ 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",
dev, ino, error);
@@ -618,14 +616,13 @@
CDEBUG(D_FILE, "GRAB: coda_inode_grab: ino %ld, ops at %x\n",
cont_inode->i_ino, (int)cont_inode->i_op);
cnp->c_ovp = cont_inode;
- cnp->c_odentry.d_inode = cont_inode;
}
cnp->c_ocount++;
/* if opened for writing flush cache entry. */
- if ( flags & (O_WRONLY | O_RDWR) ) {
- cfsnc_zapfid(&(cnp->c_fid));
- }
+/* if ( flags & (O_WRONLY | O_RDWR) ) { */
+/* cfsnc_zapfid(&(cnp->c_fid)); */
+/* } */
CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n",
error, i->i_count, i->i_ino);
@@ -641,6 +638,7 @@
struct cnode *cnp;
int error;
unsigned short flags = f->f_flags;
+ unsigned short cflags = coda_flags_to_cflags(flags);
ENTRY;
@@ -664,7 +662,7 @@
--cnp->c_owrite;
}
- error = venus_release(i->i_sb, &(cnp->c_fid), flags);
+ error = venus_release(i->i_sb, &(cnp->c_fid), cflags);
CDEBUG(D_FILE, "coda_release: result: %d\n", error);
return error;
@@ -693,6 +691,7 @@
struct venus_dirent *vdirent;
struct getdents_callback *dents_callback;
int string_offset;
+ int size;
char debug[255];
ENTRY;
@@ -703,8 +702,8 @@
dents_callback = (struct getdents_callback *) getdent;
- count = dents_callback->count;
- CODA_ALLOC(buff, void *, count);
+ size = count = dents_callback->count;
+ CODA_ALLOC(buff, void *, size);
if ( ! buff ) {
printk("coda_venus_readdir: out of memory.\n");
return -ENOMEM;
@@ -764,6 +763,6 @@
}
exit:
- CODA_FREE(buff, count);
+ CODA_FREE(buff, size);
return error;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov