summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Planeta <mcsim.planeta@gmail.com>2012-10-03 18:22:26 +0300
committerMaksym Planeta <mcsim.planeta@gmail.com>2012-10-07 21:30:46 +0300
commit17a27ad8454a1abca714819500c20a3eda427455 (patch)
tree6242d4ac35281ee6c4540152719f6338af32d8a4
parente69fd4bf4e3e130f66526f1df78e2c197c5ba100 (diff)
Move UFS to new pager interface.
This implementation transfers data by one page and uses nested functions. * ufs/pager.c (ufs_read_page): Function renamed. Old name was pager_read_page. (ufs_write_page): Function renamed. Old name was pager_write_page. (ufs_unlock_page): Function renamed. Old name was pager_unlock_page. (ufs_report_extent): Function renamed. Old name was pager_report_extent. (ufs_clear_user_data): Function renamed. Old name was pager_clear_user_data. (pager_dropweak): Delete obsolete function. (ufs_read_pages): New function. (ufs_write_pages): New function. (ufs_unlock_pages): New function. (ufs_ops): New structure. (create_disk_pager): Function changed. (diskfs_get_filemap): Likewise. * ufs/sizes.c (offer_data): Function changed.
-rw-r--r--ufs/pager.c167
-rw-r--r--ufs/sizes.c6
2 files changed, 126 insertions, 47 deletions
diff --git a/ufs/pager.c b/ufs/pager.c
index 3038932d..e633924b 100644
--- a/ufs/pager.c
+++ b/ufs/pager.c
@@ -153,13 +153,13 @@ find_address (struct user_pager_info *upi,
}
-/* Implement the pager_read_page callback from the pager library. See
+/* Implement the read_page callback from the pager library. See
<hurd/pager.h> for the interface description. */
error_t
-pager_read_page (struct user_pager_info *pager,
- vm_offset_t page,
- vm_address_t *buf,
- int *writelock)
+ufs_read_page (struct user_pager_info *pager,
+ vm_offset_t page,
+ vm_address_t *buf,
+ int *writelock)
{
error_t err;
struct rwlock *nplock;
@@ -198,12 +198,34 @@ pager_read_page (struct user_pager_info *pager,
return err;
}
-/* Implement the pager_write_page callback from the pager library. See
+void
+ufs_read_pages (struct pager *pager, struct user_pager_info *upi,
+ off_t start, off_t npages)
+{
+ off_t offset = start * vm_page_size;
+ int writelock;
+ void *buf;
+ int i;
+
+ for (i = start; i < start + npages; i++, offset += vm_page_size)
+ {
+ error_t err = ufs_read_page (upi, offset, (vm_address_t *)&buf,
+ &writelock);
+
+ if (!err)
+ pager_data_supply (pager, 0 /* precious */, writelock,
+ i, 1, buf, 1 /* dealloc */);
+ else
+ pager_data_read_error (pager, i, 1, err);
+ }
+}
+
+/* Implement the write_page callback from the pager library. See
<hurd/pager.h> for the interface description. */
error_t
-pager_write_page (struct user_pager_info *pager,
- vm_offset_t page,
- vm_address_t buf)
+ufs_write_page (struct user_pager_info *pager,
+ vm_offset_t page,
+ vm_address_t buf)
{
daddr_t addr;
int disksize;
@@ -231,11 +253,43 @@ pager_write_page (struct user_pager_info *pager,
return err;
}
+void
+ufs_write_pages (struct pager *pager, struct user_pager_info *upi,
+ off_t start, off_t npages, void *buf, int dealloc)
+{
+ void *cur_buf = buf;
+
+ inline error_t process_code (off_t block_offset)
+ {
+ error_t err = ufs_write_page (upi, block_offset, (vm_address_t)cur_buf);
+ cur_buf += vm_page_size;
+ return err;
+ }
+
+ inline void no_error_code (off_t range_start, off_t range_len)
+ {
+ return;
+ }
+
+ inline void error_code (error_t err, off_t range_start, off_t range_len)
+ {
+ off_t err_pages = round_page (range_len) / vm_page_size;
+ pager_data_write_error (pager, start, err_pages, err);
+ }
+
+ pager_process_pages (start, npages, vm_page_size,
+ process_code, no_error_code, error_code);
+
+ if (dealloc)
+ vm_deallocate (mach_task_self (), (vm_address_t) buf,
+ npages * vm_page_size);
+}
+
/* Implement the pager_unlock_page callback from the pager library. See
<hurd/pager.h> for the interface description. */
error_t
-pager_unlock_page (struct user_pager_info *pager,
- vm_offset_t address)
+ufs_unlock_page (struct user_pager_info *pager,
+ vm_offset_t address)
{
struct node *np;
error_t err;
@@ -425,29 +479,52 @@ pager_unlock_page (struct user_pager_info *pager,
return err;
}
-/* Implement the pager_report_extent callback from the pager library. See
+void
+ufs_unlock_pages (struct pager *pager,
+ struct user_pager_info *upi,
+ off_t start, off_t npages)
+{
+
+ inline error_t process_code (off_t block_offset)
+ {
+ return ufs_unlock_page (upi, block_offset);
+ }
+
+ inline void no_error_code (off_t range_start, off_t range_len)
+ {
+ pager_data_unlock (pager, range_start, range_len / vm_page_size);
+ }
+
+ inline void error_code (error_t err, off_t range_start, off_t range_len)
+ {
+ off_t err_pages = round_page (range_len) / vm_page_size;
+ pager_data_unlock_error (pager, range_start, err_pages, err);
+ }
+
+ pager_process_pages (start, npages, vm_page_size,
+ process_code, no_error_code, error_code);
+}
+
+/* Implement the report_extent callback from the pager library. See
<hurd/pager.h> for the interface description. */
-inline error_t
-pager_report_extent (struct user_pager_info *pager,
- vm_address_t *offset,
- vm_size_t *size)
+void
+ufs_report_extent (struct user_pager_info *upi,
+ off_t *offset, off_t *size)
{
- assert (pager->type == DISK || pager->type == FILE_DATA);
+ assert (upi->type == DISK || upi->type == FILE_DATA);
*offset = 0;
- if (pager->type == DISK)
+ if (upi->type == DISK)
*size = store->size;
else
- *size = pager->np->allocsize;
-
- return 0;
+ *size = upi->np->allocsize;
}
-/* Implement the pager_clear_user_data callback from the pager library.
+/* Implement the clear_user_data callback from the pager library.
See <hurd/pager.h> for the interface description. */
void
-pager_clear_user_data (struct user_pager_info *upi)
+ufs_clear_user_data (struct user_pager_info *upi)
{
/* XXX Do the right thing for the disk pager here too. */
if (upi->type == FILE_DATA)
@@ -458,27 +535,31 @@ pager_clear_user_data (struct user_pager_info *upi)
spin_unlock (&node2pagelock);
diskfs_nrele_light (upi->np);
}
- free (upi);
-}
-
-void
-pager_dropweak (struct user_pager_info *upi __attribute__ ((unused)))
-{
}
+struct pager_ops ufs_ops =
+ {
+ .read = &ufs_read_pages,
+ .write = &ufs_write_pages,
+ .unlock = &ufs_unlock_pages,
+ .report_extent = &ufs_report_extent,
+ .clear_user_data = &ufs_clear_user_data,
+ .dropweak = NULL
+ };
/* Create the DISK pager. */
void
create_disk_pager (void)
{
- struct user_pager_info *upi = malloc (sizeof (struct user_pager_info));
+ struct user_pager_info *upi;
+ pager_bucket = ports_create_bucket ();
+ diskfs_start_disk_pager (&ufs_ops, sizeof (*upi), pager_bucket,
+ MAY_CACHE, store->size, &disk_image);
+ upi = pager_get_upi (diskfs_disk_pager);
upi->type = DISK;
upi->np = 0;
- pager_bucket = ports_create_bucket ();
- diskfs_start_disk_pager (upi, pager_bucket, MAY_CACHE, store->size,
- &disk_image);
upi->p = diskfs_disk_pager;
}
@@ -562,22 +643,22 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
do
if (!np->dn->fileinfo)
{
- upi = malloc (sizeof (struct user_pager_info));
+ struct pager *temp;
+ temp = pager_create (&ufs_ops, sizeof (*upi), pager_bucket,
+ MAY_CACHE, MEMORY_OBJECT_COPY_DELAY);
+ if (temp == 0)
+ {
+ spin_unlock (&node2pagelock);
+ return MACH_PORT_NULL;
+ }
+ upi = pager_get_upi (temp);
upi->type = FILE_DATA;
upi->np = np;
upi->max_prot = prot;
upi->allow_unlocked_pagein = 0;
upi->unlocked_pagein_length = 0;
diskfs_nref_light (np);
- upi->p = pager_create (upi, pager_bucket,
- MAY_CACHE, MEMORY_OBJECT_COPY_DELAY);
- if (upi->p == 0)
- {
- diskfs_nrele_light (np);
- free (upi);
- spin_unlock (&node2pagelock);
- return MACH_PORT_NULL;
- }
+ upi->p = temp;
np->dn->fileinfo = upi;
right = pager_get_port (np->dn->fileinfo->p);
ports_port_deref (np->dn->fileinfo->p);
diff --git a/ufs/sizes.c b/ufs/sizes.c
index 58cbfc98..fa26a73f 100644
--- a/ufs/sizes.c
+++ b/ufs/sizes.c
@@ -364,15 +364,13 @@ offer_data (struct node *np,
size_t len,
vm_address_t buf)
{
- vm_address_t addr;
-
len = round_page (len);
assert (start % vm_page_size == 0);
assert (np->dn->fileinfo);
- for (addr = start; addr < start + len; addr += vm_page_size)
- pager_offer_page (np->dn->fileinfo->p, 1, 0, addr, buf + (addr - start));
+ pager_data_supply (np->dn->fileinfo->p, 1, 0, start / vm_page_size,
+ len / vm_page_size, (void *)buf, 1);
}
/* Logical block LBN of node NP has been extended with ffs_realloccg.