Skip to content

Commit 102a7e2

Browse files
committed
netfs: Allow buffered shared-writeable mmap through netfs_page_mkwrite()
Provide an entry point to delegate a filesystem's ->page_mkwrite() to. This checks for conflicting writes, then attached any netfs-specific group marking (e.g. ceph snap) to the page to be considered dirty. Signed-off-by: David Howells <[email protected]> Reviewed-by: Jeff Layton <[email protected]> cc: [email protected] cc: [email protected] cc: [email protected]
1 parent 938e13a commit 102a7e2

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

fs/netfs/buffered_write.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,62 @@ ssize_t netfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
416416
return ret;
417417
}
418418
EXPORT_SYMBOL(netfs_file_write_iter);
419+
420+
/*
421+
* Notification that a previously read-only page is about to become writable.
422+
* Note that the caller indicates a single page of a multipage folio.
423+
*/
424+
vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group)
425+
{
426+
struct folio *folio = page_folio(vmf->page);
427+
struct file *file = vmf->vma->vm_file;
428+
struct inode *inode = file_inode(file);
429+
vm_fault_t ret = VM_FAULT_RETRY;
430+
int err;
431+
432+
_enter("%lx", folio->index);
433+
434+
sb_start_pagefault(inode->i_sb);
435+
436+
if (folio_wait_writeback_killable(folio))
437+
goto out;
438+
439+
if (folio_lock_killable(folio) < 0)
440+
goto out;
441+
442+
/* Can we see a streaming write here? */
443+
if (WARN_ON(!folio_test_uptodate(folio))) {
444+
ret = VM_FAULT_SIGBUS | VM_FAULT_LOCKED;
445+
goto out;
446+
}
447+
448+
if (netfs_folio_group(folio) != netfs_group) {
449+
folio_unlock(folio);
450+
err = filemap_fdatawait_range(inode->i_mapping,
451+
folio_pos(folio),
452+
folio_pos(folio) + folio_size(folio));
453+
switch (err) {
454+
case 0:
455+
ret = VM_FAULT_RETRY;
456+
goto out;
457+
case -ENOMEM:
458+
ret = VM_FAULT_OOM;
459+
goto out;
460+
default:
461+
ret = VM_FAULT_SIGBUS;
462+
goto out;
463+
}
464+
}
465+
466+
if (folio_test_dirty(folio))
467+
trace_netfs_folio(folio, netfs_folio_trace_mkwrite_plus);
468+
else
469+
trace_netfs_folio(folio, netfs_folio_trace_mkwrite);
470+
netfs_set_group(folio, netfs_group);
471+
file_update_time(file);
472+
ret = VM_FAULT_LOCKED;
473+
out:
474+
sb_end_pagefault(inode->i_sb);
475+
return ret;
476+
}
477+
EXPORT_SYMBOL(netfs_page_mkwrite);

include/linux/netfs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ void netfs_clear_inode_writeback(struct inode *inode, const void *aux);
400400
void netfs_invalidate_folio(struct folio *folio, size_t offset, size_t length);
401401
bool netfs_release_folio(struct folio *folio, gfp_t gfp);
402402

403+
/* VMA operations API. */
404+
vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group);
405+
406+
/* (Sub)request management API. */
403407
void netfs_subreq_terminated(struct netfs_io_subrequest *, ssize_t, bool);
404408
void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
405409
enum netfs_sreq_ref_trace what);

0 commit comments

Comments
 (0)