Research
.
Skip Search Box

SELinux Mailing List

[PATCH 22/24] AFS: Implement shared-writable mmap

From: David Howells <dhowells_at_redhat.com>
Date: Wed, 26 Sep 2007 15:22:53 +0100


Implement shared-writable mmap for AFS.

The key with which to access the file is obtained from the VMA at the point where the PTE is made writable by the page_mkwrite() VMA op and cached in the affected page.

If there's an outstanding write on the page made with a different key, then page_mkwrite() will flush it before attaching a record of the new key.

Signed-off-by: David Howells <dhowells@redhat.com>

---

 fs/afs/file.c     |   20 +++++++++++++++++++-
 fs/afs/internal.h |    1 +
 fs/afs/write.c    |   35 +++++++++++++++++++++++++++++++++++
 3 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/fs/afs/file.c b/fs/afs/file.c
index 525f7c5..1323df4 100644
--- a/fs/afs/file.c

+++ b/fs/afs/file.c
@@ -22,6 +22,7 @@ static int afs_readpage(struct file *file, struct page *page); static void afs_invalidatepage(struct page *page, unsigned long offset); static int afs_releasepage(struct page *page, gfp_t gfp_flags); static int afs_launder_page(struct page *page);
+static int afs_mmap(struct file *file, struct vm_area_struct *vma);
const struct file_operations afs_file_operations = { .open = afs_open, @@ -31,7 +32,7 @@ const struct file_operations afs_file_operations = { .write = do_sync_write, .aio_read = generic_file_aio_read, .aio_write = afs_file_write, - .mmap = generic_file_readonly_mmap,
+ .mmap = afs_mmap,
.splice_read = generic_file_splice_read, .fsync = afs_fsync, .lock = afs_lock, @@ -56,6 +57,11 @@ const struct address_space_operations afs_fs_aops = { .writepages = afs_writepages, };
+static struct vm_operations_struct afs_file_vm_ops = {
+ .fault = filemap_fault,
+ .page_mkwrite = afs_page_mkwrite,
+};
+
/* * open an AFS file or directory and attach a key to it */ @@ -295,3 +301,15 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags) _leave(" = 0"); return 0; }
+
+/*
+ * memory map part of an AFS file
+ */
+static int afs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ _enter("");
+
+ file_accessed(file);
+ vma->vm_ops = &afs_file_vm_ops;
+ return 0;
+}
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e1bcce0..12afccc 100644 --- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -743,6 +743,7 @@ extern ssize_t afs_file_write(struct kiocb *, const struct iovec *, unsigned long, loff_t); extern int afs_writeback_all(struct afs_vnode *); extern int afs_fsync(struct file *, struct dentry *, int);
+extern int afs_page_mkwrite(struct vm_area_struct *, struct page *);
/*****************************************************************************/ diff --git a/fs/afs/write.c b/fs/afs/write.c index ac621e8..dd471f0 100644 --- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -155,6 +155,8 @@ static int afs_prepare_page(struct afs_vnode *vnode, struct page *page, * prepare to perform part of a write to a page * - the caller holds the page locked, preventing it from being written out or * modified by anyone else
+ * - may be called from afs_page_mkwrite() to set up a page for modification
+ * through shared-writable mmap
*/ int afs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) @@ -833,3 +835,36 @@ int afs_fsync(struct file *file, struct dentry *dentry, int datasync) _leave(" = %d", ret); return ret; }
+
+/*
+ * notification that a previously read-only page is about to become writable
+ * - if it returns an error, the caller will deliver a bus error signal
+ *
+ * we use this to make a record of the key with which the writeback should be
+ * performed and to flush any outstanding writes made with a different key
+ *
+ * the key to be used is attached to the struct file pinned by the VMA
+ */
+int afs_page_mkwrite(struct vm_area_struct *vma, struct page *page)
+{
+ struct afs_vnode *vnode = AFS_FS_I(vma->vm_file->f_mapping->host);
+ struct key *key = vma->vm_file->private_data;
+ int ret;
+
+ _enter("{{%x:%u},%x},{%lx}",
+ vnode->fid.vid, vnode->fid.vnode, key_serial(key), page->index);
+
+ do {
+ lock_page(page);
+ if (page->mapping == vma->vm_file->f_mapping)
+ ret = afs_prepare_write(vma->vm_file, page, 0,
+ PAGE_SIZE);
+ else
+ ret = 0; /* seems there was interference - let the
+ * caller deal with it */
+ unlock_page(page);
+ } while (ret == AOP_TRUNCATED_PAGE);
+
+ _leave(" = %d", ret);
+ return ret;
+}
-- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.
Received on Wed 26 Sep 2007 - 10:24:08 EDT
 

Date Posted: Jan 15, 2009 | Last Modified: Jan 15, 2009 | Last Reviewed: Jan 15, 2009

 
bottom

National Security Agency / Central Security Service