aboutsummaryrefslogtreecommitdiff
path: root/lib/libufs/sblock.c
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2010-04-24 07:05:35 +0000
committerJeff Roberson <jeff@FreeBSD.org>2010-04-24 07:05:35 +0000
commit113db2dddb719510679d71ff41679afe30c8b3d1 (patch)
treee551aa2ab43f7f11c3646b241ebf3f582988d375 /lib/libufs/sblock.c
parent07b9cc2f468471a723504ac789201a84f6dcd38a (diff)
downloadsrc-113db2dddb719510679d71ff41679afe30c8b3d1.tar.gz
src-113db2dddb719510679d71ff41679afe30c8b3d1.zip
- Merge soft-updates journaling from projects/suj/head into head. This
brings in support for an optional intent log which eliminates the need for background fsck on unclean shutdown. Sponsored by: iXsystems, Yahoo!, and Juniper. With help from: McKusick and Peter Holm
Notes
Notes: svn path=/head/; revision=207141
Diffstat (limited to 'lib/libufs/sblock.c')
-rw-r--r--lib/libufs/sblock.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c
index 8986290039fb..d6bec3ed182e 100644
--- a/lib/libufs/sblock.c
+++ b/lib/libufs/sblock.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <unistd.h>
#include <libufs.h>
@@ -49,8 +50,11 @@ static int superblocks[] = SBLOCKSEARCH;
int
sbread(struct uufsd *disk)
{
+ uint8_t block[MAXBSIZE];
struct fs *fs;
int sb, superblock;
+ int i, size, blks;
+ uint8_t *space;
ERROR(disk, NULL);
@@ -86,6 +90,34 @@ sbread(struct uufsd *disk)
}
disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
disk->d_sblock = superblock / disk->d_bsize;
+ /*
+ * Read in the superblock summary information.
+ */
+ size = fs->fs_cssize;
+ blks = howmany(size, fs->fs_fsize);
+ size += fs->fs_ncg * sizeof(int32_t);
+ space = malloc(size);
+ if (space == NULL) {
+ ERROR(disk, "failed to allocate space for summary information");
+ return (-1);
+ }
+ fs->fs_csp = (struct csum *)space;
+ for (i = 0; i < blks; i += fs->fs_frag) {
+ size = fs->fs_bsize;
+ if (i + fs->fs_frag > blks)
+ size = (blks - i) * fs->fs_fsize;
+ if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
+ == -1) {
+ ERROR(disk, "Failed to read sb summary information");
+ free(fs->fs_csp);
+ return (-1);
+ }
+ bcopy(block, space, size);
+ space += size;
+ }
+ fs->fs_maxcluster = (uint32_t *)space;
+ disk->d_sbcsum = fs->fs_csp;
+
return (0);
}
@@ -93,6 +125,8 @@ int
sbwrite(struct uufsd *disk, int all)
{
struct fs *fs;
+ int blks, size;
+ uint8_t *space;
unsigned i;
ERROR(disk, NULL);
@@ -107,6 +141,22 @@ sbwrite(struct uufsd *disk, int all)
ERROR(disk, "failed to write superblock");
return (-1);
}
+ /*
+ * Write superblock summary information.
+ */
+ blks = howmany(fs->fs_cssize, fs->fs_fsize);
+ space = (uint8_t *)disk->d_sbcsum;
+ for (i = 0; i < blks; i += fs->fs_frag) {
+ size = fs->fs_bsize;
+ if (i + fs->fs_frag > blks)
+ size = (blks - i) * fs->fs_fsize;
+ if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
+ == -1) {
+ ERROR(disk, "Failed to write sb summary information");
+ return (-1);
+ }
+ space += size;
+ }
if (all) {
for (i = 0; i < fs->fs_ncg; i++)
if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),