1109509Sjmallett/*
2109509Sjmallett * Copyright (c) 2003 Juli Mallett.  All rights reserved.
3109509Sjmallett *
4109509Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
5109509Sjmallett * FreeBSD project.  Redistribution and use in source and binary forms, with
6109509Sjmallett * or without modification, are permitted provided that the following
7109509Sjmallett * conditions are met:
8109509Sjmallett *
9109509Sjmallett * 1. Redistribution of source code must retain the above copyright notice,
10109509Sjmallett *    this list of conditions and the following disclaimer.
11109509Sjmallett * 2. Redistribution in binary form must reproduce the above copyright
12109509Sjmallett *    notice, this list of conditions and the following disclaimer in the
13109509Sjmallett *    documentation and/or other materials provided with the distribution.
14109509Sjmallett *
15109509Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16109509Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17109509Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18109509Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19109509Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20109509Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21109509Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22109509Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23109509Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24109509Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25109509Sjmallett * POSSIBILITY OF SUCH DAMAGE.
26109509Sjmallett */
27109509Sjmallett
28109509Sjmallett#include <sys/cdefs.h>
29109509Sjmallett__FBSDID("$FreeBSD$");
30109509Sjmallett
31109509Sjmallett#include <sys/param.h>
32109509Sjmallett#include <sys/mount.h>
33109509Sjmallett#include <sys/disklabel.h>
34109509Sjmallett#include <sys/stat.h>
35109509Sjmallett
36109509Sjmallett#include <ufs/ufs/ufsmount.h>
37109509Sjmallett#include <ufs/ufs/dinode.h>
38109509Sjmallett#include <ufs/ffs/fs.h>
39109509Sjmallett
40109509Sjmallett#include <errno.h>
41109509Sjmallett#include <fcntl.h>
42109509Sjmallett#include <stdio.h>
43207141Sjeff#include <stdlib.h>
44109509Sjmallett#include <string.h>
45109509Sjmallett#include <unistd.h>
46109509Sjmallett
47109509Sjmallett#include <libufs.h>
48109509Sjmallett
49207141Sjeffufs2_daddr_t
50207141Sjeffcgballoc(struct uufsd *disk)
51207141Sjeff{
52207141Sjeff	u_int8_t *blksfree;
53207141Sjeff	struct cg *cgp;
54207141Sjeff	struct fs *fs;
55207141Sjeff	long bno;
56207141Sjeff
57207141Sjeff	fs = &disk->d_fs;
58207141Sjeff	cgp = &disk->d_cg;
59207141Sjeff	blksfree = cg_blksfree(cgp);
60207141Sjeff	for (bno = 0; bno < fs->fs_fpg / fs->fs_frag; bno++)
61207141Sjeff		if (ffs_isblock(fs, blksfree, bno))
62207141Sjeff			goto gotit;
63207141Sjeff	return (0);
64207141Sjeffgotit:
65207141Sjeff	fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree--;
66207141Sjeff	ffs_clrblock(fs, blksfree, (long)bno);
67207141Sjeff	ffs_clusteracct(fs, cgp, bno, -1);
68207141Sjeff	cgp->cg_cs.cs_nbfree--;
69207141Sjeff	fs->fs_cstotal.cs_nbfree--;
70207141Sjeff	fs->fs_fmod = 1;
71207141Sjeff	return (cgbase(fs, cgp->cg_cgx) + blkstofrags(fs, bno));
72207141Sjeff}
73207141Sjeff
74109509Sjmallettint
75207141Sjeffcgbfree(struct uufsd *disk, ufs2_daddr_t bno, long size)
76207141Sjeff{
77207141Sjeff	u_int8_t *blksfree;
78207141Sjeff	struct fs *fs;
79207141Sjeff	struct cg *cgp;
80207141Sjeff	ufs1_daddr_t fragno, cgbno;
81207141Sjeff	int i, cg, blk, frags, bbase;
82207141Sjeff
83207141Sjeff	fs = &disk->d_fs;
84207141Sjeff	cg = dtog(fs, bno);
85207141Sjeff	if (cgread1(disk, cg) != 1)
86207141Sjeff		return (-1);
87207141Sjeff	cgp = &disk->d_cg;
88207141Sjeff	cgbno = dtogd(fs, bno);
89207141Sjeff	blksfree = cg_blksfree(cgp);
90207141Sjeff	if (size == fs->fs_bsize) {
91207141Sjeff		fragno = fragstoblks(fs, cgbno);
92207141Sjeff		ffs_setblock(fs, blksfree, fragno);
93207141Sjeff		ffs_clusteracct(fs, cgp, fragno, 1);
94207141Sjeff		cgp->cg_cs.cs_nbfree++;
95207141Sjeff		fs->fs_cstotal.cs_nbfree++;
96207141Sjeff		fs->fs_cs(fs, cg).cs_nbfree++;
97207141Sjeff	} else {
98207141Sjeff		bbase = cgbno - fragnum(fs, cgbno);
99207141Sjeff		/*
100207141Sjeff		 * decrement the counts associated with the old frags
101207141Sjeff		 */
102207141Sjeff		blk = blkmap(fs, blksfree, bbase);
103207141Sjeff		ffs_fragacct(fs, blk, cgp->cg_frsum, -1);
104207141Sjeff		/*
105207141Sjeff		 * deallocate the fragment
106207141Sjeff		 */
107207141Sjeff		frags = numfrags(fs, size);
108207141Sjeff		for (i = 0; i < frags; i++)
109207141Sjeff			setbit(blksfree, cgbno + i);
110207141Sjeff		cgp->cg_cs.cs_nffree += i;
111207141Sjeff		fs->fs_cstotal.cs_nffree += i;
112207141Sjeff		fs->fs_cs(fs, cg).cs_nffree += i;
113207141Sjeff		/*
114207141Sjeff		 * add back in counts associated with the new frags
115207141Sjeff		 */
116207141Sjeff		blk = blkmap(fs, blksfree, bbase);
117207141Sjeff		ffs_fragacct(fs, blk, cgp->cg_frsum, 1);
118207141Sjeff		/*
119207141Sjeff		 * if a complete block has been reassembled, account for it
120207141Sjeff		 */
121207141Sjeff		fragno = fragstoblks(fs, bbase);
122207141Sjeff		if (ffs_isblock(fs, blksfree, fragno)) {
123207141Sjeff			cgp->cg_cs.cs_nffree -= fs->fs_frag;
124207141Sjeff			fs->fs_cstotal.cs_nffree -= fs->fs_frag;
125207141Sjeff			fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
126207141Sjeff			ffs_clusteracct(fs, cgp, fragno, 1);
127207141Sjeff			cgp->cg_cs.cs_nbfree++;
128207141Sjeff			fs->fs_cstotal.cs_nbfree++;
129207141Sjeff			fs->fs_cs(fs, cg).cs_nbfree++;
130207141Sjeff		}
131207141Sjeff	}
132207141Sjeff	return cgwrite(disk);
133207141Sjeff}
134207141Sjeff
135207141Sjeffino_t
136207141Sjeffcgialloc(struct uufsd *disk)
137207141Sjeff{
138207141Sjeff	struct ufs2_dinode *dp2;
139207141Sjeff	u_int8_t *inosused;
140207141Sjeff	struct cg *cgp;
141207141Sjeff	struct fs *fs;
142207141Sjeff	ino_t ino;
143207141Sjeff	int i;
144207141Sjeff
145207141Sjeff	fs = &disk->d_fs;
146207141Sjeff	cgp = &disk->d_cg;
147207141Sjeff	inosused = cg_inosused(cgp);
148207476Semaste	for (ino = 0; ino < fs->fs_ipg; ino++)
149207141Sjeff		if (isclr(inosused, ino))
150207141Sjeff			goto gotit;
151207141Sjeff	return (0);
152207141Sjeffgotit:
153207141Sjeff	if (fs->fs_magic == FS_UFS2_MAGIC &&
154207141Sjeff	    ino + INOPB(fs) > cgp->cg_initediblk &&
155207141Sjeff	    cgp->cg_initediblk < cgp->cg_niblk) {
156207141Sjeff		char block[MAXBSIZE];
157207141Sjeff		bzero(block, (int)fs->fs_bsize);
158207141Sjeff		dp2 = (struct ufs2_dinode *)&block;
159207141Sjeff		for (i = 0; i < INOPB(fs); i++) {
160207141Sjeff			dp2->di_gen = arc4random() / 2 + 1;
161207141Sjeff			dp2++;
162207141Sjeff		}
163207141Sjeff		if (bwrite(disk, ino_to_fsba(fs,
164207141Sjeff		    cgp->cg_cgx * fs->fs_ipg + cgp->cg_initediblk),
165207141Sjeff		    block, fs->fs_bsize))
166207141Sjeff			return (0);
167207141Sjeff		cgp->cg_initediblk += INOPB(fs);
168207141Sjeff	}
169207141Sjeff
170207141Sjeff	setbit(inosused, ino);
171207141Sjeff	cgp->cg_irotor = ino;
172207141Sjeff	cgp->cg_cs.cs_nifree--;
173207141Sjeff	fs->fs_cstotal.cs_nifree--;
174207141Sjeff	fs->fs_cs(fs, cgp->cg_cgx).cs_nifree--;
175207141Sjeff	fs->fs_fmod = 1;
176207141Sjeff
177207141Sjeff	return (ino + (cgp->cg_cgx * fs->fs_ipg));
178207141Sjeff}
179207141Sjeff
180207141Sjeffint
181109509Sjmallettcgread(struct uufsd *disk)
182109509Sjmallett{
183116084Sjmallett	return (cgread1(disk, disk->d_ccg++));
184109509Sjmallett}
185109509Sjmallett
186109509Sjmallettint
187109509Sjmallettcgread1(struct uufsd *disk, int c)
188109509Sjmallett{
189109509Sjmallett	struct fs *fs;
190109509Sjmallett
191109509Sjmallett	fs = &disk->d_fs;
192109509Sjmallett
193203768Smckusick	if ((unsigned)c >= fs->fs_ncg) {
194116084Sjmallett		return (0);
195109509Sjmallett	}
196109509Sjmallett	if (bread(disk, fsbtodb(fs, cgtod(fs, c)), disk->d_cgunion.d_buf,
197109509Sjmallett	    fs->fs_bsize) == -1) {
198109509Sjmallett		ERROR(disk, "unable to read cylinder group");
199116084Sjmallett		return (-1);
200109509Sjmallett	}
201109518Sjmallett	disk->d_lcg = c;
202116084Sjmallett	return (1);
203109509Sjmallett}
204163835Spjd
205163835Spjdint
206207141Sjeffcgwrite(struct uufsd *disk)
207207141Sjeff{
208207141Sjeff	return (cgwrite1(disk, disk->d_lcg));
209207141Sjeff}
210207141Sjeff
211207141Sjeffint
212163835Spjdcgwrite1(struct uufsd *disk, int c)
213163835Spjd{
214163835Spjd	struct fs *fs;
215163835Spjd
216163835Spjd	fs = &disk->d_fs;
217163835Spjd	if (bwrite(disk, fsbtodb(fs, cgtod(fs, c)),
218163835Spjd	    disk->d_cgunion.d_buf, fs->fs_bsize) == -1) {
219163835Spjd		ERROR(disk, "unable to write cylinder group");
220163835Spjd		return (-1);
221163835Spjd	}
222163835Spjd	return (0);
223163835Spjd}
224