Coda File System

[PATCH 3/3] Replace CODA_OPEN with CODA_OPEN_BY_FD

From: Jan Harkes <jaharkes_at_cs.cmu.edu>
Date: Wed, 8 Nov 2006 16:38:51 -0500
coda_open was disabled because we can't open container files by
device/inode number pair anymore. Replace the CODA_OPEN upcall
with CODA_OPEN_BY_FD, where venus returns an open file descriptor
for the container file. We can then grab a reference on the vnode
coda_psdev.c:vc_nb_write and use this vnode for further accesses
to the container file.
---
 cnode.h      |    2 -
 coda.h       |    2 +-
 coda_psdev.c |   23 +++++++++-
 coda_venus.c |   19 +++------
 coda_venus.h |    2 +-
 coda_vnops.c |  137 ++++++++++-----------------------------------------------
 6 files changed, 54 insertions(+), 131 deletions(-)

diff --git a/cnode.h b/cnode.h
index d911af1..e19bc61 100644
--- a/cnode.h
+++ b/cnode.h
@@ -108,8 +108,6 @@ struct cnode {
     struct vattr	 c_vattr; 	/* attributes */
     char		*c_symlink;	/* pointer to symbolic link */
     u_short		 c_symlen;	/* length of symbolic link */
-    struct cdev		*c_device;	/* associated vnode device */
-    ino_t		 c_inode;	/* associated vnode inode */
     struct cnode	*c_next;	/* links if on NetBSD machine */
 };
 #define	VTOC(vp)	((struct cnode *)(vp)->v_data)
diff --git a/coda.h b/coda.h
index 6e93433..0a16217 100644
--- a/coda.h
+++ b/coda.h
@@ -679,7 +679,7 @@ struct coda_open_by_fd_in {
 struct coda_open_by_fd_out {
     struct coda_out_hdr oh;
     int fd;
-    struct file *fh;
+    struct vnode *vp;
 };
 
 /* coda_open_by_path: */
diff --git a/coda_psdev.c b/coda_psdev.c
index 530a2a1..0a54147 100644
--- a/coda_psdev.c
+++ b/coda_psdev.c
@@ -65,6 +65,7 @@ extern int coda_nc_initialized;    /* Se
 #include <sys/mutex.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
+#include <sys/filedesc.h>
 
 #include <coda/coda.h>
 #include <coda/cnode.h>
@@ -370,9 +371,29 @@ vc_nb_write(dev, uiop, flag)
     out->unique = seq;
     vmp->vm_outSize	= buf[0];	/* Amount of data transferred? */
     vmp->vm_flags |= VM_WRITE;
+
+    error = 0;
+    if (opcode == CODA_OPEN_BY_FD) {
+	struct coda_open_by_fd_out *tmp = (struct coda_open_by_fd_out *)out;
+	struct file *fp;
+	struct vnode *vp = NULL;
+
+	if (tmp->oh.result == 0) {
+	    error = getvnode(uiop->uio_td->td_proc->p_fd, tmp->fd, &fp);
+	    if (!error) {
+		mtx_lock(&Giant);
+		vp = fp->f_vnode;
+		VREF(vp);
+		fdrop(fp, uiop->uio_td);
+		mtx_unlock(&Giant);
+	    }
+	}
+	tmp->vp = vp;
+    }
+
     wakeup(&vmp->vm_sleep);
     
-    return(0);
+    return(error);
 }
 
 int
diff --git a/coda_venus.c b/coda_venus.c
index cce9f4a..5d7ad2b 100644
--- a/coda_venus.c
+++ b/coda_venus.c
@@ -198,30 +198,23 @@ venus_root(void *mdp,
 int
 venus_open(void *mdp, CodaFid *fid, int flag,
 	struct ucred *cred, struct proc *p,
-/*out*/	struct cdev **dev, ino_t *inode)
+/*out*/	struct vnode **vp)
 {
-#if 0
     int cflag;
-    DECL(coda_open);			/* sets Isize & Osize */
-    ALLOC(coda_open);			/* sets inp & outp */
+    DECL(coda_open_by_fd);			/* sets Isize & Osize */
+    ALLOC(coda_open_by_fd);			/* sets inp & outp */
 
     /* send the open to venus. */
-    INIT_IN(&inp->ih, CODA_OPEN, cred, p);
+    INIT_IN(&inp->ih, CODA_OPEN_BY_FD, cred, p);
     inp->Fid = *fid;
     CNV_OFLAG(cflag, flag);
     inp->flags = cflag;
 
     error = coda_call(mdp, Isize, &Osize, (char *)inp);
-    if (!error) {
-	*dev =  findcdev(outp->dev);
-	*inode = outp->inode;
-    }
+    *vp = error ? NULL : outp->vp;
 
-    CODA_FREE(inp, coda_open_size);
+    CODA_FREE(inp, coda_open_by_fd_size);
     return error;
-#else
-    return (EOPNOTSUPP);
-#endif
 }
 
 int
