summaryrefslogtreecommitdiff
path: root/fs/9p/vfs_file.c
diff options
context:
space:
mode:
authorLatchesar Ionkov <lucho@ionkov.net>2006-03-02 02:54:30 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-02 08:33:07 -0800
commit6a3124a3946c16159c3faf83e62ffdb5d1134b3a (patch)
tree989f1e89ed0971824db973af5347b879e12c67cd /fs/9p/vfs_file.c
parent77a3313551afd53c90012e5a87f7f2b2195fc67e (diff)
downloadlwn-6a3124a3946c16159c3faf83e62ffdb5d1134b3a.tar.gz
lwn-6a3124a3946c16159c3faf83e62ffdb5d1134b3a.zip
[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>
Diffstat (limited to 'fs/9p/vfs_file.c')
-rw-r--r--fs/9p/vfs_file.c106
1 files changed, 40 insertions, 66 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index c7e14d917215..de3a129698da 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -53,94 +53,70 @@
int v9fs_file_open(struct inode *inode, struct file *file)
{
struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
- struct v9fs_fid *v9fid, *fid;
+ struct v9fs_fid *vfid;
struct v9fs_fcall *fcall = NULL;
- int open_mode = 0;
- unsigned int iounit = 0;
- int newfid = -1;
- long result = -1;
+ int omode;
+ int fid = V9FS_NOFID;
+ int err;
dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
- v9fid = v9fs_fid_get_created(file->f_dentry);
- if (!v9fid)
- v9fid = v9fs_fid_lookup(file->f_dentry);
-
- if (!v9fid) {
+ vfid = v9fs_fid_lookup(file->f_dentry);
+ if (!vfid) {
dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
return -EBADF;
}
- if (!v9fid->fidcreate) {
- fid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (fid == NULL) {
- dprintk(DEBUG_ERROR, "Out of Memory\n");
- return -ENOMEM;
- }
-
- fid->fidopen = 0;
- fid->fidcreate = 0;
- fid->fidclunked = 0;
- fid->iounit = 0;
- fid->v9ses = v9ses;
-
- newfid = v9fs_get_idpool(&v9ses->fidpool);
- if (newfid < 0) {
+ fid = v9fs_get_idpool(&v9ses->fidpool);
+ if (fid < 0) {
eprintk(KERN_WARNING, "newfid fails!\n");
return -ENOSPC;
}
- result =
- v9fs_t_walk(v9ses, v9fid->fid, newfid, NULL, NULL);
-
- if (result < 0) {
- v9fs_put_idpool(newfid, &v9ses->fidpool);
+ err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, NULL);
+ if (err < 0) {
dprintk(DEBUG_ERROR, "rewalk didn't work\n");
- return -EBADF;
+ goto put_fid;
+ }
+
+ vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
+ if (vfid == NULL) {
+ dprintk(DEBUG_ERROR, "out of memory\n");
+ goto clunk_fid;
}
- fid->fid = newfid;
- v9fid = fid;
/* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
/* translate open mode appropriately */
- open_mode = file->f_flags & 0x3;
+ omode = v9fs_uflags2omode(file->f_flags);
+ err = v9fs_t_open(v9ses, fid, omode, &fcall);
+ if (err < 0) {
+ PRINT_FCALL_ERROR("open failed", fcall);
+ goto destroy_vfid;
+ }
- if (file->f_flags & O_EXCL)
- open_mode |= V9FS_OEXCL;
+ file->private_data = vfid;
+ vfid->fid = fid;
+ vfid->fidopen = 1;
+ vfid->fidclunked = 0;
+ vfid->iounit = fcall->params.ropen.iounit;
+ vfid->rdir_pos = 0;
+ vfid->rdir_fcall = NULL;
+ vfid->filp = file;
+ kfree(fcall);
- if (v9ses->extended) {
- if (file->f_flags & O_TRUNC)
- open_mode |= V9FS_OTRUNC;
+ return 0;
- if (file->f_flags & O_APPEND)
- open_mode |= V9FS_OAPPEND;
- }
+destroy_vfid:
+ v9fs_fid_destroy(vfid);
- result = v9fs_t_open(v9ses, newfid, open_mode, &fcall);
- if (result < 0) {
- PRINT_FCALL_ERROR("open failed", fcall);
- kfree(fcall);
- return result;
- }
+clunk_fid:
+ v9fs_t_clunk(v9ses, fid);
- iounit = fcall->params.ropen.iounit;
+put_fid:
+ v9fs_put_idpool(fid, &v9ses->fidpool);
kfree(fcall);
- } else {
- /* create case */
- newfid = v9fid->fid;
- iounit = v9fid->iounit;
- v9fid->fidcreate = 0;
- }
-
- file->private_data = v9fid;
-
- v9fid->rdir_pos = 0;
- v9fid->rdir_fcall = NULL;
- v9fid->fidopen = 1;
- v9fid->filp = file;
- v9fid->iounit = iounit;
- return 0;
+ return err;
}
/**
@@ -289,9 +265,7 @@ v9fs_file_write(struct file *filp, const char __user * data,
total += result;
} while (count);
- if(inode->i_mapping->nrpages)
invalidate_inode_pages2(inode->i_mapping);
-
return total;
}