@@ -190,15 +190,16 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
190190 char * buf ;
191191
192192 buf = of -> prealloc_buf ;
193- if (!buf )
193+ if (buf )
194+ mutex_lock (& of -> prealloc_mutex );
195+ else
194196 buf = kmalloc (len , GFP_KERNEL );
195197 if (!buf )
196198 return - ENOMEM ;
197199
198200 /*
199201 * @of->mutex nests outside active ref and is used both to ensure that
200- * the ops aren't called concurrently for the same open file, and
201- * to provide exclusive access to ->prealloc_buf (when that exists).
202+ * the ops aren't called concurrently for the same open file.
202203 */
203204 mutex_lock (& of -> mutex );
204205 if (!kernfs_get_active (of -> kn )) {
@@ -214,21 +215,23 @@ static ssize_t kernfs_file_direct_read(struct kernfs_open_file *of,
214215 else
215216 len = - EINVAL ;
216217
218+ kernfs_put_active (of -> kn );
219+ mutex_unlock (& of -> mutex );
220+
217221 if (len < 0 )
218- goto out_unlock ;
222+ goto out_free ;
219223
220224 if (copy_to_user (user_buf , buf , len )) {
221225 len = - EFAULT ;
222- goto out_unlock ;
226+ goto out_free ;
223227 }
224228
225229 * ppos += len ;
226230
227- out_unlock :
228- kernfs_put_active (of -> kn );
229- mutex_unlock (& of -> mutex );
230231 out_free :
231- if (buf != of -> prealloc_buf )
232+ if (buf == of -> prealloc_buf )
233+ mutex_unlock (& of -> prealloc_mutex );
234+ else
232235 kfree (buf );
233236 return len ;
234237}
@@ -284,15 +287,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
284287 }
285288
286289 buf = of -> prealloc_buf ;
287- if (!buf )
290+ if (buf )
291+ mutex_lock (& of -> prealloc_mutex );
292+ else
288293 buf = kmalloc (len + 1 , GFP_KERNEL );
289294 if (!buf )
290295 return - ENOMEM ;
291296
297+ if (copy_from_user (buf , user_buf , len )) {
298+ len = - EFAULT ;
299+ goto out_free ;
300+ }
301+ buf [len ] = '\0' ; /* guarantee string termination */
302+
292303 /*
293304 * @of->mutex nests outside active ref and is used both to ensure that
294- * the ops aren't called concurrently for the same open file, and
295- * to provide exclusive access to ->prealloc_buf (when that exists).
305+ * the ops aren't called concurrently for the same open file.
296306 */
297307 mutex_lock (& of -> mutex );
298308 if (!kernfs_get_active (of -> kn )) {
@@ -301,26 +311,22 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf,
301311 goto out_free ;
302312 }
303313
304- if (copy_from_user (buf , user_buf , len )) {
305- len = - EFAULT ;
306- goto out_unlock ;
307- }
308- buf [len ] = '\0' ; /* guarantee string termination */
309-
310314 ops = kernfs_ops (of -> kn );
311315 if (ops -> write )
312316 len = ops -> write (of , buf , len , * ppos );
313317 else
314318 len = - EINVAL ;
315319
320+ kernfs_put_active (of -> kn );
321+ mutex_unlock (& of -> mutex );
322+
316323 if (len > 0 )
317324 * ppos += len ;
318325
319- out_unlock :
320- kernfs_put_active (of -> kn );
321- mutex_unlock (& of -> mutex );
322326out_free :
323- if (buf != of -> prealloc_buf )
327+ if (buf == of -> prealloc_buf )
328+ mutex_unlock (& of -> prealloc_mutex );
329+ else
324330 kfree (buf );
325331 return len ;
326332}
@@ -687,6 +693,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
687693 error = - ENOMEM ;
688694 if (!of -> prealloc_buf )
689695 goto err_free ;
696+ mutex_init (& of -> prealloc_mutex );
690697 }
691698
692699 /*
0 commit comments