+
+/**
+ * v9fs_fid_clone - lookup the fid for a dentry, clone a private copy and release it
+ * @dentry: dentry to look for fid in
+ *
+ * find a fid in the dentry and then clone to a new private fid
+ *
+ * TODO: only match fids that have the same uid as current user
+ *
+ */
+
+struct v9fs_fid *v9fs_fid_clone(struct dentry *dentry)
+{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dentry->d_inode);
+ struct v9fs_fid *base_fid, *new_fid = ERR_PTR(-EBADF);
+ struct v9fs_fcall *fcall = NULL;
+ int fid, err;
+
+ base_fid = v9fs_fid_lookup(dentry);
+
+ if(IS_ERR(base_fid))
+ return base_fid;
+
+ if(base_fid) { /* clone fid */
+ fid = v9fs_get_idpool(&v9ses->fidpool);
+ if (fid < 0) {
+ eprintk(KERN_WARNING, "newfid fails!\n");
+ new_fid = ERR_PTR(-ENOSPC);
+ goto Release_Fid;
+ }
+
+ err = v9fs_t_walk(v9ses, base_fid->fid, fid, NULL, &fcall);
+ if (err < 0) {
+ dprintk(DEBUG_ERROR, "clone walk didn't work\n");
+ v9fs_put_idpool(fid, &v9ses->fidpool);
+ new_fid = ERR_PTR(err);
+ goto Free_Fcall;
+ }
+ new_fid = v9fs_fid_create(v9ses, fid);
+ if (new_fid == NULL) {
+ dprintk(DEBUG_ERROR, "out of memory\n");
+ new_fid = ERR_PTR(-ENOMEM);
+ }
+Free_Fcall:
+ kfree(fcall);
+ }
+
+Release_Fid:
+ up(&base_fid->lock);
+ return new_fid;
+}
+
+void v9fs_fid_clunk(struct v9fs_session_info *v9ses, struct v9fs_fid *fid)
+{
+ v9fs_t_clunk(v9ses, fid->fid);
+ v9fs_fid_destroy(fid);
+}