There are two problems related to the lack of fiq locking in fuse_invalidate_files(). The first is an unsafe iteration of fiq->pending list in fuse_kill_requests(). The second problem is the race between __fuse_request_send() and fuse_invalidate_files():
__fuse_request_send(): fuse_invalidate_files(): spin_lock(&fiq->waitq.lock); test_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state) spin_lock(&fc->lock); list_for_each_entry(ff, &fi->rw_files, rw_entry) set_bit(FUSE_S_FAIL_IMMEDIATELY, &ff->ff_state); spin_unlock(&fc->lock); spin_lock(&fc->lock); spin_lock(&fpq->lock); fuse_kill_requests(fc, inode, &fiq->pending); spin_unlock(&fpq->lock); spin_unlock(&fc->lock); queue_request(fiq, req); <-- add a new request after fuse_invalidate_files(), spin_unlock(&fiq->waitq.lock); that's wrong. The patch fixes both problems. Signed-off-by: Pavel Butsykin <pbutsy...@virtuozzo.com> --- fs/fuse/inode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cb275ff21991..80bfe45d5d46 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -437,9 +437,12 @@ int fuse_invalidate_files(struct fuse_conn *fc, u64 nodeid) spin_lock(&fpq->lock); for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) fuse_kill_requests(fc, inode, &fpq->processing[i]); - fuse_kill_requests(fc, inode, &fiq->pending); fuse_kill_requests(fc, inode, &fpq->io); spin_unlock(&fpq->lock); + + spin_lock(&fiq->waitq.lock); + fuse_kill_requests(fc, inode, &fiq->pending); + spin_unlock(&fiq->waitq.lock); } fuse_kill_requests(fc, inode, &fc->main_iq.pending); fuse_kill_requests(fc, inode, &fc->bg_queue); -- 2.15.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel