Anonymous avatar Anonymous committed 7f7d716

Implement function for 9p read/write.
Iounit
Fix msize
Fix open
Fix readdir

Comments (0)

Files changed (6)

  * When ref drops to zero, the o9fid is clunked.
  */
 struct o9fid {
-	int		fid;
-	int		mode;			/* open mode */
-	int		ref;			
-	struct	o9fsqid	qid;
-	int64_t	offset;
+	int32_t		fid;
+	int8_t		mode;			/* open mode */
+	uint32_t	iounit;
+	struct		o9fsqid	qid;
+	uint64_t	offset;
+
+	int			ref;
 	TAILQ_ENTRY(o9fid) next;
 };
 
 	O9FS_PBIT32(p + Minhd, fid->fid);
 
 	if (newfid == NULL) {
-		printf("cloning fid %d\n", fid->fid);
+		DBG("cloning fid %d\n", fid->fid);
 		newfid = o9fs_xgetfid(fs);
 		newfid->mode = fid->mode;
 		newfid->qid = fid->qid;
 	nwqid = O9FS_GBIT16(fs->inbuf + Minhd);
 	if (nwqid < nwname) {
 		printf("nwqid < nwname\n");
+		DRET();
 		return NULL;
 	}
 
 	return nr;
 }
 
+uint32_t
+o9fs_rdwr2(struct o9fs *fs, struct o9fid *f, uint8_t type, uint32_t len, uint64_t off)
+{
+	u_char *p;
+	long n;
+	DIN();
+
+	if (f == NULL) {
+		DRET();
+		return -1;
+	}
+
+	p = fs->outbuf;
+	O9FS_PBIT8(p + Offtype, type);
+	O9FS_PBIT16(p + Offtag, 0);
+	O9FS_PBIT32(p + Minhd, f->fid);
+	O9FS_PBIT64(p + Minhd + 4, off);
+	if (f->iounit > 0 && len > f->iounit)
+		len = f->iounit;
+	if (len > fs->msize)
+		len = fs->msize - O9FS_IOHDRSZ;
+	O9FS_PBIT32(p + Minhd + 4 + 8, len);
+	p += Minhd + 4 + 8 + 4;
+
+	n = p - fs->outbuf;
+	O9FS_PBIT32(fs->outbuf, n);
+	n = o9fs_mio(fs, n);
+	if (n <= 0) {
+		DRET();
+		return -1;
+	}
+
+	n = O9FS_GBIT32(fs->inbuf + Minhd);
+	DBG("read %ld bytes\n", n);
+	DRET();
+	return n;
+}
+	
 int
 o9fs_opencreate2(struct o9fs *fs, struct o9fid *fid, uint8_t type, uint8_t mode, uint32_t perm, char *name)
 {
 	fid->qid.type = O9FS_GBIT8(fs->inbuf + Minhd);
 	fid->qid.vers = O9FS_GBIT32(fs->inbuf + Minhd + 1);
 	fid->qid.path = O9FS_GBIT64(fs->inbuf + Minhd + 1 + 4);
+	fid->iounit = O9FS_GBIT32(fs->inbuf + Minhd + 1 + 4 + 8);
 	fid->mode = omode;
 	return 0;
 }
 char	*putstring(char *, char *);
 char	*getstring(char *);
 int		o9fs_allocvp(struct mount *, struct o9fid *, struct vnode **, u_long);
-struct	o9fsfid *o9fs_getfid(struct o9fs *);
 struct	o9fid *o9fs_xgetfid(struct o9fs *);
 void	o9fs_xputfid(struct o9fs *, struct o9fid *);
-void	o9fs_putfid(struct o9fs *, struct o9fsfid *);
 int		o9fs_ptoumode(int);
 int		o9fs_utopmode(int);
 int		o9fs_uflags2omode(int);
 void	o9fs_freefcall(struct o9fsfcall *);
 void	o9fs_freestat(struct o9fsstat *);
+void	*o9fsrealloc(void *, size_t, size_t);
 void	_printvp(struct vnode *);
 
 /* o9fs_9p.c */
 struct	o9fsstat *o9fs_fstat(struct o9fs *, struct o9fsfid *);
 long	o9fs_rdwr(struct o9fs *, int, struct o9fsfid *, void *, u_long, int64_t);
