summaryrefslogtreecommitdiffstats
path: root/fs/9p/vfs_file.c
diff options
context:
space:
mode:
authorEric Van Hensbergen <ericvh@gmail.com>2007-01-26 00:57:06 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-01-26 13:51:00 -0800
commitda977b2c7eb4d6312f063a7b486f2aad99809710 (patch)
treebb8a2afc766c16e3349e03dfb8a706dca6408395 /fs/9p/vfs_file.c
parentff76e1dfc8728278ee231feeb93146f9c57c3ec3 (diff)
[PATCH] 9p: fix segfault caused by race condition in meta-data operations
Running dbench multithreaded exposed a race condition where fid structures were removed while in use. This patch adds semaphores to meta-data operations to protect the fid structure. Some cleanup of error-case handling in the inode operations is also included. Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/9p/vfs_file.c')
-rw-r--r--fs/9p/vfs_file.c47
1 files changed, 7 insertions, 40 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index e86a0715128..9f17b0cacdd 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -55,53 +55,22 @@ int v9fs_file_open(struct inode *inode, struct file *file)
struct v9fs_fid *vfid;
struct v9fs_fcall *fcall = NULL;
int omode;
- int fid = V9FS_NOFID;
int err;
dprintk(DEBUG_VFS, "inode: %p file: %p \n", inode, file);
- vfid = v9fs_fid_lookup(file->f_path.dentry);
- if (!vfid) {
- dprintk(DEBUG_ERROR, "Couldn't resolve fid from dentry\n");
- return -EBADF;
- }
-
- fid = v9fs_get_idpool(&v9ses->fidpool);
- if (fid < 0) {
- eprintk(KERN_WARNING, "newfid fails!\n");
- return -ENOSPC;
- }
+ vfid = v9fs_fid_clone(file->f_path.dentry);
+ if (IS_ERR(vfid))
+ return PTR_ERR(vfid);
- err = v9fs_t_walk(v9ses, vfid->fid, fid, NULL, &fcall);
- if (err < 0) {
- dprintk(DEBUG_ERROR, "rewalk didn't work\n");
- if (fcall && fcall->id == RWALK)
- goto clunk_fid;
- else {
- v9fs_put_idpool(fid, &v9ses->fidpool);
- goto free_fcall;
- }
- }
- kfree(fcall);
-
- /* TODO: do special things for O_EXCL, O_NOFOLLOW, O_SYNC */
- /* translate open mode appropriately */
omode = v9fs_uflags2omode(file->f_flags);
- err = v9fs_t_open(v9ses, fid, omode, &fcall);
+ err = v9fs_t_open(v9ses, vfid->fid, omode, &fcall);
if (err < 0) {
PRINT_FCALL_ERROR("open failed", fcall);
- goto clunk_fid;
- }
-
- vfid = kmalloc(sizeof(struct v9fs_fid), GFP_KERNEL);
- if (vfid == NULL) {
- dprintk(DEBUG_ERROR, "out of memory\n");
- err = -ENOMEM;
- goto clunk_fid;
+ goto Clunk_Fid;
}
file->private_data = vfid;
- vfid->fid = fid;
vfid->fidopen = 1;
vfid->fidclunked = 0;
vfid->iounit = fcall->params.ropen.iounit;
@@ -112,10 +81,8 @@ int v9fs_file_open(struct inode *inode, struct file *file)
return 0;
-clunk_fid:
- v9fs_t_clunk(v9ses, fid);
-
-free_fcall:
+Clunk_Fid:
+ v9fs_fid_clunk(v9ses, vfid);
kfree(fcall);
return err;