Anonymous avatar Anonymous committed 335fd9d

Open, walk, stat, reference counts on o9fid, clunk.
wq

Comments (0)

Files changed (7)

 };
 
 struct o9fsstat {
-	/* system-modified data */
-	u_short	type;	/* server type */
-	u_int	dev;	/* server subtype */
-	/* file data */
-	struct	o9fsqid qid;	/* unique id from server */
+	uint16_t	type;			/* server type */
+	uint32_t	dev;			/* server subtype */
+	struct		o9fsqid qid;	/* unique id from server */
 	uint32_t	mode;			/* permissions */
 	uint32_t	atime;			/* last read time */
 	uint32_t	mtime;			/* last write time */
-	int64_t	length;			/* file length */	
-	char	*name;			/* last element of path */
-	char	*uid;			/* owner name */
-	char	*gid;			/* group name */
-	char	*muid;			/* last modifier name */
+	uint64_t	length;			/* file length */	
+	char		*name;			/* last element of path */
+	char		*uid;			/* owner name */
+	char		*gid;			/* group name */
+	char		*muid;			/* last modifier name */
 };
 
 /* 9p file */
 	struct	o9fsfid *next;
 };
 
+/*
+ * Many vnodes can refer to the same o9fid and this is accounted for in ref.
+ * When ref drops to zero, the o9fid is clunked.
+ */
 struct o9fid {
 	int		fid;
-	int		mode;
+	int		mode;			/* open mode */
+	int		ref;			
 	struct	o9fsqid	qid;
 	int64_t	offset;
 	TAILQ_ENTRY(o9fid) next;
 };
 
 void
-o9fs_fidclunk(struct o9fs *fs, struct o9fsfid *f)
+o9fs_clunk(struct o9fs *fs, struct o9fid *f)
 {
-	struct o9fsfcall tx, rx;
+	DIN();
 
-	DIN();
-	tx.type = O9FS_TCLUNK;
-	tx.fid = f->fid;
-	o9fs_rpc(fs, &tx, &rx);
+	if (f == NULL)
+		panic("o9fs_clunk: nil fid");
 
-	f->opened = 0;
-	f->mode = -1;
-	o9fs_putfid(fs, f);
+	O9FS_PBIT32(fs->outbuf, 11);
+	O9FS_PBIT8(fs->outbuf + Offtype, O9FS_TCLUNK);
+	O9FS_PBIT16(fs->outbuf + Offtag, 0);
+	O9FS_PBIT32(fs->outbuf + Minhd, f->fid);
+	
+	o9fs_mio(fs, 11);
+	o9fs_xputfid(fs, f);
 	DRET();
 }
 
 		return NULL;
 	}
 
-	newfid->qid.type = O9FS_GBIT8(fs->inbuf + Minhd + 2);
-	newfid->qid.vers = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 1);
-	newfid->qid.path = O9FS_GBIT64(fs->inbuf + Minhd + 2 + 1 + 4);
+	if (nwname > 0) {
+		newfid->qid.type = O9FS_GBIT8(fs->inbuf + Minhd + 2);
+		newfid->qid.vers = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 1);
+		newfid->qid.path = O9FS_GBIT64(fs->inbuf + Minhd + 2 + 1 + 4);
+	}
 
 	DRET();
 	return newfid;
 }
 
