fuse_copy_finish() assumes that mapaddr in fuse_copy_state refers to a valid mapping if currbuf is non-NULL, but this isn't always true when moving pages for splice I/O. This results in an unbalanced call to kunmap_atomic() and thus an unbalanced decrement of the preempt count. Avoid this by checking that mapaddr is non-NULL before calling kunmap_atomic(). This can be reproduced easily with fusexmp_fh: $ mkdir data mount $ dd if=/dev/urandom of=data/rand.bin bs=1M count=1 $ fusexmp_fh -omodules=subdir,subdir=$PWD/data,splice_write,splice_move mount $ cat mount/rand.bin >/dev/null The bug has existed in its current form since 58bda1da4 "fuse/dev: use atomic maps" and fbb32750a "pipe: kill ->map() and ->unmap()" converted all unmaps to kunmap_atomic() in 3.15. The fundamental problem of unmapping a page which hasn't been mapped goes back farther, probably to ce534fb05 "fuse: allow splice to move pages," but likely with a different impact. Cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Seth Forshee <seth.forshee@xxxxxxxxxxxxx> --- fs/fuse/dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 098f97bdcf1b..219d1e685183 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -666,12 +666,10 @@ static void fuse_copy_finish(struct fuse_copy_state *cs) if (cs->currbuf) { struct pipe_buffer *buf = cs->currbuf; - if (!cs->write) { - kunmap_atomic(cs->mapaddr); - } else { + if (cs->mapaddr) kunmap_atomic(cs->mapaddr); + if (cs->write) buf->len = PAGE_SIZE - cs->len; - } cs->currbuf = NULL; cs->mapaddr = NULL; } else if (cs->mapaddr) { -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/