|
|
1.1 root 1: /*
2: * traditional disk filesystem
3: */
4: #include "sys/param.h"
5: #include "sys/systm.h"
6: #include "sys/ino.h"
7: #include "sys/buf.h"
8: #include "sys/filsys.h"
9: #include "sys/mount.h"
10: #include "sys/dir.h"
11: #include "sys/user.h"
12: #include "sys/inode.h"
13: #include "sys/file.h"
14: #include "sys/conf.h"
15: #include "sys/vlimit.h"
16: #include "sys/stat.h"
17: #include "sys/filio.h"
18: #include "sys/cmap.h"
19: #include "sys/stream.h"
20:
21: int fsput(), fsupdat(), fsread(), fswrite(), fstrunc(), fsstat();
22: int fsnami(), fsmount(), fsioctl(), fsdirread();
23: struct inode *fsopen();
24: struct fstypsw fsfs =
25: fsinit(fsput, fsupdat, fsread, fswrite, fstrunc, fsstat,
26: fsnami, fsmount, fsioctl, fsopen, fsdirread);
27:
28: extern struct mount fsmtab[];
29: extern int fscnt;
30:
31: /*
32: * silly mount/unmount routine for fs type 0
33: */
34:
35: fsmount(sip, ip, flag, mnt, fstyp)
36: register struct inode *ip, *sip;
37: int flag, mnt, fstyp;
38: {
39:
40: if (!suser())
41: return;
42: if (mnt)
43: fson(sip, ip, flag, fstyp);
44: else
45: fsoff(ip, fstyp);
46: }
47:
48: /*
49: * mount a type 0 filesystem (sip on ip)
50: * maintain the mount table for vm code's sake
51: *
52: * magic to help booting:
53: * if rootdir == NULL, we are being called from iinit, so
54: * - allow s_valid == 0 on bitmapped filesystems so root may be mounted
55: * - call clkinit to set the clock from the super-block time
56: */
57:
58: fson(sip, ip, ronly, fstyp)
59: register struct inode *ip, *sip;
60: int ronly, fstyp;
61: {
62: dev_t dev;
63: register struct mount *mp;
64: struct mount *emp;
65: struct inode *rip;
66: register struct filsys *fp;
67: struct buf *bp;
68: struct inode pi; /* primer */
69:
70: if ((sip->i_mode&IFMT) != IFBLK) {
71: u.u_error = EINVAL;
72: return;
73: }
74: if (ip->i_fstyp == fstyp && ip->i_dev == sip->i_un.i_rdev) {
75: u.u_error = EBUSY;
76: return;
77: }
78: emp = NULL;
79: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) {
80: if (mp->m_dev == NULL)
81: emp = mp;
82: else if (mp->m_dev == sip)
83: goto hopeless;
84: }
85: if (emp == NULL)
86: goto hopeless;
87: emp->m_dev = sip;
88: dev = (dev_t)sip->i_un.i_rdev;
89: bp = bread(dev, SUPERB);
90: if(u.u_error) {
91: emp->m_dev = NULL;
92: brelse(bp);
93: return;
94: }
95: bp->b_flags |= B_LOCKED;
96: brelse(bp);
97: fp = bp->b_un.b_filsys;
98: fp->s_ilock = 0;
99: fp->s_flock = 0;
100: fp->s_ronly = ronly & 1;
101: fp->s_nbehind = 0;
102: fp->s_lasti = 1;
103: if(fp->s_cylsize == 0)
104: fp->s_cylsize = 40; /* transition hack */
105: if(fp->s_aspace == 0)
106: fp->s_aspace = 4; /* likewise */
107: if(BITFS(dev) && !fp->s_valid && !fp->s_ronly && rootdir != NULL)
108: goto failed; /* NOT IMPLEMENTED */
109: if(BITFS(dev) && fp->U.N.S_flag) {
110: if(fsbiton(dev, fp))
111: goto failed;
112: /* hack until pjw fixes chuck */
113: } else if (BITFS(dev) && fp->s_isize + BITMAP*BITCELL < fp->s_fsize)
114: if(fsbiton(dev, fp))
115: goto failed;
116: pi.i_dev = dev;
117: pi.i_fstyp = fstyp;
118: pi.i_un.i_bufp = bp;
119: if ((rip = iget(&pi, dev, ROOTINO)) == NULL)
120: goto failed;
121: if (rip->i_count == 1 && fsiread(&pi, rip) < 0)
122: goto failed;
123: if (rip->i_count != 1) { /* already mounted */
124: iput(rip);
125: goto failed;
126: }
127: emp->m_mroot = rip;
128: ip->i_mroot = rip;
129: rip->i_mpoint = ip;
130: ip->i_count++;
131: sip->i_count++;
132: prele(rip);
133: if (rootdir == NULL)
134: clkinit(fp->s_time);
135: return;
136: failed:
137: bp->b_flags &= ~B_LOCKED;
138: emp->m_dev = NULL;
139: hopeless:
140: if (u.u_error == 0)
141: u.u_error = EBUSY;
142: }
143:
144: fsoff(mip, fstyp)
145: register struct inode *mip;
146: {
147: dev_t dev;
148: register struct mount *mp;
149: register struct inode *rip;
150: struct buf *bp;
151: struct filsys *fp;
152:
153: rip = mip->i_mroot;
154: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--)
155: if (mp->m_mroot == rip)
156: break;
157: if (mp < fsmtab)
158: panic("umount mp");
159: plock(rip);
160: xumount(rip);
161: update(); /* silly */
162: if (rip->i_count > 1 || ifsbusy(rip)) {
163: u.u_error = EBUSY;
164: prele(rip);
165: return;
166: }
167: plock(mip);
168: mip->i_mroot = NULL;
169: iput(mip);
170: dev = rip->i_dev;
171: if ((bp = getblk(dev, SUPERB)) != rip->i_un.i_bufp)
172: panic("umount");
173: iput(rip);
174: bp->b_flags &= ~(B_LOCKED|B_ASYNC); /* ~async needed? */
175: if (bp->b_un.b_filsys->s_ronly)
176: brelse(bp);
177: else {
178: if (BITFS(dev)) {
179: fp = bp->b_un.b_filsys;
180: fp->s_valid = 1;
181: if(fp->U.N.S_flag)
182: fsbitoff(dev, fp, 1);
183: }
184: bwrite(bp);
185: }
186: mpurge(mp - fsmtab);
187: idec(mp->m_dev);
188: mp->m_dev = NULL;
189: }
190:
191: fsbiton(dev, fp)
192: dev_t dev;
193: register struct filsys *fp;
194: {
195: register int i, nf;
196: register struct buf **bpp;
197: register struct buf *bp;
198:
199: /* two chuck should do */
200: fp->U.N.S_flag = 1; /* bit map not in superblock */
201: nf = fp->U.N.S_bsize = BSIZE(dev) * NBBY;
202: if (fp->s_ronly)
203: return (0);
204: nf = (fp->s_fsize + nf - 1) / nf;
205: bpp = fp->U.N.S_blk;
206: for(i = 0; i < nf; i++)
207: bpp[i] = 0;
208: for(i = 0; i < nf; i++) {
209: bp = bread(dev, fp->s_fsize-nf+i);
210: if(u.u_error) {
211: brelse(bp);
212: goto failed;
213: }
214: bp->b_flags |= B_LOCKED;
215: brelse(bp);
216: bpp[i] = bp;
217: }
218: return(0);
219: failed:
220: fsbitoff(dev, fp, 0);
221: return(1);
222: }
223:
224: fsbitoff(dev, fp, wrtflg)
225: dev_t dev;
226: struct filsys *fp;
227: {
228: register struct buf **bpp;
229: register struct buf *bp;
230: register int i, nf;
231:
232: if (fp->s_ronly)
233: return;
234: nf = fp->U.N.S_bsize;
235: nf = (fp->s_fsize + nf-1)/nf;
236: bpp = fp->U.N.S_blk;
237: for(i = 0; i < nf; i++)
238: if(bpp[i]) {
239: if ((bp = getblk(dev, fp->s_fsize - nf + i)) != bpp[i])
240: panic("fsbitoff");
241: bp->b_flags &= ~B_LOCKED;
242: if(wrtflg)
243: bwrite(bp);
244: bpp[i] = 0; /* safety first */
245: }
246: }
247:
248: /*
249: * fill in inode ip from the disk copy
250: * in filesystem fip
251: * ip is an inode fresh from iget
252: */
253: fsiread(fip, ip)
254: register struct inode *fip, *ip;
255: {
256: register struct buf *bp;
257: daddr_t bno;
258:
259: if (ip->i_number <= 0) {
260: u.u_error = EINVAL;
261: iput(ip);
262: return (-1);
263: }
264: bno = itod(fip->i_dev, (ino_t)ip->i_number);
265: if (bno >= getfs(fip)->s_isize) {
266: u.u_error = EINVAL;
267: iput(ip);
268: return (-1);
269: }
270: bp = bread(fip->i_dev, bno);
271: if((bp->b_flags&B_ERROR) != 0) {
272: brelse(bp);
273: iput(ip);
274: return(-1);
275: }
276: iexpand(ip, bp->b_un.b_dino+itoo(fip->i_dev, (ino_t)ip->i_number));
277: brelse(bp);
278: ip->i_un.i_bufp = fip->i_un.i_bufp;
279: ip->i_un.i_lastr = 0;
280: return (0);
281: }
282:
283: iexpand(ip, dp)
284: register struct inode *ip;
285: register struct dinode *dp;
286: {
287: register char *p1, *p2;
288: register int i;
289:
290: ip->i_mode = dp->di_mode;
291: ip->i_nlink = dp->di_nlink;
292: ip->i_uid = dp->di_uid;
293: ip->i_gid = dp->di_gid;
294: ip->i_size = dp->di_size;
295: p1 = (char *)ip->i_un.i_addr;
296: p2 = (char *)dp->di_addr;
297: for(i=0; i<NADDR; i++) {
298: *p1++ = *p2++;
299: *p1++ = *p2++;
300: *p1++ = *p2++;
301: *p1++ = 0;
302: }
303: }
304:
305: fsput(ip)
306: struct inode *ip;
307: {
308: if (ip->i_nlink == 0) {
309: fstrunc(ip);
310: ifree(ip);
311: ip->i_mode = 0;
312: ip->i_flag |= IUPD|ICHG;
313: }
314: if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0)
315: fsiupdat(ip, &time, &time, 0);
316: }
317:
318: fsupdat(ip, ta, tm, waitfor)
319: register struct inode *ip;
320: time_t *ta, *tm;
321: {
322: fsiupdat(ip, ta, tm, waitfor);
323: if (ip->i_un.i_bufp->b_un.b_filsys->s_fmod)
324: fsfupdat(ip);
325: }
326:
327: /*
328: * update the inode on disk
329: * if the super-block is dirty, write it too
330: */
331:
332: fsiupdat(ip, ta, tm, waitfor)
333: register struct inode *ip;
334: time_t *ta, *tm;
335: {
336: register struct buf *bp;
337: struct dinode *dp;
338: register char *p1, *p2;
339: register int i;
340:
341: if (ip->i_un.i_bufp->b_un.b_filsys->s_ronly)
342: return;
343: bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number));
344: if (bp->b_flags & B_ERROR) {
345: brelse(bp);
346: return;
347: }
348: dp = bp->b_un.b_dino;
349: dp += itoo(ip->i_dev, ip->i_number);
350: dp->di_mode = ip->i_mode;
351: dp->di_nlink = ip->i_nlink;
352: dp->di_uid = ip->i_uid;
353: dp->di_gid = ip->i_gid;
354: dp->di_size = ip->i_size;
355: p1 = (char *)dp->di_addr;
356: p2 = (char *)ip->i_un.i_addr;
357: for(i=0; i<NADDR; i++) {
358: *p1++ = *p2++;
359: *p1++ = *p2++;
360: *p1++ = *p2++;
361: if(*p2++)
362: printf("ino %d dev #%x addr #%x\n", ip->i_number, ip->i_dev, ip->i_un.i_addr[i]);
363: }
364: if(ip->i_flag&IACC)
365: dp->di_atime = *ta;
366: if(ip->i_flag&IUPD)
367: dp->di_mtime = *tm;
368: if(ip->i_flag&ICHG)
369: dp->di_ctime = time;
370: ip->i_flag &= ~(IUPD|IACC|ICHG);
371: if (waitfor)
372: bwrite(bp);
373: else
374: bdwrite(bp);
375: }
376:
377: /*
378: * write the super-block
379: */
380:
381: fsfupdat(ip)
382: struct inode *ip;
383: {
384: register struct filsys *fp;
385: struct buf *bp;
386:
387: fp = ip->i_un.i_bufp->b_un.b_filsys;
388: if (fp->s_fmod == 0 || fp->s_ilock || fp->s_flock || fp->s_ronly)
389: return;
390: bp = getblk(ip->i_dev, SUPERB);
391: if (bp->b_un.b_filsys != fp)
392: panic("fsfupdat");
393: fp->s_fmod = 0;
394: fp->s_time = time;
395: bwrite(bp);
396: }
397:
398: fsstat(ip, ub)
399: register struct inode *ip;
400: struct stat *ub;
401: {
402: register struct dinode *dp;
403: register struct buf *bp;
404: struct stat ds;
405:
406: /*
407: * first copy from inode table
408: */
409: ds.st_dev = ip->i_dev;
410: ds.st_ino = ip->i_number;
411: ds.st_mode = ip->i_mode;
412: ds.st_nlink = ip->i_nlink;
413: ds.st_uid = ip->i_uid;
414: ds.st_gid = ip->i_gid;
415: ds.st_rdev = (dev_t)ip->i_un.i_rdev;
416: ds.st_size = ip->i_size;
417: /*
418: * next the dates in the disk
419: */
420: bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number));
421: dp = bp->b_un.b_dino;
422: dp += itoo(ip->i_dev, ip->i_number);
423: ds.st_atime = dp->di_atime;
424: ds.st_mtime = dp->di_mtime;
425: ds.st_ctime = dp->di_ctime;
426: brelse(bp);
427: if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
428: u.u_error = EFAULT;
429: }
430:
431: fstrunc(ip)
432: register struct inode *ip;
433: {
434: register i;
435: daddr_t bn;
436: struct inode itmp;
437:
438: i = ip->i_mode & IFMT;
439: if (i!=IFREG && i!=IFDIR && i!=IFLNK)
440: return;
441: /*
442: * Clean inode on disk before freeing blocks
443: * to insure no duplicates if system crashes.
444: */
445: itmp = *ip;
446: itmp.i_size = 0;
447: for (i = 0; i < NADDR; i++)
448: itmp.i_un.i_addr[i] = 0;
449: itmp.i_flag |= ICHG|IUPD;
450: fsiupdat(&itmp, &time, &time, 1);
451: ip->i_flag &= ~(IUPD|IACC|ICHG);
452:
453: /*
454: * Now return blocks to free list... if machine
455: * crashes, they will be harmless MISSING blocks.
456: */
457: for(i=NADDR-1; i>=0; i--) {
458: bn = ip->i_un.i_addr[i];
459: if(bn == (daddr_t)0)
460: continue;
461: ip->i_un.i_addr[i] = (daddr_t)0;
462: switch(i) {
463:
464: default:
465: free(ip, bn);
466: break;
467:
468: case NADDR-3:
469: tloop(ip, bn, 0, 0);
470: break;
471:
472: case NADDR-2:
473: tloop(ip, bn, 1, 0);
474: break;
475:
476: case NADDR-1:
477: tloop(ip, bn, 1, 1);
478: }
479: }
480: ip->i_size = 0;
481: /*
482: * Inode was written and flags updated above.
483: * No need to modify flags here.
484: */
485: }
486:
487: tloop(fip, bn, f1, f2)
488: register struct inode *fip;
489: daddr_t bn;
490: {
491: register i;
492: register struct buf *bp;
493: register daddr_t *bap;
494: daddr_t nb;
495:
496: bp = NULL;
497: for(i=NINDIR(fip->i_dev)-1; i>=0; i--) {
498: if(bp == NULL) {
499: bp = bread(fip->i_dev, bn);
500: if (bp->b_flags & B_ERROR) {
501: brelse(bp);
502: return;
503: }
504: bap = bp->b_un.b_daddr;
505: }
506: nb = bap[i];
507: if(nb == (daddr_t)0)
508: continue;
509: if(f1) {
510: brelse(bp);
511: bp = NULL;
512: tloop(fip, nb, f2, 0);
513: } else
514: free(fip, nb);
515: }
516: if(bp != NULL)
517: brelse(bp);
518: free(fip, bn);
519: }
520:
521: fsioctl(ip, cmd, cmarg, flag)
522: register struct inode *ip;
523: caddr_t cmarg;
524: {
525: int fmt;
526: register dev_t dev;
527:
528: fmt = ip->i_mode & IFMT;
529: if (fmt != IFCHR) {
530: if (cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) {
531: off_t nread = ip->i_size; /* - fp->f_offset */
532: if (copyout((caddr_t)&nread, cmarg, sizeof(off_t)))
533: u.u_error = EFAULT;
534: } else
535: u.u_error = ENOTTY;
536: return;
537: }
538: dev = ip->i_un.i_rdev;
539: u.u_r.r_val1 = 0;
540: (*cdevsw[major(dev)]->d_ioctl)(dev, cmd, cmarg, flag);
541: }
542:
543: struct inode *
544: fsopen(ip, rw)
545: register struct inode *ip;
546: {
547: dev_t dev;
548: register unsigned int maj;
549:
550: dev = (dev_t)ip->i_un.i_rdev;
551: maj = major(dev);
552:
553: switch(ip->i_mode&IFMT) {
554: case IFCHR:
555: if(maj >= nchrdev || cdevsw[maj] == NULL)
556: goto bad;
557: if (cdevsw[maj]->qinfo) /* stream device */
558: return(stopen(cdevsw[major(dev)]->qinfo, dev, rw, ip));
559: (*cdevsw[maj]->d_open)(dev, rw);
560: break;
561:
562: case IFBLK:
563: if(maj >= nblkdev || bdevsw[maj] == NULL)
564: goto bad;
565: (*bdevsw[maj]->d_open)(dev, rw);
566: }
567: if (u.u_error) {
568: iput(ip);
569: return (NULL);
570: }
571: return (ip);
572:
573: bad:
574: u.u_error = ENXIO;
575: iput(ip);
576: return(NULL);
577: }
578:
579: fsread(ip)
580: register struct inode *ip;
581: {
582: struct buf *bp;
583: dev_t dev;
584: daddr_t lbn, bn;
585: off_t diff;
586: register int on, type;
587: register unsigned n;
588:
589: dev = (dev_t)ip->i_un.i_rdev;
590: type = ip->i_mode&IFMT;
591: if (type==IFCHR) {
592: (*cdevsw[major(dev)]->d_read)(dev);
593: return;
594: }
595: if (Lsign(u.u_offset) < 0) { /* and not IFCHR */
596: u.u_error = EINVAL;
597: return;
598: }
599: if (type != IFBLK) { /* if offset >= size, avoid overflow */
600: if (Lsign(Lladd(u.u_offset, -ip->i_size))>=0)
601: return;
602: dev = ip->i_dev;
603: }
604: do {
605: lbn = bn = Lshift(u.u_offset, BSHIFT(dev));
606: on = Ltol(u.u_offset) & BMASK(dev);
607: n = MIN((unsigned)(BSIZE(dev)-on), u.u_count);
608: if (type!=IFBLK) {
609: diff = ip->i_size - Ltol(u.u_offset);
610: if (diff <= 0)
611: return;
612: if (diff < n)
613: n = diff;
614: bn = bmap(ip, bn, B_READ);
615: if (u.u_error)
616: return;
617: } else
618: rablock = bn+1;
619: if ((long)bn<0) {
620: bp = geteblk();
621: clrbuf(bp);
622: } else if (ip->i_un.i_lastr+1==lbn)
623: bp = breada(dev, bn, rablock);
624: else
625: bp = bread(dev, bn);
626: ip->i_un.i_lastr = lbn;
627: n = MIN(n, BSIZE(dev)-bp->b_resid);
628: if (n!=0)
629: iomove(bp->b_un.b_addr+on, n, B_READ);
630: brelse(bp);
631: } while(u.u_error==0 && u.u_count!=0 && n!=0);
632: }
633:
634: fsdirread(ip, len)
635: struct inode *ip;
636: { struct buf *bp = 0, *outb;
637: dev_t dev;
638: daddr_t bn, lbn;
639: int on, type, j, m, new = 0;
640: char *p, *lp, *lastp;
641: struct direct *dp;
642: char ncvt[24];
643:
644: if(Lsign(u.u_offset) < 0) {
645: u.u_error = EINVAL;
646: return;
647: }
648: type = ip->i_mode & IFMT;
649: if(type != IFDIR) {
650: u.u_error = ENOTDIR;
651: return;
652: }
653: dev = ip->i_dev;
654: outb = geteblk(); /* to hold the stuff for the user */
655: if(len > BSIZE(dev))
656: len = BSIZE(dev);
657: p = lp = outb->b_un.b_addr;
658: lastp = p + len;
659: loop:
660: if(new <= 0) { /* get some goo */
661: lbn = bn = Lshift(u.u_offset, BSHIFT(dev));
662: on = Ltol(u.u_offset) & BMASK(dev);
663: if(ip->i_size <= Ltol(u.u_offset))
664: goto done;
665: bn = bmap(ip, bn, B_READ);
666: if(u.u_error)
667: return;
668: if((long)bn < 0) { /* holes in dirs? */
669: u.u_offset = Lladd(u.u_offset, BSIZE(dev)-on);
670: goto loop; /* try the next block */
671: }
672: if(bp)
673: brelse(bp);
674: if(ip->i_un.i_lastr + 1 == lbn)
675: bp = breada(dev, bn, rablock);
676: else
677: bp = bread(dev, bn);
678: ip->i_un.i_lastr = lbn;
679: new = BSIZE(dev) - on;
680: if(new > BSIZE(dev) - bp->b_resid) /* io error? */
681: new = BSIZE(dev) - bp->b_resid; /* or paranoia */
682: if(new > ip->i_size - Ltol(u.u_offset))
683: new = ip->i_size - Ltol(u.u_offset);
684: dp = (struct direct *) (bp->b_un.b_addr + on);
685: }
686: if(dp->d_ino == 0)
687: goto incr;
688: for(m = dp->d_ino, j = sizeof(ncvt)-1; m; j--) {
689: ncvt[j] = m%10 + '0';
690: m /= 10;
691: }
692: for(++j; j < sizeof(ncvt) && p < lastp; )
693: *p++ = ncvt[j++];
694: if(j != sizeof(ncvt) || p >= lastp)
695: goto early;
696: *p++ = '\t';
697: for(j = 0; j < DIRSIZ && dp->d_name[j] && p < lastp; j++)
698: *p++ = dp->d_name[j];
699: if(p >= lastp)
700: goto early;
701: *p++ = 0;
702: incr:
703: lp = p;
704: new -= sizeof(*dp);
705: u.u_offset = Lladd(u.u_offset, sizeof(*dp));
706: dp++;
707: if(p < lastp)
708: goto loop;
709: done:
710: j = lp - outb->b_un.b_addr;
711: if(j > 0)
712: if(copyout((caddr_t)outb->b_un.b_addr, u.u_base, j))
713: u.u_error = EFAULT;
714: if(bp)
715: brelse(bp);
716: brelse(outb);
717: u.u_r.r_val1 = j;
718: return;
719: early:
720: *lp = 0;
721: if(lp > outb->b_un.b_addr)
722: goto done;
723: u.u_error = ENOSPC;
724: if(bp)
725: brelse(bp);
726: brelse(outb);
727: }
728:
729: fswrite(ip)
730: register struct inode *ip;
731: {
732: struct buf *bp;
733: dev_t dev;
734: daddr_t bn;
735: register int on, type;
736: register unsigned n;
737: register int i;
738:
739: dev = (dev_t)ip->i_un.i_rdev;
740: type = ip->i_mode&IFMT;
741: if (type==IFCHR) {
742: ip->i_flag |= IUPD|ICHG;
743: (*cdevsw[major(dev)]->d_write)(dev);
744: return;
745: }
746: if (Lsign(u.u_offset) < 0) { /* and not IFCHR */
747: u.u_error = EINVAL;
748: return;
749: }
750: if (u.u_count == 0)
751: return;
752: if ((ip->i_mode&IFMT)==IFREG &&
753: (Lsign(Luadd(u.u_offset, u.u_count))!=0 ||
754: Ltol(u.u_offset) + u.u_count > u.u_limit[LIM_FSIZE])) {
755: u.u_error = EMFILE;
756: return;
757: }
758: if (type != IFBLK)
759: dev = ip->i_dev;
760: do {
761: bn = Lshift(u.u_offset, BSHIFT(dev));
762: on = Ltol(u.u_offset) & BMASK(dev);
763: n = MIN((unsigned)(BSIZE(dev)-on), u.u_count);
764: if (type!=IFBLK) {
765: bn = bmap(ip, bn, B_WRITE);
766: if((long)bn<0)
767: return;
768: }
769: i = getfsx(dev);
770: if (bn && mfind(i, bn))
771: munhash(i, bn);
772: if(n == BSIZE(dev))
773: bp = getblk(dev, bn);
774: else
775: bp = bread(dev, bn);
776: iomove(bp->b_un.b_addr+on, n, B_WRITE);
777: if(u.u_error != 0)
778: brelse(bp);
779: else {
780: if ((ip->i_mode&IFMT) == IFDIR &&
781: ((struct direct *)(bp->b_un.b_addr+on))->d_ino == 0)
782: bwrite(bp); /* consistency */
783: else if ((n+on) == BSIZE(dev))
784: bawrite(bp);
785: else
786: bdwrite(bp);
787: }
788: if(Ltol(u.u_offset) > ip->i_size &&
789: (type==IFDIR || type==IFREG || type==IFLNK))
790: ip->i_size = Ltol(u.u_offset);
791: ip->i_flag |= IUPD|ICHG;
792: } while(u.u_error==0 && u.u_count!=0);
793: }
794:
795: /*
796: * Getfsx returns the index in the file system
797: * table of the specified device. The swap device
798: * is also assigned a pseudo-index. The index may
799: * be used as a compressed indication of the location
800: * of a block, recording
801: * <getfsx(dev),blkno>
802: * rather than
803: * <dev, blkno>
804: * provided the information need remain valid only
805: * as long as the file system is mounted.
806: *
807: * only the vm code calls this.
808: */
809: getfsx(dev)
810: dev_t dev;
811: {
812: register struct mount *mp;
813:
814: if (dev == swapdev)
815: return (MSWAPX);
816: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) {
817: if (mp->m_dev == NULL)
818: continue;
819: if (mp->m_dev->i_un.i_rdev == dev)
820: return (mp - fsmtab);
821: }
822: return (-1);
823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.