-struct o9fsfid*
-o9fs_twalk(struct o9fs *fs, struct o9fsfid *f, struct o9fsfid *nf, char *oname)
+struct o9fsstat *
+o9fs_stat(struct o9fs *fs, struct o9fid *fid)
 {
-	struct o9fsfcall tx, rx;
-	int n;
-	char *name;
+	long n, nstat;
+	struct o9fsstat *stat;
+	DIN();
 
-	name = oname;
-	if (nf == NULL) {
-		DBG("twalk: cloning fid=%d\n", f->fid);
-		nf = o9fs_fidclone(fs, f);
-		n = 0;
-	}
-	
-	if (name) {
-		uint64_t len;
-		len = strlen(name);
-		tx.wname[0] = malloc(len, M_O9FS, M_WAITOK);
-		memcpy(tx.wname[0], name, len);
-		tx.wname[0][len] = 0;
-		n = 1;
-	}
-	tx.type = O9FS_TWALK;
-	tx.fid = f->fid;
-	tx.newfid = nf->fid;
-	tx.nwname = n;
-
-	if ((o9fs_rpc(fs, &tx, &rx)) < 0) {
-		printf("walk: rpc failed\n");
-		o9fs_putfid(fs, nf);
+	if (fid == NULL) {
+		DRET();
 		return NULL;
 	}
-	if (rx.nwqid < n) {
-		printf("walk: nwqid < n\n");
+
+	O9FS_PBIT32(fs->outbuf, Minhd + 4);
+	O9FS_PBIT8(fs->outbuf + Offtype, O9FS_TSTAT);
+	O9FS_PBIT16(fs->outbuf + Offtag, 0);
+	O9FS_PBIT32(fs->outbuf + Minhd, fid->fid);
+	n = o9fs_mio(fs, Minhd + 4);
+	if (n <= 0) {
+		DRET();
 		return NULL;
 	}
+
+	n = O9FS_GBIT16(fs->inbuf + Minhd + 2);
+	stat = malloc(n, M_O9FS, M_WAITOK);
+
+	stat->type = O9FS_GBIT16(fs->inbuf + Minhd + 2 + 2);
+	stat->dev = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 2 + 2);
+	stat->qid.type = O9FS_GBIT8(fs->inbuf + Minhd + 2 + 2 + 2 + 4);
+	stat->qid.vers = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1);
+	stat->qid.path = O9FS_GBIT64(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1 + 4);
+	stat->mode = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1 + 4 + 8);
+	stat->atime = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1 + 4 + 8 + 4);
+	stat->mtime = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1 + 4 + 8 + 4 + 4);
+	stat->length = O9FS_GBIT64(fs->inbuf + Minhd + 2 + 2 + 2 + 4 + 1 + 4 + 8 + 4 + 4 + 4);
+
+	/* For now the other fields are not used, so we don't bother parsing them */
+
+	DRET();
+	return stat;
+}
 	
-	/* no negative numbers on the qid */
-	if (rx.nwqid > 0)
-		nf->qid = rx.wqid[n-1];
-	else
-		nf->qid = rx.wqid[0];
-	return nf;
-}
 
 struct o9fsstat *
 o9fs_fstat(struct o9fs *fs, struct o9fsfid *fid)
 }
 
 int
