[PATCH] v9fs: fix atomic create open
In order to assure atomic create+open v9fs stores the open fid produced by v9fs_vfs_create in the dentry, from where v9fs_file_open retrieves it and associates it with the open file. This patch modifies v9fs to use nameidata.intent.open values to do the atomic create+open. Signed-off-by: Latchesar Ionkov <lucho@ionkov.net> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
committed by
Linus Torvalds
parent
77a3313551
commit
6a3124a394
73
fs/9p/fid.c
73
fs/9p/fid.c
@@ -40,7 +40,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
|
||||
int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
|
||||
{
|
||||
struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
|
||||
dprintk(DEBUG_9P, "fid %d (%p) dentry %s (%p)\n", fid->fid, fid,
|
||||
@@ -68,14 +68,11 @@ static int v9fs_fid_insert(struct v9fs_fid *fid, struct dentry *dentry)
|
||||
*
|
||||
*/
|
||||
|
||||
struct v9fs_fid *v9fs_fid_create(struct dentry *dentry,
|
||||
struct v9fs_session_info *v9ses, int fid, int create)
|
||||
struct v9fs_fid *v9fs_fid_create(struct v9fs_session_info *v9ses, int fid)
|
||||
{
|
||||
struct v9fs_fid *new;
|
||||
|
||||
dprintk(DEBUG_9P, "fid create dentry %p, fid %d, create %d\n",
|
||||
dentry, fid, create);
|
||||
|
||||
dprintk(DEBUG_9P, "fid create fid %d\n", fid);
|
||||
new = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
|
||||
if (new == NULL) {
|
||||
dprintk(DEBUG_ERROR, "Out of Memory\n");
|
||||
@@ -85,19 +82,13 @@ struct v9fs_fid *v9fs_fid_create(struct dentry *dentry,
|
||||
new->fid = fid;
|
||||
new->v9ses = v9ses;
|
||||
new->fidopen = 0;
|
||||
new->fidcreate = create;
|
||||
new->fidclunked = 0;
|
||||
new->iounit = 0;
|
||||
new->rdir_pos = 0;
|
||||
new->rdir_fcall = NULL;
|
||||
INIT_LIST_HEAD(&new->list);
|
||||
|
||||
if (v9fs_fid_insert(new, dentry) == 0)
|
||||
return new;
|
||||
else {
|
||||
dprintk(DEBUG_ERROR, "Problems inserting to dentry\n");
|
||||
kfree(new);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +110,7 @@ void v9fs_fid_destroy(struct v9fs_fid *fid)
|
||||
static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
|
||||
{
|
||||
int fidnum, cfidnum, err;
|
||||
struct v9fs_fid *cfid;
|
||||
struct v9fs_fid *cfid, *fid;
|
||||
struct dentry *cde;
|
||||
struct v9fs_session_info *v9ses;
|
||||
|
||||
@@ -158,7 +149,16 @@ static struct v9fs_fid *v9fs_fid_walk_up(struct dentry *dentry)
|
||||
cde = cde->d_parent;
|
||||
}
|
||||
|
||||
return v9fs_fid_create(dentry, v9ses, fidnum, 0);
|
||||
fid = v9fs_fid_create(v9ses, fidnum);
|
||||
if (fid) {
|
||||
err = v9fs_fid_insert(fid, dentry);
|
||||
if (err < 0) {
|
||||
kfree(fid);
|
||||
goto clunk_fid;
|
||||
}
|
||||
}
|
||||
|
||||
return fid;
|
||||
|
||||
clunk_fid:
|
||||
v9fs_t_clunk(v9ses, fidnum);
|
||||
@@ -179,29 +179,12 @@ clunk_fid:
|
||||
struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
|
||||
{
|
||||
struct list_head *fid_list = (struct list_head *)dentry->d_fsdata;
|
||||
struct v9fs_fid *current_fid = NULL;
|
||||
struct v9fs_fid *temp = NULL;
|
||||
struct v9fs_fid *return_fid = NULL;
|
||||
|
||||
dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
|
||||
|
||||
if (fid_list) {
|
||||
list_for_each_entry_safe(current_fid, temp, fid_list, list) {
|
||||
if (!current_fid->fidcreate) {
|
||||
return_fid = current_fid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!return_fid)
|
||||
return_fid = current_fid;
|
||||
}
|
||||
|
||||
/* we are at the root but didn't match */
|
||||
if ((!return_fid) && (dentry->d_parent == dentry)) {
|
||||
/* TODO: clone attach with new uid */
|
||||
return_fid = current_fid;
|
||||
}
|
||||
if (fid_list)
|
||||
return_fid = list_entry(fid_list->next, struct v9fs_fid, list);
|
||||
|
||||
if (!return_fid) {
|
||||
struct dentry *par = current->fs->pwd->d_parent;
|
||||
@@ -228,25 +211,3 @@ struct v9fs_fid *v9fs_fid_lookup(struct dentry *dentry)
|
||||
|
||||
return return_fid;
|
||||
}
|
||||
|
||||
struct v9fs_fid *v9fs_fid_get_created(struct dentry *dentry)
|
||||
{
|
||||
struct list_head *fid_list;
|
||||
struct v9fs_fid *fid, *ftmp, *ret;
|
||||
|
||||
dprintk(DEBUG_9P, " dentry: %s (%p)\n", dentry->d_iname, dentry);
|
||||
fid_list = (struct list_head *)dentry->d_fsdata;
|
||||
ret = NULL;
|
||||
if (fid_list) {
|
||||
list_for_each_entry_safe(fid, ftmp, fid_list, list) {
|
||||
if (fid->fidcreate && fid->pid == current->pid) {
|
||||
list_del(&fid->list);
|
||||
ret = fid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dprintk(DEBUG_9P, "return %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user