]> Zhao Yanbai Git Server - minix.git/commitdiff
ext2: perform super I/O with contiguous memory 78/2878/2
authorDavid van Moolenbroek <david@minix3.org>
Sun, 9 Nov 2014 12:59:39 +0000 (12:59 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Tue, 11 Nov 2014 21:43:55 +0000 (21:43 +0000)
Issue reported by Antoine Leca.

Change-Id: Ie6f3ab6c1943b0b7ea9d5a68d4c24b92bab17233

minix/fs/ext2/super.c

index 15976a06411d0a076e01226b26987612f8c784cc..a727ecf816b9f049b26d94eabd7fe6ae2596afec 100644 (file)
@@ -17,6 +17,7 @@
 #include <minix/bdev.h>
 #include <machine/param.h>
 #include <machine/vmparam.h>
+#include <sys/mman.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
@@ -74,10 +75,13 @@ register struct super_block *sp; /* pointer to a superblock */
   /* group descriptors, sp->s_group_desc points to this. */
   static struct group_desc *group_descs;
   block_t gd_size; /* group descriptors table size in blocks */
-  int gdt_position;
-  static char superblock_buf[1024];
+  u64_t gdt_position;
+  size_t off, chunk;
 
-  ondisk_superblock = (struct super_block *) superblock_buf;
+  ondisk_superblock = (struct super_block *)mmap(NULL, SUPER_SIZE_D,
+       PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+  if (ondisk_superblock == MAP_FAILED)
+       panic("can't allocate buffer for super block");
 
   dev = sp->s_dev;              /* save device (will be overwritten by copy) */
   if (dev == NO_DEV)
@@ -90,10 +94,10 @@ register struct super_block *sp; /* pointer to a superblock */
        super_block_offset = opt.block_with_super * 1024;
   }
 
-  r = bdev_read(dev, ((u64_t)(super_block_offset)), (char*) ondisk_superblock,
-       sizeof(superblock_buf), BDEV_NOFLAGS);
+  r = bdev_read(dev, super_block_offset, (char*) ondisk_superblock,
+       SUPER_SIZE_D, BDEV_NOFLAGS);
 
-  if (r != sizeof(superblock_buf))
+  if (r != SUPER_SIZE_D)
        return(EINVAL);
 
   super_copy(sp, ondisk_superblock);
@@ -150,7 +154,9 @@ register struct super_block *sp; /* pointer to a superblock */
 
   if(!(group_descs = malloc(gd_size * sizeof(struct group_desc))))
        panic("can't allocate group desc array");
-  if(!(ondisk_group_descs = malloc(gd_size * sizeof(struct group_desc))))
+  ondisk_group_descs = mmap(NULL, gd_size * sizeof(struct group_desc),
+       PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
+  if (ondisk_group_descs == MAP_FAILED)
        panic("can't allocate group desc array");
 
   /* s_first_data_block (block number, where superblock is stored)
@@ -168,11 +174,18 @@ register struct super_block *sp; /* pointer to a superblock */
        gdt_position = (opt.block_with_super + 1) * 1024;
   }
 
-  r = bdev_read(dev, ((u64_t)(gdt_position)), (char*) ondisk_group_descs,
-       gd_size, BDEV_NOFLAGS);
-  if (r != (ssize_t) gd_size) {
-       printf("Can not read group descriptors\n");
-       return(EINVAL);
+  /* The driver requires contiguous memory chunks, so use page granularity. */
+  for (off = 0; off < gd_size; off += chunk) {
+       chunk = gd_size - off;
+       if (chunk > PAGE_SIZE)
+               chunk = PAGE_SIZE;
+
+       r = bdev_read(dev, gdt_position + off,
+           (char *)ondisk_group_descs + off, chunk, BDEV_NOFLAGS);
+       if (r != (ssize_t)chunk) {
+               printf("Can not read group descriptors\n");
+               return(EINVAL);
+       }
   }
 
   /* TODO: check descriptors we just read */
@@ -211,7 +224,8 @@ struct super_block *sp; /* pointer to a superblock */
 /* Write a superblock and gdt. */
   int r;
   block_t gd_size; /* group descriptors table size in blocks */
-  int gdt_position;
+  u64_t gdt_position;
+  size_t off, chunk;
 
   if (sp->s_rd_only)
        panic("can't write superblock on read-only filesys.");
@@ -221,8 +235,8 @@ struct super_block *sp; /* pointer to a superblock */
 
   super_copy(ondisk_superblock, sp);
 
-  r = bdev_write(sp->s_dev, ((u64_t)(super_block_offset)), (char *) sp,
-       SUPER_SIZE_D, BDEV_NOFLAGS);
+  r = bdev_write(sp->s_dev, super_block_offset, (char *) sp, SUPER_SIZE_D,
+       BDEV_NOFLAGS);
   if (r != SUPER_SIZE_D)
        printf("ext2: Warning, failed to write superblock to the disk!\n");
 
@@ -239,11 +253,19 @@ struct super_block *sp; /* pointer to a superblock */
         copy_group_descriptors(ondisk_group_descs, sp->s_group_desc,
                               sp->s_groups_count);
 
-       r = bdev_write(sp->s_dev, ((u64_t)(gdt_position)),
-               (char*) ondisk_group_descs, gd_size, BDEV_NOFLAGS);
-       if (r != (ssize_t) gd_size) {
-               printf("Can not write group descriptors\n");
+       /* As above. Yes, lame. */
+       for (off = 0; off < gd_size; off += chunk) {
+               chunk = gd_size - off;
+               if (chunk > PAGE_SIZE)
+                       chunk = PAGE_SIZE;
+
+               r = bdev_write(sp->s_dev, gdt_position + off,
+                   (char *)ondisk_group_descs + off, chunk, BDEV_NOFLAGS);
+               if (r != (ssize_t)chunk) {
+                       printf("Can not write group descriptors\n");
+               }
        }
+
        group_descriptors_dirty = 0;
   }
 }