xref: /freebsd/lib/libufs/cgroup.c (revision f0cfa1b168014f56c02b83e5f28412cc5f78d117)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2003 Juli Mallett.  All rights reserved.
5  *
6  * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
7  * FreeBSD project.  Redistribution and use in source and binary forms, with
8  * or without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  * 1. Redistribution of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  * 2. Redistribution in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/mount.h>
35 #include <sys/disklabel.h>
36 #include <sys/stat.h>
37 
38 #include <ufs/ufs/ufsmount.h>
39 #include <ufs/ufs/dinode.h>
40 #include <ufs/ffs/fs.h>
41 
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 
49 #include <libufs.h>
50 
51 ufs2_daddr_t
52 cgballoc(struct uufsd *disk)
53 {
54 	u_int8_t *blksfree;
55 	struct cg *cgp;
56 	struct fs *fs;
57 	long bno;
58 
59 	fs = &disk->d_fs;
60 	cgp = &disk->d_cg;
61 	blksfree = cg_blksfree(cgp);
62 	for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++)
63 		if (ffs_isblock(fs, blksfree, bno))
64 			goto gotit;
65 	return (0);
66 gotit:
67 	fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
68 	ffs_clrblock(fs, blksfree, (long)bno);
69 	ffs_clusteracct(fs, cgp, bno, -1);
70 	cgp->cg_cs.cs_nbfree--;
71 	fs->fs_cstotal.cs_nbfree--;
72 	fs->fs_fmod = 1;
73 	return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno));
74 }
75 
76 int
77 cgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size)
78 {
79 	u_int8_t *blksfree;
80 	struct fs *fs;
81 	struct cg *cgp;
82 	ufs1_daddr_t fragno, cgbno;
83 	int i, cg, blk, frags, bbase;
84 
85 	fs = &disk->d_fs;
86 	cg = dtog(fs, bno);
87 	if (cgread1(disk, cg) != 1)
88 		return (-1);
89 	cgp = &disk->d_cg;
90 	cgbno = dtogd(fs, bno);
91 	blksfree = cg_blksfree(cgp);
92 	if (size == fs->fs_bsize) {
93 		fragno = fragstoblks(fs, cgbno);
94 		ffs_setblock(fs, blksfree, fragno);
95 		ffs_clusteracct(fs, cgp, fragno, 1);
96 		cgp->cg_cs.cs_nbfree++;
97 		fs->fs_cstotal.cs_nbfree++;
98 		fs->fs_cs(fs, cg).cs_nbfree++;
99 	} else {
100 		bbase = cgbno - fragnum(fs, cgbno);
101 		/*
102 		 * decrement the counts associated with the old frags
103 		 */
104 		blk = blkmap(fs, blksfree, bbase);
105 		ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
106 		/*
107 		 * deallocate the fragment
108 		 */
109 		frags = numfrags(fs, size);
110 		for (i = 0; i < frags; i++)
111 			setbit(blksfree, cgbno + i);
112 		cgp->cg_cs.cs_nffree += i;
113 		fs->fs_cstotal.cs_nffree += i;
114 		fs->fs_cs(fs, cg).cs_nffree += i;
115 		/*
116 		 * add back in counts associated with the new frags
117 		 */
118 		blk = blkmap(fs, blksfree, bbase);
119 		ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
120 		/*
121 		 * if a complete block has been reassembled, account for it
122 		 */
123 		fragno = fragstoblks(fs, bbase);
124 		if (ffs_isblock(fs, blksfree, fragno)) {
125 			cgp->cg_cs.cs_nffree -= fs->fs_frag;
126 			fs->fs_cstotal.cs_nffree -= fs->fs_frag;
127 			fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
128 			ffs_clusteracct(fs, cgp, fragno, 1);
129 			cgp->cg_cs.cs_nbfree++;
130 			fs->fs_cstotal.cs_nbfree++;
131 			fs->fs_cs(fs, cg).cs_nbfree++;
132 		}
133 	}
134 	return cgwrite(disk);
135 }
136 
137 ino_t
138 cgialloc(struct uufsd *disk)
139 {
140 	struct ufs2_dinode *dp2;
141 	u_int8_t *inosused;
142 	struct cg *cgp;
143 	struct fs *fs;
144 	ino_t ino;
145 	int i;
146 
147 	fs = &disk->d_fs;
148 	cgp = &disk->d_cg;
149 	inosused = cg_inosused(cgp);
150 	for (ino = 0; ino < fs->fs_ipg; ino++)
151 		if (isclr(inosused, ino))
152 			goto gotit;
153 	return (0);
154 gotit:
155 	if (fs->fs_magic == FS_UFS2_MAGIC &&
156 	    ino + INOPB(fs) > cgp->cg_initediblk &&
157 	    cgp->cg_initediblk < cgp->cg_niblk) {
158 		char block[MAXBSIZE];
159 		bzero(block, (int)fs->fs_bsize);
160 		dp2 = (struct ufs2_dinode *)&block;
161 		for (i = 0; i < INOPB(fs); i++) {
162 			dp2->di_gen = arc4random();
163 			dp2++;
164 		}
165 		if (bwrite(disk, ino_to_fsba(fs,
166 		    cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk),
167 		    block, fs->fs_bsize))
168 			return (0);
169 		cgp->cg_initediblk += INOPB(fs);
170 	}
171 
172 	setbit(inosused, ino);
173 	cgp->cg_irotor = ino;
174 	cgp->cg_cs.cs_nifree--;
175 	fs->fs_cstotal.cs_nifree--;
176 	fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--;
177 	fs->fs_fmod = 1;
178 
179 	return (ino + (cgp->cg_cgx * fs->fs_ipg));
180 }
181 
182 int
183 cgread(struct uufsd *disk)
184 {
185 	return (cgread1(disk, disk->d_ccg++));
186 }
187 
188 int
189 cgread1(struct uufsd *disk, int c)
190 {
191 	struct fs *fs;
192 
193 	fs = &disk->d_fs;
194 
195 	if ((unsigned)c >= fs->fs_ncg) {
196 		return (0);
197 	}
198 	if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf,
199 	    fs->fs_bsize) == -1) {
200 		ERROR(disk, "unable to read cylinder group");
201 		return (-1);
202 	}
203 	disk->d_lcg = c;
204 	return (1);
205 }
206 
207 int
208 cgwrite(struct uufsd *disk)
209 {
210 	return (cgwrite1(disk, disk->d_lcg));
211 }
212 
213 int
214 cgwrite1(struct uufsd *disk, int c)
215 {
216 	struct fs *fs;
217 
218 	fs = &disk->d_fs;
219 	if ((fs->fs_metackhash & CK_CYLGRP) != 0) {
220 		disk->d_cg.cg_ckhash = 0;
221 		disk->d_cg.cg_ckhash =
222 		    calculate_crc32c(~0L, (void *)&disk->d_cg, fs->fs_cgsize);
223 	}
224 	if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)),
225 	    disk->d_cgunion.d_buf, fs->fs_bsize) == -1) {
226 		ERROR(disk, "unable to write cylinder group");
227 		return (-1);
228 	}
229 	return (0);
230 }
231