diff --git a/coda_venus.h b/coda_venus.h
index 329ea32..8f0acb6 100644
--- a/coda_venus.h
+++ b/coda_venus.h
@@ -39,7 +39,7 @@ venus_root(void *mdp,
 int
 venus_open(void *mdp, CodaFid *fid, int flag,
 	struct ucred *cred, struct proc *p,
-/*out*/	struct cdev **dev, ino_t *inode);
+/*out*/	struct vnode **vp);
 
 int
 venus_close(void *mdp, CodaFid *fid, int flag,
diff --git a/coda_vnops.c b/coda_vnops.c
index 6ff193d..ed2e7c4 100644
--- a/coda_vnops.c
+++ b/coda_vnops.c
@@ -178,9 +178,10 @@ coda_vnodeopstats_init(void)
 }
 		
 /* 
- * coda_open calls Venus to return the device, inode pair of the cache
- * file holding the data. Using iget, coda_open finds the vnode of the
- * cache file, and then opens it.
+ * coda_open calls Venus which returns an open file descriptor the cache
+ * file holding the data. We get the vnode while we are still in the
+ * context of the venus process in coda_psdev.c. This vnode is then
+ * passed back to the caller and opened.
  */
 int
 coda_open(struct vop_open_args *ap)
@@ -199,8 +200,6 @@ coda_open(struct vop_open_args *ap)
 /* locals */
     int error;
     struct vnode *vp;
-    struct cdev *dev;
-    ino_t inode;
 
     MARK_ENTRY(CODA_OPEN_STATS);
 
@@ -216,23 +215,12 @@ coda_open(struct vop_open_args *ap)
 	return(0);
     }
 
-    error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, td->td_proc, &dev, &inode);
+    error = venus_open(vtomi((*vpp)), &cp->c_fid, flag, cred, td->td_proc, &vp);
     if (error)
 	return (error);
-    if (!error) {
-	CODADEBUG( CODA_OPEN,myprintf(("open: dev %#lx inode %lu result %d\n",
-				       (u_long)dev2udev(dev), (u_long)inode,
-				       error)); )
-    }
 
-    /* Translate the <device, inode> pair for the cache file into
-       an inode pointer. */
-    error = coda_grab_vnode(dev, inode, &vp);
-    if (error)
-	return (error);
+    CODADEBUG( CODA_OPEN,myprintf(("open: vp %p result %d\n", vp, error));)
 
-    /* We get the vnode back locked.  Needs unlocked */
-    VOP_UNLOCK(vp, 0, td);
     /* Keep a reference until the close comes in. */
     vref(*vpp);                
 
@@ -251,11 +239,6 @@ coda_open(struct vop_open_args *ap)
 	cp->c_flags &= ~C_VATTR;
     }
 
-    /* Save the <device, inode> pair for the cache file to speed
-       up subsequent page_read's. */
-    cp->c_device = dev;
-    cp->c_inode = inode;
-
     /* Open the cache file. */
     error = VOP_OPEN(vp, flag, cred, td, -1); 
     if (error) {
@@ -290,28 +273,13 @@ coda_close(struct vop_close_args *ap)
 	return(0);
     }
 
-    if (IS_UNMOUNTING(cp)) {
-	if (cp->c_ovp) {
-#ifdef	CODA_VERBOSE
-	    printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n",
-		    vrefcnt(vp), cp->c_ovp, vp, cp);
-#endif
-#ifdef	hmm
-	    vgone(cp->c_ovp);
-#else
-	    VOP_CLOSE(cp->c_ovp, flag, cred, td); /* Do errors matter here? */
-	    vrele(cp->c_ovp);
-#endif
-	} else {
-#ifdef	CODA_VERBOSE
-	    printf("coda_close: NO container vp %p/cp %p\n", vp, cp);
-#endif
-	}
-	return ENODEV;
-    } else {
+    if (cp->c_ovp) {
 	VOP_CLOSE(cp->c_ovp, flag, cred, td); /* Do errors matter here? */
 	vrele(cp->c_ovp);
     }
+#ifdef CODA_VERBOSE
+    else printf("coda_close: NO container vp %p/cp %p\n", vp, cp);
+#endif
 
     if (--cp->c_ocount == 0)
 	cp->c_ovp = NULL;
@@ -319,8 +287,11 @@ coda_close(struct vop_close_args *ap)
     if (flag & FWRITE)                    /* file was opened for write */
 	--cp->c_owrite;
 
-    error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, td->td_proc);
-    vrele(CTOV(cp));
+    if (!IS_UNMOUNTING(cp))
+         error = venus_close(vtomi(vp), &cp->c_fid, flag, cred, td->td_proc);
+    else error = ENODEV;
+
+    vrele(vp);
 
     CODADEBUG(CODA_CLOSE, myprintf(("close: result %d\n",error)); )
     return(error);
