GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/fsck_ffs/../../sys/ufs/ffs/ffs_subr.c Lines: 16 47 34.0 %
Date: 2017-11-07 Branches: 8 24 33.3 %

Line Branch Exec Source
1
/*	$OpenBSD: ffs_subr.c,v 1.32 2016/08/10 11:33:01 natano Exp $	*/
2
/*	$NetBSD: ffs_subr.c,v 1.6 1996/03/17 02:16:23 christos Exp $	*/
3
4
/*
5
 * Copyright (c) 1982, 1986, 1989, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions 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
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 *
32
 *	@(#)ffs_subr.c	8.2 (Berkeley) 9/21/93
33
 */
34
35
#include <sys/param.h>
36
#include <ufs/ffs/fs.h>
37
38
#ifdef _KERNEL
39
#include <sys/systm.h>
40
#include <sys/vnode.h>
41
#include <sys/mount.h>
42
#include <sys/buf.h>
43
44
#include <ufs/ufs/quota.h>
45
#include <ufs/ufs/inode.h>
46
#include <ufs/ufs/ufsmount.h>
47
#include <ufs/ufs/ufs_extern.h>
48
49
#include <ufs/ffs/ffs_extern.h>
50
51
/*
52
 * Return buffer with the contents of block "offset" from the beginning of
53
 * directory "ip".  If "res" is non-zero, fill it in with a pointer to the
54
 * remaining space in the directory.
55
 */
56
int
57
ffs_bufatoff(struct inode *ip, off_t offset, char **res, struct buf **bpp)
58
{
59
	struct fs *fs;
60
	struct vnode *vp;
61
	struct buf *bp;
62
	daddr_t lbn;
63
	int bsize, error;
64
65
	vp = ITOV(ip);
66
	fs = ip->i_fs;
67
	lbn = lblkno(fs, offset);
68
	bsize = blksize(fs, ip, lbn);
69
70
	*bpp = NULL;
71
	if ((error = bread(vp, lbn, fs->fs_bsize, &bp)) != 0) {
72
		brelse(bp);
73
		return (error);
74
	}
75
	buf_adjcnt(bp, bsize);
76
	if (res)
77
		*res = (char *)bp->b_data + blkoff(fs, offset);
78
	*bpp = bp;
79
	return (0);
80
}
81
#else
82
/* Prototypes for userland */
83
void	ffs_fragacct(struct fs *, int, int32_t[], int);
84
int	ffs_isfreeblock(struct fs *, u_char *, daddr_t);
85
int	ffs_isblock(struct fs *, u_char *, daddr_t);
86
void	ffs_clrblock(struct fs *, u_char *, daddr_t);
87
void	ffs_setblock(struct fs *, u_char *, daddr_t);
88
__dead void panic(const char *, ...);
89
#endif
90
91
/*
92
 * Update the frsum fields to reflect addition or deletion
93
 * of some frags.
94
 */
95
void
96
ffs_fragacct(struct fs *fs, int fragmap, int32_t fraglist[], int cnt)
97
{
98
	int inblk;
99
	int field, subfield;
100
	int siz, pos;
101
102
32
	inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
103
16
	fragmap <<= 1;
104
256
	for (siz = 1; siz < fs->fs_frag; siz++) {
105
112
		if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
106
			continue;
107
16
		field = around[siz];
108
16
		subfield = inside[siz];
109
96
		for (pos = siz; pos <= fs->fs_frag; pos++) {
110
32
			if ((fragmap & field) == subfield) {
111
16
				fraglist[siz] += cnt;
112
16
				pos += siz;
113
16
				field <<= siz;
114
16
				subfield <<= siz;
115
16
			}
116
32
			field <<= 1;
117
32
			subfield <<= 1;
118
		}
119
	}
120
16
}
121
122
#if defined(_KERNEL) && defined(DIAGNOSTIC)
123
void
124
ffs_checkoverlap(struct buf *bp, struct inode *ip)
125
{
126
	daddr_t start, last;
127
	struct vnode *vp;
128
	struct buf *ep;
129
130
	start = bp->b_blkno;
131
	last = start + btodb(bp->b_bcount) - 1;
132
	LIST_FOREACH(ep, &bufhead, b_list) {
133
		if (ep == bp || (ep->b_flags & B_INVAL) ||
134
		    ep->b_vp == NULLVP)
135
			continue;
136
		if (VOP_BMAP(ep->b_vp, 0, &vp, NULL, NULL))
137
			continue;
138
		if (vp != ip->i_devvp)
139
			continue;
140
		/* look for overlap */
141
		if (ep->b_bcount == 0 || ep->b_blkno > last ||
142
		    ep->b_blkno + btodb(ep->b_bcount) <= start)
143
			continue;
144
		vprint("Disk overlap", vp);
145
		(void)printf("\tstart %lld, end %lld overlap start %llu, "
146
		    "end %llu\n", (long long)start, (long long)last,
147
		    (long long)ep->b_blkno,
148
		    (long long)(ep->b_blkno + btodb(ep->b_bcount) - 1));
149
		panic("Disk buffer overlap");
150
	}
151
}
152
#endif /* DIAGNOSTIC */
153
154
/*
155
 * block operations
156
 *
157
 * check if a block is available
158
 */
