--- x/fs/kernfs/file.c +++ y/fs/kernfs/file.c @@ -298,6 +298,7 @@ static ssize_t kernfs_fop_read_iter(stru return kernfs_file_read_iter(iocb, iter); } +static DEFINE_MUTEX(drain_mutex); /* * Copy data in from userland and pass it to the matching kernfs write * operation. @@ -322,13 +323,17 @@ static ssize_t kernfs_fop_write_iter(str len = min_t(size_t, len, PAGE_SIZE); } + if (!mutex_trylock(&drain_mutex)) + return -EINVAL; buf = of->prealloc_buf; if (buf) mutex_lock(&of->prealloc_mutex); else buf = kmalloc(len + 1, GFP_KERNEL); - if (!buf) + if (!buf) { + mutex_unlock(&drain_mutex); return -ENOMEM; + } if (copy_from_iter(buf, len, iter) != len) { len = -EFAULT; @@ -364,6 +369,7 @@ out_free: mutex_unlock(&of->prealloc_mutex); else kfree(buf); + mutex_unlock(&drain_mutex); return len; } @@ -814,10 +820,12 @@ void kernfs_drain_open_files(struct kern struct kernfs_open_file *of; struct mutex *mutex; + mutex_lock(&drain_mutex); mutex = kernfs_open_file_mutex_lock(kn); on = kernfs_deref_open_node_locked(kn); if (!on) { mutex_unlock(mutex); + mutex_unlock(&drain_mutex); return; } @@ -836,6 +844,7 @@ void kernfs_drain_open_files(struct kern WARN_ON_ONCE(on->nr_mmapped || on->nr_to_release); mutex_unlock(mutex); + mutex_unlock(&drain_mutex); } /*