[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:
committed by
Linus Torvalds
parent
ff76e1dfc8
commit
da977b2c7e
@ -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;
|
||||
|
Reference in New Issue
Block a user