|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Rick Macklem at The University of Guelph.
7: *
8: * Redistribution is only permitted until one year after the first shipment
9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and
10: * binary forms are permitted provided that: (1) source distributions retain
11: * this entire copyright notice and comment, and (2) distributions including
12: * binaries display the following acknowledgement: This product includes
13: * software developed by the University of California, Berkeley and its
14: * contributors'' in the documentation or other materials provided with the
15: * distribution and in all advertising materials mentioning features or use
16: * of this software. Neither the name of the University nor the names of
17: * its contributors may be used to endorse or promote products derived from
18: * this software without specific prior written permission.
19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22: *
23: * @(#)nfs_bio.c 7.16 (Berkeley) 6/28/90
24: */
25:
26: #include "param.h"
27: #include "user.h"
28: #include "buf.h"
29: #include "vnode.h"
30: #include "trace.h"
31: #include "mount.h"
32: #include "nfsnode.h"
33: #include "nfsv2.h"
34: #include "nfs.h"
35: #include "nfsiom.h"
36: #include "nfsmount.h"
37:
38: /* True and false, how exciting */
39: #define TRUE 1
40: #define FALSE 0
41:
42: /*
43: * Vnode op for read using bio
44: * Any similarity to readip() is purely coincidental
45: */
46: nfs_bioread(vp, uio, ioflag, cred)
47: register struct vnode *vp;
48: register struct uio *uio;
49: int ioflag;
50: struct ucred *cred;
51: {
52: register struct nfsnode *np = VTONFS(vp);
53: register int biosize;
54: struct buf *bp;
55: struct vattr vattr;
56: daddr_t lbn, bn, rablock;
57: int diff, error = 0;
58: long n, on;
59:
60: #ifdef lint
61: ioflag = ioflag;
62: #endif /* lint */
63: if (uio->uio_rw != UIO_READ)
64: panic("nfs_read mode");
65: if (uio->uio_resid == 0)
66: return (0);
67: if (uio->uio_offset < 0 && vp->v_type != VDIR)
68: return (EINVAL);
69: biosize = VFSTONFS(vp->v_mount)->nm_rsize;
70: /*
71: * If the file's modify time on the server has changed since the
72: * last read rpc or you have written to the file,
73: * you may have lost data cache consistency with the
74: * server, so flush all of the file's data out of the cache.
75: * Then force a getattr rpc to ensure that you have up to date
76: * attributes.
77: * NB: This implies that cache data can be read when up to
78: * NFS_ATTRTIMEO seconds out of date. If you find that you need current
79: * attributes this could be forced by setting n_attrstamp to 0 before
80: * the nfs_dogetattr() call.
81: */
82: if (vp->v_type != VLNK) {
83: if (np->n_flag & NMODIFIED) {
84: np->n_flag &= ~NMODIFIED;
85: vinvalbuf(vp, TRUE);
86: np->n_attrstamp = 0;
87: np->n_direofoffset = 0;
88: if (error = nfs_dogetattr(vp, &vattr, cred, 1))
89: return (error);
90: np->n_mtime = vattr.va_mtime.tv_sec;
91: } else {
92: if (error = nfs_dogetattr(vp, &vattr, cred, 1))
93: return (error);
94: if (np->n_mtime != vattr.va_mtime.tv_sec) {
95: np->n_direofoffset = 0;
96: vinvalbuf(vp, TRUE);
97: np->n_mtime = vattr.va_mtime.tv_sec;
98: }
99: }
100: }
101: do {
102: switch (vp->v_type) {
103: case VREG:
104: nfsstats.biocache_reads++;
105: lbn = uio->uio_offset / biosize;
106: on = uio->uio_offset & (biosize-1);
107: n = MIN((unsigned)(biosize - on), uio->uio_resid);
108: diff = np->n_size - uio->uio_offset;
109: if (diff <= 0)
110: return (error);
111: if (diff < n)
112: n = diff;
113: bn = lbn*(biosize/DEV_BSIZE);
114: rablock = (lbn+1)*(biosize/DEV_BSIZE);
115: if (vp->v_lastr + 1 == lbn &&
116: np->n_size > (rablock * DEV_BSIZE))
117: error = breada(vp, bn, biosize, rablock, biosize,
118: cred, &bp);
119: else
120: error = bread(vp, bn, biosize, cred, &bp);
121: vp->v_lastr = lbn;
122: if (bp->b_resid) {
123: diff = (on >= (biosize-bp->b_resid)) ? 0 :
124: (biosize-bp->b_resid-on);
125: n = MIN(n, diff);
126: }
127: break;
128: case VLNK:
129: nfsstats.biocache_readlinks++;
130: on = 0;
131: error = bread(vp, (daddr_t)0, NFS_MAXPATHLEN, cred, &bp);
132: n = MIN(uio->uio_resid, NFS_MAXPATHLEN - bp->b_resid);
133: break;
134: case VDIR:
135: nfsstats.biocache_readdirs++;
136: on = 0;
137: error = bread(vp, uio->uio_offset, DIRBLKSIZ, cred, &bp);
138: n = MIN(uio->uio_resid, DIRBLKSIZ - bp->b_resid);
139: break;
140: };
141: if (error) {
142: brelse(bp);
143: return (error);
144: }
145: if (n > 0)
146: error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
147: switch (vp->v_type) {
148: case VREG:
149: if (n+on == biosize || uio->uio_offset == np->n_size)
150: bp->b_flags |= B_AGE;
151: break;
152: case VLNK:
153: n = 0;
154: break;
155: case VDIR:
156: uio->uio_offset = bp->b_blkno;
157: break;
158: };
159: brelse(bp);
160: } while (error == 0 && uio->uio_resid > 0 && n != 0);
161: return (error);
162: }
163:
164: /*
165: * Vnode op for write using bio
166: */
167: nfs_write(vp, uio, ioflag, cred)
168: register struct vnode *vp;
169: register struct uio *uio;
170: int ioflag;
171: struct ucred *cred;
172: {
173: register int biosize;
174: struct buf *bp;
175: struct nfsnode *np = VTONFS(vp);
176: struct vattr vattr;
177: daddr_t lbn, bn;
178: int n, on, error = 0;
179:
180: if (uio->uio_rw != UIO_WRITE)
181: panic("nfs_write mode");
182: if (vp->v_type != VREG)
183: return (EIO);
184: /* Should we try and do this ?? */
185: if (ioflag & (IO_APPEND | IO_SYNC)) {
186: if (np->n_flag & NMODIFIED) {
187: np->n_flag &= ~NMODIFIED;
188: vinvalbuf(vp, TRUE);
189: }
190: if (ioflag & IO_APPEND) {
191: np->n_attrstamp = 0;
192: if (error = nfs_dogetattr(vp, &vattr, cred, 1))
193: return (error);
194: uio->uio_offset = np->n_size;
195: }
196: return (nfs_writerpc(vp, uio, cred, u.u_procp));
197: }
198: #ifdef notdef
199: cnt = uio->uio_resid;
200: osize = np->n_size;
201: #endif
202: if (uio->uio_offset < 0)
203: return (EINVAL);
204: if (uio->uio_resid == 0)
205: return (0);
206: /*
207: * Maybe this should be above the vnode op call, but so long as
208: * file servers have no limits, i don't think it matters
209: */
210: if (uio->uio_offset + uio->uio_resid >
211: u.u_rlimit[RLIMIT_FSIZE].rlim_cur) {
212: psignal(u.u_procp, SIGXFSZ);
213: return (EFBIG);
214: }
215: /*
216: * I use nm_rsize, not nm_wsize so that all buffer cache blocks
217: * will be the same size within a filesystem. nfs_writerpc will
218: * still use nm_wsize when sizing the rpc's.
219: */
220: biosize = VFSTONFS(vp->v_mount)->nm_rsize;
221: np->n_flag |= NMODIFIED;
222: do {
223: nfsstats.biocache_writes++;
224: lbn = uio->uio_offset / biosize;
225: on = uio->uio_offset & (biosize-1);
226: n = MIN((unsigned)(biosize - on), uio->uio_resid);
227: if (uio->uio_offset+n > np->n_size)
228: np->n_size = uio->uio_offset+n;
229: bn = lbn*(biosize/DEV_BSIZE);
230: again:
231: bp = getblk(vp, bn, biosize);
232: if (bp->b_wcred == NOCRED) {
233: crhold(cred);
234: bp->b_wcred = cred;
235: }
236: if (bp->b_dirtyend > 0) {
237: /*
238: * If the new write will leave a contiguous dirty
239: * area, just update the b_dirtyoff and b_dirtyend,
240: * otherwise force a write rpc of the old dirty area.
241: */
242: if (on <= bp->b_dirtyend && (on+n) >= bp->b_dirtyoff) {
243: bp->b_dirtyoff = MIN(on, bp->b_dirtyoff);
244: bp->b_dirtyend = MAX((on+n), bp->b_dirtyend);
245: } else {
246: bp->b_proc = u.u_procp;
247: if (error = bwrite(bp))
248: return (error);
249: goto again;
250: }
251: } else {
252: bp->b_dirtyoff = on;
253: bp->b_dirtyend = on+n;
254: }
255: if (error = uiomove(bp->b_un.b_addr + on, n, uio)) {
256: brelse(bp);
257: return (error);
258: }
259: if ((n+on) == biosize) {
260: bp->b_flags |= B_AGE;
261: bp->b_proc = (struct proc *)0;
262: bawrite(bp);
263: } else {
264: bp->b_proc = (struct proc *)0;
265: bdwrite(bp);
266: }
267: } while (error == 0 && uio->uio_resid > 0 && n != 0);
268: #ifdef notdef
269: /* Should we try and do this for nfs ?? */
270: if (error && (ioflag & IO_UNIT)) {
271: np->n_size = osize;
272: uio->uio_offset -= cnt - uio->uio_resid;
273: uio->uio_resid = cnt;
274: }
275: #endif
276: return (error);
277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.