diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index 47db55a..d480554 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -57,26 +57,36 @@ void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid)
  * v9fs_fid_find - retrieve a fid that belongs to the specified uid
  * @dentry: dentry to look for fid in
  * @uid: return fid that belongs to the specified user
- * @any: if non-zero, return any fid associated with the dentry
+ * @flags: modifiers for fid lookup
  *
  */
-
-static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
+static struct p9_fid *
+v9fs_fid_find(struct dentry *dentry, kuid_t uid, int flags)
 {
 	struct p9_fid *fid, *ret;

-	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p) uid %d any %d\n",
+	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p) uid %d flags %d\n",
 		 dentry, dentry, from_kuid(&init_user_ns, uid),
-		 any);
+		 flags);
 	ret = NULL;
 	/* we'll recheck under lock if there's anything to look in */
 	if (dentry->d_fsdata) {
 		struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata;
 		spin_lock(&dentry->d_lock);
 		hlist_for_each_entry(fid, h, dlist) {
-			if (any || uid_eq(fid->uid, uid)) {
-				ret = fid;
-				break;
+			if ((flags & FID_ANY) || uid_eq(fid->uid, uid)) {
+				if (flags & FID_OPEN) {
+					p9_debug(P9_DEBUG_9P,
+					 " fid: %d fid->mode: %d\n", fid->fid,
+					 fid->mode);
+					if (fid->mode != -1) {
+						ret = fid;
+						break;
+					}
+				} else {
+					ret = fid;
+					break;
+				}
 			}
 		}
 		spin_unlock(&dentry->d_lock);
@@ -114,7 +124,7 @@ err_out:
 }

 static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
-					       kuid_t uid, int any)
+					       kuid_t uid, int flags)
 {
 	struct dentry *ds;
 	char **wnames, *uname;
@@ -124,9 +134,13 @@ static struct p9_fid
*v9fs_fid_lookup_with_uid(struct dentry *dentry,

 	v9ses = v9fs_dentry2v9ses(dentry);
 	access = v9ses->flags & V9FS_ACCESS_MASK;
-	fid = v9fs_fid_find(dentry, uid, any);
+	fid = v9fs_fid_find(dentry, uid, flags);
 	if (fid)
 		return fid;
+
+	if (flags & FID_OPEN)
+		return ERR_PTR(-ENOENT);
+
 	/*
 	 * we don't have a matching fid. To do a TWALK we need
 	 * parent fid. We need to prevent rename when we want to
@@ -134,7 +148,7 @@ static struct p9_fid
*v9fs_fid_lookup_with_uid(struct dentry *dentry,
 	 */
 	down_read(&v9ses->rename_sem);
 	ds = dentry->d_parent;
-	fid = v9fs_fid_find(ds, uid, any);
+	fid = v9fs_fid_find(ds, uid, flags);
 	if (fid) {
 		/* Found the parent fid do a lookup with that */
 		fid = p9_client_walk(fid, 1, (char **)&dentry->d_name.name, 1);
@@ -143,7 +157,7 @@ static struct p9_fid
*v9fs_fid_lookup_with_uid(struct dentry *dentry,
 	up_read(&v9ses->rename_sem);

 	/* start from the root and try to do a lookup */
-	fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any);
+	fid = v9fs_fid_find(dentry->d_sb->s_root, uid, flags);
 	if (!fid) {
 		/* the user is not attached to the fs yet */
 		if (access == V9FS_ACCESS_SINGLE)
@@ -227,11 +241,26 @@ err_out:
  * dentry (if it has one), or the root dentry. If the user haven't accessed
  * the fs yet, attach now and walk from the root.
  */
-
 struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 {
+	return v9fs_fid_lookup_flags(dentry, 0);
+}
+
+/**
+ * v9fs_fid_lookup_flags - lookup for a fid w/flags, try to walk if not found
+ * @dentry: dentry to look for fid in
+ * @flags: potential flags
+ *   FID_OPEN: favor open fids
+ *
+ * Look for a fid in the specified dentry for the current user.
+ * If no fid is found, try to create one walking from a fid from the parent
+ * dentry (if it has one), or the root dentry. If the user haven't accessed
+ * the fs yet, attach now and walk from the root.
+ */
+struct p9_fid *v9fs_fid_lookup_flags(struct dentry *dentry, int flags)
+{
 	kuid_t uid;
-	int  any, access;
+	int access;
 	struct v9fs_session_info *v9ses;

 	v9ses = v9fs_dentry2v9ses(dentry);
@@ -241,20 +270,18 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
 	case V9FS_ACCESS_USER:
 	case V9FS_ACCESS_CLIENT:
 		uid = current_fsuid();
-		any = 0;
 		break;

 	case V9FS_ACCESS_ANY:
 		uid = v9ses->uid;
-		any = 1;
+		flags |= FID_ANY;
 		break;

 	default:
 		uid = INVALID_UID;
-		any = 0;
 		break;
 	}
-	return v9fs_fid_lookup_with_uid(dentry, uid, any);
+	return v9fs_fid_lookup_with_uid(dentry, uid, flags);
 }

 struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index 2b6787f..e631c0f 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -23,7 +23,14 @@
 #define FS_9P_FID_H
 #include <linux/list.h>

+enum p9_fid_flags {
+	FID_NONE	= 0x0,
+	FID_ANY		= 0x1,
+	FID_OPEN	= 0x2,
+};
+
 struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
+struct p9_fid *v9fs_fid_lookup_flags(struct dentry *dentry, int flags);
 struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
 void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
 struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index a345b2d..577815b 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -69,8 +69,12 @@ static void v9fs_dentry_release(struct dentry *dentry)
 	struct hlist_node *p, *n;
 	p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
 		 dentry, dentry);
-	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
-		p9_client_clunk(hlist_entry(p, struct p9_fid, dlist));
+	hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) {
+		struct p9_fid *fid = hlist_entry(p, struct p9_fid, dlist);
+		/* only clunk unopen fids when cleaning up dentry */
+		if (fid->mode == -1)
+			p9_client_clunk(fid);
+	}
 	dentry->d_fsdata = NULL;
 }

diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 6054c16b..2f17675 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -308,6 +308,9 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir,
struct dentry *dentry,
 	}
 	v9fs_invalidate_inode_attr(dir);

+	/* add the open FID to the dentry */
+	v9fs_fid_add(dentry, ofid);
+
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