+o9fs_opencreate2(struct o9fs *fs, struct o9fid *fid, uint8_t type, uint8_t mode, uint32_t perm, char *name)
+{
+	long n;
+	u_char *p;
+	uint8_t omode;
+	DIN();
+
+	if (fid == NULL) {
+		DRET();
+		return -1;
+	}
+
+	p = fs->outbuf;
+	O9FS_PBIT8(p + Offtype, type);
+	O9FS_PBIT16(p + Offtag, 0);
+	O9FS_PBIT32(p + Minhd, fid->fid);
+	omode = o9fs_uflags2omode(mode);
+	O9FS_PBIT8(p + Minhd + 4, omode);
+	
+	n = Minhd + 4 + 1;
+	O9FS_PBIT32(fs->outbuf, n);
+	n = o9fs_mio(fs, n);
+	if (n <= 0) {
+		DRET();
+		return -1;
+	}
+	
+	fid->qid.type = O9FS_GBIT8(fs->inbuf + Minhd + 2);
+	fid->qid.vers = O9FS_GBIT32(fs->inbuf + Minhd + 2 + 1);
+	fid->qid.path = O9FS_GBIT64(fs->inbuf + Minhd + 2 + 1 + 4);
+	fid->mode = omode;
+	return 0;
+}
+
+int
 o9fs_opencreate(int type, struct o9fs *fs, struct o9fsfid *f, int mode, ulong perm, char *name)
 {
 	int omode, error;
 /* o9fs_subr.c */
 void	o9fs_dump(u_char *, long);
 char	*putstring(char *, char *);
+char	*getstring(char *);
 int		o9fs_allocvp(struct mount *, struct o9fid *, struct vnode **, u_long);
-void	o9fs_freevp(struct vnode *);
-u_int	o9fs_tokenize(char **, u_int, char *, char);
 struct	o9fsfid *o9fs_getfid(struct o9fs *);
 struct	o9fid *o9fs_xgetfid(struct o9fs *);
 void	o9fs_xputfid(struct o9fs *, struct o9fid *);
 int		o9fs_uflags2omode(int);
 void	o9fs_freefcall(struct o9fsfcall *);
 void	o9fs_freestat(struct o9fsstat *);
-struct	o9fsfid *o9fs_findfid(struct o9fs *, int);
-void	printfidvp(struct o9fsfid *);
-struct	o9fsfid *o9fs_fidclone(struct o9fs *, struct o9fsfid *);
-struct	o9fsfid *o9fs_fidunique(struct o9fs *, struct o9fsfid *);
-struct	o9fsfid *o9fs_clone(struct o9fs *, struct o9fsfid *);
+void	printvp(struct vnode *);
 
 /* o9fs_9p.c */
 struct	o9fsstat *o9fs_fstat(struct o9fs *, struct o9fsfid *);
 void	o9fs_fidclunk(struct o9fs *, struct o9fsfid *);
 struct	o9fsfid *o9fs_twalk(struct o9fs *, struct o9fsfid *, struct o9fsfid *, char *);
 int		o9fs_opencreate(int, struct o9fs *, struct o9fsfid *, int, ulong, char *);
+int		o9fs_opencreate2(struct o9fs *, struct o9fid *, uint8_t, uint8_t, uint32_t, char *);
 struct	o9fid *o9fs_walk(struct o9fs *, struct o9fid *, struct o9fid *, char *);
+void	o9fs_clunk(struct o9fs *, struct o9fid *);
+struct	o9fsstat *o9fs_stat(struct o9fs *, struct o9fid *);
 
 /* o9fs_conv* */
 u_char	*pstring(u_char *, char *);
 		return n;
 
 	if (O9FS_GBIT8(fs->inbuf + Offtype) == O9FS_RERROR) {
-		printf("%.*s\n", O9FS_GBIT16(fs->inbuf + Minhd), fs->inbuf + Minhd + 4);
+		printf("%.*s\n", O9FS_GBIT16(fs->inbuf + Minhd), fs->inbuf + Minhd + 2);
 		return -1;
 	}
 
 {
 	struct o9fid *f;
 
-	if (fs->freefid == NULL) {
+	if (TAILQ_EMPTY(&fs->freeq)) {
 		f = (struct o9fid *) malloc(sizeof(struct o9fid), M_O9FS, M_WAITOK);
 		f->fid = fs->nextfid++;
 		TAILQ_INSERT_TAIL(&fs->activeq, f, next);
 		f = TAILQ_FIRST(&fs->freeq);
 		TAILQ_REMOVE(&fs->freeq, f, next);
 	}
-	
+
+	f->ref = 0;
 	f->offset = 0;
 	f->mode = -1;
 	f->qid.path = 0;
         return f;
 }
 
-void
-o9fs_putfid(struct o9fs *fs, struct o9fsfid *f)
-{        
-		DBG("putfid: enter\n");
-		if (f == NULL)
-			return;
-		f->next = fs->freefid;
-		fs->freefid = f;
-		DBG("putfid: return\n");
-}
-
-/* clone a fid, client-side */
-struct o9fsfid *
-o9fs_fidclone(struct o9fs *fs, struct o9fsfid *f)
-{
-	struct o9fsfid *nf;
-	DBG("o9fs_fidclone: enter\n");
-	if (f->opened)
-		panic("clone of open fid=%d\n", f->fid);
-	
-	nf = o9fs_getfid(fs);
-	nf->mode = f->mode;
-	nf->qid = f->qid;
-	nf->offset = f->offset;
-	DBG("o9fs_fidclone: return\n");
-	return nf;
-}
-
-/* clone a fid, server-side */
-struct o9fsfid *
-o9fs_clone(struct o9fs *fs, struct o9fsfid *f)
-{
-	return o9fs_twalk(fs, f, 0, 0);
-}
-
-/* guarantee the only copy of f */
-struct o9fsfid *
-o9fs_fidunique(struct o9fs *fs, struct o9fsfid *f)
-{
-	struct o9fsfid *nf;
-	nf = o9fs_clone(fs, f);
-	o9fs_fidclunk(fs, f);
-	f = nf;
-	return f;
-}
-
 char *
 putstring(char *buf, char *s)
 {
 	return buf + 2 + n;
 }
 
+char *
+getstring(char *buf)
+{
+	long n;
+	char *s;
+
+	if (buf == NULL)
+		panic("getstring was given a nul pointer");
+
+	n = O9FS_GBIT16(buf);
+	s = malloc(n + 1, M_O9FS, M_WAITOK);
+	memcpy(s, buf + 2, n);
+	s[n] = '\0';
+	return s;
+}	
+
 void
 o9fs_freestat(struct o9fsstat *s)
 {
 	p = NULL;
 }
 
-
-u_int
-o9fs_tokenize(char *res[], u_int reslen, char *str, char delim)
-{
-	char *s;
-	u_int i;
-	
-	i = 0;
-	s = str;
-
-	while (i < reslen && *s) {
-		while (*s == delim)
-			*(s++) = '\0';
-		if (*s)
-			res[i++] = s;
-		while (*s && *s != delim)
-			s++;
-	}
-	return i;
-}
-
 int
 o9fs_allocvp(struct mount *mp, struct o9fid *f, struct vnode **vpp, u_long flag)
 {
 	error = 0;
 	
 	/* Get a new vnode and associate it with our fid */
-	error = getnewvnode(VT_O9FS, mp, &o9fs_vops, &vp);
+	error = getnewvnode(VT_O9FS, mp, &o9fs_vops, vpp);
 	if (error) {
 		*vpp = NULL;
 		printf("error in getnewvnode %d\n", error);
 		DRET();
 		return error;
 	}
-
-	error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
-	if (error) {
-		vp->v_data = NULL;
-		vp = NULL;
-		*vpp = NULL;
-		printf("could not lock vnode, %d\n", error);
-		DRET();
-		return error;
-	}
+	vp = *vpp;
 
 	if (f->qid.type == O9FS_QTDIR)
 		vp->v_type = VDIR;
 		vp->v_type = VREG;
 
 	vp->v_data = f;
-	vp->v_flag = 0;
-	vp->v_flag |= flag;
-out:
-	*vpp = vp;
+	f->ref++;
+	vp->v_flag = flag;
+
 	DRET();
 	return error;
 }
 
-void
-o9fs_freevp(struct vnode *vp)
-{
-	vp->v_data = NULL;
-}
-
 int
 o9fs_ptoumode(int mode)
 {
 	umode = mode & (0777|O9FS_DMDIR);
 	if ((mode & O9FS_DMDIR) == O9FS_DMDIR)
 		umode |= S_IFDIR;
-
 	return umode;
 }
 
 }
 
 void
-printfidvp(struct o9fsfid *f)
+printvp(struct vnode *vp)
 {
-	if(!f)
+	struct o9fid *f;
+
+	if (vp == NULL || VTO92(vp) == NULL)
 		return;
-	printf("f=%p f->fid=%d ", f, f->fid);
+	f = VTO92(vp);
+	printf("[%p] %p fid %d ref %d qid (%.16llx %lu %d) mode %d\n", vp, f, f->fid, f->ref, f->qid.path, f->qid.vers, f->qid.type);
 }
-
-	
 
 	if (mounto9fs(mp, fp) != 0)
 		return EIO;
-	printf("after mounto9fs\n");
 
 	error = copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &len);
 	if (error)
 	if (error)
 		return error;
 	bzero(mp->mnt_stat.f_mntfromname + len, MNAMELEN - len);
