bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH tarfs 3/6] Implement basic read-only mmap support


From: Sergey Bugaev
Subject: [RFC PATCH tarfs 3/6] Implement basic read-only mmap support
Date: Thu, 29 Apr 2021 21:57:13 +0300

Each node can have a pager attached. The pager gets created
the first time io_map () is invoked on the node, and destroyed
once it has no clients. The pager gets its data the same way
tarfs_read_node () does: by ask the cache to copy out the data.

Note that this ommit only implement read-only mappings, and even
then it does nothing to provide coherency between what can be read
from the created mappings and subsequent modifications done to the
underlying file. The implementation will be enhanced in the following
commits.

This is enough for ld.so to successfully mmap shared libraries from
a tarfs instance.
---
 Makefile |   2 +-
 main.c   |   1 +
 pager.c  | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pager.h  |   9 +++++
 tarfs.c  |  22 ++++++++++-
 tarfs.h  |   2 +
 6 files changed, 150 insertions(+), 3 deletions(-)
 create mode 100644 pager.c
 create mode 100644 pager.h

diff --git a/Makefile b/Makefile
index 6e2eb422e..49b1950a9 100644
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ LDFLAGS = -L~ -lz -L. -lnetfs -lfshelp -liohelp -lports \
 CTAGS   = ctags
 
 SRC     = main.c netfs.c tarfs.c tarlist.c fs.c cache.c tar.c names.c \
-          store-bzip2.c store-gzip.c debug.c
+          store-bzip2.c store-gzip.c debug.c pager.c
 
 OBJ     = $(SRC:%.c=%.o)
 
diff --git a/main.c b/main.c
index 90286de08..64b48a973 100644
--- a/main.c
+++ b/main.c
@@ -30,6 +30,7 @@
 #include <maptime.h>
 
 #include "backend.h"
+#include "pager.h"
 
 /* Choose the right backend here. */
 extern struct fs_backend tarfs_backend;
diff --git a/pager.c b/pager.c
new file mode 100644
index 000000000..ecd564020
--- /dev/null
+++ b/pager.c
@@ -0,0 +1,117 @@
+#include <errno.h>
+#include <assert-backtrace.h>
+#include <error.h>
+#include <string.h>
+#include <sys/mman.h>
+
+#include <hurd.h>
+#include <hurd/netfs.h>
+#include <hurd/pager.h>
+
+#include "pager.h"
+#include "cache.h"
+#include "backend.h"
+
+error_t
+pager_read_page (struct user_pager_info *upi, vm_offset_t page,
+                 vm_address_t *buf, int *writelock)
+{
+  error_t err;
+  struct node *node;
+  size_t actual;
+  void *data;
+
+  data = mmap (0, vm_page_size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+  if (data == MAP_FAILED)
+    return ENOSPC;
+  *buf = (vm_address_t) data;
+
+  node = (struct node *) upi;
+
+  pthread_mutex_lock (&node->lock);
+  err = cache_read (node, page, vm_page_size, data, &actual);
+  pthread_mutex_unlock (&node->lock);
+
+  if (err)
+    {
+      munmap (data, vm_page_size);
+      return err;
+    }
+
+  memset(data + actual, 0, vm_page_size - actual);
+  *writelock = 1;
+
+  return 0;
+}
+
+error_t
+pager_write_page (struct user_pager_info *upi,
+                  vm_offset_t page,
+                  vm_address_t buf)
+{
+  assert_backtrace (!"we only create read-only pages");
+}
+
+error_t
+pager_unlock_page (struct user_pager_info *upi,
+                   vm_offset_t address)
+{
+  return EROFS;
+}
+
+void
+pager_notify_evict (struct user_pager_info *upi,
+                    vm_offset_t page)
+{
+  assert_backtrace (!"unrequested notification on eviction");
+}
+
+/* Tell how big the file is. */
+error_t
+pager_report_extent (struct user_pager_info *upi,
+                     vm_address_t *offset,
+                     vm_size_t *size)
+{
+  struct node *node;
+
+  node = (struct node *) upi;
+  *offset = 0;
+  *size = node->nn_stat.st_size;
+  return 0;
+}
+
+error_t
+create_pager (struct node *node, memory_object_t *obj)
+{
+  struct pager *pager;
+
+  /* The pager holds a hard reference on the node. */
+  netfs_nref (node);
+  pager = pager_create ((struct user_pager_info *) node, tarfs_pager_bucket,
+                        1, MEMORY_OBJECT_COPY_NONE, 0);
+  if (!pager)
+    return errno;
+
+  NODE_INFO(node)->pager = pager;
+
+  *obj = pager_get_port (pager);
+  ports_port_deref (pager);
+
+  return 0;
+}
+
+void
+pager_clear_user_data (struct user_pager_info *upi)
+{
+  struct node *node;
+
+  node = (struct node *) upi;
+  NODE_INFO(node)->pager = NULL;
+  netfs_nrele (node);
+}
+
+void
+pager_dropweak (struct user_pager_info *upi)
+{
+}
+
diff --git a/pager.h b/pager.h
new file mode 100644
index 000000000..34447c8c9
--- /dev/null
+++ b/pager.h
@@ -0,0 +1,9 @@
+#ifndef PAGER_H
+#define PAGER_H
+
+struct user_pager_info;
+extern struct port_bucket *tarfs_pager_bucket;
+
+error_t create_pager (struct node *node, memory_object_t *obj);
+
+#endif  /* PAGER_H_ */
diff --git a/tarfs.c b/tarfs.c
index c1d9a5cc1..2f5c53dad 100644
--- a/tarfs.c
+++ b/tarfs.c
@@ -18,6 +18,7 @@
 
 #include <hurd.h>
 #include <hurd/netfs.h>
+#include <hurd/pager.h>
 
 #include <stdlib.h>
 #include <unistd.h>
@@ -36,6 +37,7 @@
 #include "cache.h"
 #include "zipstores.h"
 #include "debug.h"
+#include "pager.h"
 
 /* New netfs variables */
 char *netfs_server_name = "tarfs";
@@ -1013,8 +1015,24 @@ tarfs_mkdev_node (struct node *node, mode_t type, dev_t 
indexes)
 error_t
 tarfs_io_map (struct node *node, memory_object_t *rdobj, memory_object_t 
*wrobj)
 {
-  error (0, 0, "Warning: io_map () not supported");
-  return EOPNOTSUPP;
+  error_t err;
+  memory_object_t obj;
+
+  if (!NODE_INFO(node)->pager)
+    {
+      err = create_pager (node, &obj);
+      if (err)
+        return err;
+    }
+  else
+    obj = pager_get_port (NODE_INFO(node)->pager);
+
+  if (rdobj)
+    *rdobj = obj;
+  if (wrobj)
+    *wrobj = MACH_PORT_NULL;
+
+  return 0;
 }
 
 
diff --git a/tarfs.h b/tarfs.h
index 2cc55ac92..1986fa2be 100644
--- a/tarfs.h
+++ b/tarfs.h
@@ -132,6 +132,8 @@ struct tarfs_info
   struct cache    cache;
 
   int stat_changed;    /* TRUE when stat changed.  */
+
+  struct pager *pager;
 };
 
 /* The following macros take struct node *_N as an argument. */
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]