This source file includes following definitions.
- ext2fs_alloc
- ext2fs_inode_alloc
- ext2fs_dirpref
- ext2fs_blkpref
- ext2fs_hashalloc
- ext2fs_alloccg
- ext2fs_nodealloccg
- ext2fs_blkfree
- ext2fs_inode_free
- ext2fs_mapsearch
- ext2fs_fserr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/buf.h>
40 #include <sys/proc.h>
41 #include <sys/vnode.h>
42 #include <sys/mount.h>
43 #include <sys/kernel.h>
44 #include <sys/syslog.h>
45
46 #include <ufs/ufs/quota.h>
47 #include <ufs/ufs/inode.h>
48 #include <ufs/ufs/ufsmount.h>
49 #include <ufs/ufs/ufs_extern.h>
50
51 #include <ufs/ext2fs/ext2fs.h>
52 #include <ufs/ext2fs/ext2fs_extern.h>
53
54 u_long ext2gennumber;
55
56 static int32_t ext2fs_alloccg(struct inode *, int, int32_t, int);
57 static u_long ext2fs_dirpref(struct m_ext2fs *);
58 static void ext2fs_fserr(struct m_ext2fs *, uid_t, char *);
59 static u_long ext2fs_hashalloc(struct inode *, int, long, int,
60 int32_t (*)(struct inode *, int, int32_t, int));
61 static int32_t ext2fs_nodealloccg(struct inode *, int, int32_t, int);
62 static int32_t ext2fs_mapsearch(struct m_ext2fs *, char *, int32_t);
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 int
82 ext2fs_alloc(struct inode *ip, int32_t lbn, int32_t bpref,
83 struct ucred *cred, int32_t *bnp)
84 {
85 struct m_ext2fs *fs;
86 int32_t bno;
87 int cg;
88
89 *bnp = 0;
90 fs = ip->i_e2fs;
91 #ifdef DIAGNOSTIC
92 if (cred == NOCRED)
93 panic("ext2fs_alloc: missing credential");
94 #endif
95 if (fs->e2fs.e2fs_fbcount == 0)
96 goto nospace;
97 if (cred->cr_uid != 0 && freespace(fs) <= 0)
98 goto nospace;
99 if (bpref >= fs->e2fs.e2fs_bcount)
100 bpref = 0;
101 if (bpref == 0)
102 cg = ino_to_cg(fs, ip->i_number);
103 else
104 cg = dtog(fs, bpref);
105 bno = (int32_t)ext2fs_hashalloc(ip, cg, bpref, fs->e2fs_bsize,
106 ext2fs_alloccg);
107 if (bno > 0) {
108 ip->i_e2fs_nblock += btodb(fs->e2fs_bsize);
109 ip->i_flag |= IN_CHANGE | IN_UPDATE;
110 *bnp = bno;
111 return (0);
112 }
113 nospace:
114 ext2fs_fserr(fs, cred->cr_uid, "file system full");
115 uprintf("\n%s: write failed, file system is full\n", fs->e2fs_fsmnt);
116 return (ENOSPC);
117 }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 int
135 ext2fs_inode_alloc(struct inode *pip, mode_t mode, struct ucred *cred,
136 struct vnode **vpp)
137 {
138 struct vnode *pvp;
139 struct m_ext2fs *fs;
140 struct inode *ip;
141 ino_t ino, ipref;
142 int cg, error;
143
144 *vpp = NULL;
145 pvp = ITOV(pip);
146 fs = pip->i_e2fs;
147 if (fs->e2fs.e2fs_ficount == 0)
148 goto noinodes;
149
150 if ((mode & IFMT) == IFDIR)
151 cg = ext2fs_dirpref(fs);
152 else
153 cg = ino_to_cg(fs, pip->i_number);
154 ipref = cg * fs->e2fs.e2fs_ipg + 1;
155 ino = (ino_t)ext2fs_hashalloc(pip, cg, (long)ipref, mode, ext2fs_nodealloccg);
156 if (ino == 0)
157 goto noinodes;
158 error = VFS_VGET(pvp->v_mount, ino, vpp);
159 if (error) {
160 ext2fs_inode_free(pip, ino, mode);
161 return (error);
162 }
163 ip = VTOI(*vpp);
164 if (ip->i_e2fs_mode && ip->i_e2fs_nlink != 0) {
165 printf("mode = 0%o, nlinks %d, inum = %d, fs = %s\n",
166 ip->i_e2fs_mode, ip->i_e2fs_nlink, ip->i_number, fs->e2fs_fsmnt);
167 panic("ext2fs_valloc: dup alloc");
168 }
169
170 bzero(ip->i_e2din, sizeof(struct ext2fs_dinode));
171
172
173
174
175 if (++ext2gennumber < (u_long)time_second)
176 ext2gennumber = time_second;
177 ip->i_e2fs_gen = ext2gennumber;
178 return (0);
179 noinodes:
180 ext2fs_fserr(fs, cred->cr_uid, "out of inodes");
181 uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt);
182 return (ENOSPC);
183 }
184
185
186
187
188
189
190
191
192 static u_long
193 ext2fs_dirpref(struct m_ext2fs *fs)
194 {
195 int cg, maxspace, mincg, avgifree;
196
197 avgifree = fs->e2fs.e2fs_ficount / fs->e2fs_ncg;
198 maxspace = 0;
199 mincg = -1;
200 for (cg = 0; cg < fs->e2fs_ncg; cg++)
201 if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) {
202 if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > maxspace) {
203 mincg = cg;
204 maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree;
205 }
206 }
207 return mincg;
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221 int32_t
222 ext2fs_blkpref(struct inode *ip, int32_t lbn, int indx, int32_t *bap)
223 {
224 struct m_ext2fs *fs;
225 int cg, i;
226
227 fs = ip->i_e2fs;
228
229
230
231
232
233 if ( ip->i_e2fs_last_blk && lbn == ip->i_e2fs_last_lblk + 1) {
234 return ip->i_e2fs_last_blk + 1;
235 }
236
237
238
239
240
241
242 if (bap) {
243 for (i = indx; i >= 0 ; i--) {
244 if (bap[i]) {
245 return fs2h32(bap[i]) + 1;
246 }
247 }
248 }
249
250
251
252 cg = ino_to_cg(fs, ip->i_number);
253 return fs->e2fs.e2fs_bpg * cg + fs->e2fs.e2fs_first_dblock + 1;
254 }
255
256
257
258
259
260
261
262
263
264 static u_long
265 ext2fs_hashalloc(struct inode *ip, int cg, long pref, int size,
266 int32_t (*allocator)(struct inode *, int, int32_t, int))
267 {
268 struct m_ext2fs *fs;
269 long result;
270 int i, icg = cg;
271
272 fs = ip->i_e2fs;
273
274
275
276 result = (*allocator)(ip, cg, pref, size);
277 if (result)
278 return (result);
279
280
281
282 for (i = 1; i < fs->e2fs_ncg; i *= 2) {
283 cg += i;
284 if (cg >= fs->e2fs_ncg)
285 cg -= fs->e2fs_ncg;
286 result = (*allocator)(ip, cg, 0, size);
287 if (result)
288 return (result);
289 }
290
291
292
293
294
295 cg = (icg + 2) % fs->e2fs_ncg;
296 for (i = 2; i < fs->e2fs_ncg; i++) {
297 result = (*allocator)(ip, cg, 0, size);
298 if (result)
299 return (result);
300 cg++;
301 if (cg == fs->e2fs_ncg)
302 cg = 0;
303 }
304 return (0);
305 }
306
307
308
309
310
311
312
313
314 static int32_t
315 ext2fs_alloccg(struct inode *ip, int cg, int32_t bpref, int size)
316 {
317 struct m_ext2fs *fs;
318 char *bbp;
319 struct buf *bp;
320 int error, bno, start, end, loc;
321
322 fs = ip->i_e2fs;
323 if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
324 return (0);
325 error = bread(ip->i_devvp, fsbtodb(fs,
326 fs->e2fs_gd[cg].ext2bgd_b_bitmap),
327 (int)fs->e2fs_bsize, NOCRED, &bp);
328 if (error || fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
329 brelse(bp);
330 return (0);
331 }
332 bbp = (char *)bp->b_data;
333
334 if (dtog(fs, bpref) != cg)
335 bpref = 0;
336 if (bpref != 0) {
337 bpref = dtogd(fs, bpref);
338
339
340
341 if (isclr(bbp, bpref)) {
342 bno = bpref;
343 goto gotit;
344 }
345 }
346
347
348
349
350
351
352 if (bpref)
353 start = dtogd(fs, bpref) / NBBY;
354 else
355 start = 0;
356 end = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
357 for (loc = start; loc < end; loc++) {
358 if (bbp[loc] == 0) {
359 bno = loc * NBBY;
360 goto gotit;
361 }
362 }
363 for (loc = 0; loc < start; loc++) {
364 if (bbp[loc] == 0) {
365 bno = loc * NBBY;
366 goto gotit;
367 }
368 }
369
370 bno = ext2fs_mapsearch(fs, bbp, bpref);
371 if (bno < 0)
372 return (0);
373 gotit:
374 #ifdef DIAGNOSTIC
375 if (isset(bbp, (long)bno)) {
376 printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n",
377 cg, bno, fs->e2fs_fsmnt);
378 panic("ext2fs_alloccg: dup alloc");
379 }
380 #endif
381 setbit(bbp, (long)bno);
382 fs->e2fs.e2fs_fbcount--;
383 fs->e2fs_gd[cg].ext2bgd_nbfree--;
384 fs->e2fs_fmod = 1;
385 bdwrite(bp);
386 return (cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno);
387 }
388
389
390
391
392
393
394
395
396
397
398 static int32_t
399 ext2fs_nodealloccg(struct inode *ip, int cg, int32_t ipref, int mode)
400 {
401 struct m_ext2fs *fs;
402 char *ibp;
403 struct buf *bp;
404 int error, start, len, loc, map, i;
405
406 ipref--;
407 fs = ip->i_e2fs;
408 if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
409 return (0);
410 error = bread(ip->i_devvp, fsbtodb(fs,
411 fs->e2fs_gd[cg].ext2bgd_i_bitmap),
412 (int)fs->e2fs_bsize, NOCRED, &bp);
413 if (error) {
414 brelse(bp);
415 return (0);
416 }
417 ibp = (char *)bp->b_data;
418 if (ipref) {
419 ipref %= fs->e2fs.e2fs_ipg;
420 if (isclr(ibp, ipref))
421 goto gotit;
422 }
423 start = ipref / NBBY;
424 len = howmany(fs->e2fs.e2fs_ipg - ipref, NBBY);
425 loc = skpc(0xff, len, &ibp[start]);
426 if (loc == 0) {
427 len = start + 1;
428 start = 0;
429 loc = skpc(0xff, len, &ibp[0]);
430 if (loc == 0) {
431 printf("cg = %d, ipref = %d, fs = %s\n",
432 cg, ipref, fs->e2fs_fsmnt);
433 panic("ext2fs_nodealloccg: map corrupted");
434
435 }
436 }
437 i = start + len - loc;
438 map = ibp[i];
439 ipref = i * NBBY;
440 for (i = 1; i < (1 << NBBY); i <<= 1, ipref++) {
441 if ((map & i) == 0) {
442 goto gotit;
443 }
444 }
445 printf("fs = %s\n", fs->e2fs_fsmnt);
446 panic("ext2fs_nodealloccg: block not in map");
447
448 gotit:
449 setbit(ibp, ipref);
450 fs->e2fs.e2fs_ficount--;
451 fs->e2fs_gd[cg].ext2bgd_nifree--;
452 fs->e2fs_fmod = 1;
453 if ((mode & IFMT) == IFDIR) {
454 fs->e2fs_gd[cg].ext2bgd_ndirs++;
455 }
456 bdwrite(bp);
457 return (cg * fs->e2fs.e2fs_ipg + ipref +1);
458 }
459
460
461
462
463
464
465
466 void
467 ext2fs_blkfree(struct inode *ip, int32_t bno)
468 {
469 struct m_ext2fs *fs;
470 char *bbp;
471 struct buf *bp;
472 int error, cg;
473
474 fs = ip->i_e2fs;
475 cg = dtog(fs, bno);
476 if ((u_int)bno >= fs->e2fs.e2fs_bcount) {
477 printf("bad block %d, ino %d\n", bno, ip->i_number);
478 ext2fs_fserr(fs, ip->i_e2fs_uid, "bad block");
479 return;
480 }
481 error = bread(ip->i_devvp,
482 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
483 (int)fs->e2fs_bsize, NOCRED, &bp);
484 if (error) {
485 brelse(bp);
486 return;
487 }
488 bbp = (char *)bp->b_data;
489 bno = dtogd(fs, bno);
490 if (isclr(bbp, bno)) {
491 printf("dev = 0x%x, block = %d, fs = %s\n",
492 ip->i_dev, bno, fs->e2fs_fsmnt);
493 panic("blkfree: freeing free block");
494 }
495 clrbit(bbp, bno);
496 fs->e2fs.e2fs_fbcount++;
497 fs->e2fs_gd[cg].ext2bgd_nbfree++;
498
499 fs->e2fs_fmod = 1;
500 bdwrite(bp);
501 }
502
503
504
505
506
507
508 int
509 ext2fs_inode_free(struct inode *pip, ino_t ino, mode_t mode)
510 {
511 struct m_ext2fs *fs;
512 char *ibp;
513 struct buf *bp;
514 int error, cg;
515
516 fs = pip->i_e2fs;
517 if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
518 panic("ifree: range: dev = 0x%x, ino = %d, fs = %s",
519 pip->i_dev, ino, fs->e2fs_fsmnt);
520 cg = ino_to_cg(fs, ino);
521 error = bread(pip->i_devvp,
522 fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
523 (int)fs->e2fs_bsize, NOCRED, &bp);
524 if (error) {
525 brelse(bp);
526 return (0);
527 }
528 ibp = (char *)bp->b_data;
529 ino = (ino - 1) % fs->e2fs.e2fs_ipg;
530 if (isclr(ibp, ino)) {
531 printf("dev = 0x%x, ino = %d, fs = %s\n",
532 pip->i_dev, ino, fs->e2fs_fsmnt);
533 if (fs->e2fs_ronly == 0)
534 panic("ifree: freeing free inode");
535 }
536 clrbit(ibp, ino);
537 fs->e2fs.e2fs_ficount++;
538 fs->e2fs_gd[cg].ext2bgd_nifree++;
539 if ((mode & IFMT) == IFDIR) {
540 fs->e2fs_gd[cg].ext2bgd_ndirs--;
541 }
542 fs->e2fs_fmod = 1;
543 bdwrite(bp);
544 return (0);
545 }
546
547
548
549
550
551
552
553
554 static int32_t
555 ext2fs_mapsearch(struct m_ext2fs *fs, char *bbp, int32_t bpref)
556 {
557 int32_t bno;
558 int start, len, loc, i, map;
559
560
561
562
563
564 if (bpref)
565 start = dtogd(fs, bpref) / NBBY;
566 else
567 start = 0;
568 len = howmany(fs->e2fs.e2fs_fpg, NBBY) - start;
569 loc = skpc(0xff, len, &bbp[start]);
570 if (loc == 0) {
571 len = start + 1;
572 start = 0;
573 loc = skpc(0xff, len, &bbp[start]);
574 if (loc == 0) {
575 printf("start = %d, len = %d, fs = %s\n",
576 start, len, fs->e2fs_fsmnt);
577 panic("ext2fs_alloccg: map corrupted");
578
579 }
580 }
581 i = start + len - loc;
582 map = bbp[i];
583 bno = i * NBBY;
584 for (i = 1; i < (1 << NBBY); i <<= 1, bno++) {
585 if ((map & i) == 0)
586 return (bno);
587 }
588 printf("fs = %s\n", fs->e2fs_fsmnt);
589 panic("ext2fs_mapsearch: block not in map");
590
591 }
592
593
594
595
596
597
598
599 static void
600 ext2fs_fserr(struct m_ext2fs *fs, uid_t uid, char *cp)
601 {
602
603 log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp);
604 }