-	printf("returning from mount ok\n");
 	return 0;
 }
 
 int
 o9fs_root(struct mount *mp, struct vnode **vpp)
 {
-	struct vnode *vp;
-	struct proc *p;
 	struct o9fid *f;
 	struct o9fs *fs;
 	int error;
 
 	DIN();
 
-	p = curproc;
 	fs = VFSTOO9FS(mp);
-
-	f = o9fs_walk(fs, VTO92(fs->vroot), NULL, NULL);
+/*	f = o9fs_walk(fs, VTO92(fs->vroot), NULL, NULL);
 	if (f == NULL) {
 		DRET();
 		return -1;
-	}
-	DBG("cloned root to %d\n", f->fid);
+	}  */
 
-	if (error = o9fs_allocvp(fs->mp, f, &vp, VROOT)) {
+    DBG("root fid qid.type %d\n", VTO92(fs->vroot)->qid.type);
+	error = o9fs_allocvp(mp, VTO92(fs->vroot), vpp, VROOT);
+	if (error) {
+		DBG("failed to alloc vnode\n");
 		DRET();
 		return error;
 	}
-	vp->v_data = f;
-	vp->v_flag = VROOT;
-	vp->v_type = VDIR;
-	*vpp = vp; 
+	vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curproc);
 
+	DBG("cloned root to vp %p\n", *vpp); 
 	DRET();
 	return 0;
 }
 	struct o9fid *f;
 	struct file *fp;
 	int error, flags;