+uint32_t	o9fs_rdwr2(struct o9fs *, struct o9fid *, uint8_t, uint32_t, uint64_t);
 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 *);
 	f->ref = 0;
 	f->offset = 0;
 	f->mode = -1;
+	f->iounit = 0;
 	f->qid.path = 0;
 	f->qid.vers = 0;
 	f->qid.type = 0;
 	TAILQ_INSERT_TAIL(&fs->freeq, f, next);
 }
 
-struct o9fsfid *
-o9fs_getfid(struct o9fs *fs)
-{
-        struct o9fsfid *f;
-        int i;
-        
-        if (fs->freefid == NULL) {
-				f = (struct o9fsfid *) malloc(sizeof(struct o9fsfid) * Chunk,
-                	M_O9FS, M_WAITOK);
-				for (i = 0; i < Chunk; i++) {
-						f[i].fid = fs->nextfid++;
-						f[i].next = &f[i+1];
-						f[i].opened = 0;
-               			 }
-				f[i-1].next = NULL;
-				fs->freefid = f;
-        }
-        f = fs->freefid;
-        fs->freefid = f->next;
-        f->offset = 0;
-        f->mode = -1;
-	//	f->ref = 0;
-        f->qid.path = 0;
-        f->qid.vers = 0;
-        f->qid.type = 0;
-        return f;
-}
-
 char *
 putstring(char *buf, char *s)
 {
 	p = curproc;
 	error = 0;
 	
-	/* Get a new vnode and associate it with our fid */
 	error = getnewvnode(VT_O9FS, mp, &o9fs_vops, vpp);
 	if (error) {
 		*vpp = NULL;
 	return omode;
 }
 
+void *
+o9fsrealloc(void *ptr, size_t oldsize, size_t newsize)
+{
+	void *p;
+	
+	if (newsize == oldsize)
+		return ptr;
+	p = malloc(newsize, M_O9FS, M_WAITOK);
+	if (ptr)
+		bcopy(ptr, p, oldsize);
+	ptr = p;
+	return p;
+}
+
 void
 _printvp(struct vnode *vp)
 {
 	if (vp == NULL || VTO92(vp) == NULL)
 		return;
 	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, mode);
+	printf("[%p] %p fid %d ref %d qid (%.16llx %lu %d) mode %d iounit %ld\n", vp, f, f->fid, f->ref, f->qid.path, f->qid.vers, f->qid.type, f->mode, f->iounit);
 }
 	n = o9fs_mio(fs, 19);
 	if (n <= 0)
 		return -1;
-	return fs->msize = O9FS_GBIT16(fs->inbuf + Minhd + 4);
+	return fs->msize = O9FS_GBIT16(fs->inbuf + Minhd);
 }	
 
 struct o9fid *
 	TAILQ_INIT(&fs->freeq);
 	fs->nextfid = 0;	
 
-	if(o9fs_version(fs, 8192) < 0)
+	if(o9fs_version(fs, 8192+O9FS_IOHDRSZ) < 0)
 		return EIO;
 
 	fid = o9fs_attach(fs, o9fs_auth(fs, "none", ""), "iru", "");
 	Debug = 1,
 };
 
-static void *o9fsrealloc(void *, size_t, size_t);
-
 int o9fs_open(void *);
 int o9fs_close(void *);
 int o9fs_lookup(void *);
 	struct vnode *vp;
 	struct proc *p;
 	struct o9fs *fs;
-	struct o9fid *f;
+	struct o9fid *f, *nf;
 	int error, mode;
 
 	DIN();
 	f = VTO92(vp);
 
 	printvp(vp);
