diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2006-01-17 01:14:52 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-17 02:15:31 -0500 |
commit | 095da6cbb6a1c54c19b11190218eb0fbac666b6d (patch) | |
tree | 29ba46cea17454fe1888182f6722aee64e1a7ef5 /fs/fuse/inode.c | |
parent | bacac382fbf53f717ca7f83558e45cce44e67df9 (diff) |
[PATCH] fuse: fix bitfield race
Fix race in setting bitfields of fuse_conn. Spotted by Andrew Morton.
The two fields ->connected and ->mounted were always changed with the
fuse_lock held. But other bitfields in the same structure were changed
without the lock. In theory this could lead to losing the assignment of
even the ones under lock. The chosen solution is to change these two
fields to be a full unsigned type. The other bitfields aren't "important"
enough to warrant the extra complexity of full locking or changing them to
bitops.
For all bitfields document why they are safe wrt. concurrent
assignments.
Also make the initialization of the 'num_waiting' atomic counter explicit.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 8683e7254d53..c755a0440a66 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -397,6 +397,7 @@ static struct fuse_conn *new_conn(void) | |||
397 | init_rwsem(&fc->sbput_sem); | 397 | init_rwsem(&fc->sbput_sem); |
398 | kobj_set_kset_s(fc, connections_subsys); | 398 | kobj_set_kset_s(fc, connections_subsys); |
399 | kobject_init(&fc->kobj); | 399 | kobject_init(&fc->kobj); |
400 | atomic_set(&fc->num_waiting, 0); | ||
400 | for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { | 401 | for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { |
401 | struct fuse_req *req = fuse_request_alloc(); | 402 | struct fuse_req *req = fuse_request_alloc(); |
402 | if (!req) { | 403 | if (!req) { |
@@ -492,6 +493,7 @@ static void fuse_send_init(struct fuse_conn *fc) | |||
492 | to be exactly one request available */ | 493 | to be exactly one request available */ |
493 | struct fuse_req *req = fuse_get_request(fc); | 494 | struct fuse_req *req = fuse_get_request(fc); |
494 | struct fuse_init_in *arg = &req->misc.init_in; | 495 | struct fuse_init_in *arg = &req->misc.init_in; |
496 | |||
495 | arg->major = FUSE_KERNEL_VERSION; | 497 | arg->major = FUSE_KERNEL_VERSION; |
496 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 498 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
497 | req->in.h.opcode = FUSE_INIT; | 499 | req->in.h.opcode = FUSE_INIT; |