-	
+	DIN();
+
 	flags = 0;
 	fs = VFSTOO9FS(mp);
 	fp = fs->servfp;
-
 	vp = fs->vroot;
 	f = VTO92(vp);
 
 	if (mntflags & MNT_FORCE)
 		flags |= FORCECLOSE;
 
-	error = vflush(mp, vp, flags);
-	if (error)
-		return error;
-
-	vput(vp);
-//	if (f)
-//		o9fs_fidclunk(fs, f);
 	fp->f_count--;
 	FRELE(fp);
-	free(fs->rpc, M_O9FS);
-	free(fs, M_MISCFSMNT);
+
+	error = vflush(mp, NULL, flags);
+	if (error) {
+		DBG("error in vflush %d\n", error);
+		DRET();
+		return error;
+	}
+
+/*	free(fs->rpc, M_O9FS);
+	free(fs->inbuf, M_O9FS);
+	free(fs->outbuf, M_O9FS);
+	free(fs, M_MISCFSMNT); */
 	fs = mp->mnt_data = (qaddr_t)0;
 	
+	DRET();
 	return 0;
 }
 
 	struct vnode *vp;
 	struct proc *p;
 	struct o9fs *fs;
-	struct o9fsfid *f;
+	struct o9fid *f;
 	int error, mode;
 
-	DBG("open: enter\n");
+	DIN();
 	ap = v;
 	vp = ap->a_vp;
 	p = ap->a_p;
 	mode = o9fs_uflags2omode(ap->a_mode);
 	fs = VFSTOO9FS(vp->v_mount);
-	f = VTO9(vp);
+	f = VTO92(vp);
 
