Commits

iru  committed e23d6c0

VOP_CREATE

  • Participants
  • Parent commits a88222a

Comments (0)

Files changed (3)

 	O9FS_PBIT8(p + Offtype, type);
 	O9FS_PBIT16(p + Offtag, 0);
 	O9FS_PBIT32(p + Minhd, fid->fid);
+	p += Minhd + 4;
+
+	if (type == O9FS_TCREATE) {
+		if (name == NULL) {
+			DRET();
+			return -1;
+		}
+		p = putstring(p, name);
+		O9FS_PBIT32(p, perm);
+		p += 4;
+	}
 	omode = o9fs_uflags2omode(mode);
-	O9FS_PBIT8(p + Minhd + 4, omode);
-	
-	n = Minhd + 4 + 1;
+	O9FS_PBIT8(p, omode);
+	n = p + 1 - fs->outbuf;
+
 	O9FS_PBIT32(fs->outbuf, n);
 	n = o9fs_mio(fs, n);
 	if (n <= 0) {
 	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;
-	struct o9fsfcall tx, rx;
-	
-	omode = o9fs_uflags2omode(mode);
-
-	tx.type = type;
-	tx.fid = f->fid;
-	tx.mode = omode;
-	if (type == O9FS_TCREATE) {
-		tx.name = name;
-		tx.mode = O9FS_ORDWR; /* try ORDWR on open */
-		tx.perm = o9fs_utopmode(perm);
-	}
-
-	error = o9fs_rpc(fs, &tx, &rx);
-	if (error)
-		return error;
-
-	f->qid = rx.qid;
-	f->offset = 0;
-	f->opened = 1;
-	f->mode = omode;
-	return 0;
-}
-
 o9fs_allocvp(struct mount *mp, struct o9fid *f, struct vnode **vpp, u_long flag)
 {
 	struct vnode *vp;
-	struct proc *p;
 	int error;
-
 	DIN();
 
-	p = curproc;
-	error = 0;
-	
 	error = getnewvnode(VT_O9FS, mp, &o9fs_vops, vpp);
 	if (error) {
 		*vpp = NULL;
 	vp->v_flag = flag;
 	printvp(vp);
 	DRET();
-	return error;
+	return 0;
 }
 
 int

File o9fs_vnops.c

 	.vop_bmap = eopnotsupp,
 	.vop_bwrite = eopnotsupp,
 	.vop_close = o9fs_close,
-	.vop_create = eopnotsupp,
+	.vop_create = o9fs_create,
 	.vop_fsync = nullop,
 	.vop_getattr = o9fs_getattr,
 	.vop_inactive = o9fs_inactive,
 	struct proc *p;
 	struct o9fs *fs;
 	struct o9fid *f, *nf;
-	int error, mode;
+	DIN();
 
-	DIN();
 	ap = v;
 	vp = ap->a_vp;
 	p = ap->a_p;
-	mode = o9fs_uflags2omode(ap->a_mode);
 	fs = VFSTOO9FS(vp->v_mount);
 	f = VTO92(vp);
 
 	struct vnode *dvp, **vpp;
 	struct componentname *cnp;
 	struct vattr *vap;
-	struct o9fsfid *f, *dirfid;
+	struct o9fid *f, *nf;
 	struct o9fs *fs;
 	int error;
-	
+	DIN();
+
 	ap = v;
 	dvp = ap->a_dvp;
 	cnp = ap->a_cnp;
 	vap = ap->a_vap;
 	vpp = ap->a_vpp;
-	dirfid = VTO9(dvp);
 
+	f = VTO92(dvp);
 	*vpp = NULL;
+
 	fs = VFSTOO9FS(dvp->v_mount);
-	if (f == NULL)
+	if (f == NULL) {
+		DRET();
 		return -1;
-
-
-//	f = o9fs_clone(fs, dirfid);
-	if (f == NULL)
-		goto out;
-
-	if(o9fs_opencreate(O9FS_TCREATE, fs, f, 0, vap->va_mode, cnp->cn_nameptr))
-		goto out;
-
-	error = o9fs_allocvp(dvp->v_mount, f, vpp, 0);
-	if (error) {
-		//o9fs_freevp(*vpp);
-		goto out;
 	}
 
-	if(f->qid.type == O9FS_QTDIR)
-		(*vpp)->v_type = VDIR;
-	else
-		(*vpp)->v_type = VREG;
-out:
+	/* BUG: old fid leakage */
+	nf = o9fs_walk(fs, f, NULL, NULL);
+	if (nf == NULL) {
+		o9fs_xputfid(fs, nf);
+		DRET();
+		return -1;
+	}
+
+	if (o9fs_opencreate2(fs, nf, O9FS_TCREATE, 0, vap->va_mode, cnp->cn_nameptr) < 0) {
+		o9fs_xputfid(fs, nf);
+		DRET();
+		return -1;
+	}
+	o9fs_clunk(fs, nf);
+	o9fs_xputfid(fs, nf);
+
+	/* walk from parent dir to get an unopened fid, break create+open atomicity of 9P */
+	nf = o9fs_walk(fs, f, NULL, cnp->cn_nameptr);
+	if (nf == NULL) {
+		o9fs_xputfid(fs, nf);
+		DRET();
+		return -1;
+	}
+	
+	error = o9fs_allocvp(dvp->v_mount, nf, vpp, 0);
 	vput(dvp);
+	DRET();
 	return error;
 }
 
 	parf = VTO92(dvp);			/* parent fid */
 	error = 0;
 	*vpp = NULL;
-
 	path = NULL;
 
 	if (parf->mode != -1) {