+ int err;
+ u32 fid, perm, iounit;
+ int flags;
+ struct v9fs_session_info *v9ses;
+ struct v9fs_fid *dfid, *vfid, *ffid;
+ struct inode *inode;
+ struct v9fs_qid qid;
+ struct file *filp;
+
+ inode = NULL;
+ vfid = NULL;
+ v9ses = v9fs_inode2v9ses(dir);
+ dfid = v9fs_fid_lookup(dentry->d_parent);
+ perm = unixmode2p9mode(v9ses, mode);
+
+ if (nd && nd->flags & LOOKUP_OPEN)
+ flags = nd->intent.open.flags - 1;
+ else
+ flags = O_RDWR;
+
+ err = v9fs_create(v9ses, dfid->fid, (char *) dentry->d_name.name,
+ perm, v9fs_uflags2omode(flags), NULL, &fid, &qid, &iounit);
+
+ if (err)
+ goto error;
+
+ vfid = v9fs_clone_walk(v9ses, dfid->fid, dentry);
+ if (IS_ERR(vfid)) {
+ err = PTR_ERR(vfid);
+ vfid = NULL;
+ goto error;
+ }
+
+ inode = v9fs_inode_from_fid(v9ses, vfid->fid, dir->i_sb);
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ inode = NULL;
+ goto error;
+ }
+
+ dentry->d_op = &v9fs_dentry_operations;
+ d_instantiate(dentry, inode);
+
+ if (nd && nd->flags & LOOKUP_OPEN) {
+ ffid = v9fs_fid_create(v9ses, fid);
+ if (!ffid)
+ return -ENOMEM;
+
+ filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created);
+ if (IS_ERR(filp)) {
+ v9fs_fid_destroy(ffid);
+ return PTR_ERR(filp);
+ }
+
+ ffid->rdir_pos = 0;
+ ffid->rdir_fcall = NULL;
+ ffid->fidopen = 1;
+ ffid->iounit = iounit;
+ ffid->filp = filp;
+ filp->private_data = ffid;
+ }
+
+ return 0;
+
+error:
+ if (vfid)
+ v9fs_fid_destroy(vfid);
+
+ if (inode)
+ iput(inode);
+
+ return err;