Deleted Added
sdiff udiff text old ( 101018 ) new ( 108315 )
full compact
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
34 * $FreeBSD: head/sys/ufs/ffs/ffs_subr.c 108315 2002-12-27 10:23:03Z phk $
35 */
36
37#include <sys/param.h>
38
39#ifndef _KERNEL
40#include <ufs/ufs/dinode.h>
41#include <ufs/ffs/fs.h>
42#include "fsck.h"
43#else
44#include "opt_ddb.h"
45
46#include <sys/systm.h>
47#include <sys/stdint.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mount.h>
51#include <sys/vnode.h>
52#include <sys/bio.h>
53#include <sys/buf.h>
54#include <sys/ucred.h>
55
56#include <ufs/ufs/quota.h>
57#include <ufs/ufs/inode.h>
58#include <ufs/ufs/extattr.h>
59#include <ufs/ufs/ufsmount.h>
60#include <ufs/ufs/ufs_extern.h>
61#include <ufs/ffs/ffs_extern.h>
62#include <ufs/ffs/fs.h>
63
64#ifdef DDB
65void ffs_checkoverlap(struct buf *, struct inode *);
66#endif
67
68/*
69 * Return buffer with the contents of block "offset" from the beginning of
70 * directory "ip". If "res" is non-zero, fill it in with a pointer to the
71 * remaining space in the directory.
72 */
73int
74ffs_blkatoff(vp, offset, res, bpp)
75 struct vnode *vp;
76 off_t offset;
77 char **res;
78 struct buf **bpp;
79{
80 struct inode *ip;
81 struct fs *fs;
82 struct buf *bp;
83 ufs_lbn_t lbn;
84 int bsize, error;
85
86 ip = VTOI(vp);
87 fs = ip->i_fs;
88 lbn = lblkno(fs, offset);
89 bsize = blksize(fs, ip, lbn);
90
91 *bpp = NULL;
92 error = bread(vp, lbn, bsize, NOCRED, &bp);
93 if (error) {
94 brelse(bp);
95 return (error);
96 }
97 if (res)
98 *res = (char *)bp->b_data + blkoff(fs, offset);
99 *bpp = bp;
100 return (0);
101}
102
103/*
104 * Load up the contents of an inode and copy the appropriate pieces
105 * to the incore copy.
106 */
107void
108ffs_load_inode(bp, ip, fs, ino)
109 struct buf *bp;
110 struct inode *ip;
111 struct fs *fs;
112 ino_t ino;
113{
114
115 if (ip->i_ump->um_fstype == UFS1) {
116 *ip->i_din1 =
117 *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
118 ip->i_mode = ip->i_din1->di_mode;
119 ip->i_nlink = ip->i_din1->di_nlink;
120 ip->i_size = ip->i_din1->di_size;
121 ip->i_flags = ip->i_din1->di_flags;
122 ip->i_gen = ip->i_din1->di_gen;
123 ip->i_uid = ip->i_din1->di_uid;
124 ip->i_gid = ip->i_din1->di_gid;
125 } else {
126 *ip->i_din2 =
127 *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
128 ip->i_mode = ip->i_din2->di_mode;
129 ip->i_nlink = ip->i_din2->di_nlink;
130 ip->i_size = ip->i_din2->di_size;
131 ip->i_flags = ip->i_din2->di_flags;
132 ip->i_gen = ip->i_din2->di_gen;
133 ip->i_uid = ip->i_din2->di_uid;
134 ip->i_gid = ip->i_din2->di_gid;
135 }
136}
137#endif /* KERNEL */
138
139/*
140 * Update the frsum fields to reflect addition or deletion
141 * of some frags.
142 */
143void
144ffs_fragacct(fs, fragmap, fraglist, cnt)
145 struct fs *fs;
146 int fragmap;
147 int32_t fraglist[];
148 int cnt;
149{
150 int inblk;
151 int field, subfield;
152 int siz, pos;
153
154 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
155 fragmap <<= 1;
156 for (siz = 1; siz < fs->fs_frag; siz++) {
157 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
158 continue;
159 field = around[siz];
160 subfield = inside[siz];
161 for (pos = siz; pos <= fs->fs_frag; pos++) {
162 if ((fragmap & field) == subfield) {
163 fraglist[siz] += cnt;
164 pos += siz;
165 field <<= siz;
166 subfield <<= siz;
167 }
168 field <<= 1;
169 subfield <<= 1;
170 }
171 }
172}
173
174#ifdef DDB
175void
176ffs_checkoverlap(bp, ip)
177 struct buf *bp;
178 struct inode *ip;
179{
180 struct buf *ebp, *ep;
181 ufs2_daddr_t start, last;
182 struct vnode *vp;
183
184 ebp = &buf[nbuf];
185 start = bp->b_blkno;
186 last = start + btodb(bp->b_bcount) - 1;
187 for (ep = buf; ep < ebp; ep++) {
188 if (ep == bp || (ep->b_flags & B_INVAL) ||
189 ep->b_vp == NULLVP)
190 continue;
191 vp = ip->i_devvp;
192 /* look for overlap */
193 if (ep->b_bcount == 0 || ep->b_blkno > last ||
194 ep->b_blkno + btodb(ep->b_bcount) <= start)
195 continue;
196 vprint("Disk overlap", vp);
197 printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
198 (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
199 (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
200 panic("ffs_checkoverlap: Disk buffer overlap");
201 }
202}
203#endif /* DDB */
204
205/*
206 * block operations
207 *
208 * check if a block is available
209 */
210int
211ffs_isblock(fs, cp, h)
212 struct fs *fs;
213 unsigned char *cp;
214 ufs1_daddr_t h;
215{
216 unsigned char mask;
217
218 switch ((int)fs->fs_frag) {
219 case 8:
220 return (cp[h] == 0xff);
221 case 4:
222 mask = 0x0f << ((h & 0x1) << 2);
223 return ((cp[h >> 1] & mask) == mask);
224 case 2:
225 mask = 0x03 << ((h & 0x3) << 1);
226 return ((cp[h >> 2] & mask) == mask);
227 case 1:
228 mask = 0x01 << (h & 0x7);
229 return ((cp[h >> 3] & mask) == mask);
230 default:
231 panic("ffs_isblock");
232 }
233 return (0);
234}
235
236/*
237 * take a block out of the map
238 */
239void
240ffs_clrblock(fs, cp, h)
241 struct fs *fs;
242 u_char *cp;
243 ufs1_daddr_t h;
244{
245
246 switch ((int)fs->fs_frag) {
247 case 8:
248 cp[h] = 0;
249 return;
250 case 4:
251 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
252 return;
253 case 2:
254 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
255 return;
256 case 1:
257 cp[h >> 3] &= ~(0x01 << (h & 0x7));
258 return;
259 default:
260 panic("ffs_clrblock");
261 }
262}
263
264/*
265 * put a block into the map
266 */
267void
268ffs_setblock(fs, cp, h)
269 struct fs *fs;
270 unsigned char *cp;
271 ufs1_daddr_t h;
272{
273
274 switch ((int)fs->fs_frag) {
275
276 case 8:
277 cp[h] = 0xff;
278 return;
279 case 4:
280 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
281 return;
282 case 2:
283 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
284 return;
285 case 1:
286 cp[h >> 3] |= (0x01 << (h & 0x7));
287 return;
288 default:
289 panic("ffs_setblock");
290 }
291}