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 101018 2002-07-31 07:01:18Z 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, mtype, fs, ino)
109 struct buf *bp;
110 struct inode *ip;
111 struct malloc_type *mtype;
112 struct fs *fs;
113 ino_t ino;
114{
115
116 if (ip->i_ump->um_fstype == UFS1) {
117 if (mtype != NULL)
118 MALLOC(ip->i_din1, struct ufs1_dinode *,
119 sizeof(struct ufs1_dinode), mtype, M_WAITOK);
120 *ip->i_din1 =
121 *((struct ufs1_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
122 ip->i_mode = ip->i_din1->di_mode;
123 ip->i_nlink = ip->i_din1->di_nlink;
124 ip->i_size = ip->i_din1->di_size;
125 ip->i_flags = ip->i_din1->di_flags;
126 ip->i_gen = ip->i_din1->di_gen;
127 ip->i_uid = ip->i_din1->di_uid;
128 ip->i_gid = ip->i_din1->di_gid;
129 } else {
130 if (mtype != NULL)
131 MALLOC(ip->i_din2, struct ufs2_dinode *,
132 sizeof(struct ufs2_dinode), mtype, M_WAITOK);
133 *ip->i_din2 =
134 *((struct ufs2_dinode *)bp->b_data + ino_to_fsbo(fs, ino));
135 ip->i_mode = ip->i_din2->di_mode;
136 ip->i_nlink = ip->i_din2->di_nlink;
137 ip->i_size = ip->i_din2->di_size;
138 ip->i_flags = ip->i_din2->di_flags;
139 ip->i_gen = ip->i_din2->di_gen;
140 ip->i_uid = ip->i_din2->di_uid;
141 ip->i_gid = ip->i_din2->di_gid;
142 }
143}
144#endif /* KERNEL */
145
146/*
147 * Update the frsum fields to reflect addition or deletion
148 * of some frags.
149 */
150void
151ffs_fragacct(fs, fragmap, fraglist, cnt)
152 struct fs *fs;
153 int fragmap;
154 int32_t fraglist[];
155 int cnt;
156{
157 int inblk;
158 int field, subfield;
159 int siz, pos;
160
161 inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
162 fragmap <<= 1;
163 for (siz = 1; siz < fs->fs_frag; siz++) {
164 if ((inblk & (1 << (siz + (fs->fs_frag % NBBY)))) == 0)
165 continue;
166 field = around[siz];
167 subfield = inside[siz];
168 for (pos = siz; pos <= fs->fs_frag; pos++) {
169 if ((fragmap & field) == subfield) {
170 fraglist[siz] += cnt;
171 pos += siz;
172 field <<= siz;
173 subfield <<= siz;
174 }
175 field <<= 1;
176 subfield <<= 1;
177 }
178 }
179}
180
181#ifdef DDB
182void
183ffs_checkoverlap(bp, ip)
184 struct buf *bp;
185 struct inode *ip;
186{
187 struct buf *ebp, *ep;
188 ufs2_daddr_t start, last;
189 struct vnode *vp;
190
191 ebp = &buf[nbuf];
192 start = bp->b_blkno;
193 last = start + btodb(bp->b_bcount) - 1;
194 for (ep = buf; ep < ebp; ep++) {
195 if (ep == bp || (ep->b_flags & B_INVAL) ||
196 ep->b_vp == NULLVP)
197 continue;
198 vp = ip->i_devvp;
199 /* look for overlap */
200 if (ep->b_bcount == 0 || ep->b_blkno > last ||
201 ep->b_blkno + btodb(ep->b_bcount) <= start)
202 continue;
203 vprint("Disk overlap", vp);
204 printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
205 (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
206 (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
207 panic("ffs_checkoverlap: Disk buffer overlap");
208 }
209}
210#endif /* DDB */
211
212/*
213 * block operations
214 *
215 * check if a block is available
216 */
217int
218ffs_isblock(fs, cp, h)
219 struct fs *fs;
220 unsigned char *cp;
221 ufs1_daddr_t h;
222{
223 unsigned char mask;
224
225 switch ((int)fs->fs_frag) {
226 case 8:
227 return (cp[h] == 0xff);
228 case 4:
229 mask = 0x0f << ((h & 0x1) << 2);
230 return ((cp[h >> 1] & mask) == mask);
231 case 2:
232 mask = 0x03 << ((h & 0x3) << 1);
233 return ((cp[h >> 2] & mask) == mask);
234 case 1:
235 mask = 0x01 << (h & 0x7);
236 return ((cp[h >> 3] & mask) == mask);
237 default:
238 panic("ffs_isblock");
239 }
240 return (0);
241}
242
243/*
244 * take a block out of the map
245 */
246void
247ffs_clrblock(fs, cp, h)
248 struct fs *fs;
249 u_char *cp;
250 ufs1_daddr_t h;
251{
252
253 switch ((int)fs->fs_frag) {
254 case 8:
255 cp[h] = 0;
256 return;
257 case 4:
258 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
259 return;
260 case 2:
261 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
262 return;
263 case 1:
264 cp[h >> 3] &= ~(0x01 << (h & 0x7));
265 return;
266 default:
267 panic("ffs_clrblock");
268 }
269}
270
271/*
272 * put a block into the map
273 */
274void
275ffs_setblock(fs, cp, h)
276 struct fs *fs;
277 unsigned char *cp;
278 ufs1_daddr_t h;
279{
280
281 switch ((int)fs->fs_frag) {
282
283 case 8:
284 cp[h] = 0xff;
285 return;
286 case 4:
287 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
288 return;
289 case 2:
290 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
291 return;
292 case 1:
293 cp[h >> 3] |= (0x01 << (h & 0x7));
294 return;
295 default:
296 panic("ffs_setblock");
297 }
298}