|
47 | 47 | #include <linux/splice.h>
|
48 | 48 | #include <linux/rcupdate_wait.h>
|
49 | 49 | #include <linux/sched/mm.h>
|
| 50 | +#include <linux/fsnotify.h> |
50 | 51 | #include <asm/pgalloc.h>
|
51 | 52 | #include <asm/tlbflush.h>
|
52 | 53 | #include "internal.h"
|
@@ -3288,6 +3289,48 @@ static vm_fault_t filemap_fault_recheck_pte_none(struct vm_fault *vmf)
|
3288 | 3289 | return ret;
|
3289 | 3290 | }
|
3290 | 3291 |
|
| 3292 | +/** |
| 3293 | + * filemap_fsnotify_fault - maybe emit a pre-content event. |
| 3294 | + * @vmf: struct vm_fault containing details of the fault. |
| 3295 | + * |
| 3296 | + * If we have a pre-content watch on this file we will emit an event for this |
| 3297 | + * range. If we return anything the fault caller should return immediately, we |
| 3298 | + * will return VM_FAULT_RETRY if we had to emit an event, which will trigger the |
| 3299 | + * fault again and then the fault handler will run the second time through. |
| 3300 | + * |
| 3301 | + * Return: a bitwise-OR of %VM_FAULT_ codes, 0 if nothing happened. |
| 3302 | + */ |
| 3303 | +vm_fault_t filemap_fsnotify_fault(struct vm_fault *vmf) |
| 3304 | +{ |
| 3305 | + struct file *fpin = NULL; |
| 3306 | + int mask = (vmf->flags & FAULT_FLAG_WRITE) ? MAY_WRITE : MAY_ACCESS; |
| 3307 | + loff_t pos = vmf->pgoff >> PAGE_SHIFT; |
| 3308 | + size_t count = PAGE_SIZE; |
| 3309 | + int err; |
| 3310 | + |
| 3311 | + /* |
| 3312 | + * We already did this and now we're retrying with everything locked, |
| 3313 | + * don't emit the event and continue. |
| 3314 | + */ |
| 3315 | + if (vmf->flags & FAULT_FLAG_TRIED) |
| 3316 | + return 0; |
| 3317 | + |
| 3318 | + /* No watches, we're done. */ |
| 3319 | + if (likely(!FMODE_FSNOTIFY_HSM(vmf->vma->vm_file->f_mode))) |
| 3320 | + return 0; |
| 3321 | + |
| 3322 | + fpin = maybe_unlock_mmap_for_io(vmf, fpin); |
| 3323 | + if (!fpin) |
| 3324 | + return VM_FAULT_SIGBUS; |
| 3325 | + |
| 3326 | + err = fsnotify_file_area_perm(fpin, mask, &pos, count); |
| 3327 | + fput(fpin); |
| 3328 | + if (err) |
| 3329 | + return VM_FAULT_SIGBUS; |
| 3330 | + return VM_FAULT_RETRY; |
| 3331 | +} |
| 3332 | +EXPORT_SYMBOL_GPL(filemap_fsnotify_fault); |
| 3333 | + |
3291 | 3334 | /**
|
3292 | 3335 | * filemap_fault - read in file data for page fault handling
|
3293 | 3336 | * @vmf: struct vm_fault containing details of the fault
|
@@ -3391,6 +3434,37 @@ vm_fault_t filemap_fault(struct vm_fault *vmf)
|
3391 | 3434 | * or because readahead was otherwise unable to retrieve it.
|
3392 | 3435 | */
|
3393 | 3436 | if (unlikely(!folio_test_uptodate(folio))) {
|
| 3437 | + /* |
| 3438 | + * If this is a precontent file we have can now emit an event to |
| 3439 | + * try and populate the folio. |
| 3440 | + */ |
| 3441 | + if (!(vmf->flags & FAULT_FLAG_TRIED) && |
| 3442 | + unlikely(FMODE_FSNOTIFY_HSM(file->f_mode))) { |
| 3443 | + loff_t pos = folio_pos(folio); |
| 3444 | + size_t count = folio_size(folio); |
| 3445 | + |
| 3446 | + /* We're NOWAIT, we have to retry. */ |
| 3447 | + if (vmf->flags & FAULT_FLAG_RETRY_NOWAIT) { |
| 3448 | + folio_unlock(folio); |
| 3449 | + goto out_retry; |
| 3450 | + } |
| 3451 | + |
| 3452 | + if (mapping_locked) |
| 3453 | + filemap_invalidate_unlock_shared(mapping); |
| 3454 | + mapping_locked = false; |
| 3455 | + |
| 3456 | + folio_unlock(folio); |
| 3457 | + fpin = maybe_unlock_mmap_for_io(vmf, fpin); |
| 3458 | + if (!fpin) |
| 3459 | + goto out_retry; |
| 3460 | + |
| 3461 | + error = fsnotify_file_area_perm(fpin, MAY_ACCESS, &pos, |
| 3462 | + count); |
| 3463 | + if (error) |
| 3464 | + ret = VM_FAULT_SIGBUS; |
| 3465 | + goto out_retry; |
| 3466 | + } |
| 3467 | + |
3394 | 3468 | /*
|
3395 | 3469 | * If the invalidate lock is not held, the folio was in cache
|
3396 | 3470 | * and uptodate and now it is not. Strange but possible since we
|
|
0 commit comments