[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:
Latchesar Ionkov
2006-03-02 02:54:30 -08:00
committed by Linus Torvalds
parent 77a3313551
commit 6a3124a394
6 changed files with 401 additions and 318 deletions

View File

@@ -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;
}