aboutsummaryrefslogtreecommitdiff
path: root/lib/libufs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libufs')
-rw-r--r--lib/libufs/Makefile3
-rw-r--r--lib/libufs/cgread.3118
-rw-r--r--lib/libufs/cgroup.c68
-rw-r--r--lib/libufs/libufs.35
-rw-r--r--lib/libufs/libufs.h2
5 files changed, 155 insertions, 41 deletions
diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile
index c80183d3b428..d24526e829c1 100644
--- a/lib/libufs/Makefile
+++ b/lib/libufs/Makefile
@@ -12,7 +12,10 @@ MAN= bread.3 cgread.3 libufs.3 sbread.3 ufs_disk_close.3
MLINKS+= bread.3 bwrite.3
MLINKS+= bread.3 berase.3
MLINKS+= cgread.3 cgread1.3
+MLINKS+= cgread.3 cgget.3
+MLINKS+= cgread.3 cgwrite.3
MLINKS+= cgread.3 cgwrite1.3
+MLINKS+= cgread.3 cgput.3
MLINKS+= sbread.3 sbwrite.3
MLINKS+= ufs_disk_close.3 ufs_disk_fillout.3
MLINKS+= ufs_disk_close.3 ufs_disk_fillout_blank.3
diff --git a/lib/libufs/cgread.3 b/lib/libufs/cgread.3
index 28feaad11764..1feb93bed133 100644
--- a/lib/libufs/cgread.3
+++ b/lib/libufs/cgread.3
@@ -2,19 +2,22 @@
.\" Date: June 04, 2003
.\" Description:
.\" Manual page for libufs functions:
+.\" cgget(3)
+.\" cgput(3)
.\" cgread(3)
.\" cgread1(3)
+.\" cgwrite(3)
.\" cgwrite1(3)
.\"
.\" This file is in the public domain.
.\"
.\" $FreeBSD$
.\"
-.Dd June 4, 2003
+.Dd January 19, 2018
.Dt CGREAD 3
.Os
.Sh NAME
-.Nm cgread , cgread1, cgwrite1
+.Nm cgget , cgput , cgread , cgread1 , cgwrite , cgwrite1
.Nd read/write cylinder groups of UFS disks
.Sh LIBRARY
.Lb libufs
@@ -26,30 +29,72 @@
.In ufs/ffs/fs.h
.In libufs.h
.Ft int
+.Fn cgget "struct uufsd *disk" "int cg" "struct cg *cgp"
+.Ft int
+.Fn cgput "struct uufsd *disk" "struct cg *cgp"
+.Ft int
.Fn cgread "struct uufsd *disk"
.Ft int
-.Fn cgread1 "struct uufsd *disk" "int c"
+.Fn cgread1 "struct uufsd *disk" "int cg"
+.Ft int
+.Fn cgwrite "struct uufsd *disk"
.Ft int
-.Fn cgwrite1 "struct uufsd *disk" "int c"
+.Fn cgwrite1 "struct uufsd *disk" "int cg"
.Sh DESCRIPTION
The
-.Fn cgread
+.Fn cgget ,
+.Fn cgread ,
and
.Fn cgread1
functions provide cylinder group reads for
.Xr libufs 3
consumers.
The
+.Fn cgput ,
+.Fn cgwrite ,
+and
+.Fn cgwrite1
+functions provide cylinder group writes for
+.Xr libufs 3
+consumers.
+.Pp
+The
+.Fn cgget
+function reads the cylinder group specified by
+.Fa cg
+into the buffer pointed to by
+.Fa cgp
+from the disk referenced by the user-land UFS-disk structure.
+The
+.Fn cgget
+function is the only cylinder group read function that is safe to use
+in threaded applications.
+.Pp
+The
+.Fn cgput
+function writes the cylinder group specified by
+.Va cgp
+to the disk referenced by the user-land UFS-disk structure.
+The
+.Fn cgput
+function is the only cylinder group write function that is safe to use
+in threaded applications.
+Note that the
+.Fn cgput
+function needs to be called only if the cylinder group has been
+modified and the on-disk copy needs to be updated.
+.Pp
+The
.Fn cgread1
-function reads from one cylinder group, specified by
-.Fa c
+function reads from the cylinder group specified by
+.Fa cg
into the
.Va d_cg
-field of a userland UFS disk structure.
+cylinder-group structure in a user-land UFS-disk structure.
It sets the
.Va d_lcg
field to the cylinder group number
-.Fa c .
+.Fa cg .
.Pp
The
.Fn cgread
@@ -65,34 +110,57 @@ field, and then incrementing the
field.
.Pp
The
-.Fn cgwrite1
-function stores cylinder group specified by
-.Fa c
-from
+.Fn cgwrite
+function stores on disk the cylinder group held in the
.Va d_cg
-field of a userland UFS disk structure on disk.
+cylinder-group structure in a user-land UFS-disk structure.
+.Pp
+The
+.Fn cgwrite1
+function provides no additional functionality over the
+.Fn cgwrite
+function as there is only one place that a given cylinder group
+can correctly be written.
+If the caller gets the
+.Fa cg
+parameter wrong, the function fails with the error
+.Er EDOOFUS .
+This function remains only to provide backward compatibility.
.Sh RETURN VALUES
-Both functions return 0 if there are no more cylinder groups to read,
+The
+.Fn cgread
+function returns 0 if there are no more cylinder groups to read,
1 if there are more cylinder groups, and \-1 on error.
+The
+.Fn cgread1
+function returns 1 on success and \-1 on error.
+The other functions return 0 on success and \-1 on error;
.Sh ERRORS
-The function
-.Fn cgread
-may fail and set
+The
+.Fn cgget ,
+.Fn cgread ,
+and
+.Fn cgread1
+functions may fail and set
.Va errno
for any of the errors specified for the library function
.Xr bread 3 .
.Pp
-The function
-.Fn cgread1
-has semantically identical failure conditions to those of
-.Fn cgread .
-.Pp
-The function
+The
+.Fn cgput ,
+.Fn cgwrite ,
+and
.Fn cgwrite1
-may fail and set
+functions may fail and set
.Va errno
for any of the errors specified for the library function
.Xr bwrite 3 .
+Additionally the
+.Fn cgwrite1
+will return the
+.Er EDOOFUS
+error if the cylinder group specified does not match the
+cylinder group that it is requesting to write.
.Sh SEE ALSO
.Xr bread 3 ,
.Xr bwrite 3 ,
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);
}
diff --git a/lib/libufs/libufs.3 b/lib/libufs/libufs.3
index 5b5dd9b1c898..595df91e0e95 100644
--- a/lib/libufs/libufs.3
+++ b/lib/libufs/libufs.3
@@ -7,7 +7,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 4, 2003
+.Dd January 19, 2018
.Dt LIBUFS 3
.Os
.Sh NAME
@@ -55,8 +55,11 @@ to a string describing the error.
.Sh SEE ALSO
.Xr bread 3 ,
.Xr bwrite 3 ,
+.Xr cgget 3 ,
+.Xr cgput 3 ,
.Xr cgread 3 ,
.Xr cgread1 3 ,
+.Xr cgwrite 3 ,
.Xr cgwrite1 3 ,
.Xr sbread 3 ,
.Xr sbwrite 3 ,
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
index 7201d00b2715..400704596148 100644
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -111,6 +111,8 @@ int berase(struct uufsd *, ufs2_daddr_t, ufs2_daddr_t);
ufs2_daddr_t cgballoc(struct uufsd *);
int cgbfree(struct uufsd *, ufs2_daddr_t, long);
ino_t cgialloc(struct uufsd *);
+int cgget(struct uufsd *, int, struct cg *);
+int cgput(struct uufsd *, struct cg *);
int cgread(struct uufsd *);
int cgread1(struct uufsd *, int);
int cgwrite(struct uufsd *);