-	if (o9fs_opencreate2(fs, f, O9FS_TOPEN, ap->a_mode, 0, 0) < 0) {
-		DBG("failed\n");
+
+	/* BUG: old fid leakage */
+	nf = o9fs_walk(fs, f, NULL, NULL);
+	if (nf == NULL) {
+		DRET();
+		return -1;
+	}
+	free(f, M_O9FS);
+
+	if (o9fs_opencreate2(fs, nf, O9FS_TOPEN, ap->a_mode, 0, 0) < 0) {
 		DRET();
 		return -1;
 	}
 
-	vp->v_data = f; /* walk has set other properties */
-
-	if(f->qid.type == O9FS_QTDIR)
-		vp->v_type = VDIR;
-	else
-		vp->v_type = VREG;
+	vp->v_data = nf; /* walk has set other properties */
 
 out:
 	DRET();
 	f = VTO92(vp);
 
 	if (f == NULL) {
-		DBG("nil fid\n");
 		DRET();
 		return 0;
 	}
 	struct vop_readdir_args *ap;
 	struct vnode *vp;
 	struct uio *uio;
-	struct o9fsfid *f;
+	struct o9fid *f;
 	struct o9fs *fs;
 	struct o9fsstat *stat;
 	struct dirent d;
 	u_char *buf, *nbuf;
 	long n, ts;
-	int error, *eofflag, i, msize;
+	int error, i;
 	int64_t len;
 	DIN();
 
 	ap = v;
 	vp = ap->a_vp;
 	uio = ap->a_uio;
-	eofflag = ap->a_eofflag;
 	fs = VFSTOO9FS(vp->v_mount);
 	f = VTO92(vp);
-	error = i = n = 0;
+	error = 0;
+
+	if (vp->v_type != VDIR) {
+		DRET();
+		return ENOTDIR;
+	}
 
 	if (uio->uio_resid == 0) {
 		DRET();
 	}
 
 	len = uio->uio_resid;
-	msize = fs->msize - O9FS_IOHDRSZ;
-	if (len > msize)
-		len = msize;
+	ts = n = 0;
+	buf = malloc(O9FS_DIRMAX, M_O9FS, M_WAITOK);
 
-	buf = malloc(O9FS_DIRMAX, M_O9FS, M_WAITOK);
-	ts = n = 0;
 	for (;;) {
 		nbuf = o9fsrealloc(buf, ts+O9FS_DIRMAX-n, ts+O9FS_DIRMAX);
 		buf = nbuf;
-		n = o9fs_rdwr(fs, O9FS_TREAD, f, buf+ts, 1024, -1);
+		n = o9fs_rdwr2(fs, f, O9FS_TREAD, len, f->offset);
 		if (n <= 0)
 			break;
+		memcpy(buf + ts, fs->inbuf + Minhd + 4, n);
+		f->offset += n;
 		ts += n;
+		len -= n;
 	}
+
 	if (ts >= 0) {
 		ts = dirpackage(buf, ts, &stat);
 		if (ts < 0)
 		DRET();
 		return -1;
 	}
+
 	for (i = 0; i < ts; i++) {
 		d.d_fileno = (uint32_t)stat[i].qid.path;
 		d.d_type = vp->v_type == VDIR ? DT_DIR : DT_REG;
 		error = uiomove(&d, d.d_reclen, uio);
 		if (error) {
 			DBG("uiomove error\n");
-			DRET():
+			DRET();
 			return -1;
 		}
 	}
 	*vpp = NULL;
 
 	path = NULL;
+	DBG("name %s\n", cnp->cn_nameptr);
 	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);
 		nf = o9fs_xgetfid(fs);
 	}
 
-	/* todo: watch for fid and path leakage */
+	/* BUG: fid and path leakage */
 	f = o9fs_walk(fs, parf, nf, path);
 	if (f == NULL) {
 		DBG("%s not found\n", cnp->cn_nameptr);
 		flags |= PDIRUNLOCK;
 	}
 	
+	if(f->qid.type == O9FS_QTDIR)
+		(*vpp)->v_type = VDIR;
+	else
+		(*vpp)->v_type = VREG;
+	printvp(*vpp);
+
 	DRET();
 	return 0;
 }
  	struct vop_setattr_args *ap;
 	ap = v;
 
-	/*
-	 * Can't mess with the root vnode
-	 */
-
 	if (ap->a_vp->v_flag & VROOT)
 		return EACCES;
 
 	return 0;
 }
 
-static void *
-o9fsrealloc(void *ptr, size_t oldsize, size_t newsize)
-{
-	void *p;
-	
-	if (newsize == oldsize)
-		return ptr;
-	p = malloc(newsize, M_O9FS, M_WAITOK);
-	if (ptr)
-		bcopy(ptr, p, oldsize);
-	ptr = p;
-	return p;
-}
-
 int
 o9fs_inactive(void *v)
 {
 	return 0;
 }
 
-/* this should suffice for now */
 int
 o9fs_reclaim(void *v)
 {
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.