|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution is only permitted until one year after the first shipment
6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
7: * binary forms are permitted provided that: (1) source distributions retain
8: * this entire copyright notice and comment, and (2) distributions including
9: * binaries display the following acknowledgement: This product includes
10: * software developed by the University of California, Berkeley and its
11: * contributors'' in the documentation or other materials provided with the
12: * distribution and in all advertising materials mentioning features or use
13: * of this software. Neither the name of the University nor the names of
14: * its contributors may be used to endorse or promote products derived from
15: * this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: * @(#)vfs_vnops.c 7.23 (Berkeley) 6/28/90
21: */
22:
23: #include "param.h"
24: #include "systm.h"
25: #include "user.h"
26: #include "kernel.h"
27: #include "file.h"
28: #include "stat.h"
29: #include "buf.h"
30: #include "proc.h"
31: #include "uio.h"
32: #include "socket.h"
33: #include "socketvar.h"
34: #include "mount.h"
35: #include "vnode.h"
36: #include "ioctl.h"
37: #include "tty.h"
38:
39: int vn_read(), vn_write(), vn_ioctl(), vn_select(), vn_close();
40: struct fileops vnops =
41: { vn_read, vn_write, vn_ioctl, vn_select, vn_close };
42:
43: /*
44: * Common code for vnode open operations.
45: * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
46: */
47: vn_open(ndp, fmode, cmode)
48: register struct nameidata *ndp;
49: int fmode, cmode;
50: {
51: register struct vnode *vp;
52: struct vattr vat;
53: struct vattr *vap = &vat;
54: int error;
55:
56: if (fmode & FCREAT) {
57: ndp->ni_nameiop = CREATE | LOCKPARENT | LOCKLEAF;
58: if ((fmode & FEXCL) == 0)
59: ndp->ni_nameiop |= FOLLOW;
60: if (error = namei(ndp))
61: return (error);
62: if (ndp->ni_vp == NULL) {
63: VATTR_NULL(vap);
64: vap->va_type = VREG;
65: vap->va_mode = cmode;
66: if (error = VOP_CREATE(ndp, vap))
67: return (error);
68: fmode &= ~FTRUNC;
69: vp = ndp->ni_vp;
70: } else {
71: if (ndp->ni_dvp == ndp->ni_vp)
72: vrele(ndp->ni_dvp);
73: else
74: vput(ndp->ni_dvp);
75: ndp->ni_dvp = NULL;
76: vp = ndp->ni_vp;
77: if (fmode & FEXCL) {
78: error = EEXIST;
79: goto bad;
80: }
81: fmode &= ~FCREAT;
82: }
83: } else {
84: ndp->ni_nameiop = LOOKUP | FOLLOW | LOCKLEAF;
85: if (error = namei(ndp))
86: return (error);
87: vp = ndp->ni_vp;
88: }
89: if (vp->v_type == VSOCK) {
90: error = EOPNOTSUPP;
91: goto bad;
92: }
93: if ((fmode & FCREAT) == 0) {
94: if (fmode & FREAD) {
95: if (error = VOP_ACCESS(vp, VREAD, ndp->ni_cred))
96: goto bad;
97: }
98: if (fmode & (FWRITE|FTRUNC)) {
99: if (vp->v_type == VDIR) {
100: error = EISDIR;
101: goto bad;
102: }
103: if ((error = vn_writechk(vp)) ||
104: (error = VOP_ACCESS(vp, VWRITE, ndp->ni_cred)))
105: goto bad;
106: }
107: }
108: if (fmode & FTRUNC) {
109: VATTR_NULL(vap);
110: vap->va_size = 0;
111: if (error = VOP_SETATTR(vp, vap, ndp->ni_cred))
112: goto bad;
113: }
114: VOP_UNLOCK(vp);
115: error = VOP_OPEN(vp, fmode, ndp->ni_cred);
116: if (error)
117: vrele(vp);
118: return (error);
119:
120: bad:
121: vput(vp);
122: return (error);
123: }
124:
125: /*
126: * Check for write permissions on the specified vnode.
127: * The read-only status of the file system is checked.
128: * Also, prototype text segments cannot be written.
129: */
130: vn_writechk(vp)
131: register struct vnode *vp;
132: {
133:
134: /*
135: * Disallow write attempts on read-only file systems;
136: * unless the file is a socket or a block or character
137: * device resident on the file system.
138: */
139: if ((vp->v_mount->mnt_flag & MNT_RDONLY) && vp->v_type != VCHR &&
140: vp->v_type != VBLK && vp->v_type != VSOCK)
141: return (EROFS);
142: /*
143: * If there's shared text associated with
144: * the vnode, try to free it up once. If
145: * we fail, we can't allow writing.
146: */
147: if (vp->v_flag & VTEXT)
148: xrele(vp);
149: if (vp->v_flag & VTEXT)
150: return (ETXTBSY);
151: return (0);
152: }
153:
154: /*
155: * Vnode version of rdwri() for calls on file systems.
156: */
157: vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid)
158: enum uio_rw rw;
159: struct vnode *vp;
160: caddr_t base;
161: int len;
162: off_t offset;
163: enum uio_seg segflg;
164: int ioflg;
165: struct ucred *cred;
166: int *aresid;
167: {
168: struct uio auio;
169: struct iovec aiov;
170: int error;
171:
172: if ((ioflg & IO_NODELOCKED) == 0)
173: VOP_LOCK(vp);
174: auio.uio_iov = &aiov;
175: auio.uio_iovcnt = 1;
176: aiov.iov_base = base;
177: aiov.iov_len = len;
178: auio.uio_resid = len;
179: auio.uio_offset = offset;
180: auio.uio_segflg = segflg;
181: auio.uio_rw = rw;
182: if (rw == UIO_READ)
183: error = VOP_READ(vp, &auio, ioflg, cred);
184: else
185: error = VOP_WRITE(vp, &auio, ioflg, cred);
186: if (aresid)
187: *aresid = auio.uio_resid;
188: else
189: if (auio.uio_resid && error == 0)
190: error = EIO;
191: if ((ioflg & IO_NODELOCKED) == 0)
192: VOP_UNLOCK(vp);
193: return (error);
194: }
195:
196: vn_read(fp, uio, cred)
197: struct file *fp;
198: struct uio *uio;
199: struct ucred *cred;
200: {
201: register struct vnode *vp = (struct vnode *)fp->f_data;
202: int count, error;
203:
204: VOP_LOCK(vp);
205: uio->uio_offset = fp->f_offset;
206: count = uio->uio_resid;
207: error = VOP_READ(vp, uio, (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred);
208: fp->f_offset += count - uio->uio_resid;
209: VOP_UNLOCK(vp);
210: return (error);
211: }
212:
213: vn_write(fp, uio, cred)
214: struct file *fp;
215: struct uio *uio;
216: struct ucred *cred;
217: {
218: register struct vnode *vp = (struct vnode *)fp->f_data;
219: int count, error, ioflag = 0;
220:
221: if (vp->v_type == VREG && (fp->f_flag & FAPPEND))
222: ioflag |= IO_APPEND;
223: if (fp->f_flag & FNDELAY)
224: ioflag |= IO_NDELAY;
225: VOP_LOCK(vp);
226: uio->uio_offset = fp->f_offset;
227: count = uio->uio_resid;
228: error = VOP_WRITE(vp, uio, ioflag, cred);
229: if (ioflag & IO_APPEND)
230: fp->f_offset = uio->uio_offset;
231: else
232: fp->f_offset += count - uio->uio_resid;
233: VOP_UNLOCK(vp);
234: return (error);
235: }
236:
237: /*
238: * Get stat info for a vnode.
239: */
240: vn_stat(vp, sb)
241: struct vnode *vp;
242: register struct stat *sb;
243: {
244: struct vattr vattr;
245: register struct vattr *vap;
246: int error;
247: u_short mode;
248:
249: vap = &vattr;
250: error = VOP_GETATTR(vp, vap, u.u_cred);
251: if (error)
252: return (error);
253: /*
254: * Copy from vattr table
255: */
256: sb->st_dev = vap->va_fsid;
257: sb->st_ino = vap->va_fileid;
258: mode = vap->va_mode;
259: switch (vp->v_type) {
260: case VREG:
261: mode |= S_IFREG;
262: break;
263: case VDIR:
264: mode |= S_IFDIR;
265: break;
266: case VBLK:
267: mode |= S_IFBLK;
268: break;
269: case VCHR:
270: mode |= S_IFCHR;
271: break;
272: case VLNK:
273: mode |= S_IFLNK;
274: break;
275: case VSOCK:
276: mode |= S_IFSOCK;
277: break;
278: case VFIFO:
279: mode |= S_IFIFO;
280: break;
281: default:
282: return (EBADF);
283: };
284: sb->st_mode = mode;
285: sb->st_nlink = vap->va_nlink;
286: sb->st_uid = vap->va_uid;
287: sb->st_gid = vap->va_gid;
288: sb->st_rdev = vap->va_rdev;
289: sb->st_size = vap->va_size;
290: sb->st_atime = vap->va_atime.tv_sec;
291: sb->st_spare1 = 0;
292: sb->st_mtime = vap->va_mtime.tv_sec;
293: sb->st_spare2 = 0;
294: sb->st_ctime = vap->va_ctime.tv_sec;
295: sb->st_spare3 = 0;
296: sb->st_blksize = vap->va_blocksize;
297: sb->st_flags = vap->va_flags;
298: sb->st_gen = vap->va_gen;
299: sb->st_blocks = vap->va_bytes / S_BLKSIZE;
300: return (0);
301: }
302:
303: /*
304: * Vnode ioctl call
305: */
306: vn_ioctl(fp, com, data)
307: struct file *fp;
308: int com;
309: caddr_t data;
310: {
311: register struct vnode *vp = ((struct vnode *)fp->f_data);
312: struct vattr vattr;
313: int error;
314:
315: switch (vp->v_type) {
316:
317: case VREG:
318: case VDIR:
319: if (com == FIONREAD) {
320: if (error = VOP_GETATTR(vp, &vattr, u.u_cred))
321: return (error);
322: *(off_t *)data = vattr.va_size - fp->f_offset;
323: return (0);
324: }
325: if (com == FIONBIO || com == FIOASYNC) /* XXX */
326: return (0); /* XXX */
327: /* fall into ... */
328:
329: default:
330: return (ENOTTY);
331:
332: case VFIFO:
333: case VCHR:
334: case VBLK:
335: error = VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred);
336: if (error == 0 && com == TIOCSCTTY) {
337: u.u_procp->p_session->s_ttyvp = vp;
338: VREF(vp);
339: }
340: return (error);
341: }
342: }
343:
344: /*
345: * Vnode select call
346: */
347: vn_select(fp, which)
348: struct file *fp;
349: int which;
350: {
351: return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag,
352: u.u_cred));
353: }
354:
355: /*
356: * Vnode close call
357: */
358: vn_close(fp)
359: register struct file *fp;
360: {
361: struct vnode *vp = ((struct vnode *)fp->f_data);
362: int error;
363:
364: if (fp->f_flag & (FSHLOCK|FEXLOCK))
365: vn_unlock(fp, FSHLOCK|FEXLOCK);
366: /*
367: * Must delete vnode reference from this file entry
368: * before VOP_CLOSE, so that only other references
369: * will prevent close.
370: */
371: fp->f_data = (caddr_t) 0;
372: error = VOP_CLOSE(vp, fp->f_flag, u.u_cred);
373: vrele(vp);
374: return (error);
375: }
376:
377: /*
378: * Place an advisory lock on a vnode.
379: * !! THIS IMPLIES THAT ALL STATEFUL FILE SERVERS WILL USE file table entries
380: */
381: vn_lock(fp, cmd)
382: register struct file *fp;
383: int cmd;
384: {
385: register int priority = PLOCK;
386: register struct vnode *vp = (struct vnode *)fp->f_data;
387: int error = 0;
388: static char lockstr[] = "flock";
389:
390: if ((cmd & LOCK_EX) == 0)
391: priority += 4;
392: priority |= PCATCH;
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 (vp->v_flag & VEXLOCK) {
401: /*
402: * If we're holding an exclusive
403: * lock, then release it.
404: */
405: if (fp->f_flag & FEXLOCK) {
406: vn_unlock(fp, FEXLOCK);
407: continue;
408: }
409: if (cmd & LOCK_NB)
410: return (EWOULDBLOCK);
411: vp->v_flag |= VLWAIT;
412: if (error = tsleep((caddr_t)&vp->v_exlockc, priority,
413: lockstr, 0))
414: return (error);
415: }
416: if (error = 0 && (cmd & LOCK_EX) && (vp->v_flag & VSHLOCK)) {
417: /*
418: * Must wait for any shared locks to finish
419: * before we try to apply a exclusive lock.
420: *
421: * If we're holding a shared
422: * lock, then release it.
423: */
424: if (fp->f_flag & FSHLOCK) {
425: vn_unlock(fp, FSHLOCK);
426: goto again;
427: }
428: if (cmd & LOCK_NB)
429: return (EWOULDBLOCK);
430: vp->v_flag |= VLWAIT;
431: if (error = tsleep((caddr_t)&vp->v_shlockc, PLOCK | PCATCH,
432: lockstr, 0) == 0)
433: return (error);
434: }
435: if (fp->f_flag & FEXLOCK)
436: panic("vn_lock");
437: if (cmd & LOCK_EX) {
438: cmd &= ~LOCK_SH;
439: vp->v_exlockc++;
440: vp->v_flag |= VEXLOCK;
441: fp->f_flag |= FEXLOCK;
442: }
443: if ((cmd & LOCK_SH) && (fp->f_flag & FSHLOCK) == 0) {
444: vp->v_shlockc++;
445: vp->v_flag |= VSHLOCK;
446: fp->f_flag |= FSHLOCK;
447: }
448: return (0);
449: }
450:
451: /*
452: * Unlock a file.
453: */
454: vn_unlock(fp, kind)
455: register struct file *fp;
456: int kind;
457: {
458: register struct vnode *vp = (struct vnode *)fp->f_data;
459: int flags;
460:
461: kind &= fp->f_flag;
462: if (vp == NULL || kind == 0)
463: return;
464: flags = vp->v_flag;
465: if (kind & FSHLOCK) {
466: if ((flags & VSHLOCK) == 0)
467: panic("vn_unlock: SHLOCK");
468: if (--vp->v_shlockc == 0) {
469: vp->v_flag &= ~VSHLOCK;
470: if (flags & VLWAIT)
471: wakeup((caddr_t)&vp->v_shlockc);
472: }
473: fp->f_flag &= ~FSHLOCK;
474: }
475: if (kind & FEXLOCK) {
476: if ((flags & VEXLOCK) == 0)
477: panic("vn_unlock: EXLOCK");
478: if (--vp->v_exlockc == 0) {
479: vp->v_flag &= ~(VEXLOCK|VLWAIT);
480: if (flags & VLWAIT)
481: wakeup((caddr_t)&vp->v_exlockc);
482: }
483: fp->f_flag &= ~FEXLOCK;
484: }
485: }
486:
487: /*
488: * vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
489: * - look up fsid in mount list (if not found ret error)
490: * - get vp by calling VFS_FHTOVP() macro
491: * - if lockflag lock it with VOP_LOCK()
492: */
493: vn_fhtovp(fhp, lockflag, vpp)
494: fhandle_t *fhp;
495: int lockflag;
496: struct vnode **vpp;
497: {
498: register struct mount *mp;
499:
500: if ((mp = getvfs(&fhp->fh_fsid)) == NULL)
501: return (ESTALE);
502: if (VFS_FHTOVP(mp, &fhp->fh_fid, vpp))
503: return (ESTALE);
504: if (!lockflag)
505: VOP_UNLOCK(*vpp);
506: return (0);
507: }
508:
509: /*
510: * Noop
511: */
512: vfs_noop()
513: {
514:
515: return (ENXIO);
516: }
517:
518: /*
519: * Null op
520: */
521: vfs_nullop()
522: {
523:
524: return (0);
525: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.