|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)sys_inode.c 6.13 (Berkeley) 8/4/85
7: */
8:
9: #include "param.h"
10: #include "systm.h"
11: #include "dir.h"
12: #include "user.h"
13: #include "inode.h"
14: #include "proc.h"
15: #include "fs.h"
16: #include "conf.h"
17: #include "buf.h"
18: #include "mount.h"
19: #include "file.h"
20: #include "uio.h"
21: #include "ioctl.h"
22: #include "tty.h"
23: #include "cmap.h"
24: #include "stat.h"
25: #include "kernel.h"
26: #include "quota.h"
27:
28: int ino_rw(), ino_ioctl(), ino_select(), ino_close();
29: struct fileops inodeops =
30: { ino_rw, ino_ioctl, ino_select, ino_close };
31:
32: ino_rw(fp, rw, uio)
33: struct file *fp;
34: enum uio_rw rw;
35: struct uio *uio;
36: {
37: register struct inode *ip = (struct inode *)fp->f_data;
38: int error;
39:
40: if ((ip->i_mode&IFMT) == IFREG) {
41: ILOCK(ip);
42: if (fp->f_flag&FAPPEND && rw == UIO_WRITE)
43: uio->uio_offset = fp->f_offset = ip->i_size;
44: error = rwip(ip, uio, rw);
45: IUNLOCK(ip);
46: } else
47: error = rwip(ip, uio, rw);
48: return (error);
49: }
50:
51: rdwri(rw, ip, base, len, offset, segflg, aresid)
52: struct inode *ip;
53: caddr_t base;
54: int len, offset, segflg;
55: int *aresid;
56: enum uio_rw rw;
57: {
58: struct uio auio;
59: struct iovec aiov;
60: int error;
61:
62: auio.uio_iov = &aiov;
63: auio.uio_iovcnt = 1;
64: aiov.iov_base = base;
65: aiov.iov_len = len;
66: auio.uio_resid = len;
67: auio.uio_offset = offset;
68: auio.uio_segflg = segflg;
69: error = rwip(ip, &auio, rw);
70: if (aresid)
71: *aresid = auio.uio_resid;
72: else
73: if (auio.uio_resid)
74: error = EIO;
75: return (error);
76: }
77:
78: rwip(ip, uio, rw)
79: register struct inode *ip;
80: register struct uio *uio;
81: enum uio_rw rw;
82: {
83: dev_t dev = (dev_t)ip->i_rdev;
84: struct buf *bp;
85: struct fs *fs;
86: daddr_t lbn, bn;
87: register int n, on, type;
88: int size;
89: long bsize;
90: extern int mem_no;
91: int error = 0;
92:
93: if (rw != UIO_READ && rw != UIO_WRITE)
94: panic("rwip");
95: if (rw == UIO_READ && uio->uio_resid == 0)
96: return (0);
97: if (uio->uio_offset < 0 &&
98: ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev)))
99: return (EINVAL);
100: if (rw == UIO_READ)
101: ip->i_flag |= IACC;
102: type = ip->i_mode&IFMT;
103: if (type == IFCHR) {
104: if (rw == UIO_READ)
105: error = (*cdevsw[major(dev)].d_read)(dev, uio);
106: else {
107: ip->i_flag |= IUPD|ICHG;
108: error = (*cdevsw[major(dev)].d_write)(dev, uio);
109: }
110: return (error);
111: }
112: if (uio->uio_resid == 0)
113: return (0);
114: if (rw == UIO_WRITE && type == IFREG &&
115: uio->uio_offset + uio->uio_resid >
116: u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
117: psignal(u.u_procp, SIGXFSZ);
118: return (EFBIG);
119: }
120: if (type != IFBLK) {
121: dev = ip->i_dev;
122: fs = ip->i_fs;
123: bsize = fs->fs_bsize;
124: } else
125: bsize = BLKDEV_IOSIZE;
126: do {
127: lbn = uio->uio_offset / bsize;
128: on = uio->uio_offset % bsize;
129: n = MIN((unsigned)(bsize - on), uio->uio_resid);
130: if (type != IFBLK) {
131: if (rw == UIO_READ) {
132: int diff = ip->i_size - uio->uio_offset;
133: if (diff <= 0)
134: return (0);
135: if (diff < n)
136: n = diff;
137: }
138: bn = fsbtodb(fs,
139: bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
140: if (u.u_error || rw == UIO_WRITE && (long)bn<0)
141: return (u.u_error);
142: if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
143: (type == IFDIR || type == IFREG || type == IFLNK))
144: ip->i_size = uio->uio_offset + n;
145: size = blksize(fs, ip, lbn);
146: } else {
147: bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
148: rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
149: rasize = size = bsize;
150: }
151: if (rw == UIO_READ) {
152: if ((long)bn<0) {
153: bp = geteblk(size);
154: clrbuf(bp);
155: } else if (ip->i_lastr + 1 == lbn)
156: bp = breada(dev, bn, size, rablock, rasize);
157: else
158: bp = bread(dev, bn, size);
159: ip->i_lastr = lbn;
160: } else {
161: int i, count, s;
162: extern struct cmap *mfind();
163:
164: count = howmany(size, DEV_BSIZE);
165: s = splimp();
166: for (i = 0; i < count; i += CLBYTES / DEV_BSIZE)
167: if (mfind(dev, bn + i))
168: munhash(dev, bn + i);
169: splx(s);
170: if (n == bsize)
171: bp = getblk(dev, bn, size);
172: else
173: bp = bread(dev, bn, size);
174: }
175: n = MIN(n, size - bp->b_resid);
176: if (bp->b_flags & B_ERROR) {
177: error = EIO;
178: brelse(bp);
179: goto bad;
180: }
181: u.u_error =
182: uiomove(bp->b_un.b_addr+on, n, rw, uio);
183: if (rw == UIO_READ) {
184: if (n + on == bsize || uio->uio_offset == ip->i_size)
185: bp->b_flags |= B_AGE;
186: brelse(bp);
187: } else {
188: if ((ip->i_mode&IFMT) == IFDIR)
189: bwrite(bp);
190: else if (n + on == bsize) {
191: bp->b_flags |= B_AGE;
192: bawrite(bp);
193: } else
194: bdwrite(bp);
195: ip->i_flag |= IUPD|ICHG;
196: if (u.u_ruid != 0)
197: ip->i_mode &= ~(ISUID|ISGID);
198: }
199: } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
200: if (error == 0) /* XXX */
201: error = u.u_error; /* XXX */
202: bad:
203: return (error);
204: }
205:
206: ino_ioctl(fp, com, data)
207: struct file *fp;
208: register int com;
209: caddr_t data;
210: {
211: register struct inode *ip = ((struct inode *)fp->f_data);
212: register int fmt = ip->i_mode & IFMT;
213: dev_t dev;
214:
215: switch (fmt) {
216:
217: case IFREG:
218: case IFDIR:
219: if (com == FIONREAD) {
220: *(off_t *)data = ip->i_size - fp->f_offset;
221: return (0);
222: }
223: if (com == FIONBIO || com == FIOASYNC) /* XXX */
224: return (0); /* XXX */
225: /* fall into ... */
226:
227: default:
228: return (ENOTTY);
229:
230: case IFCHR:
231: dev = ip->i_rdev;
232: u.u_r.r_val1 = 0;
233: if (setjmp(&u.u_qsave)) {
234: if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
235: return(EINTR);
236: u.u_eosys = RESTARTSYS;
237: return (0);
238: }
239: return ((*cdevsw[major(dev)].d_ioctl)(dev, com, data,
240: fp->f_flag));
241: }
242: }
243:
244: ino_select(fp, which)
245: struct file *fp;
246: int which;
247: {
248: register struct inode *ip = (struct inode *)fp->f_data;
249: register dev_t dev;
250:
251: switch (ip->i_mode & IFMT) {
252:
253: default:
254: return (1); /* XXX */
255:
256: case IFCHR:
257: dev = ip->i_rdev;
258: return (*cdevsw[major(dev)].d_select)(dev, which);
259: }
260: }
261:
262: #ifdef notdef
263: ino_clone()
264: {
265:
266: return (EOPNOTSUPP);
267: }
268: #endif
269:
270: ino_stat(ip, sb)
271: register struct inode *ip;
272: register struct stat *sb;
273: {
274:
275: ITIMES(ip, &time, &time);
276: /*
277: * Copy from inode table
278: */
279: sb->st_dev = ip->i_dev;
280: sb->st_ino = ip->i_number;
281: sb->st_mode = ip->i_mode;
282: sb->st_nlink = ip->i_nlink;
283: sb->st_uid = ip->i_uid;
284: sb->st_gid = ip->i_gid;
285: sb->st_rdev = (dev_t)ip->i_rdev;
286: sb->st_size = ip->i_size;
287: sb->st_atime = ip->i_atime;
288: sb->st_spare1 = 0;
289: sb->st_mtime = ip->i_mtime;
290: sb->st_spare2 = 0;
291: sb->st_ctime = ip->i_ctime;
292: sb->st_spare3 = 0;
293: /* this doesn't belong here */
294: if ((ip->i_mode&IFMT) == IFBLK)
295: sb->st_blksize = BLKDEV_IOSIZE;
296: else if ((ip->i_mode&IFMT) == IFCHR)
297: sb->st_blksize = MAXBSIZE;
298: else
299: sb->st_blksize = ip->i_fs->fs_bsize;
300: sb->st_blocks = ip->i_blocks;
301: sb->st_spare4[0] = sb->st_spare4[1] = 0;
302: return (0);
303: }
304:
305: ino_close(fp)
306: register struct file *fp;
307: {
308: register struct inode *ip = (struct inode *)fp->f_data;
309: register struct mount *mp;
310: int flag, mode;
311: dev_t dev;
312: register int (*cfunc)();
313:
314: if (fp->f_flag & (FSHLOCK|FEXLOCK))
315: ino_unlock(fp, FSHLOCK|FEXLOCK);
316: flag = fp->f_flag;
317: dev = (dev_t)ip->i_rdev;
318: mode = ip->i_mode & IFMT;
319: ilock(ip);
320: iput(ip);
321: fp->f_data = (caddr_t) 0; /* XXX */
322: switch (mode) {
323:
324: case IFCHR:
325: cfunc = cdevsw[major(dev)].d_close;
326: break;
327:
328: case IFBLK:
329: /*
330: * We don't want to really close the device if it is mounted
331: */
332: /* MOUNT TABLE SHOULD HOLD INODE */
333: for (mp = mount; mp < &mount[NMOUNT]; mp++)
334: if (mp->m_bufp != NULL && mp->m_dev == dev)
335: return;
336: cfunc = bdevsw[major(dev)].d_close;
337: break;
338:
339: default:
340: return;
341: }
342:
343: /*
344: * Check that another inode for the same device isn't active.
345: * This is because the same device can be referenced by
346: * two different inodes.
347: */
348: for (fp = file; fp < fileNFILE; fp++) {
349: if (fp->f_type != DTYPE_INODE) /* XXX */
350: continue;
351: if (fp->f_count && (ip = (struct inode *)fp->f_data) &&
352: ip->i_rdev == dev && (ip->i_mode&IFMT) == mode)
353: return;
354: }
355: if (mode == IFBLK) {
356: /*
357: * On last close of a block device (that isn't mounted)
358: * we must invalidate any in core blocks, so that
359: * we can, for instance, change floppy disks.
360: */
361: bflush(dev);
362: binval(dev);
363: }
364: if (setjmp(&u.u_qsave)) {
365: /*
366: * If device close routine is interrupted,
367: * must return so closef can clean up.
368: */
369: if (u.u_error == 0)
370: u.u_error = EINTR; /* ??? */
371: return;
372: }
373: (*cfunc)(dev, flag);
374: }
375:
376: /*
377: * Place an advisory lock on an inode.
378: */
379: ino_lock(fp, cmd)
380: register struct file *fp;
381: int cmd;
382: {
383: register int priority = PLOCK;
384: register struct inode *ip = (struct inode *)fp->f_data;
385:
386: if ((cmd & LOCK_EX) == 0)
387: priority += 4;
388: if (setjmp(&u.u_qsave)) {
389: if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
390: return(EINTR);
391: u.u_eosys = RESTARTSYS;
392: return (0);
393: }
394: /*
395: * If there's a exclusive lock currently applied
396: * to the file, then we've gotta wait for the
397: * lock with everyone else.
398: */
399: again:
400: while (ip->i_flag & IEXLOCK) {
401: /*
402: * If we're holding an exclusive
403: * lock, then release it.
404: */
405: if (fp->f_flag & FEXLOCK) {
406: ino_unlock(fp, FEXLOCK);
407: continue;
408: }
409: if (cmd & LOCK_NB)
410: return (EWOULDBLOCK);
411: ip->i_flag |= ILWAIT;
412: sleep((caddr_t)&ip->i_exlockc, priority);
413: }
414: if ((cmd & LOCK_EX) && (ip->i_flag & ISHLOCK)) {
415: /*
416: * Must wait for any shared locks to finish
417: * before we try to apply a exclusive lock.
418: *
419: * If we're holding a shared
420: * lock, then release it.
421: */
422: if (fp->f_flag & FSHLOCK) {
423: ino_unlock(fp, FSHLOCK);
424: goto again;
425: }
426: if (cmd & LOCK_NB)
427: return (EWOULDBLOCK);
428: ip->i_flag |= ILWAIT;
429: sleep((caddr_t)&ip->i_shlockc, PLOCK);
430: goto again;
431: }
432: if (fp->f_flag & FEXLOCK)
433: panic("ino_lock");
434: if (cmd & LOCK_EX) {
435: cmd &= ~LOCK_SH;
436: ip->i_exlockc++;
437: ip->i_flag |= IEXLOCK;
438: fp->f_flag |= FEXLOCK;
439: }
440: if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
441: ip->i_shlockc++;
442: ip->i_flag |= ISHLOCK;
443: fp->f_flag |= FSHLOCK;
444: }
445: return (0);
446: }
447:
448: /*
449: * Unlock a file.
450: */
451: ino_unlock(fp, kind)
452: register struct file *fp;
453: int kind;
454: {
455: register struct inode *ip = (struct inode *)fp->f_data;
456: int flags;
457:
458: kind &= fp->f_flag;
459: if (ip == NULL || kind == 0)
460: return;
461: flags = ip->i_flag;
462: if (kind & FSHLOCK) {
463: if ((flags & ISHLOCK) == 0)
464: panic("ino_unlock: SHLOCK");
465: if (--ip->i_shlockc == 0) {
466: ip->i_flag &= ~ISHLOCK;
467: if (flags & ILWAIT)
468: wakeup((caddr_t)&ip->i_shlockc);
469: }
470: fp->f_flag &= ~FSHLOCK;
471: }
472: if (kind & FEXLOCK) {
473: if ((flags & IEXLOCK) == 0)
474: panic("ino_unlock: EXLOCK");
475: if (--ip->i_exlockc == 0) {
476: ip->i_flag &= ~(IEXLOCK|ILWAIT);
477: if (flags & ILWAIT)
478: wakeup((caddr_t)&ip->i_exlockc);
479: }
480: fp->f_flag &= ~FEXLOCK;
481: }
482: }
483:
484: /*
485: * Openi called to allow handler
486: * of special files to initialize and
487: * validate before actual IO.
488: */
489: openi(ip, mode)
490: register struct inode *ip;
491: {
492: dev_t dev = (dev_t)ip->i_rdev;
493: register int maj = major(dev);
494: int minnum = minor(dev);
495: register int error;
496:
497: switch (ip->i_mode&IFMT) {
498:
499: case IFCHR:
500: if ((u_int)maj >= nchrdev)
501: return (ENXIO);
502: error = (*cdevsw[maj].d_open)(dev, mode, &minnum);
503:
504: /*
505: * Test for new minor device inode allocation
506: */
507: if ((error == 0) && (minnum != minor(dev))) {
508: register struct inode *nip;
509:
510: /*
511: * Allocate new inode with new minor device
512: * Release old inode. Set vpp to point to new one.
513: * This inode will go away when the last reference
514: * to it goes away.
515: * Warning: if you stat this, and try to match it
516: * with a name in the filesystem you will fail,
517: * unless you had previously put names in that match.
518: */
519: nip = ialloc(ip, dirpref(ip->i_fs), (int)ip->i_mode);
520: if (nip == (struct inode *)0) {
521: /*
522: * Give driver a chance to clean up;
523: * this is iffy since other instances
524: * of this device could be active.
525: */
526: cdevsw[maj].d_close(makedev(maj, minnum),
527: mode&FMASK);
528: return (ENXIO);
529: }
530: nip->i_flag |= IACC|IUPD|ICHG;
531: nip->i_mode = ip->i_mode;
532: nip->i_nlink = 0;
533: nip->i_uid = ip->i_uid;
534: nip->i_gid = ip->i_gid;
535: nip->i_rdev = makedev(maj, minnum);
536: #ifdef QUOTA
537: nip->i_dquot = inoquota(nip);
538: #endif
539: irele(ip);
540: ip = nip;
541: iunlock(ip);
542: /*
543: * This next line depends on the way copen()
544: * works; it's a kludge.
545: */
546: u.u_ofile[u.u_r.r_val1]->f_data = (caddr_t)ip;
547: }
548: return(error);
549:
550: case IFBLK:
551: if ((u_int)maj >= nblkdev)
552: return (ENXIO);
553: return ((*bdevsw[maj].d_open)(dev, mode));
554: }
555: return (0);
556: }
557:
558: /*
559: * Revoke access the current tty by all processes.
560: * Used only by the super-user in init
561: * to give ``clean'' terminals at login.
562: */
563: vhangup()
564: {
565:
566: if (!suser())
567: return;
568: if (u.u_ttyp == NULL)
569: return;
570: forceclose(u.u_ttyd);
571: if ((u.u_ttyp->t_state) & TS_ISOPEN)
572: gsignal(u.u_ttyp->t_pgrp, SIGHUP);
573: }
574:
575: forceclose(dev)
576: dev_t dev;
577: {
578: register struct file *fp;
579: register struct inode *ip;
580:
581: for (fp = file; fp < fileNFILE; fp++) {
582: if (fp->f_count == 0)
583: continue;
584: if (fp->f_type != DTYPE_INODE)
585: continue;
586: ip = (struct inode *)fp->f_data;
587: if (ip == 0)
588: continue;
589: if ((ip->i_mode & IFMT) != IFCHR)
590: continue;
591: if (ip->i_rdev != dev)
592: continue;
593: fp->f_flag &= ~(FREAD|FWRITE);
594: }
595: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.