summaryrefslogtreecommitdiffstats
path: root/fs/coda/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda/super.c')
-rw-r--r--fs/coda/super.c444
1 files changed, 101 insertions, 343 deletions
diff --git a/fs/coda/super.c b/fs/coda/super.c
index 85a5ccbb3..5410fb50d 100644
--- a/fs/coda/super.c
+++ b/fs/coda/super.c
@@ -1,13 +1,14 @@
/*
* Super block/filesystem wide operations
*
- * Peter J. Braam <braam@maths.ox.ac.uk>,
- * Michael Callahan <callahan@maths.ox.ac.uk> Aug 1996
- * Rewritten for Linux 2.1.57 Peter Braam <braam@cs.cmu.edu>
+ * Copryright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk> and
+ * Michael Callahan <callahan@maths.ox.ac.uk>
+ *
+ * Rewritten for Linux 2.1.?? Peter Braam <braam@cs.cmu.edu>
+ * Copyright (C) Carnegie Mellon University
*/
#define __NO_VERSION__
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -32,45 +33,25 @@
#include <linux/coda.h>
#include <linux/coda_linux.h>
#include <linux/coda_psdev.h>
-#include <linux/coda_cnode.h>
-#include <linux/coda_namecache.h>
+#include <linux/coda_fs_i.h>
+#include <linux/coda_cache.h>
/* VFS super_block ops */
static struct super_block *coda_read_super(struct super_block *, void *, int);
static void coda_read_inode(struct inode *);
-static int coda_notify_change(struct inode *inode, struct iattr *attr);
+static int coda_notify_change(struct dentry *dentry, struct iattr *attr);
static void coda_put_inode(struct inode *);
static void coda_delete_inode(struct inode *);
static void coda_put_super(struct super_block *);
static int coda_statfs(struct super_block *sb, struct statfs *buf,
int bufsiz);
-
/* helper functions */
-void print_vattr( struct coda_vattr *attr );
-static inline struct coda_sb_info *coda_psinode2sb(struct inode *inode);
static inline struct vcomm *coda_psinode2vcomm(struct inode *inode);
static int coda_get_psdev(void *, struct inode **);
-static void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
-static void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
-int coda_fetch_inode(struct inode *, struct coda_vattr *);
-
-extern inline struct vcomm *coda_psdev_vcomm(struct inode *inode);
-extern int coda_cnode_make(struct inode **inode, ViceFid *fid,
- struct super_block *sb);
-extern struct cnode *coda_cnode_alloc(void);
-extern void coda_cnode_free(struct cnode *);
-char *coda_f2s(struct ViceFid *, char *);
-
-extern int cfsnc_initialized;
-extern int coda_debug;
-extern int coda_print_entry;
-
-extern struct inode_operations coda_file_inode_operations;
-extern struct inode_operations coda_dir_inode_operations;
-extern struct inode_operations coda_ioctl_inode_operations;
-extern struct inode_operations coda_symlink_inode_operations;
+static struct coda_sb_info *coda_psinode2sbi(struct inode *inode);
+
/* exported operations */
struct super_operations coda_super_operations =
{
@@ -91,37 +72,39 @@ struct super_operations coda_super_operations =
struct coda_sb_info coda_super_info[MAX_CODADEVS];
-
static struct super_block * coda_read_super(struct super_block *sb,
void *data, int silent)
{
struct inode *psdev = 0, *root = 0;
struct coda_sb_info *sbi = NULL;
- struct vcomm *vc;
+ struct vcomm *vc = NULL;
ViceFid fid;
kdev_t dev = sb->s_dev;
int error;
char str[50];
-ENTRY;
+ ENTRY;
MOD_INC_USE_COUNT;
if (coda_get_psdev(data, &psdev))
- goto exit;
+ goto error;
vc = coda_psinode2vcomm(psdev);
if ( !vc )
- goto exit;
+ goto error;
+ vc->vc_sb = sb;
+ vc->vc_inuse = 1;
- sbi = coda_psinode2sb(psdev);
+ sbi = coda_psinode2sbi(psdev);
if ( !sbi )
- goto exit;
-
+ goto error;
sbi->sbi_psdev = psdev;
sbi->sbi_vcomm = vc;
+ INIT_LIST_HEAD(&(sbi->sbi_cchead));
+ INIT_LIST_HEAD(&(sbi->sbi_volroothead));
lock_super(sb);
sb->u.generic_sbp = sbi;
- sb->s_blocksize = 1024; /* XXXXX */
+ sb->s_blocksize = 1024; /* XXXXX what do we put here?? */
sb->s_blocksize_bits = 10;
sb->s_magic = CODA_SUPER_MAGIC;
sb->s_dev = dev;
@@ -129,22 +112,22 @@ ENTRY;
/* get root fid from Venus: this needs the root inode */
error = venus_rootfid(sb, &fid);
-
if ( error ) {
- unlock_super(sb);
printk("coda_read_super: coda_get_rootfid failed with %d\n",
- error);
- goto exit;
+ error);
+ sb->s_dev = 0;
+ unlock_super(sb);
+ goto error;
}
- printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid, str));
+ printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
+ /* make root inode */
error = coda_cnode_make(&root, &fid, sb);
if ( error || !root ) {
printk("Failure of coda_cnode_make for root: error %d\n", error);
- unlock_super(sb);
sb->s_dev = 0;
- root = NULL;
- goto exit;
+ unlock_super(sb);
+ goto error;
}
printk("coda_read_super: rootinode is %ld dev %d\n",
@@ -152,22 +135,27 @@ ENTRY;
sbi->sbi_root = root;
sb->s_root = d_alloc_root(root, NULL);
unlock_super(sb);
+ EXIT;
return sb;
-EXIT;
-exit:
+error:
+EXIT;
MOD_DEC_USE_COUNT;
- sbi->sbi_vcomm = NULL;
- sbi->sbi_root = NULL;
+ if (sbi) {
+ sbi->sbi_vcomm = NULL;
+ sbi->sbi_root = NULL;
+ }
+ if ( vc ) {
+ vc->vc_sb = NULL;
+ vc->vc_inuse = 0;
+ }
if (root) {
iput(root);
- coda_cnode_free(ITOC(root));
}
sb->s_dev = 0;
return NULL;
}
-
static void coda_put_super(struct super_block *sb)
{
struct coda_sb_info *sb_info;
@@ -177,78 +165,94 @@ static void coda_put_super(struct super_block *sb)
lock_super(sb);
sb->s_dev = 0;
+ coda_cache_clear_all(sb);
sb_info = coda_sbp(sb);
+ sb_info->sbi_vcomm->vc_inuse = 0;
+ sb_info->sbi_vcomm->vc_sb = NULL;
+ printk("Coda: Bye bye.\n");
memset(sb_info, 0, sizeof(* sb_info));
unlock_super(sb);
MOD_DEC_USE_COUNT;
-EXIT;
+ EXIT;
}
+
/* all filling in of inodes postponed until lookup */
static void coda_read_inode(struct inode *inode)
{
- inode->u.generic_ip = NULL;
- /* inode->i_blksize = inode->i_sb->s_blocksize;
- inode->i_mode = 0;
- inode->i_op = NULL;
- NFS_CACHEINV(inode); */
+ struct coda_inode_info *cnp;
+ ENTRY;
+ cnp = ITOC(inode);
+ cnp->c_magic = 0;
+ return;
}
-static void coda_put_inode(struct inode *inode)
+static void coda_put_inode(struct inode *in)
{
- CDEBUG(D_INODE,"ino: %ld, cnp: %x\n", inode->i_ino,
- (int) inode->u.generic_ip);
+ ENTRY;
+
+ CDEBUG(D_INODE,"ino: %ld, count %d\n", in->i_ino, in->i_count);
+
+ if ( in->i_count == 1 )
+ in->i_nlink = 0;
+
}
static void coda_delete_inode(struct inode *inode)
{
- struct cnode *cnp;
+ struct coda_inode_info *cnp;
struct inode *open_inode;
ENTRY;
CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n",
inode->i_ino, inode->i_count);
- if ( inode->i_ino == CTL_INO ) {
+ cnp = ITOC(inode);
+ if ( inode->i_ino == CTL_INO || cnp->c_magic != CODA_CNODE_MAGIC ) {
clear_inode(inode);
return;
}
- cnp = ITOC(inode);
+
+ if ( coda_fid_is_volroot(&cnp->c_fid) )
+ list_del(&cnp->c_volrootlist);
open_inode = cnp->c_ovp;
if ( open_inode ) {
CDEBUG(D_SUPER, "DELINO cached file: ino %ld count %d.\n",
open_inode->i_ino, open_inode->i_count);
cnp->c_ovp = NULL;
- cnp->c_odentry.d_inode = NULL;
- iput( open_inode );
+ iput(open_inode);
}
+
+ coda_cache_clear_cnp(cnp);
+
inode->u.generic_ip = NULL;
- coda_cnode_free(cnp);
clear_inode(inode);
-EXIT;
+ EXIT;
}
-static int coda_notify_change(struct inode *inode, struct iattr *iattr)
+static int coda_notify_change(struct dentry *de, struct iattr *iattr)
{
- struct cnode *cnp;
+ struct inode *inode = de->d_inode;
+ struct coda_inode_info *cnp;
struct coda_vattr vattr;
int error;
-ENTRY;
+
+ ENTRY;
memset(&vattr, 0, sizeof(vattr));
cnp = ITOC(inode);
CHECK_CNODE(cnp);
coda_iattr_to_vattr(iattr, &vattr);
- vattr.va_type = VNON; /* cannot set type */
+ vattr.va_type = C_VNON; /* cannot set type */
CDEBUG(D_SUPER, "vattr.va_mode %o\n", vattr.va_mode);
error = venus_setattr(inode->i_sb, &cnp->c_fid, &vattr);
if ( !error ) {
coda_vattr_to_iattr(inode, &vattr);
- cfsnc_zapfid(&(cnp->c_fid));
+ coda_cache_clear_cnp(cnp);
}
CDEBUG(D_SUPER, "inode.i_mode %o, error %d\n",
inode->i_mode, error);
@@ -257,14 +261,12 @@ ENTRY;
return error;
}
-/* we need _something_ */
+/* 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;
-#define NB_SFS_SIZ 0x895440
-
tmp.f_type = CODA_SUPER_MAGIC;
tmp.f_bsize = 1024;
tmp.f_blocks = 9000000;
@@ -284,278 +286,38 @@ struct file_system_type coda_fs_type = {
"coda", 0, coda_read_super, NULL
};
-
-
-
int init_coda_fs(void)
{
return register_filesystem(&coda_fs_type);
}
+/* MODULE stuff is in psdev.c */
-/* utility functions below */
-static void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
-{
- int inode_type;
- /* inode's i_dev, i_flags, i_ino are set by iget
- XXX: is this all we need ??
- */
- switch (attr->va_type) {
- case VNON:
- inode_type = 0;
- break;
- case VREG:
- inode_type = S_IFREG;
- break;
- case VDIR:
- inode_type = S_IFDIR;
- break;
- case VLNK:
- inode_type = S_IFLNK;
- break;
- default:
- inode_type = 0;
- }
- inode->i_mode |= inode_type;
-
- if (attr->va_mode != (u_short) -1)
- inode->i_mode = attr->va_mode | inode_type;
- if (attr->va_uid != -1)
- inode->i_uid = (uid_t) attr->va_uid;
- if (attr->va_gid != -1)
- inode->i_gid = (gid_t) attr->va_gid;
- if (attr->va_nlink != -1)
- inode->i_nlink = attr->va_nlink;
- if (attr->va_size != -1)
- inode->i_size = attr->va_size;
- /* XXX This needs further study */
- /*
- inode->i_blksize = attr->va_blocksize;
- inode->i_blocks = attr->va_size/attr->va_blocksize
- + (attr->va_size % attr->va_blocksize ? 1 : 0);
- */
- if (attr->va_atime.tv_sec != -1)
- inode->i_atime = attr->va_atime.tv_sec;
- if (attr->va_mtime.tv_sec != -1)
- inode->i_mtime = attr->va_mtime.tv_sec;
- 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
- * looked at. The BSD type field needs to be deduced from linux
- * mode.
- * So we have to do some translations here.
- */
-
-void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
-{
- umode_t mode;
- unsigned int valid;
-
- /* clean out */
- vattr->va_mode = (umode_t) -1;
- vattr->va_uid = (vuid_t) -1;
- vattr->va_gid = (vgid_t) -1;
- vattr->va_size = (off_t) -1;
- vattr->va_atime.tv_sec = (time_t) -1;
- vattr->va_mtime.tv_sec = (time_t) -1;
- vattr->va_ctime.tv_sec = (time_t) -1;
- vattr->va_atime.tv_nsec = (time_t) -1;
- vattr->va_mtime.tv_nsec = (time_t) -1;
- vattr->va_ctime.tv_nsec = (time_t) -1;
- vattr->va_type = VNON;
- vattr->va_fileid = (long)-1;
- vattr->va_gen = (long)-1;
- vattr->va_bytes = (long)-1;
- vattr->va_fsid = (long)-1;
- vattr->va_nlink = (short)-1;
- vattr->va_blocksize = (long)-1;
- vattr->va_rdev = (dev_t)-1;
- vattr->va_flags = 0;
-
- /* determine the type */
- mode = iattr->ia_mode;
- if ( S_ISDIR(mode) ) {
- vattr->va_type = VDIR;
- } else if ( S_ISREG(mode) ) {
- vattr->va_type = VREG;
- } else if ( S_ISLNK(mode) ) {
- vattr->va_type = VLNK;
- } else {
- /* don't do others */
- vattr->va_type = VNON;
- }
-
- /* set those vattrs that need change */
- valid = iattr->ia_valid;
- if ( valid & ATTR_MODE ) {
- vattr->va_mode = iattr->ia_mode;
- }
- if ( valid & ATTR_UID ) {
- vattr->va_uid = (vuid_t) iattr->ia_uid;
- }
- if ( valid & ATTR_GID ) {
- vattr->va_gid = (vgid_t) iattr->ia_gid;
- }
- if ( valid & ATTR_SIZE ) {
- vattr->va_size = iattr->ia_size;
- }
- if ( valid & ATTR_ATIME ) {
- vattr->va_atime.tv_sec = iattr->ia_atime;
- vattr->va_atime.tv_nsec = 0;
- }
- if ( valid & ATTR_MTIME ) {
- vattr->va_mtime.tv_sec = iattr->ia_mtime;
- vattr->va_mtime.tv_nsec = 0;
- }
- if ( valid & ATTR_CTIME ) {
- vattr->va_ctime.tv_sec = iattr->ia_ctime;
- vattr->va_ctime.tv_nsec = 0;
- }
-
-}
-
-
-void print_vattr(struct coda_vattr *attr)
-{
- char *typestr;
-
- switch (attr->va_type) {
- case VNON:
- typestr = "VNON";
- break;
- case VREG:
- typestr = "VREG";
- break;
- case VDIR:
- typestr = "VDIR";
- break;
- case VBLK:
- typestr = "VBLK";
- break;
- case VCHR:
- typestr = "VCHR";
- break;
- case VLNK:
- typestr = "VLNK";
- break;
- case VSOCK:
- typestr = "VSCK";
- break;
- case VFIFO:
- typestr = "VFFO";
- break;
- case VBAD:
- typestr = "VBAD";
- break;
- default:
- typestr = "????";
- break;
- }
-
-
- printk("attr: type %s (%o) mode %o uid %d gid %d fsid %d rdev %d\n",
- typestr, (int)attr->va_type, (int)attr->va_mode, (int)attr->va_uid,
- (int)attr->va_gid, (int)attr->va_fsid, (int)attr->va_rdev);
-
- printk(" fileid %d nlink %d size %d blocksize %d bytes %d\n",
- (int)attr->va_fileid, (int)attr->va_nlink,
- (int)attr->va_size,
- (int)attr->va_blocksize,(int)attr->va_bytes);
- printk(" gen %ld flags %ld vaflags %d\n",
- attr->va_gen, attr->va_flags, attr->va_vaflags);
- printk(" atime sec %d nsec %d\n",
- (int)attr->va_atime.tv_sec, (int)attr->va_atime.tv_nsec);
- printk(" mtime sec %d nsec %d\n",
- (int)attr->va_mtime.tv_sec, (int)attr->va_mtime.tv_nsec);
- printk(" ctime sec %d nsec %d\n",
- (int)attr->va_ctime.tv_sec, (int)attr->va_ctime.tv_nsec);
-}
-
-/* */
-int coda_fetch_inode (struct inode *inode, struct coda_vattr *attr)
-{
- struct cnode *cp;
- int ino, error=0;
- CDEBUG(D_SUPER, "fetch for ino: %ld\n", inode->i_ino);
-
- ino = inode->i_ino;
- if (!ino)
- printk("coda_fetch_inode: inode called with i_ino = 0 (don't worry)\n");
-
- inode->i_op = NULL;
- inode->i_mode = 0;
-
- cp = ITOC(inode);
- CHECK_CNODE(cp);
-
- /* root inode */
- if (cp->c_fid.Volume == 0 &&
- cp->c_fid.Vnode == 0 &&
- cp->c_fid.Unique == 0) {
- inode->i_ino = 1;
- inode->i_op = NULL;
- return 0;
- }
-
- if (IS_CTL_FID( &(cp->c_fid) )) {
- /* This is the special magic control file.
- Venus doesn't want
- to hear a GETATTR about this! */
- inode->i_op = &coda_ioctl_inode_operations;
- return 0;
- }
-
- if ( ! attr ) {
- printk("coda_fetch_inode: called with NULL vattr, ino %ld\n",
- inode->i_ino);
- return -1; /* XXX */
- }
-
- if (coda_debug & D_SUPER ) print_vattr(attr);
- coda_vattr_to_iattr(inode, attr);
-
- if (S_ISREG(inode->i_mode))
- 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 {
- printk ("coda_read_inode: what kind of inode is this? i_mode = %o\n", inode->i_mode);
- inode->i_op = NULL;
- }
- return error;
-}
-
-static inline struct vcomm *
-coda_psinode2vcomm(struct inode *inode)
+/* helpers */
+static inline struct vcomm *coda_psinode2vcomm(struct inode *inode)
{
unsigned int minor = MINOR(inode->i_rdev);
-CDEBUG(D_PSDEV,"minor %d\n", minor);
+ CDEBUG(D_PSDEV,"minor %d\n", minor);
if ( minor < MAX_CODADEVS )
return &(psdev_vcomm[minor]);
else
return NULL;
}
-static inline struct coda_sb_info *
-coda_psinode2sb(struct inode *inode)
+static struct coda_sb_info *coda_psinode2sbi(struct inode *inode)
{
unsigned int minor = MINOR(inode->i_rdev);
-CDEBUG(D_PSDEV,"minor %d\n", minor);
- if ( minor < MAX_CODADEVS )
+ CDEBUG(D_PSDEV,"minor %d\n", minor);
+ if ( (minor >= 0) && (minor < MAX_CODADEVS))
return &(coda_super_info[minor]);
else
return NULL;
}
-static int
-coda_get_psdev(void *data, struct inode **res_dev)
+/* name lookup for psdev passed in by mount */
+static int coda_get_psdev(void *data, struct inode **res_dev)
{
char **psdev_path;
struct inode *psdev = 0;
@@ -563,50 +325,46 @@ coda_get_psdev(void *data, struct inode **res_dev)
if ( ! data ) {
- printk("coda_read_super: no data!\n");
- goto error;
- } else {
- psdev_path = data;
- }
+ printk("coda_get_psdev: no data!\n");
+ return 1;
+ }
+
+ psdev_path = data;
ent = namei((char *) *psdev_path);
if (IS_ERR(ent)) {
printk("namei error %ld for %d\n", PTR_ERR(ent),
(int) psdev_path);
- goto error;
+ return 1;
}
psdev = ent->d_inode;
-
if (!S_ISCHR(psdev->i_mode)) {
printk("not a character device\n");
- goto error;
+ return 1;
}
-CDEBUG(D_PSDEV,"major %d, minor %d, count %d\n", MAJOR(psdev->i_rdev),
- MINOR(psdev->i_rdev), psdev->i_count);
+ CDEBUG(D_PSDEV,"major %d, minor %d, count %d\n",
+ MAJOR(psdev->i_rdev),
+ MINOR(psdev->i_rdev), psdev->i_count);
if (MAJOR(psdev->i_rdev) != CODA_PSDEV_MAJOR) {
printk("device %d not a Coda PSDEV device\n",
MAJOR(psdev->i_rdev));
- goto error;
+ return 1;
}
if (MINOR(psdev->i_rdev) >= MAX_CODADEVS) {
printk("minor %d not an allocated Coda PSDEV\n",
psdev->i_rdev);
- goto error;
+ return 1;
}
if (psdev->i_count < 1) {
printk("coda device minor %d not open (i_count = %d)\n",
MINOR(psdev->i_rdev), psdev->i_count);
- goto error;
+ return 1;
}
*res_dev = psdev;
-
+ EXIT;
return 0;
-
-EXIT;
-error:
- return 1;
}