@@ -353,12 +324,8 @@ coda_rdwr(struct vnode *vp, struct uio *
 /* locals */
     struct cnode *cp = VTOC(vp);
     struct vnode *cfvp = cp->c_ovp;
-    struct proc *p = td->td_proc;
-    struct thread *ltd = td;
-    int igot_internally = 0;
     int opened_internally = 0;
     int error = 0;
-    int iscore = 0;
 
     MARK_ENTRY(CODA_RDWR_STATS);
 
@@ -373,51 +340,19 @@ coda_rdwr(struct vnode *vp, struct uio *
     }
 
     /* 
-     * If file is not already open this must be a page
-     * {read,write} request.  Iget the cache file's inode
-     * pointer if we still have its <device, inode> pair.
-     * Otherwise, we must do an internal open to derive the
-     * pair. 
+     * If file is not already open this must be a page {read,write} request
+     * and we should open it internally.
      */
     if (cfvp == NULL) {
-	/* 
-	 * If we're dumping core, do the internal open. Otherwise
-	 * venus won't have the correct size of the core when
-	 * it's completely written.
-	 */
-	if (p) {
-	    PROC_LOCK(p);
-	    iscore = (p->p_acflag & ACORE);
-	    PROC_UNLOCK(p);
-	}
-	else
-	    ltd = curthread; 
-
-	if (cp->c_inode != 0 && !iscore) {
-	    igot_internally = 1;
-	    error = coda_grab_vnode(cp->c_device, cp->c_inode, &cfvp);
-	    if (error) {
-		MARK_INT_FAIL(CODA_RDWR_STATS);
-		return(error);
-	    }
-	    /* 
-	     * We get the vnode back locked by curthread in both Mach and
-	     * NetBSD.  Needs unlocked 
-	     */
-	    VOP_UNLOCK(cfvp, 0, ltd);
-	}
-	else {
-	    opened_internally = 1;
-	    MARK_INT_GEN(CODA_OPEN_STATS);
-	    error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), 
-			     cred, td, -1);
-printf("coda_rdwr: Internally Opening %p\n", vp);
-	    if (error) {
+	opened_internally = 1;
+	MARK_INT_GEN(CODA_OPEN_STATS);
+	error = VOP_OPEN(vp, (rw == UIO_READ ? FREAD : FWRITE), cred, td, -1);
+	printf("coda_rdwr: Internally Opening %p\n", vp);
+	if (error) {
 		printf("coda_rdwr: VOP_OPEN on container failed %d\n", error);
 		return (error);
-	    }
-	    cfvp = cp->c_ovp;
 	}
+	cfvp = cp->c_ovp;
     }
 
     /* Have UFS handle the call. */
@@ -1526,7 +1461,7 @@ coda_readdir(struct vop_readdir_args *ap
 	    opened_internally = 1;
 	    MARK_INT_GEN(CODA_OPEN_STATS);
 	    error = VOP_OPEN(vp, FREAD, cred, td, -1);
-printf("coda_readdir: Internally Opening %p\n", vp);
+	    printf("coda_readdir: Internally Opening %p\n", vp);
 	    if (error) {
 		printf("coda_readdir: VOP_OPEN on container failed %d\n", error);
 		return (error);
@@ -1677,30 +1612,6 @@ coda_islocked(struct vop_islocked_args *
     return (vop_stdislocked(ap));
 }
 
-/* How one looks up a vnode given a device/inode pair: */
-int
-coda_grab_vnode(struct cdev *dev, ino_t ino, struct vnode **vpp)
-{
-    /* This is like VFS_VGET() or igetinode()! */
-    int           error;
-    struct mount *mp;
-
-    if (!(mp = devtomp(dev))) {
-	myprintf(("coda_grab_vnode: devtomp(%#lx) returns NULL\n",
-		  (u_long)dev2udev(dev)));
-	return(ENXIO);
-    }
-
-    /* XXX - ensure that nonzero-return means failure */
-    error = VFS_VGET(mp,ino,LK_EXCLUSIVE,vpp);
-    if (error) {
-	myprintf(("coda_grab_vnode: iget/vget(%lx, %lu) returns %p, err %d\n", 
-		  (u_long)dev2udev(dev), (u_long)ino, (void *)*vpp, error));
-	return(ENOENT);
-    }
-    return(0);
-}
-
 void
 print_vattr(struct vattr *attr)
 {
-- 
1.4.3.3.gc26a
Received on 2006-11-08 16:42:22