[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>
This commit is contained in:
Eric Van Hensbergen
2007-01-26 00:57:06 -08:00
committed by Linus Torvalds
parent ff76e1dfc8
commit da977b2c7e
4 changed files with 196 additions and 129 deletions

View File

@ -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;
}
vfid = v9fs_fid_clone(file->f_path.dentry);
if (IS_ERR(vfid))
return PTR_ERR(vfid);
fid = v9fs_get_idpool(&v9ses->fidpool);
if (fid < 0) {
eprintk(KERN_WARNING, "newfid fails!\n");
return -ENOSPC;
}
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;