diff options
author | jeff <jeff@FreeBSD.org> | 2010-04-24 07:05:35 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2010-04-24 07:05:35 +0000 |
commit | a57449541074720475dfc21dfb8b025695b573eb (patch) | |
tree | e551aa2ab43f7f11c3646b241ebf3f582988d375 /lib/libufs | |
parent | 671efe7b2286fbfddcd385e966f431f529ca6376 (diff) | |
download | FreeBSD-src-a57449541074720475dfc21dfb8b025695b573eb.zip FreeBSD-src-a57449541074720475dfc21dfb8b025695b573eb.tar.gz |
- 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
Diffstat (limited to 'lib/libufs')
-rw-r--r-- | lib/libufs/Makefile | 7 | ||||
-rw-r--r-- | lib/libufs/cgroup.c | 140 | ||||
-rw-r--r-- | lib/libufs/inode.c | 16 | ||||
-rw-r--r-- | lib/libufs/libufs.h | 16 | ||||
-rw-r--r-- | lib/libufs/sblock.c | 50 | ||||
-rw-r--r-- | lib/libufs/type.c | 5 |
6 files changed, 230 insertions, 4 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile index c9232ef..1dfc242 100644 --- a/lib/libufs/Makefile +++ b/lib/libufs/Makefile @@ -3,7 +3,7 @@ LIB= ufs SHLIBDIR?= /lib -SRCS= block.c cgroup.c inode.c sblock.c type.c +SRCS= block.c cgroup.c inode.c sblock.c type.c ffs_subr.c ffs_tables.c INCS= libufs.h MAN= bread.3 cgread.3 libufs.3 sbread.3 ufs_disk_close.3 @@ -16,8 +16,11 @@ MLINKS+= ufs_disk_close.3 ufs_disk_fillout.3 MLINKS+= ufs_disk_close.3 ufs_disk_fillout_blank.3 MLINKS+= ufs_disk_close.3 ufs_disk_write.3 -WARNS?= 3 +.PATH: ${.CURDIR}/../../sys/ufs/ffs +WARNS?= 2 + +DEBUG_FLAGS = -g CFLAGS+= -D_LIBUFS .if defined(LIBUFS_DEBUG) CFLAGS+= -D_LIBUFS_DEBUGGING diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c index 28e5ea8..b0cb4a7 100644 --- a/lib/libufs/cgroup.c +++ b/lib/libufs/cgroup.c @@ -40,11 +40,143 @@ __FBSDID("$FreeBSD$"); #include <errno.h> #include <fcntl.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> #include <libufs.h> +ufs2_daddr_t +cgballoc(struct uufsd *disk) +{ + u_int8_t *blksfree; + struct cg *cgp; + struct fs *fs; + long bno; + + fs = &disk->d_fs; + cgp = &disk->d_cg; + blksfree = cg_blksfree(cgp); + for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++) + if (ffs_isblock(fs, blksfree, bno)) + goto gotit; + return (0); +gotit: + fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--; + ffs_clrblock(fs, blksfree, (long)bno); + ffs_clusteracct(fs, cgp, bno, -1); + cgp->cg_cs.cs_nbfree--; + fs->fs_cstotal.cs_nbfree--; + fs->fs_fmod = 1; + return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno)); +} + +int +cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size) +{ + u_int8_t *blksfree; + struct fs *fs; + struct cg *cgp; + ufs1_daddr_t fragno, cgbno; + int i, cg, blk, frags, bbase; + + fs = &disk->d_fs; + cg = dtog(fs, bno); + if (cgread1(disk, cg) != 1) + return (-1); + cgp = &disk->d_cg; + cgbno = dtogd(fs, bno); + blksfree = cg_blksfree(cgp); + if (size == fs->fs_bsize) { + fragno = fragstoblks(fs, cgbno); + ffs_setblock(fs, blksfree, fragno); + ffs_clusteracct(fs, cgp, fragno, 1); + cgp->cg_cs.cs_nbfree++; + fs->fs_cstotal.cs_nbfree++; + fs->fs_cs(fs, cg).cs_nbfree++; + } else { + bbase = cgbno - fragnum(fs, cgbno); + /* + * decrement the counts associated with the old frags + */ + blk = blkmap(fs, blksfree, bbase); + ffs_fragacct(fs, blk, cgp->cg_frsum, -1); + /* + * deallocate the fragment + */ + frags = numfrags(fs, size); + for (i = 0; i < frags; i++) + setbit(blksfree, cgbno + i); + cgp->cg_cs.cs_nffree += i; + fs->fs_cstotal.cs_nffree += i; + fs->fs_cs(fs, cg).cs_nffree += i; + /* + * add back in counts associated with the new frags + */ + blk = blkmap(fs, blksfree, bbase); + ffs_fragacct(fs, blk, cgp->cg_frsum, 1); + /* + * if a complete block has been reassembled, account for it + */ + fragno = fragstoblks(fs, bbase); + if (ffs_isblock(fs, blksfree, fragno)) { + cgp->cg_cs.cs_nffree -= fs->fs_frag; + fs->fs_cstotal.cs_nffree -= fs->fs_frag; + fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag; + ffs_clusteracct(fs, cgp, fragno, 1); + cgp->cg_cs.cs_nbfree++; + fs->fs_cstotal.cs_nbfree++; + fs->fs_cs(fs, cg).cs_nbfree++; + } + } + return cgwrite(disk); +} + +ino_t +cgialloc(struct uufsd *disk) +{ + struct ufs2_dinode *dp2; + u_int8_t *inosused; + struct cg *cgp; + struct fs *fs; + ino_t ino; + int i; + + fs = &disk->d_fs; + cgp = &disk->d_cg; + inosused = cg_inosused(cgp); + for (ino = 0; ino < fs->fs_ipg / NBBY; ino++) + if (isclr(inosused, ino)) + goto gotit; + return (0); +gotit: + if (fs->fs_magic == FS_UFS2_MAGIC && + ino + INOPB(fs) > cgp->cg_initediblk && + cgp->cg_initediblk < cgp->cg_niblk) { + char block[MAXBSIZE]; + bzero(block, (int)fs->fs_bsize); + dp2 = (struct ufs2_dinode *)█ + for (i = 0; i < INOPB(fs); i++) { + dp2->di_gen = arc4random() / 2 + 1; + dp2++; + } + if (bwrite(disk, ino_to_fsba(fs, + cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk), + block, fs->fs_bsize)) + return (0); + cgp->cg_initediblk += INOPB(fs); + } + + setbit(inosused, ino); + cgp->cg_irotor = ino; + cgp->cg_cs.cs_nifree--; + fs->fs_cstotal.cs_nifree--; + fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--; + fs->fs_fmod = 1; + + return (ino + (cgp->cg_cgx * fs->fs_ipg)); +} + int cgread(struct uufsd *disk) { @@ -55,14 +187,12 @@ int cgread1(struct uufsd *disk, int c) { struct fs *fs; - off_t ccg; fs = &disk->d_fs; if ((unsigned)c >= fs->fs_ncg) { return (0); } - ccg = fsbtodb(fs, cgtod(fs, c)) * disk->d_bsize; if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf, fs->fs_bsize) == -1) { ERROR(disk, "unable to read cylinder group"); @@ -73,6 +203,12 @@ cgread1(struct uufsd *disk, int c) } int +cgwrite(struct uufsd *disk) +{ + return (cgwrite1(disk, disk->d_lcg)); +} + +int cgwrite1(struct uufsd *disk, int c) { struct fs *fs; diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c index d8bef61..6d94582 100644 --- a/lib/libufs/inode.c +++ b/lib/libufs/inode.c @@ -93,3 +93,19 @@ gotit: switch (disk->d_ufs) { ERROR(disk, "unknown UFS filesystem type"); return (-1); } + +int +putino(struct uufsd *disk) +{ + struct fs *fs; + + fs = &disk->d_fs; + if (disk->d_inoblock == NULL) { + ERROR(disk, "No inode block allocated"); + return (-1); + } + if (bwrite(disk, fsbtodb(fs, ino_to_fsba(&disk->d_fs, disk->d_inomin)), + disk->d_inoblock, disk->d_fs.fs_bsize) <= 0) + return (-1); + return (0); +} diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h index 42a64f7..c3541a0 100644 --- a/lib/libufs/libufs.h +++ b/lib/libufs/libufs.h @@ -71,6 +71,7 @@ struct uufsd { int d_fd; /* raw device file descriptor */ long d_bsize; /* device bsize */ ufs2_daddr_t d_sblock; /* superblock location */ + struct csum *d_sbcsum; /* Superblock summary info */ caddr_t d_inoblock; /* inode block */ ino_t d_inomin; /* low inode */ ino_t d_inomax; /* high inode */ @@ -109,14 +110,19 @@ int berase(struct uufsd *, ufs2_daddr_t, ufs2_daddr_t); /* * cgroup.c */ +ufs2_daddr_t cgballoc(struct uufsd *); +int cgbfree(struct uufsd *, ufs2_daddr_t, long); +ino_t cgialloc(struct uufsd *); int cgread(struct uufsd *); int cgread1(struct uufsd *, int); +int cgwrite(struct uufsd *); int cgwrite1(struct uufsd *, int); /* * inode.c */ int getino(struct uufsd *, void **, ino_t, int *); +int putino(struct uufsd *); /* * sblock.c @@ -132,6 +138,16 @@ int ufs_disk_fillout(struct uufsd *, const char *); int ufs_disk_fillout_blank(struct uufsd *, const char *); int ufs_disk_write(struct uufsd *); +/* + * ffs_subr.c + */ +void ffs_clrblock(struct fs *, u_char *, ufs1_daddr_t); +void ffs_clusteracct(struct fs *, struct cg *, ufs1_daddr_t, int); +void ffs_fragacct(struct fs *, int, int32_t [], int); +int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t); +int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t); +void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); + __END_DECLS #endif /* __LIBUFS_H__ */ diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c index 8986290..d6bec3e 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)), diff --git a/lib/libufs/type.c b/lib/libufs/type.c index 8a553be..05904b9 100644 --- a/lib/libufs/type.c +++ b/lib/libufs/type.c @@ -66,6 +66,10 @@ ufs_disk_close(struct uufsd *disk) free((char *)(uintptr_t)disk->d_name); disk->d_name = NULL; } + if (disk->d_sbcsum != NULL) { + free(disk->d_sbcsum); + disk->d_sbcsum = NULL; + } return (0); } @@ -156,6 +160,7 @@ again: if ((ret = stat(name, &st)) < 0) { disk->d_mine = 0; disk->d_ufs = 0; disk->d_error = NULL; + disk->d_sbcsum = NULL; if (oname != name) { name = strdup(name); |