-	if (f->opened == 1) {
-		DBG("open: already opened\n");
-		goto out;
+	if (o9fs_opencreate2(fs, f, O9FS_TOPEN, ap->a_mode, 0, 0) < 0) {
+		DBG("failed\n");
+		DRET();
+		return -1;
 	}
-	
-	f = o9fs_clone(fs, f);
-	if (f == NULL)
-		return -1;
-	
-	if(o9fs_opencreate(O9FS_TOPEN, fs, f, ap->a_mode, 0, 0))
-		return -1;
 
 	vp->v_data = f; /* walk has set other properties */
 
 		vp->v_type = VREG;
 
 out:
-	DBG("open: return (%p)->v_type=%d\n", vp, vp->v_type);
+	DRET();
 	return 0;
 }
 
 {
 	struct vop_close_args *ap;
 	struct vnode *vp;
-	struct o9fsfid *f;
+	struct o9fid *f;
 	struct o9fs *fs;
-	
-	DBG("close: enter\n");
+	DIN();
+
 	ap = v;
 	vp = ap->a_vp;
-	f = VTO9(vp);
+	f = VTO92(vp);
 
 	if (f == NULL) {
-		DBG("close: nil fid\n");
-		DBG("close: return\n");
+		DBG("nil fid\n");
+		DRET();
 		return 0;
 	}
 
-	DBG("close: fid=%d\n", f->fid);
 	fs = VFSTOO9FS(vp->v_mount);
-
-	o9fs_fidclunk(fs, f);
-	vp->v_data = NULL;
-	DBG("close: return\n");
+//	o9fs_clunk(fs, f);
+	DRET();
 	return 0;
 }
 
 		return -1;
 
 
-	f = o9fs_clone(fs, dirfid);
+//	f = o9fs_clone(fs, dirfid);
 	if (f == NULL)
 		goto out;
 
 
 	error = o9fs_allocvp(dvp->v_mount, f, vpp, 0);
 	if (error) {
-		o9fs_freevp(*vpp);
+		//o9fs_freevp(*vpp);
 		goto out;
 	}
 
 		(*vpp)->v_type = VDIR;
 	else
 		(*vpp)->v_type = VREG;
-	o9fs_fidclunk(fs, dirfid);
 out:
 	vput(dvp);
 	return error;
 	struct vnode **vpp, *dvp;
 	struct proc *p;
 	struct o9fs *fs;
-	struct o9fid *f, *parf;
+	struct o9fid *f, *parf, *nf;
 	int flags, op, islast, error;
 	long n;
 	char *path;
 	error = 0;
 	*vpp = NULL;
 
-	DBG("parent (%p) fid %d\n", parf, parf->fid);
-	
+	path = NULL;
 	if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
-		DBG("dot\n");
+	/*	DBG("dot\n");
 		vref(dvp);
 		*vpp = dvp;
 		DRET();
-		return 0;
+		return 0; */
+		nf = NULL;
+	} else {
+		path = malloc(cnp->cn_namelen, M_O9FS, M_WAITOK);
+		strlcpy(path, cnp->cn_nameptr, cnp->cn_namelen+1);
+		nf = o9fs_xgetfid(fs);
 	}
 
