aboutsummaryrefslogtreecommitdiff
path: root/lib/libufs/cgroup.c
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2018-01-17 17:58:24 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2018-01-17 17:58:24 +0000
commit72f854ce8f359100d957a07da44ae98591d3dfd9 (patch)
tree6603c949e870e1510902951cb2391e730e174006 /lib/libufs/cgroup.c
parent64e12b4140ffeaea04b7230d506ee0326e3b077d (diff)
downloadsrc-72f854ce8f359100d957a07da44ae98591d3dfd9.tar.gz
src-72f854ce8f359100d957a07da44ae98591d3dfd9.zip
Correct fsck journal-recovery code to update a cylinder-group
check-hash after making changes to the cylinder group. The problem was that the journal-recovery code was calling the libufs bwrite() function instead of the cgput() function. The cgput() function updates the cylinder-group check-hash before writing the cylinder group. This change required the additions of the cgget() and cgput() functions to the libufs API to avoid a gratuitous bcopy of every cylinder group to be read or written. These new functions have been added to the libufs manual pages. This was the first opportunity that I have had to use and document the use of the EDOOFUS error code. Reviewed by: kib Reported by: emaste and others
Notes
Notes: svn path=/head/; revision=328092
Diffstat (limited to 'lib/libufs/cgroup.c')
-rw-r--r--lib/libufs/cgroup.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c
index 319629c338f4..1f42155ba4e7 100644
--- a/lib/libufs/cgroup.c
+++ b/lib/libufs/cgroup.c
@@ -182,47 +182,85 @@ gotit:
int
cgread(struct uufsd *disk)
{
+
+ if (disk->d_ccg >= disk->d_fs.fs_ncg)
+ return (0);
return (cgread1(disk, disk->d_ccg++));
}
int
cgread1(struct uufsd *disk, int c)
{
+
+ if ((cgget(disk, c, &disk->d_cg)) == 0)
+ return (1);
+ return (-1);
+}
+
+int
+cgget(struct uufsd *disk, int cg, struct cg *cgp)
+{
struct fs *fs;
+ uint32_t cghash, calchash;
fs = &disk->d_fs;
-
- if ((unsigned)c >= fs->fs_ncg) {
- return (0);
- }
- if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf,
- fs->fs_bsize) == -1) {
+ if (bread(disk, fsbtodb(fs, cgtod(fs, cg)), (void *)cgp,
+ fs->fs_cgsize) == -1) {
ERROR(disk, "unable to read cylinder group");
return (-1);
}
- disk->d_lcg = c;
- return (1);
+ calchash = cgp->cg_ckhash;
+ if ((fs->fs_metackhash & CK_CYLGRP) != 0) {
+ cghash = cgp->cg_ckhash;
+ cgp->cg_ckhash = 0;
+ calchash = calculate_crc32c(~0L, (void *)cgp, fs->fs_cgsize);
+ cgp->cg_ckhash = cghash;
+ }
+ if (cgp->cg_ckhash != calchash || !cg_chkmagic(cgp) ||
+ cgp->cg_cgx != cg) {
+ ERROR(disk, "cylinder group checks failed");
+ errno = EIO;
+ return (-1);
+ }
+ disk->d_lcg = cg;
+ return (0);
}
int
cgwrite(struct uufsd *disk)
{
- return (cgwrite1(disk, disk->d_lcg));
+
+ return (cgput(disk, &disk->d_cg));
+}
+
+int
+cgwrite1(struct uufsd *disk, int cg)
+{
+ static char errmsg[BUFSIZ];
+
+ if (cg == disk->d_cg.cg_cgx)
+ return (cgput(disk, &disk->d_cg));
+ snprintf(errmsg, BUFSIZ, "Cylinder group %d in buffer does not match "
+ "the cylinder group %d that cgwrite1 requested",
+ disk->d_cg.cg_cgx, cg);
+ ERROR(disk, errmsg);
+ errno = EDOOFUS;
+ return (-1);
}
int
-cgwrite1(struct uufsd *disk, int c)
+cgput(struct uufsd *disk, struct cg *cgp)
{
struct fs *fs;
fs = &disk->d_fs;
if ((fs->fs_metackhash & CK_CYLGRP) != 0) {
- disk->d_cg.cg_ckhash = 0;
- disk->d_cg.cg_ckhash =
- calculate_crc32c(~0L, (void *)&disk->d_cg, fs->fs_cgsize);
+ cgp->cg_ckhash = 0;
+ cgp->cg_ckhash =
+ calculate_crc32c(~0L, (void *)cgp, fs->fs_cgsize);
}
- if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)),
- disk->d_cgunion.d_buf, fs->fs_bsize) == -1) {
+ if (bwrite(disk, fsbtodb(fs, cgtod(fs, cgp->cg_cgx)), cgp,
+ fs->fs_cgsize) == -1) {
ERROR(disk, "unable to write cylinder group");
return (-1);
}