159
int
160
ffs_isblock(struct fs *fs, u_char *cp, daddr_t h)
161
{
162
	u_char mask;
163
164
	switch (fs->fs_frag) {
165
	default:
166
	case 8:
167
		return (cp[h] == 0xff);
168
	case 4:
169
		mask = 0x0f << ((h & 0x1) << 2);
170
		return ((cp[h >> 1] & mask) == mask);
171
	case 2:
172
		mask = 0x03 << ((h & 0x3) << 1);
173
		return ((cp[h >> 2] & mask) == mask);
174
	case 1:
175
		mask = 0x01 << (h & 0x7);
176
		return ((cp[h >> 3] & mask) == mask);
177
	}
178
}
179
180
/*
181
 * take a block out of the map
182
 */
183
void
184
ffs_clrblock(struct fs *fs, u_char *cp, daddr_t h)
185
{
186
187
	switch (fs->fs_frag) {
188
	default:
189
	case 8:
190
		cp[h] = 0;
191
		return;
192
	case 4:
193
		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
194
		return;
195
	case 2:
196
		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
197
		return;
198
	case 1:
199
		cp[h >> 3] &= ~(0x01 << (h & 0x7));
200
		return;
201
	}
202
}
203
204
/*
205
 * put a block into the map
206
 */
207
void
208
ffs_setblock(struct fs *fs, u_char *cp, daddr_t h)
209
{
210
211
	switch (fs->fs_frag) {
212
	default:
213
	case 8:
214
		cp[h] = 0xff;
215
		return;
216
	case 4:
217
		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
218
		return;
219
	case 2:
220
		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
221
		return;
222
	case 1:
223
		cp[h >> 3] |= (0x01 << (h & 0x7));
224
		return;
225
	}
226
}
227
228
/*
229
 * check if a block is free
230
 */
231
int
232
ffs_isfreeblock(struct fs *fs, u_char *cp, daddr_t h)
233
{
234
235
	switch (fs->fs_frag) {
236
	default:
237
	case 8:
238
		return (cp[h] == 0);
239
	case 4:
240
		return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
241
	case 2:
242
		return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
243
	case 1:
244
		return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
245
	}
246
}
247
248
#ifdef _KERNEL
249
/*
250
 * Initialize the vnode associated with a new inode, handle aliased
251
 * vnodes.
252
 */
253
int
254
ffs_vinit(struct mount *mntp, struct vnode **vpp)
255
{
256
	struct inode *ip;
257
	struct vnode *vp, *nvp;
258
	struct timeval mtv;
259
260
	vp = *vpp;
261
	ip = VTOI(vp);
262
	switch(vp->v_type = IFTOVT(DIP(ip, mode))) {
263
	case VCHR:
264
	case VBLK:
265
		vp->v_op = &ffs_specvops;
266
		if ((nvp = checkalias(vp, DIP(ip, rdev), mntp)) != NULL) {
267
			/*
268
			 * Discard unneeded vnode, but save its inode.
269
			 * Note that the lock is carried over in the inode
270
			 * to the replacement vnode.
271
			 */
272
			nvp->v_data = vp->v_data;
273
			vp->v_data = NULL;
274
			vp->v_op = &spec_vops;
275
#ifdef VFSLCKDEBUG
276
			vp->v_flag &= ~VLOCKSWORK;
277
#endif
278
			vrele(vp);
279
			vgone(vp);
280
			/*
281
			 * Reinitialize aliased inode.
282
			 */
283
			vp = nvp;
284
			ip->i_vnode = vp;
285
		}
286
		break;
287
	case VFIFO:
288
#ifdef FIFO
289
		vp->v_op = &ffs_fifovops;
290
		break;
291
#else
292
		return (EOPNOTSUPP);
293
#endif
294
	case VNON:
295
	case VBAD:
296
	case VSOCK:
297
	case VLNK:
298
	case VDIR:
299
	case VREG:
300
		break;
301
	}
302
	if (ip->i_number == ROOTINO)
303
		vp->v_flag |= VROOT;
304
	/*
305
	 * Initialize modrev times
306
	 */
307
	getmicrouptime(&mtv);
308
	ip->i_modrev = (u_quad_t)mtv.tv_sec << 32;
309
	ip->i_modrev |= (u_quad_t)mtv.tv_usec * 4294;
310
	*vpp = vp;
311
	return (0);
312
}
313
#endif /* _KERNEL */