-	path = malloc(cnp->cn_namelen, M_O9FS, M_WAITOK);
-	strlcpy(path, cnp->cn_nameptr, cnp->cn_namelen+1);
-
-	/* todo: watch for fid leakage */
-	f = o9fs_walk(fs, parf, o9fs_xgetfid(fs), path);
+	/* todo: watch for fid and path leakage */
+	f = o9fs_walk(fs, parf, nf, path);
 	if (f == NULL) {
 		DBG("%s not found\n", cnp->cn_nameptr);
 		if (islast && (op == CREATE || op == RENAME)) {
 	error = o9fs_allocvp(fs->mp, f, vpp, 0);
 	if (error) {
 		*vpp = NULL;
+		DBG("could not alloc vnode\n");
 		DRET();
 		return ENOENT;
 	}
 	struct o9fid *f;
 	struct o9fsstat *stat;
 	struct o9fs *fs;
-
-	DBG("getattr: enter\n");
+	DIN();
 
 	ap = v;
 	vp = ap->a_vp;
 	f = VTO92(vp);
 	fs = VFSTOO9FS(vp->v_mount);
 
-	if (f == NULL)
+	if (f == NULL) {
+		DRET();
 		return 0;
+	}
 
-/*	stat = o9fs_fstat(fs, f);
+	stat = o9fs_stat(fs, f);
 	if (stat == NULL) {
-		DBG("getattr: Tstat failed\n");
-		DBG("getattr: return\n");
-		return -1;
+		DRET();
+		return 0;
 	}
-*/
-
+	
 	bzero(vap, sizeof(*vap));
 	vattr_null(vap);
 	vap->va_uid = 0;
 	vap->va_gid = 0;
 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
-	vap->va_size = 512; //stat->length;
+	vap->va_size = stat->length;
 	vap->va_blocksize = VFSTOO9FS(vp->v_mount)->msize;
-	vap->va_atime.tv_sec = 0; //stat->atime;
-	vap->va_mtime.tv_sec = 0; // stat->mtime;
-	vap->va_ctime.tv_sec = 0; //stat->atime;
+	vap->va_atime.tv_sec = stat->atime;
+	vap->va_mtime.tv_sec = stat->mtime;
+	vap->va_ctime.tv_sec = stat->atime;
 	vap->va_gen = 0;
 	vap->va_flags = 0;
 	vap->va_rdev = 0;
 	vap->va_bytes = 0;
-	if (vp->v_flag & VROOT) {
-		vap->va_type = VDIR;
-		vap->va_fileid = 2;
-	}
-
-	/*
-	 * vap->va_type being VDIR does not guarantee that user applications
-	 * will see us as a dir, we have to set the mode explicitly.
-	 */
 	vap->va_type = vp->v_type;
-	vap->va_mode = 0777; //o9fs_ptoumode(stat->mode);
-	if(vap->va_type == VDIR)
-		vap->va_mode |= S_IFDIR;
-
+	vap->va_mode = o9fs_ptoumode(stat->mode);
 	vap->va_nlink = 0;
-	vap->va_fileid = f->qid.path; /* path is bigger. truncate? */
+	vap->va_fileid = f->qid.path;	/* qid.path is 64bit, va_fileid 32bit */
 	vap->va_filerev = f->qid.vers;
 
-//	o9fs_freestat(stat);
-//	free(stat, M_O9FS);
-	DBG("getattr: return\n");
+	free(stat, M_O9FS);
+	DRET();
 	return 0;
 }
 
 o9fs_inactive(void *v)
 {
 	struct vop_inactive_args *ap;
+	struct o9fid *f;
 	DIN();
+
+	ap = v;
+	VOP_UNLOCK(ap->a_vp, 0, ap->a_p);
+	f = VTO92(ap->a_vp);
+	f->ref--;
+	printvp(ap->a_vp);
+
+	/* TODO: is this an appropriate approach? */
+	if (f->ref == 0)
+		o9fs_clunk(VFSTOO9FS(ap->a_vp->v_mount), f);
+	
 	DRET();
 	return 0;
 }
 {
 	struct vop_reclaim_args *ap;
 	struct vnode *vp;
-	struct o9fsfid *f;
-	struct o9fs *fs;
-
-	DBG("reclaim: enter\n");
+	DIN();
+	
 	ap = v;
 	vp = ap->a_vp;
-	f = VTO9(vp);
-	fs = VFSTOO9FS(vp->v_mount);
 
-	cache_purge(vp);
-	DBG("reclaiming fid %d\n", f->fid);
-	if(f)
-		o9fs_fidclunk(fs, f);
-	o9fs_freevp(vp);
-
-	DBG("reclaim: return\n");
+	DRET();
 	return 0;
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.