Commit ea0c3926 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '9p-for-5.20' of https://github.com/martinetd/linux

Pull 9p updates from Dominique Martinet:

 - a couple of fixes

 - add a tracepoint for fid refcounting

 - some cleanup/followup on fid lookup

 - some cleanup around req refcounting

* tag '9p-for-5.20' of https://github.com/martinetd/linux:
  net/9p: Initialize the iounit field during fid creation
  net: 9p: fix refcount leak in p9_read_work() error handling
  9p: roll p9_tag_remove into p9_req_put
  9p: Add client parameter to p9_req_put()
  9p: Drop kref usage
  9p: Fix some kernel-doc comments
  9p fid refcount: cleanup p9_fid_put calls
  9p fid refcount: add a 9p_fid_ref tracepoint
  9p fid refcount: add p9_fid_get/put wrappers
  9p: Fix minor typo in code comment
  9p: Remove unnecessary variable for old fids while walking from d_parent
  9p: Make the path walk logic more clear about when cloning is required
  9p: Track the root fid with its own variable during lookups
parents c42b729e aa7aeee1
...@@ -28,14 +28,18 @@ static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid) ...@@ -28,14 +28,18 @@ static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid)
/** /**
* v9fs_fid_add - add a fid to a dentry * v9fs_fid_add - add a fid to a dentry
* @dentry: dentry that the fid is being added to * @dentry: dentry that the fid is being added to
* @fid: fid to add * @pfid: fid to add, NULLed out
* *
*/ */
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) void v9fs_fid_add(struct dentry *dentry, struct p9_fid **pfid)
{ {
struct p9_fid *fid = *pfid;
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
__add_fid(dentry, fid); __add_fid(dentry, fid);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
*pfid = NULL;
} }
/** /**
...@@ -56,7 +60,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid) ...@@ -56,7 +60,7 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
h = (struct hlist_head *)&inode->i_private; h = (struct hlist_head *)&inode->i_private;
hlist_for_each_entry(fid, h, ilist) { hlist_for_each_entry(fid, h, ilist) {
if (uid_eq(fid->uid, uid)) { if (uid_eq(fid->uid, uid)) {
refcount_inc(&fid->count); p9_fid_get(fid);
ret = fid; ret = fid;
break; break;
} }
...@@ -68,15 +72,19 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid) ...@@ -68,15 +72,19 @@ static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid)
/** /**
* v9fs_open_fid_add - add an open fid to an inode * v9fs_open_fid_add - add an open fid to an inode
* @inode: inode that the fid is being added to * @inode: inode that the fid is being added to
* @fid: fid to add * @pfid: fid to add, NULLed out
* *
*/ */
void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid) void v9fs_open_fid_add(struct inode *inode, struct p9_fid **pfid)
{ {
struct p9_fid *fid = *pfid;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
hlist_add_head(&fid->ilist, (struct hlist_head *)&inode->i_private); hlist_add_head(&fid->ilist, (struct hlist_head *)&inode->i_private);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
*pfid = NULL;
} }
...@@ -104,7 +112,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) ...@@ -104,7 +112,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any)
hlist_for_each_entry(fid, h, dlist) { hlist_for_each_entry(fid, h, dlist) {
if (any || uid_eq(fid->uid, uid)) { if (any || uid_eq(fid->uid, uid)) {
ret = fid; ret = fid;
refcount_inc(&ret->count); p9_fid_get(ret);
break; break;
} }
} }
...@@ -150,9 +158,9 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -150,9 +158,9 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
{ {
struct dentry *ds; struct dentry *ds;
const unsigned char **wnames, *uname; const unsigned char **wnames, *uname;
int i, n, l, clone, access; int i, n, l, access;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *fid, *old_fid; struct p9_fid *fid, *root_fid, *old_fid;
v9ses = v9fs_dentry2v9ses(dentry); v9ses = v9fs_dentry2v9ses(dentry);
access = v9ses->flags & V9FS_ACCESS_MASK; access = v9ses->flags & V9FS_ACCESS_MASK;
...@@ -169,17 +177,17 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -169,17 +177,17 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
fid = v9fs_fid_find(ds, uid, any); fid = v9fs_fid_find(ds, uid, any);
if (fid) { if (fid) {
/* Found the parent fid do a lookup with that */ /* Found the parent fid do a lookup with that */
struct p9_fid *ofid = fid; old_fid = fid;
fid = p9_client_walk(ofid, 1, &dentry->d_name.name, 1); fid = p9_client_walk(old_fid, 1, &dentry->d_name.name, 1);
p9_client_clunk(ofid); p9_fid_put(old_fid);
goto fid_out; goto fid_out;
} }
up_read(&v9ses->rename_sem); up_read(&v9ses->rename_sem);
/* start from the root and try to do a lookup */ /* start from the root and try to do a lookup */
fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any); root_fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any);
if (!fid) { if (!root_fid) {
/* the user is not attached to the fs yet */ /* the user is not attached to the fs yet */
if (access == V9FS_ACCESS_SINGLE) if (access == V9FS_ACCESS_SINGLE)
return ERR_PTR(-EPERM); return ERR_PTR(-EPERM);
...@@ -194,12 +202,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -194,12 +202,13 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
if (IS_ERR(fid)) if (IS_ERR(fid))
return fid; return fid;
refcount_inc(&fid->count); root_fid = p9_fid_get(fid);
v9fs_fid_add(dentry->d_sb->s_root, fid); v9fs_fid_add(dentry->d_sb->s_root, &fid);
} }
/* If we are root ourself just return that */ /* If we are root ourself just return that */
if (dentry->d_sb->s_root == dentry) if (dentry->d_sb->s_root == dentry)
return fid; return root_fid;
/* /*
* Do a multipath walk with attached root. * Do a multipath walk with attached root.
* When walking parent we need to make sure we * When walking parent we need to make sure we
...@@ -211,19 +220,20 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -211,19 +220,20 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
fid = ERR_PTR(n); fid = ERR_PTR(n);
goto err_out; goto err_out;
} }
old_fid = fid; fid = root_fid;
clone = 1; old_fid = root_fid;
i = 0; i = 0;
while (i < n) { while (i < n) {
l = min(n - i, P9_MAXWELEM); l = min(n - i, P9_MAXWELEM);
/* /*
* We need to hold rename lock when doing a multipath * We need to hold rename lock when doing a multipath
* walk to ensure none of the patch component change * walk to ensure none of the path components change
*/ */
fid = p9_client_walk(fid, l, &wnames[i], clone); fid = p9_client_walk(old_fid, l, &wnames[i],
old_fid == root_fid /* clone */);
/* non-cloning walk will return the same fid */ /* non-cloning walk will return the same fid */
if (fid != old_fid) { if (fid != old_fid) {
p9_client_clunk(old_fid); p9_fid_put(old_fid);
old_fid = fid; old_fid = fid;
} }
if (IS_ERR(fid)) { if (IS_ERR(fid)) {
...@@ -231,7 +241,6 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -231,7 +241,6 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
goto err_out; goto err_out;
} }
i += l; i += l;
clone = 0;
} }
kfree(wnames); kfree(wnames);
fid_out: fid_out:
...@@ -239,11 +248,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, ...@@ -239,11 +248,11 @@ static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
spin_lock(&dentry->d_lock); spin_lock(&dentry->d_lock);
if (d_unhashed(dentry)) { if (d_unhashed(dentry)) {
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
p9_client_clunk(fid); p9_fid_put(fid);
fid = ERR_PTR(-ENOENT); fid = ERR_PTR(-ENOENT);
} else { } else {
__add_fid(dentry, fid); __add_fid(dentry, fid);
refcount_inc(&fid->count); p9_fid_get(fid);
spin_unlock(&dentry->d_lock); spin_unlock(&dentry->d_lock);
} }
} }
...@@ -300,7 +309,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) ...@@ -300,7 +309,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
fid = clone_fid(ofid); fid = clone_fid(ofid);
if (IS_ERR(fid)) if (IS_ERR(fid))
goto error_out; goto error_out;
p9_client_clunk(ofid); p9_fid_put(ofid);
/* /*
* writeback fid will only be used to write back the * writeback fid will only be used to write back the
* dirty pages. We always request for the open fid in read-write * dirty pages. We always request for the open fid in read-write
...@@ -309,7 +318,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) ...@@ -309,7 +318,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
*/ */
err = p9_client_open(fid, O_RDWR); err = p9_client_open(fid, O_RDWR);
if (err < 0) { if (err < 0) {
p9_client_clunk(fid); p9_fid_put(fid);
fid = ERR_PTR(err); fid = ERR_PTR(err);
goto error_out; goto error_out;
} }
......
...@@ -13,9 +13,9 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry) ...@@ -13,9 +13,9 @@ static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry)
{ {
return v9fs_fid_lookup(dentry->d_parent); return v9fs_fid_lookup(dentry->d_parent);
} }
void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); void v9fs_fid_add(struct dentry *dentry, struct p9_fid **fid);
struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
void v9fs_open_fid_add(struct inode *inode, struct p9_fid *fid); void v9fs_open_fid_add(struct inode *inode, struct p9_fid **fid);
static inline struct p9_fid *clone_fid(struct p9_fid *fid) static inline struct p9_fid *clone_fid(struct p9_fid *fid)
{ {
return IS_ERR(fid) ? fid : p9_client_walk(fid, 0, NULL, 1); return IS_ERR(fid) ? fid : p9_client_walk(fid, 0, NULL, 1);
...@@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry) ...@@ -29,7 +29,7 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
return fid; return fid;
nfid = clone_fid(fid); nfid = clone_fid(fid);
p9_client_clunk(fid); p9_fid_put(fid);
return nfid; return nfid;
} }
#endif #endif
...@@ -73,7 +73,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) ...@@ -73,7 +73,7 @@ static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file)
BUG_ON(!fid); BUG_ON(!fid);
} }
refcount_inc(&fid->count); p9_fid_get(fid);
rreq->netfs_priv = fid; rreq->netfs_priv = fid;
return 0; return 0;
} }
...@@ -86,7 +86,7 @@ static void v9fs_free_request(struct netfs_io_request *rreq) ...@@ -86,7 +86,7 @@ static void v9fs_free_request(struct netfs_io_request *rreq)
{ {
struct p9_fid *fid = rreq->netfs_priv; struct p9_fid *fid = rreq->netfs_priv;
p9_client_clunk(fid); p9_fid_put(fid);
} }
/** /**
......
...@@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry) ...@@ -54,7 +54,7 @@ static void v9fs_dentry_release(struct dentry *dentry)
p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n",
dentry, dentry); dentry, dentry);
hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata)
p9_client_clunk(hlist_entry(p, struct p9_fid, dlist)); p9_fid_put(hlist_entry(p, struct p9_fid, dlist));
dentry->d_fsdata = NULL; dentry->d_fsdata = NULL;
} }
...@@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) ...@@ -85,7 +85,7 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
retval = v9fs_refresh_inode_dotl(fid, inode); retval = v9fs_refresh_inode_dotl(fid, inode);
else else
retval = v9fs_refresh_inode(fid, inode); retval = v9fs_refresh_inode(fid, inode);
p9_client_clunk(fid); p9_fid_put(fid);
if (retval == -ENOENT) if (retval == -ENOENT)
return 0; return 0;
......
...@@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) ...@@ -218,7 +218,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
hlist_del(&fid->ilist); hlist_del(&fid->ilist);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
p9_client_clunk(fid); p9_fid_put(fid);
} }
if ((filp->f_mode & FMODE_WRITE)) { if ((filp->f_mode & FMODE_WRITE)) {
......
...@@ -63,15 +63,16 @@ int v9fs_file_open(struct inode *inode, struct file *file) ...@@ -63,15 +63,16 @@ int v9fs_file_open(struct inode *inode, struct file *file)
err = p9_client_open(fid, omode); err = p9_client_open(fid, omode);
if (err < 0) { if (err < 0) {
p9_client_clunk(fid); p9_fid_put(fid);
return err; return err;
} }
if ((file->f_flags & O_APPEND) && if ((file->f_flags & O_APPEND) &&
(!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)))
generic_file_llseek(file, 0, SEEK_END); generic_file_llseek(file, 0, SEEK_END);
file->private_data = fid;
} }
file->private_data = fid;
mutex_lock(&v9inode->v_mutex); mutex_lock(&v9inode->v_mutex);
if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) &&
!v9inode->writeback_fid && !v9inode->writeback_fid &&
...@@ -95,10 +96,10 @@ int v9fs_file_open(struct inode *inode, struct file *file) ...@@ -95,10 +96,10 @@ int v9fs_file_open(struct inode *inode, struct file *file)
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
fscache_use_cookie(v9fs_inode_cookie(v9inode), fscache_use_cookie(v9fs_inode_cookie(v9inode),
file->f_mode & FMODE_WRITE); file->f_mode & FMODE_WRITE);
v9fs_open_fid_add(inode, fid); v9fs_open_fid_add(inode, &fid);
return 0; return 0;
out_error: out_error:
p9_client_clunk(file->private_data); p9_fid_put(file->private_data);
file->private_data = NULL; file->private_data = NULL;
return err; return err;
} }
......
...@@ -399,10 +399,8 @@ void v9fs_evict_inode(struct inode *inode) ...@@ -399,10 +399,8 @@ void v9fs_evict_inode(struct inode *inode)
fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false); fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
/* clunk the fid stashed in writeback_fid */ /* clunk the fid stashed in writeback_fid */
if (v9inode->writeback_fid) { p9_fid_put(v9inode->writeback_fid);
p9_client_clunk(v9inode->writeback_fid); v9inode->writeback_fid = NULL;
v9inode->writeback_fid = NULL;
}
} }
static int v9fs_test_inode(struct inode *inode, void *data) static int v9fs_test_inode(struct inode *inode, void *data)
...@@ -569,7 +567,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) ...@@ -569,7 +567,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
if (v9fs_proto_dotl(v9ses)) if (v9fs_proto_dotl(v9ses))
retval = p9_client_unlinkat(dfid, dentry->d_name.name, retval = p9_client_unlinkat(dfid, dentry->d_name.name,
v9fs_at_to_dotl_flags(flags)); v9fs_at_to_dotl_flags(flags));
p9_client_clunk(dfid); p9_fid_put(dfid);
if (retval == -EOPNOTSUPP) { if (retval == -EOPNOTSUPP) {
/* Try the one based on path */ /* Try the one based on path */
v9fid = v9fs_fid_clone(dentry); v9fid = v9fs_fid_clone(dentry);
...@@ -633,14 +631,12 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, ...@@ -633,14 +631,12 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
if (IS_ERR(ofid)) { if (IS_ERR(ofid)) {
err = PTR_ERR(ofid); err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
p9_client_clunk(dfid); goto error;
return ERR_PTR(err);
} }
err = p9_client_fcreate(ofid, name, perm, mode, extension); err = p9_client_fcreate(ofid, name, perm, mode, extension);
if (err < 0) { if (err < 0) {
p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err);
p9_client_clunk(dfid);
goto error; goto error;
} }
...@@ -651,8 +647,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, ...@@ -651,8 +647,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
err = PTR_ERR(fid); err = PTR_ERR(fid);
p9_debug(P9_DEBUG_VFS, p9_debug(P9_DEBUG_VFS,
"p9_client_walk failed %d\n", err); "p9_client_walk failed %d\n", err);
fid = NULL;
p9_client_clunk(dfid);
goto error; goto error;
} }
/* /*
...@@ -663,21 +657,17 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, ...@@ -663,21 +657,17 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
err = PTR_ERR(inode); err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS, p9_debug(P9_DEBUG_VFS,
"inode creation failed %d\n", err); "inode creation failed %d\n", err);
p9_client_clunk(dfid);
goto error; goto error;
} }
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
} }
p9_client_clunk(dfid); p9_fid_put(dfid);
return ofid; return ofid;
error: error:
if (ofid) p9_fid_put(dfid);
p9_client_clunk(ofid); p9_fid_put(ofid);
p9_fid_put(fid);
if (fid)
p9_client_clunk(fid);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -708,7 +698,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -708,7 +698,7 @@ v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir,
return PTR_ERR(fid); return PTR_ERR(fid);
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
p9_client_clunk(fid); p9_fid_put(fid);
return 0; return 0;
} }
...@@ -744,7 +734,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -744,7 +734,7 @@ static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
} }
if (fid) if (fid)
p9_client_clunk(fid); p9_fid_put(fid);
return err; return err;
} }
...@@ -785,7 +775,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -785,7 +775,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
*/ */
name = dentry->d_name.name; name = dentry->d_name.name;
fid = p9_client_walk(dfid, 1, &name, 1); fid = p9_client_walk(dfid, 1, &name, 1);
p9_client_clunk(dfid); p9_fid_put(dfid);
if (fid == ERR_PTR(-ENOENT)) if (fid == ERR_PTR(-ENOENT))
inode = NULL; inode = NULL;
else if (IS_ERR(fid)) else if (IS_ERR(fid))
...@@ -804,11 +794,11 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, ...@@ -804,11 +794,11 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
res = d_splice_alias(inode, dentry); res = d_splice_alias(inode, dentry);
if (!IS_ERR(fid)) { if (!IS_ERR(fid)) {
if (!res) if (!res)
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
else if (!IS_ERR(res)) else if (!IS_ERR(res))
v9fs_fid_add(res, fid); v9fs_fid_add(res, &fid);
else else
p9_client_clunk(fid); p9_fid_put(fid);
} }
return res; return res;
} }
...@@ -847,7 +837,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -847,7 +837,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
v9fs_proto_dotu(v9ses))); v9fs_proto_dotu(v9ses)));
if (IS_ERR(fid)) { if (IS_ERR(fid)) {
err = PTR_ERR(fid); err = PTR_ERR(fid);
fid = NULL;
goto error; goto error;
} }
...@@ -882,7 +871,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -882,7 +871,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
fscache_use_cookie(v9fs_inode_cookie(v9inode), fscache_use_cookie(v9fs_inode_cookie(v9inode),
file->f_mode & FMODE_WRITE); file->f_mode & FMODE_WRITE);
v9fs_open_fid_add(inode, fid); v9fs_open_fid_add(inode, &fid);
file->f_mode |= FMODE_CREATED; file->f_mode |= FMODE_CREATED;
out: out:
...@@ -890,8 +879,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -890,8 +879,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
return err; return err;
error: error:
if (fid) p9_fid_put(fid);
p9_client_clunk(fid);
goto out; goto out;
} }
...@@ -939,9 +927,9 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, ...@@ -939,9 +927,9 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
struct inode *old_inode; struct inode *old_inode;
struct inode *new_inode; struct inode *new_inode;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *oldfid, *dfid; struct p9_fid *oldfid = NULL, *dfid = NULL;
struct p9_fid *olddirfid; struct p9_fid *olddirfid = NULL;
struct p9_fid *newdirfid; struct p9_fid *newdirfid = NULL;
struct p9_wstat wstat; struct p9_wstat wstat;
if (flags) if (flags)
...@@ -958,21 +946,22 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, ...@@ -958,21 +946,22 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
dfid = v9fs_parent_fid(old_dentry); dfid = v9fs_parent_fid(old_dentry);
olddirfid = clone_fid(dfid); olddirfid = clone_fid(dfid);
if (dfid && !IS_ERR(dfid)) p9_fid_put(dfid);
p9_client_clunk(dfid); dfid = NULL;
if (IS_ERR(olddirfid)) { if (IS_ERR(olddirfid)) {
retval = PTR_ERR(olddirfid); retval = PTR_ERR(olddirfid);
goto done; goto error;
} }
dfid = v9fs_parent_fid(new_dentry); dfid = v9fs_parent_fid(new_dentry);
newdirfid = clone_fid(dfid); newdirfid = clone_fid(dfid);
p9_client_clunk(dfid); p9_fid_put(dfid);
dfid = NULL;
if (IS_ERR(newdirfid)) { if (IS_ERR(newdirfid)) {
retval = PTR_ERR(newdirfid); retval = PTR_ERR(newdirfid);
goto clunk_olddir; goto error;
} }
down_write(&v9ses->rename_sem); down_write(&v9ses->rename_sem);
...@@ -983,7 +972,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, ...@@ -983,7 +972,7 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
retval = p9_client_rename(oldfid, newdirfid, retval = p9_client_rename(oldfid, newdirfid,
new_dentry->d_name.name); new_dentry->d_name.name);
if (retval != -EOPNOTSUPP) if (retval != -EOPNOTSUPP)
goto clunk_newdir; goto error_locked;
} }
if (old_dentry->d_parent != new_dentry->d_parent) { if (old_dentry->d_parent != new_dentry->d_parent) {
/* /*
...@@ -992,14 +981,14 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, ...@@ -992,14 +981,14 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n"); p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n");
retval = -EXDEV; retval = -EXDEV;
goto clunk_newdir; goto error_locked;
} }
v9fs_blank_wstat(&wstat); v9fs_blank_wstat(&wstat);
wstat.muid = v9ses->uname; wstat.muid = v9ses->uname;
wstat.name = new_dentry->d_name.name; wstat.name = new_dentry->d_name.name;
retval = p9_client_wstat(oldfid, &wstat); retval = p9_client_wstat(oldfid, &wstat);
clunk_newdir: error_locked:
if (!retval) { if (!retval) {
if (new_inode) { if (new_inode) {
if (S_ISDIR(new_inode->i_mode)) if (S_ISDIR(new_inode->i_mode))
...@@ -1020,13 +1009,11 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, ...@@ -1020,13 +1009,11 @@ v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
d_move(old_dentry, new_dentry); d_move(old_dentry, new_dentry);
} }
up_write(&v9ses->rename_sem); up_write(&v9ses->rename_sem);
p9_client_clunk(newdirfid);
clunk_olddir:
p9_client_clunk(olddirfid);
done: error:
p9_client_clunk(oldfid); p9_fid_put(newdirfid);
p9_fid_put(olddirfid);
p9_fid_put(oldfid);
return retval; return retval;
} }
...@@ -1060,7 +1047,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path, ...@@ -1060,7 +1047,7 @@ v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
return PTR_ERR(fid); return PTR_ERR(fid);
st = p9_client_stat(fid); st = p9_client_stat(fid);
p9_client_clunk(fid); p9_fid_put(fid);
if (IS_ERR(st)) if (IS_ERR(st))
return PTR_ERR(st); return PTR_ERR(st);
...@@ -1136,7 +1123,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns, ...@@ -1136,7 +1123,7 @@ static int v9fs_vfs_setattr(struct user_namespace *mnt_userns,
retval = p9_client_wstat(fid, &wstat); retval = p9_client_wstat(fid, &wstat);
if (use_dentry) if (use_dentry)
p9_client_clunk(fid); p9_fid_put(fid);
if (retval < 0) if (retval < 0)
return retval; return retval;
...@@ -1261,7 +1248,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry, ...@@ -1261,7 +1248,7 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry,
return ERR_CAST(fid); return ERR_CAST(fid);
st = p9_client_stat(fid); st = p9_client_stat(fid);
p9_client_clunk(fid); p9_fid_put(fid);
if (IS_ERR(st)) if (IS_ERR(st))
return ERR_CAST(st); return ERR_CAST(st);
...@@ -1308,7 +1295,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, ...@@ -1308,7 +1295,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
return PTR_ERR(fid); return PTR_ERR(fid);
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
p9_client_clunk(fid); p9_fid_put(fid);
return 0; return 0;
} }
...@@ -1364,7 +1351,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, ...@@ -1364,7 +1351,7 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
v9fs_refresh_inode(oldfid, d_inode(old_dentry)); v9fs_refresh_inode(oldfid, d_inode(old_dentry));
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
} }
p9_client_clunk(oldfid); p9_fid_put(oldfid);
return retval; return retval;
} }
......
...@@ -238,7 +238,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -238,7 +238,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
struct inode *inode; struct inode *inode;
struct p9_fid *fid = NULL; struct p9_fid *fid = NULL;
struct v9fs_inode *v9inode; struct v9fs_inode *v9inode;
struct p9_fid *dfid, *ofid, *inode_fid; struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct posix_acl *pacl = NULL, *dacl = NULL; struct posix_acl *pacl = NULL, *dacl = NULL;
struct dentry *res = NULL; struct dentry *res = NULL;
...@@ -274,7 +274,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -274,7 +274,6 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (IS_ERR(ofid)) { if (IS_ERR(ofid)) {
err = PTR_ERR(ofid); err = PTR_ERR(ofid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
p9_client_clunk(dfid);
goto out; goto out;
} }
...@@ -286,38 +285,34 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -286,38 +285,34 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (err) { if (err) {
p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
err); err);
p9_client_clunk(dfid); goto out;
goto error;
} }
err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
mode, gid, &qid); mode, gid, &qid);
if (err < 0) { if (err < 0) {
p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
err); err);
p9_client_clunk(dfid); goto out;
goto error;
} }
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
/* instantiate inode and assign the unopened fid to the dentry */ /* instantiate inode and assign the unopened fid to the dentry */
fid = p9_client_walk(dfid, 1, &name, 1); fid = p9_client_walk(dfid, 1, &name, 1);
p9_client_clunk(dfid);
if (IS_ERR(fid)) { if (IS_ERR(fid)) {
err = PTR_ERR(fid); err = PTR_ERR(fid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
fid = NULL; goto out;
goto error;
} }
inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
if (IS_ERR(inode)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
goto error; goto out;
} }
/* Now set the ACL based on the default value */ /* Now set the ACL based on the default value */
v9fs_set_create_acl(inode, fid, dacl, pacl); v9fs_set_create_acl(inode, fid, dacl, pacl);
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
v9inode = V9FS_I(inode); v9inode = V9FS_I(inode);
...@@ -336,7 +331,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -336,7 +331,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
if (IS_ERR(inode_fid)) { if (IS_ERR(inode_fid)) {
err = PTR_ERR(inode_fid); err = PTR_ERR(inode_fid);
mutex_unlock(&v9inode->v_mutex); mutex_unlock(&v9inode->v_mutex);
goto err_clunk_old_fid; goto out;
} }
v9inode->writeback_fid = (void *) inode_fid; v9inode->writeback_fid = (void *) inode_fid;
} }
...@@ -344,25 +339,20 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, ...@@ -344,25 +339,20 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
/* Since we are opening a file, assign the open fid to the file */ /* Since we are opening a file, assign the open fid to the file */
err = finish_open(file, dentry, generic_file_open); err = finish_open(file, dentry, generic_file_open);
if (err) if (err)
goto err_clunk_old_fid; goto out;
file->private_data = ofid; file->private_data = ofid;
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
fscache_use_cookie(v9fs_inode_cookie(v9inode), fscache_use_cookie(v9fs_inode_cookie(v9inode),
file->f_mode & FMODE_WRITE); file->f_mode & FMODE_WRITE);
v9fs_open_fid_add(inode, ofid); v9fs_open_fid_add(inode, &ofid);
file->f_mode |= FMODE_CREATED; file->f_mode |= FMODE_CREATED;
out: out:
p9_fid_put(dfid);
p9_fid_put(ofid);
p9_fid_put(fid);
v9fs_put_acl(dacl, pacl); v9fs_put_acl(dacl, pacl);
dput(res); dput(res);
return err; return err;
error:
if (fid)
p9_client_clunk(fid);
err_clunk_old_fid:
if (ofid)
p9_client_clunk(ofid);
goto out;
} }
/** /**
...@@ -400,7 +390,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns, ...@@ -400,7 +390,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
if (IS_ERR(dfid)) { if (IS_ERR(dfid)) {
err = PTR_ERR(dfid); err = PTR_ERR(dfid);
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
dfid = NULL;
goto error; goto error;
} }
...@@ -422,7 +411,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns, ...@@ -422,7 +411,6 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
err = PTR_ERR(fid); err = PTR_ERR(fid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
err); err);
fid = NULL;
goto error; goto error;
} }
...@@ -435,10 +423,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns, ...@@ -435,10 +423,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
err); err);
goto error; goto error;
} }
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
v9fs_set_create_acl(inode, fid, dacl, pacl); v9fs_set_create_acl(inode, fid, dacl, pacl);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
fid = NULL;
err = 0; err = 0;
} else { } else {
/* /*
...@@ -457,10 +444,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns, ...@@ -457,10 +444,9 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns,
inc_nlink(dir); inc_nlink(dir);
v9fs_invalidate_inode_attr(dir); v9fs_invalidate_inode_attr(dir);
error: error:
if (fid) p9_fid_put(fid);
p9_client_clunk(fid);
v9fs_put_acl(dacl, pacl); v9fs_put_acl(dacl, pacl);
p9_client_clunk(dfid); p9_fid_put(dfid);
return err; return err;
} }
...@@ -489,7 +475,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns, ...@@ -489,7 +475,7 @@ v9fs_vfs_getattr_dotl(struct user_namespace *mnt_userns,
*/ */
st = p9_client_getattr_dotl(fid, P9_STATS_ALL); st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
p9_client_clunk(fid); p9_fid_put(fid);
if (IS_ERR(st)) if (IS_ERR(st))
return PTR_ERR(st); return PTR_ERR(st);
...@@ -603,7 +589,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns, ...@@ -603,7 +589,7 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
retval = p9_client_setattr(fid, &p9attr); retval = p9_client_setattr(fid, &p9attr);
if (retval < 0) { if (retval < 0) {
if (use_dentry) if (use_dentry)
p9_client_clunk(fid); p9_fid_put(fid);
return retval; return retval;
} }
...@@ -619,12 +605,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns, ...@@ -619,12 +605,12 @@ int v9fs_vfs_setattr_dotl(struct user_namespace *mnt_userns,
retval = v9fs_acl_chmod(inode, fid); retval = v9fs_acl_chmod(inode, fid);
if (retval < 0) { if (retval < 0) {
if (use_dentry) if (use_dentry)
p9_client_clunk(fid); p9_fid_put(fid);
return retval; return retval;
} }
} }
if (use_dentry) if (use_dentry)
p9_client_clunk(fid); p9_fid_put(fid);
return 0; return 0;
} }
...@@ -743,7 +729,6 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -743,7 +729,6 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
err = PTR_ERR(fid); err = PTR_ERR(fid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
err); err);
fid = NULL;
goto error; goto error;
} }
...@@ -755,9 +740,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -755,9 +740,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
err); err);
goto error; goto error;
} }
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
fid = NULL;
err = 0; err = 0;
} else { } else {
/* Not in cached mode. No need to populate inode with stat */ /* Not in cached mode. No need to populate inode with stat */
...@@ -770,10 +754,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -770,10 +754,8 @@ v9fs_vfs_symlink_dotl(struct user_namespace *mnt_userns, struct inode *dir,
} }
error: error:
if (fid) p9_fid_put(fid);
p9_client_clunk(fid); p9_fid_put(dfid);
p9_client_clunk(dfid);
return err; return err;
} }
...@@ -803,14 +785,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, ...@@ -803,14 +785,14 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
oldfid = v9fs_fid_lookup(old_dentry); oldfid = v9fs_fid_lookup(old_dentry);
if (IS_ERR(oldfid)) { if (IS_ERR(oldfid)) {
p9_client_clunk(dfid); p9_fid_put(dfid);
return PTR_ERR(oldfid); return PTR_ERR(oldfid);
} }
err = p9_client_link(dfid, oldfid, dentry->d_name.name); err = p9_client_link(dfid, oldfid, dentry->d_name.name);
p9_client_clunk(dfid); p9_fid_put(dfid);
p9_client_clunk(oldfid); p9_fid_put(oldfid);
if (err < 0) { if (err < 0) {
p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err);
return err; return err;
...@@ -826,7 +808,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, ...@@ -826,7 +808,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
return PTR_ERR(fid); return PTR_ERR(fid);
v9fs_refresh_inode_dotl(fid, d_inode(old_dentry)); v9fs_refresh_inode_dotl(fid, d_inode(old_dentry));
p9_client_clunk(fid); p9_fid_put(fid);
} }
ihold(d_inode(old_dentry)); ihold(d_inode(old_dentry));
d_instantiate(dentry, d_inode(old_dentry)); d_instantiate(dentry, d_inode(old_dentry));
...@@ -866,7 +848,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -866,7 +848,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
if (IS_ERR(dfid)) { if (IS_ERR(dfid)) {
err = PTR_ERR(dfid); err = PTR_ERR(dfid);
p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
dfid = NULL;
goto error; goto error;
} }
...@@ -891,7 +872,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -891,7 +872,6 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
err = PTR_ERR(fid); err = PTR_ERR(fid);
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
err); err);
fid = NULL;
goto error; goto error;
} }
...@@ -905,9 +885,8 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -905,9 +885,8 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
goto error; goto error;
} }
v9fs_set_create_acl(inode, fid, dacl, pacl); v9fs_set_create_acl(inode, fid, dacl, pacl);
v9fs_fid_add(dentry, fid); v9fs_fid_add(dentry, &fid);
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
fid = NULL;
err = 0; err = 0;
} else { } else {
/* /*
...@@ -923,10 +902,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir, ...@@ -923,10 +902,9 @@ v9fs_vfs_mknod_dotl(struct user_namespace *mnt_userns, struct inode *dir,
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
} }
error: error:
if (fid) p9_fid_put(fid);
p9_client_clunk(fid);
v9fs_put_acl(dacl, pacl); v9fs_put_acl(dacl, pacl);
p9_client_clunk(dfid); p9_fid_put(dfid);
return err; return err;
} }
...@@ -956,7 +934,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry, ...@@ -956,7 +934,7 @@ v9fs_vfs_get_link_dotl(struct dentry *dentry,
if (IS_ERR(fid)) if (IS_ERR(fid))
return ERR_CAST(fid); return ERR_CAST(fid);
retval = p9_client_readlink(fid, &target); retval = p9_client_readlink(fid, &target);
p9_client_clunk(fid); p9_fid_put(fid);
if (retval) if (retval)
return ERR_PTR(retval); return ERR_PTR(retval);
set_delayed_call(done, kfree_link, target); set_delayed_call(done, kfree_link, target);
......
...@@ -184,13 +184,13 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, ...@@ -184,13 +184,13 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
retval = v9fs_get_acl(inode, fid); retval = v9fs_get_acl(inode, fid);
if (retval) if (retval)
goto release_sb; goto release_sb;
v9fs_fid_add(root, fid); v9fs_fid_add(root, &fid);
p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n");
return dget(sb->s_root); return dget(sb->s_root);
clunk_fid: clunk_fid:
p9_client_clunk(fid); p9_fid_put(fid);
v9fs_session_close(v9ses); v9fs_session_close(v9ses);
free_session: free_session:
kfree(v9ses); kfree(v9ses);
...@@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, ...@@ -203,7 +203,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
* attached the fid to dentry so it won't get clunked * attached the fid to dentry so it won't get clunked
* automatically. * automatically.
*/ */
p9_client_clunk(fid); p9_fid_put(fid);
deactivate_locked_super(sb); deactivate_locked_super(sb);
return ERR_PTR(retval); return ERR_PTR(retval);
} }
...@@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -270,7 +270,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
} }
res = simple_statfs(dentry, buf); res = simple_statfs(dentry, buf);
done: done:
p9_client_clunk(fid); p9_fid_put(fid);
return res; return res;
} }
......
...@@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, ...@@ -44,7 +44,7 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
if (err) if (err)
retval = err; retval = err;
} }
p9_client_clunk(attr_fid); p9_fid_put(attr_fid);
return retval; return retval;
} }
...@@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, ...@@ -71,7 +71,7 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
if (IS_ERR(fid)) if (IS_ERR(fid))
return PTR_ERR(fid); return PTR_ERR(fid);
ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size); ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
p9_client_clunk(fid); p9_fid_put(fid);
return ret; return ret;
} }
...@@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, ...@@ -98,7 +98,7 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name,
if (IS_ERR(fid)) if (IS_ERR(fid))
return PTR_ERR(fid); return PTR_ERR(fid);
ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags); ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
p9_client_clunk(fid); p9_fid_put(fid);
return ret; return ret;
} }
...@@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, ...@@ -128,7 +128,7 @@ int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
retval); retval);
else else
p9_client_write(fid, 0, &from, &retval); p9_client_write(fid, 0, &from, &retval);
err = p9_client_clunk(fid); err = p9_fid_put(fid);
if (!retval && err) if (!retval && err)
retval = err; retval = err;
return retval; return retval;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/tracepoint-defs.h>
/* Number of requests per row */ /* Number of requests per row */
#define P9_ROW_MAXTAG 255 #define P9_ROW_MAXTAG 255
...@@ -76,7 +77,7 @@ enum p9_req_status_t { ...@@ -76,7 +77,7 @@ enum p9_req_status_t {
struct p9_req_t { struct p9_req_t {
int status; int status;
int t_err; int t_err;
struct kref refcount; refcount_t refcount;
wait_queue_head_t wq; wait_queue_head_t wq;
struct p9_fcall tc; struct p9_fcall tc;
struct p9_fcall rc; struct p9_fcall rc;
...@@ -227,15 +228,55 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag); ...@@ -227,15 +228,55 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag);
static inline void p9_req_get(struct p9_req_t *r) static inline void p9_req_get(struct p9_req_t *r)
{ {
kref_get(&r->refcount); refcount_inc(&r->refcount);
} }
static inline int p9_req_try_get(struct p9_req_t *r) static inline int p9_req_try_get(struct p9_req_t *r)
{ {
return kref_get_unless_zero(&r->refcount); return refcount_inc_not_zero(&r->refcount);
} }
int p9_req_put(struct p9_req_t *r); int p9_req_put(struct p9_client *c, struct p9_req_t *r);
/* We cannot have the real tracepoints in header files,
* use a wrapper function */
DECLARE_TRACEPOINT(9p_fid_ref);
void do_trace_9p_fid_get(struct p9_fid *fid);
void do_trace_9p_fid_put(struct p9_fid *fid);
/* fid reference counting helpers:
* - fids used for any length of time should always be referenced through
* p9_fid_get(), and released with p9_fid_put()
* - v9fs_fid_lookup() or similar will automatically call get for you
* and also require a put
* - the *_fid_add() helpers will stash the fid in the inode,
* at which point it is the responsibility of evict_inode()
* to call the put
* - the last put will automatically send a clunk to the server
*/
static inline struct p9_fid *p9_fid_get(struct p9_fid *fid)
{
if (tracepoint_enabled(9p_fid_ref))
do_trace_9p_fid_get(fid);
refcount_inc(&fid->count);
return fid;
}
static inline int p9_fid_put(struct p9_fid *fid)
{
if (!fid || IS_ERR(fid))
return 0;
if (tracepoint_enabled(9p_fid_ref))
do_trace_9p_fid_put(fid);
if (!refcount_dec_and_test(&fid->count))
return 0;
return p9_client_clunk(fid);
}
void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status); void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status);
......
...@@ -77,6 +77,13 @@ ...@@ -77,6 +77,13 @@
EM( P9_TWSTAT, "P9_TWSTAT" ) \ EM( P9_TWSTAT, "P9_TWSTAT" ) \
EMe(P9_RWSTAT, "P9_RWSTAT" ) EMe(P9_RWSTAT, "P9_RWSTAT" )
#define P9_FID_REFTYPE \
EM( P9_FID_REF_CREATE, "create " ) \
EM( P9_FID_REF_GET, "get " ) \
EM( P9_FID_REF_PUT, "put " ) \
EMe(P9_FID_REF_DESTROY, "destroy" )
/* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */ /* Define EM() to export the enums to userspace via TRACE_DEFINE_ENUM() */
#undef EM #undef EM
#undef EMe #undef EMe
...@@ -84,6 +91,21 @@ ...@@ -84,6 +91,21 @@
#define EMe(a, b) TRACE_DEFINE_ENUM(a); #define EMe(a, b) TRACE_DEFINE_ENUM(a);
P9_MSG_T P9_MSG_T
P9_FID_REFTYPE
/* And also use EM/EMe to define helper enums -- once */
#ifndef __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
#define __9P_DECLARE_TRACE_ENUMS_ONLY_ONCE
#undef EM
#undef EMe
#define EM(a, b) a,
#define EMe(a, b) a
enum p9_fid_reftype {
P9_FID_REFTYPE
} __mode(byte);
#endif
/* /*
* Now redefine the EM() and EMe() macros to map the enums to the strings * Now redefine the EM() and EMe() macros to map the enums to the strings
...@@ -96,6 +118,8 @@ P9_MSG_T ...@@ -96,6 +118,8 @@ P9_MSG_T
#define show_9p_op(type) \ #define show_9p_op(type) \
__print_symbolic(type, P9_MSG_T) __print_symbolic(type, P9_MSG_T)
#define show_9p_fid_reftype(type) \
__print_symbolic(type, P9_FID_REFTYPE)
TRACE_EVENT(9p_client_req, TRACE_EVENT(9p_client_req,
TP_PROTO(struct p9_client *clnt, int8_t type, int tag), TP_PROTO(struct p9_client *clnt, int8_t type, int tag),
...@@ -168,6 +192,30 @@ TRACE_EVENT(9p_protocol_dump, ...@@ -168,6 +192,30 @@ TRACE_EVENT(9p_protocol_dump,
__entry->tag, 0, __entry->line, 16, __entry->line + 16) __entry->tag, 0, __entry->line, 16, __entry->line + 16)
); );
TRACE_EVENT(9p_fid_ref,
TP_PROTO(struct p9_fid *fid, __u8 type),
TP_ARGS(fid, type),
TP_STRUCT__entry(
__field( int, fid )
__field( int, refcount )
__field( __u8, type )
),
TP_fast_assign(
__entry->fid = fid->fid;
__entry->refcount = refcount_read(&fid->count);
__entry->type = type;
),
TP_printk("%s fid %d, refcount %d",
show_9p_fid_reftype(__entry->type),
__entry->fid, __entry->refcount)
);
#endif /* _TRACE_9P_H */ #endif /* _TRACE_9P_H */
/* This part must be outside protection */ /* This part must be outside protection */
......
This diff is collapsed.
...@@ -343,6 +343,7 @@ static void p9_read_work(struct work_struct *work) ...@@ -343,6 +343,7 @@ static void p9_read_work(struct work_struct *work)
p9_debug(P9_DEBUG_ERROR, p9_debug(P9_DEBUG_ERROR,
"No recv fcall for tag %d (req %p), disconnecting!\n", "No recv fcall for tag %d (req %p), disconnecting!\n",
m->rc.tag, m->rreq); m->rc.tag, m->rreq);
p9_req_put(m->client, m->rreq);
m->rreq = NULL; m->rreq = NULL;
err = -EIO; err = -EIO;
goto error; goto error;
...@@ -378,7 +379,7 @@ static void p9_read_work(struct work_struct *work) ...@@ -378,7 +379,7 @@ static void p9_read_work(struct work_struct *work)
m->rc.sdata = NULL; m->rc.sdata = NULL;
m->rc.offset = 0; m->rc.offset = 0;
m->rc.capacity = 0; m->rc.capacity = 0;
p9_req_put(m->rreq); p9_req_put(m->client, m->rreq);
m->rreq = NULL; m->rreq = NULL;
} }
...@@ -492,7 +493,7 @@ static void p9_write_work(struct work_struct *work) ...@@ -492,7 +493,7 @@ static void p9_write_work(struct work_struct *work)
m->wpos += err; m->wpos += err;
if (m->wpos == m->wsize) { if (m->wpos == m->wsize) {
m->wpos = m->wsize = 0; m->wpos = m->wsize = 0;
p9_req_put(m->wreq); p9_req_put(m->client, m->wreq);
m->wreq = NULL; m->wreq = NULL;
} }
...@@ -695,7 +696,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) ...@@ -695,7 +696,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req)
if (req->status == REQ_STATUS_UNSENT) { if (req->status == REQ_STATUS_UNSENT) {
list_del(&req->req_list); list_del(&req->req_list);
req->status = REQ_STATUS_FLSHD; req->status = REQ_STATUS_FLSHD;
p9_req_put(req); p9_req_put(client, req);
ret = 0; ret = 0;
} }
spin_unlock(&client->lock); spin_unlock(&client->lock);
...@@ -722,7 +723,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) ...@@ -722,7 +723,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req)
list_del(&req->req_list); list_del(&req->req_list);
req->status = REQ_STATUS_FLSHD; req->status = REQ_STATUS_FLSHD;
spin_unlock(&client->lock); spin_unlock(&client->lock);
p9_req_put(req); p9_req_put(client, req);
return 0; return 0;
} }
...@@ -883,12 +884,12 @@ static void p9_conn_destroy(struct p9_conn *m) ...@@ -883,12 +884,12 @@ static void p9_conn_destroy(struct p9_conn *m)
p9_mux_poll_stop(m); p9_mux_poll_stop(m);
cancel_work_sync(&m->rq); cancel_work_sync(&m->rq);
if (m->rreq) { if (m->rreq) {
p9_req_put(m->rreq); p9_req_put(m->client, m->rreq);
m->rreq = NULL; m->rreq = NULL;
} }
cancel_work_sync(&m->wq); cancel_work_sync(&m->wq);
if (m->wreq) { if (m->wreq) {
p9_req_put(m->wreq); p9_req_put(m->client, m->wreq);
m->wreq = NULL; m->wreq = NULL;
} }
......
...@@ -350,7 +350,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc) ...@@ -350,7 +350,7 @@ send_done(struct ib_cq *cq, struct ib_wc *wc)
c->busa, c->req->tc.size, c->busa, c->req->tc.size,
DMA_TO_DEVICE); DMA_TO_DEVICE);
up(&rdma->sq_sem); up(&rdma->sq_sem);
p9_req_put(c->req); p9_req_put(client, c->req);
kfree(c); kfree(c);
} }
......
...@@ -199,7 +199,7 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) ...@@ -199,7 +199,7 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
/* Reply won't come, so drop req ref */ /* Reply won't come, so drop req ref */
static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req) static int p9_virtio_cancelled(struct p9_client *client, struct p9_req_t *req)
{ {
p9_req_put(req); p9_req_put(client, req);
return 0; return 0;
} }
...@@ -557,7 +557,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, ...@@ -557,7 +557,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
kvfree(out_pages); kvfree(out_pages);
if (!kicked) { if (!kicked) {
/* reply won't come */ /* reply won't come */
p9_req_put(req); p9_req_put(client, req);
} }
return err; return err;
} }
......
...@@ -163,7 +163,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req) ...@@ -163,7 +163,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
ring->intf->out_prod = prod; ring->intf->out_prod = prod;
spin_unlock_irqrestore(&ring->lock, flags); spin_unlock_irqrestore(&ring->lock, flags);
notify_remote_via_irq(ring->irq); notify_remote_via_irq(ring->irq);
p9_req_put(p9_req); p9_req_put(client, p9_req);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment