Annotation of sys/xfs/xfs_vnodeops-common.c, Revision 1.1.1.1
1.1 nbrk 1: /*
2: * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
3: * (Royal Institute of Technology, Stockholm, Sweden).
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: *
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: *
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: *
17: * 3. Neither the name of the Institute nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: */
33:
34: /*
35: * NNPFS operations.
36: */
37:
38: #include <xfs/xfs_locl.h>
39: #include <xfs/xfs_message.h>
40: #include <xfs/xfs_common.h>
41: #include <xfs/xfs_fs.h>
42: #include <xfs/xfs_dev.h>
43: #include <xfs/xfs_deb.h>
44: #include <xfs/xfs_syscalls.h>
45: #include <xfs/xfs_vnodeops.h>
46:
47: RCSID("$arla: xfs_vnodeops-common.c,v 1.94 2003/01/27 11:58:50 lha Exp $");
48:
49: static void
50: xfs_handle_stale(struct xfs_node *xn)
51: {
52: #if __APPLE__
53: struct vnode *vp = XNODE_TO_VNODE(xn);
54: #endif
55:
56: if ((xn->flags & NNPFS_STALE) == 0)
57: return;
58:
59: #if __APPLE__
60: if (UBCISVALID(vp) && !ubc_isinuse(vp, 1)) {
61: xn->flags &= ~NNPFS_STALE;
62: ubc_setsize(vp, 0);
63: NNPFS_TOKEN_CLEAR(xn, ~0,
64: NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
65: NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
66: }
67: #endif
68: }
69:
70: int
71: xfs_open_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
72: u_int tok)
73: {
74: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
75: struct xfs_node *xn = VNODE_TO_XNODE(vp);
76: int error = 0;
77:
78: NNPFSDEB(XDEBVFOPS, ("xfs_open_valid\n"));
79:
80: xfs_handle_stale(xn);
81:
82: do {
83: if (!NNPFS_TOKEN_GOT(xn, tok)) {
84: struct xfs_message_open msg;
85:
86: msg.header.opcode = NNPFS_MSG_OPEN;
87: msg.cred.uid = cred->cr_uid;
88: msg.cred.pag = xfs_get_pag(cred);
89: msg.handle = xn->handle;
90: msg.tokens = tok;
91:
92: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
93:
94: if (error == 0)
95: error = ((struct xfs_message_wakeup *) & msg)->error;
96: } else {
97: goto done;
98: }
99: } while (error == 0);
100:
101: done:
102: NNPFSDEB(XDEBVFOPS, ("xfs_open_valid: error = %d\n", error));
103:
104: return error;
105: }
106:
107: int
108: xfs_attr_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
109: u_int tok)
110: {
111: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
112: struct xfs_node *xn = VNODE_TO_XNODE(vp);
113: int error = 0;
114: xfs_pag_t pag = xfs_get_pag(cred);
115:
116: do {
117: if (!NNPFS_TOKEN_GOT(xn, tok) || !xfs_has_pag(xn, pag)) {
118: struct xfs_message_getattr msg;
119:
120: msg.header.opcode = NNPFS_MSG_GETATTR;
121: msg.cred.uid = cred->cr_uid;
122: msg.cred.pag = pag;
123: msg.handle = xn->handle;
124: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
125: if (error == 0)
126: error = ((struct xfs_message_wakeup *) & msg)->error;
127: } else {
128: goto done;
129: }
130: } while (error == 0);
131:
132: done:
133: return error;
134: }
135:
136: int
137: xfs_data_valid(struct vnode *vp, struct ucred *cred, d_thread_t *p,
138: u_int tok, uint32_t want_offset)
139: {
140: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
141: struct xfs_node *xn = VNODE_TO_XNODE(vp);
142: int error = 0;
143: uint32_t offset;
144: struct xfs_message_getdata msg;
145:
146: do {
147: offset = want_offset;
148: if (NNPFS_TOKEN_GOT(xn, tok|NNPFS_ATTR_R) && offset > xn->attr.va_size) {
149: offset = xn->attr.va_size;
150: }
151:
152: NNPFSDEB(XDEBVNOPS, ("xfs_data_valid: offset: want %ld has %ld, "
153: "tokens: want %lx has %lx length: %ld\n",
154: (long) offset, (long) xn->offset,
155: (long) tok, (long) xn->tokens,
156: (long) xn->attr.va_size));
157:
158: if (NNPFS_TOKEN_GOT(xn, tok)) {
159: if (offset <= xn->offset || xn->attr.va_type == VDIR) {
160: break;
161: }
162: }
163:
164: msg.header.opcode = NNPFS_MSG_GETDATA;
165: msg.cred.uid = cred->cr_uid;
166: msg.cred.pag = xfs_get_pag(cred);
167: msg.handle = xn->handle;
168: msg.tokens = tok;
169: msg.offset = offset;
170:
171: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
172:
173: if (error == 0)
174: error = ((struct xfs_message_wakeup *) & msg)->error;
175:
176: } while (error == 0);
177:
178: return error;
179: }
180:
181: int
182: xfs_open_common(struct vnode *vp,
183: int mode,
184: struct ucred *cred,
185: d_thread_t *p)
186: {
187: struct xfs_node *xn = VNODE_TO_XNODE(vp);
188: int ret;
189:
190: NNPFSDEB(XDEBVNOPS, ("xfs_open\n"));
191:
192: if (mode & FWRITE) {
193: ret = xfs_open_valid(vp, cred, p, NNPFS_OPEN_NW);
194: } else {
195: ret = xfs_open_valid(vp, cred, p, NNPFS_OPEN_NR);
196: }
197:
198: /* always update the read cred */
199:
200: if (mode & FWRITE)
201: xfs_update_write_cred(xn, cred);
202: xfs_update_read_cred(xn, cred);
203:
204: return ret;
205: }
206:
207: static int
208: do_fsync(struct xfs *xfsp,
209: struct xfs_node *xn,
210: struct ucred *cred,
211: d_thread_t *p,
212: u_int flag)
213: {
214: int error;
215: struct xfs_message_putdata msg;
216:
217: msg.header.opcode = NNPFS_MSG_PUTDATA;
218: if (cred != NOCRED) {
219: msg.cred.uid = cred->cr_uid;
220: msg.cred.pag = xfs_get_pag(cred);
221: } else {
222: msg.cred.uid = 0;
223: msg.cred.pag = NNPFS_ANONYMOUSID;
224: }
225: msg.handle = xn->handle;
226: vattr2xfs_attr(&xn->attr, &msg.attr);
227: msg.flag = flag;
228:
229: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
230:
231: if (error == 0)
232: error = ((struct xfs_message_wakeup *) & msg)->error;
233:
234: if (error == 0)
235: xn->flags &= ~NNPFS_DATA_DIRTY;
236:
237: return error;
238: }
239:
240: int
241: xfs_fsync_common(struct vnode *vp, struct ucred *cred,
242: int waitfor, d_thread_t *proc)
243: {
244: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
245: struct xfs_node *xn = VNODE_TO_XNODE(vp);
246: int error = 0;
247:
248: NNPFSDEB(XDEBVNOPS, ("xfs_fsync: %lx\n", (unsigned long)vp));
249:
250: /*
251: * It seems that fsync is sometimes called after reclaiming a node.
252: * In that case we just look happy.
253: */
254:
255: if (xn == NULL) {
256: printf("NNPFS PANIC WARNING! xfs_fsync called after reclaiming!\n");
257: return 0;
258: }
259:
260: xfs_pushdirty(vp, cred, proc);
261:
262: if (xn->flags & NNPFS_DATA_DIRTY) {
263: #ifdef FSYNC_RECLAIM
264: /* writing back the data from this vnode failed */
265: if (waitfor & FSYNC_RECLAIM) {
266: printf("xfs_fsync: data lost, failed to write back\n");
267: xn->flags &= ~NNPFS_DATA_DIRTY;
268: return 0;
269: }
270: #endif
271: error = do_fsync(xfsp, xn, cred, proc, NNPFS_WRITE | NNPFS_FSYNC);
272: }
273:
274: return error;
275: }
276:
277: int
278: xfs_close_common(struct vnode *vp, int fflag,
279: d_thread_t *proc, struct ucred *cred)
280: {
281: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
282: struct xfs_node *xn = VNODE_TO_XNODE(vp);
283: int error = 0;
284:
285: NNPFSDEB(XDEBVNOPS,
286: ("xfs_close cred = %lx, fflag = %x, xn->flags = %x\n",
287: (unsigned long)cred, fflag, xn->flags));
288:
289: if (vp->v_type == VREG)
290: xfs_pushdirty(vp, cred, proc);
291:
292: if (fflag & FWRITE && xn->flags & NNPFS_DATA_DIRTY)
293: error = do_fsync(xfsp, xn, cred, proc, NNPFS_WRITE);
294:
295: return error;
296: }
297:
298: size_t
299: xfs_uio_end_length (struct uio *uio)
300: {
301: #ifdef DIAGNOSTIC
302: size_t sz = 0;
303: int i;
304:
305: for (i = 0; i < uio->uio_iovcnt; i++)
306: sz += uio->uio_iov[i].iov_len;
307: if (sz != uio->uio_resid)
308: panic("xfs_uio_end_length");
309: #endif
310: return uio->uio_offset + uio->uio_resid;
311: }
312:
313:
314: int
315: xfs_read_common(struct vnode *vp, struct uio *uio, int ioflag,
316: struct ucred *cred)
317: {
318: int error = 0;
319: int i;
320:
321: NNPFSDEB(XDEBVNOPS, ("xfs_read\n"));
322:
323: xfs_update_read_cred(VNODE_TO_XNODE(vp), cred);
324:
325: #ifdef HAVE_FREEBSD_THREAD
326: error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uio), NNPFS_DATA_R,
327: xfs_uio_end_length(uio));
328: #else
329: error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uio), NNPFS_DATA_R,
330: xfs_uio_end_length(uio));
331: #endif
332:
333: NNPFSDEB(XDEBVNOPS, ("xfs_read: iovcnt: %d\n", uio->uio_iovcnt));
334: for (i = 0; i < uio->uio_iovcnt; i++)
335: NNPFSDEB(XDEBVNOPS, (" base: %lx len: %lu\n",
336: (unsigned long)uio->uio_iov[i].iov_base,
337: (unsigned long)uio->uio_iov[i].iov_len));
338:
339: if (error == 0) {
340: struct vnode *t = DATA_FROM_VNODE(vp);
341:
342: #ifdef HAVE_FREEBSD_THREAD
343: xfs_vfs_readlock(t, xfs_uio_to_thread(uio));
344: xfs_vop_read(t, uio, ioflag, cred, error);
345: xfs_vfs_unlock(t, xfs_uio_to_thread(uio));
346: #else
347: xfs_vfs_readlock(t, xfs_uio_to_proc(uio));
348: xfs_vop_read(t, uio, ioflag, cred, error);
349: xfs_vfs_unlock(t, xfs_uio_to_proc(uio));
350: #endif
351: }
352:
353: NNPFSDEB(XDEBVNOPS, ("xfs_read offset: %lu resid: %lu\n",
354: (unsigned long)uio->uio_offset,
355: (unsigned long)uio->uio_resid));
356: NNPFSDEB(XDEBVNOPS, ("xfs_read error: %d\n", error));
357:
358: return error;
359: }
360:
361: int
362: xfs_write_common(struct vnode *vp, struct uio *uiop, int ioflag,
363: struct ucred *cred)
364: {
365: struct xfs_node *xn = VNODE_TO_XNODE(vp);
366: int error = 0;
367:
368: NNPFSDEB(XDEBVNOPS, ("xfs_write\n"));
369:
370: xfs_update_write_cred(xn, cred);
371:
372: #ifdef HAVE_FREEBSD_THREAD
373: error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_W,
374: VNODE_TO_XNODE(vp)->attr.va_size);
375: #else
376: error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_W,
377: VNODE_TO_XNODE(vp)->attr.va_size);
378: #endif
379:
380: if (error == 0) {
381: struct vnode *t = DATA_FROM_XNODE(xn);
382: struct vattr sub_attr;
383: int error2 = 0;
384:
385: #ifdef HAVE_FREEBSD_THREAD
386: xfs_vfs_writelock(t, xfs_uio_to_thread(uiop));
387: xfs_vop_write(t, uiop, ioflag, cred, error);
388: VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
389: xfs_vop_getattr(t, &sub_attr, cred, xfs_uio_to_thread(uiop), error2);
390: #else
391: xfs_vfs_writelock(t, xfs_uio_to_proc(uiop));
392: xfs_vop_write(t, uiop, ioflag, cred, error);
393: VNODE_TO_XNODE(vp)->flags |= NNPFS_DATA_DIRTY;
394: xfs_vop_getattr(t, &sub_attr, cred, xfs_uio_to_proc(uiop), error2);
395: #endif
396:
397: if (error2 == 0) {
398: xn->attr.va_size = sub_attr.va_size;
399: xn->attr.va_bytes = sub_attr.va_size;
400: xn->attr.va_mtime = sub_attr.va_mtime;
401: xfs_set_vp_size(vp, sub_attr.va_size);
402: xn->offset = sub_attr.va_size;
403: }
404: #ifdef HAVE_FREEBSD_THREAD
405: xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
406: #else
407: xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
408: #endif
409: }
410:
411: return error;
412: }
413:
414: int
415: xfs_getattr_common(struct vnode *vp, struct vattr *vap,
416: struct ucred *cred, d_thread_t *p)
417: {
418: int error = 0;
419:
420: struct xfs_node *xn = VNODE_TO_XNODE(vp);
421:
422: NNPFSDEB(XDEBVNOPS, ("xfs_getattr\n"));
423:
424: error = xfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
425: if (error == 0)
426: *vap = xn->attr;
427: return error;
428: }
429:
430: int
431: xfs_setattr_common(struct vnode *vp, struct vattr *vap,
432: struct ucred *cred, d_thread_t *p)
433: {
434: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
435: struct xfs_node *xn = VNODE_TO_XNODE(vp);
436: int error = 0;
437:
438: NNPFSDEB(XDEBVNOPS, ("xfs_setattr\n"));
439:
440: #define CHECK_NNPFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A)
441: if (CHECK_NNPFSATTR(va_mode,(mode_t)) &&
442: CHECK_NNPFSATTR(va_nlink,(short)) &&
443: CHECK_NNPFSATTR(va_size,(va_size_t)) &&
444: CHECK_NNPFSATTR(va_uid,(uid_t)) &&
445: CHECK_NNPFSATTR(va_gid,(gid_t)) &&
446: CHECK_NNPFSATTR(va_mtime.tv_sec,(unsigned int)) &&
447: CHECK_NNPFSATTR(va_fileid,(long)) &&
448: CHECK_NNPFSATTR(va_type,(enum vtype)))
449: return 0; /* Nothing to do */
450: #undef CHECK_NNPFSATTR
451:
452: if (NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_W)) {
453: /* Update attributes and mark them dirty. */
454: VNODE_TO_XNODE(vp)->flags |= NNPFS_ATTR_DIRTY;
455: error = EINVAL; /* XXX not yet implemented */
456: goto done;
457: } else {
458: struct xfs_message_putattr msg;
459:
460: msg.header.opcode = NNPFS_MSG_PUTATTR;
461: if (cred != NOCRED) {
462: msg.cred.uid = cred->cr_uid;
463: msg.cred.pag = xfs_get_pag(cred);
464: } else {
465: msg.cred.uid = 0;
466: msg.cred.pag = NNPFS_ANONYMOUSID;
467: }
468: msg.handle = xn->handle;
469: vattr2xfs_attr(vap, &msg.attr);
470: if (NNPFS_TOKEN_GOT(xn, NNPFS_DATA_R)) {
471: if (vp->v_type == VREG) {
472: if (vap->va_size != (va_size_t)VNOVAL)
473: XA_SET_SIZE(&msg.attr, vap->va_size);
474: else
475: XA_SET_SIZE(&msg.attr, xn->attr.va_size);
476: #ifdef __APPLE__
477: /* XXX needed ? */
478: if (UBCINFOEXISTS(vp))
479: ubc_setsize(vp, msg.attr.xa_size);
480: #endif
481: }
482: if (vap->va_mtime.tv_sec != (unsigned int)VNOVAL)
483: XA_SET_MTIME(&msg.attr, vap->va_mtime.tv_sec);
484: else
485: XA_SET_MTIME(&msg.attr, xn->attr.va_mtime.tv_sec);
486: }
487:
488: NNPFS_TOKEN_CLEAR(xn, NNPFS_ATTR_VALID, NNPFS_ATTR_MASK);
489: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
490: if (error == 0)
491: error = ((struct xfs_message_wakeup *) & msg)->error;
492: }
493:
494: done:
495: return error;
496: }
497:
498: static int
499: check_rights (u_char rights, int mode)
500: {
501: int error = 0;
502:
503: if (mode & VREAD)
504: if ((rights & NNPFS_RIGHT_R) == 0)
505: error = EACCES;
506: if (mode & VWRITE)
507: if ((rights & NNPFS_RIGHT_W) == 0)
508: error = EACCES;
509: if (mode & VEXEC)
510: if ((rights & NNPFS_RIGHT_X) == 0)
511: error = EACCES;
512: return error;
513: }
514:
515: int
516: xfs_access_common(struct vnode *vp, int mode, struct ucred *cred,
517: d_thread_t *p)
518: {
519: int error = 0;
520: xfs_pag_t pag = xfs_get_pag(cred);
521:
522: NNPFSDEB(XDEBVNOPS, ("xfs_access mode = 0%o\n", mode));
523:
524: error = xfs_attr_valid(vp, cred, p, NNPFS_ATTR_R);
525: if (error == 0) {
526: struct xfs_node *xn = VNODE_TO_XNODE(vp);
527: int i;
528:
529: error = check_rights (xn->anonrights, mode);
530:
531: if (error == 0)
532: goto done;
533:
534: NNPFSDEB(XDEBVNOPS, ("xfs_access anonaccess failed\n"));
535:
536: error = EACCES; /* default to EACCES if pag isn't in xn->id */
537:
538: for (i = 0; i < MAXRIGHTS; i++)
539: if (xn->id[i] == pag) {
540: error = check_rights (xn->rights[i], mode);
541: break;
542: }
543: }
544:
545: done:
546: NNPFSDEB(XDEBVNOPS, ("xfs_access(0%o) = %d\n", mode, error));
547:
548: return error;
549: }
550:
551: int
552: xfs_lookup_common(struct vnode *dvp,
553: xfs_componentname *cnp,
554: struct vnode **vpp)
555: {
556: struct xfs_message_getnode msg;
557: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
558: struct xfs_node *d = VNODE_TO_XNODE(dvp);
559: int error = 0;
560: #ifdef HAVE_FREEBSD_THREAD
561: d_thread_t *proc = xfs_cnp_to_thread(cnp);
562: struct ucred *cred = xfs_thread_to_cred(proc);
563: #else
564: d_thread_t *proc = xfs_cnp_to_proc(cnp);
565: struct ucred *cred = xfs_proc_to_cred(proc);
566: #endif
567:
568: NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: enter\n"));
569:
570: *vpp = NULL;
571:
572: if (cnp->cn_namelen >= NNPFS_MAX_NAME)
573: return ENAMETOOLONG;
574:
575: if (dvp->v_type != VDIR)
576: return ENOTDIR;
577:
578: if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
579: *vpp = dvp;
580: VREF(*vpp);
581: return 0;
582: }
583:
584: do {
585: xfs_vop_access(dvp, VEXEC, cred, proc, error);
586: if (error != 0)
587: goto done;
588:
589: NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: dvp = %lx\n",
590: (unsigned long) dvp));
591: NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: cnp = %lx, "
592: "cnp->cn_nameiop = %d\n",
593: (unsigned long) cnp, (int)cnp->cn_nameiop));
594:
595:
596: error = xfs_dnlc_lookup(dvp, cnp, vpp);
597: if (error == 0) {
598:
599: /*
600: * Doesn't quite work.
601: */
602:
603: #if 0
604: if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
605: && (cnp->cn_flags & ISLASTCN)) {
606: error = EJUSTRETURN;
607: goto done;
608: }
609: #endif
610:
611: msg.header.opcode = NNPFS_MSG_GETNODE;
612: if (cnp->cn_cred != NOCRED) {
613: msg.cred.uid = cnp->cn_cred->cr_uid;
614: msg.cred.pag = xfs_get_pag(cnp->cn_cred);
615: } else {
616: msg.cred.uid = 0;
617: msg.cred.pag = NNPFS_ANONYMOUSID;
618: }
619: msg.parent_handle = d->handle;
620: memcpy(msg.name, cnp->cn_nameptr, cnp->cn_namelen);
621: msg.name[cnp->cn_namelen] = '\0';
622: error = xfs_message_rpc(xfsp->fd, &msg.header,
623: sizeof(msg), proc);
624: if (error == 0)
625: error = ((struct xfs_message_wakeup *) & msg)->error;
626: if(error == ENOENT && cnp->cn_nameiop != CREATE) {
627: NNPFSDEB(XDEBVNOPS, ("xfs_lookup: neg cache %lx (%s, %ld)\n",
628: (unsigned long)dvp,
629: cnp->cn_nameptr, cnp->cn_namelen));
630: xfs_dnlc_enter (dvp, cnp, NULL);
631: }
632: } else if (error == -1) {
633: error = 0;
634: goto done;
635: }
636: } while (error == 0);
637:
638: done:
639: NNPFSDEB(XDEBVNOPS, ("xfs_lookup_common: return error = %d\n", error));
640: return error;
641: }
642:
643: int
644: xfs_create_common(struct vnode *dvp,
645: const char *name,
646: struct vattr *vap,
647: struct ucred *cred,
648: d_thread_t *p)
649: {
650: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
651: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
652: int error = 0;
653:
654: NNPFSDEB(XDEBVNOPS, ("xfs_create: (%lx, %s)\n",
655: (unsigned long)dvp, name));
656: {
657: struct xfs_message_create msg;
658:
659: msg.header.opcode = NNPFS_MSG_CREATE;
660: msg.parent_handle = xn->handle;
661: if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
662: return ENAMETOOLONG;
663: vattr2xfs_attr(vap, &msg.attr);
664:
665: msg.mode = 0; /* XXX - mode */
666: if (cred != NOCRED) {
667: msg.cred.uid = cred->cr_uid;
668: msg.cred.pag = xfs_get_pag(cred);
669: } else {
670: msg.cred.uid = 0;
671: msg.cred.pag = NNPFS_ANONYMOUSID;
672: }
673:
674:
675: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
676:
677: if (error == 0)
678: error = ((struct xfs_message_wakeup *) & msg)->error;
679: }
680:
681: #if 0
682: if (error == EEXIST)
683: error = 0;
684: #endif
685:
686: return error;
687: }
688:
689: int
690: xfs_remove_common(struct vnode *dvp,
691: struct vnode *vp,
692: const char *name,
693: struct ucred *cred,
694: d_thread_t *p)
695: {
696: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
697: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
698: struct xfs_message_remove msg;
699: int error;
700:
701: NNPFSDEB(XDEBVNOPS, ("xfs_remove: %s\n", name));
702:
703: msg.header.opcode = NNPFS_MSG_REMOVE;
704: msg.parent_handle = xn->handle;
705: msg.cred.uid = cred->cr_uid;
706: msg.cred.pag = xfs_get_pag(cred);
707:
708: if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
709: error = ENAMETOOLONG;
710: else
711: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
712: if (error == 0)
713: error = ((struct xfs_message_wakeup *) &msg)->error;
714:
715: if (error == 0)
716: xfs_dnlc_purge (vp);
717:
718: return error;
719: }
720:
721: int
722: xfs_rename_common(struct vnode *fdvp,
723: struct vnode *fvp,
724: const char *fname,
725: struct vnode *tdvp,
726: struct vnode *tvp,
727: const char *tname,
728: struct ucred *cred,
729: d_thread_t *p)
730: {
731: struct xfs *xfsp = NNPFS_FROM_VNODE(fdvp);
732: int error;
733:
734: NNPFSDEB(XDEBVNOPS, ("xfs_rename: %s %s\n", fname, tname));
735:
736: if ((fvp->v_mount != tdvp->v_mount)
737: || (tvp && (fvp->v_mount != tvp->v_mount))) {
738: return EXDEV;
739: }
740:
741: {
742: struct xfs_message_rename msg;
743:
744: msg.header.opcode = NNPFS_MSG_RENAME;
745: msg.old_parent_handle = VNODE_TO_XNODE(fdvp)->handle;
746: if (strlcpy(msg.old_name, fname, sizeof(msg.old_name)) >= NNPFS_MAX_NAME)
747: return ENAMETOOLONG;
748: msg.new_parent_handle = VNODE_TO_XNODE(tdvp)->handle;
749: if (strlcpy(msg.new_name, tname, sizeof(msg.new_name)) >= NNPFS_MAX_NAME)
750: return ENAMETOOLONG;
751: msg.cred.uid = cred->cr_uid;
752: msg.cred.pag = xfs_get_pag(cred);
753: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
754: if (error == 0)
755: error = ((struct xfs_message_wakeup *) &msg)->error;
756:
757: }
758:
759: NNPFSDEB(XDEBVNOPS, ("xfs_rename: error = %d\n", error));
760:
761: return error;
762: }
763:
764: int
765: xfs_mkdir_common(struct vnode *dvp,
766: const char *name,
767: struct vattr *vap,
768: struct ucred *cred,
769: d_thread_t *p)
770: {
771: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
772: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
773: int error = 0;
774:
775: NNPFSDEB(XDEBVNOPS, ("xfs_mkdir: %s\n", name));
776: {
777: struct xfs_message_mkdir msg;
778:
779: msg.header.opcode = NNPFS_MSG_MKDIR;
780: msg.parent_handle = xn->handle;
781: if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
782: return ENAMETOOLONG;
783: vattr2xfs_attr(vap, &msg.attr);
784: if (cred != NOCRED) {
785: msg.cred.uid = cred->cr_uid;
786: msg.cred.pag = xfs_get_pag(cred);
787: } else {
788: msg.cred.uid = 0;
789: msg.cred.pag = NNPFS_ANONYMOUSID;
790: }
791: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
792: if (error == 0)
793: error = ((struct xfs_message_wakeup *) & msg)->error;
794: }
795:
796: return error;
797: }
798:
799: int
800: xfs_rmdir_common(struct vnode *dvp,
801: struct vnode *vp,
802: const char *name,
803: struct ucred *cred,
804: d_thread_t *p)
805: {
806: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
807: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
808: struct xfs_message_rmdir msg;
809: int error;
810:
811: NNPFSDEB(XDEBVNOPS, ("xfs_rmdir: %s\n", name));
812:
813: msg.header.opcode = NNPFS_MSG_RMDIR;
814: msg.parent_handle = xn->handle;
815: msg.cred.uid = cred->cr_uid;
816: msg.cred.pag = xfs_get_pag(cred);
817: if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
818: error = ENAMETOOLONG;
819: else
820: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
821: if (error == 0)
822: error = ((struct xfs_message_wakeup *) &msg)->error;
823:
824: if (error == 0)
825: xfs_dnlc_purge (vp);
826:
827: NNPFSDEB(XDEBVNOPS, ("xfs_rmdir error: %d\n", error));
828:
829: return error;
830: }
831:
832: int
833: xfs_readdir_common(struct vnode *vp,
834: struct uio *uiop,
835: struct ucred *cred,
836: d_thread_t *p,
837: int *eofflag)
838: {
839: int error = 0;
840:
841: NNPFSDEB(XDEBVNOPS, ("xfs_readdir\n"));
842:
843: if(eofflag)
844: *eofflag = 0;
845: #ifdef HAVE_FREEBSD_THREAD
846: error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_R,
847: xfs_uio_end_length(uiop));
848: #else
849: error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_R,
850: xfs_uio_end_length(uiop));
851: #endif
852: if (error == 0) {
853: struct vnode *t = DATA_FROM_VNODE(vp);
854:
855: #ifdef HAVE_FREEBSD_THREAD
856: xfs_vfs_readlock(t, xfs_uio_to_thread(uiop));
857: #else
858: xfs_vfs_readlock(t, xfs_uio_to_proc(uiop));
859: #endif
860: xfs_vop_read(t, uiop, 0, cred, error);
861: if (eofflag) {
862: struct vattr t_attr;
863: int error2;
864:
865: #ifdef HAVE_FREEBSD_THREAD
866: xfs_vop_getattr(t, &t_attr, cred, xfs_uio_to_thread(uiop), error2);
867: #else
868: xfs_vop_getattr(t, &t_attr, cred, xfs_uio_to_proc(uiop), error2);
869: #endif
870: if (error2 == 0)
871: *eofflag = t_attr.va_size <= uiop->uio_offset;
872: }
873: #ifdef HAVE_FREEBSD_THREAD
874: xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
875: #else
876: xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
877: #endif
878: }
879: return error;
880: }
881:
882: int
883: xfs_link_common(struct vnode *dvp,
884: struct vnode *vp,
885: const char *name,
886: struct ucred *cred,
887: d_thread_t *p)
888: {
889: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
890: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
891: struct xfs_node *xn2 = VNODE_TO_XNODE(vp);
892: struct xfs_message_link msg;
893: int error = 0;
894:
895: NNPFSDEB(XDEBVNOPS, ("xfs_link: %s\n", name));
896:
897: msg.header.opcode = NNPFS_MSG_LINK;
898: msg.parent_handle = xn->handle;
899: msg.from_handle = xn2->handle;
900: if (strlcpy(msg.name, name, sizeof(msg.name)) >= NNPFS_MAX_NAME)
901: return ENAMETOOLONG;
902: msg.cred.uid = cred->cr_uid;
903: msg.cred.pag = xfs_get_pag(cred);
904:
905: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
906: if (error == 0)
907: error = ((struct xfs_message_wakeup *) & msg)->error;
908:
909: return error;
910: }
911:
912: int
913: xfs_symlink_common(struct vnode *dvp,
914: struct vnode **vpp,
915: xfs_componentname *cnp,
916: struct vattr *vap,
917: char *target)
918: {
919: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
920: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
921: #ifdef HAVE_FREEBSD_THREAD
922: d_thread_t *proc = xfs_cnp_to_thread(cnp);
923: struct ucred *cred = xfs_thread_to_cred(proc);
924: #else
925: d_thread_t *proc = xfs_cnp_to_proc(cnp);
926: struct ucred *cred = xfs_proc_to_cred(proc);
927: #endif
928: struct xfs_message_symlink *msg = NULL;
929: const char *name = cnp->cn_nameptr;
930: int error = 0;
931:
932: NNPFSDEB(XDEBVNOPS, ("xfs_symlink: %s\n", name));
933:
934: msg = malloc(sizeof(struct xfs_message_symlink), M_TEMP, M_WAITOK);
935: if (msg == NULL) {
936: error = ENOMEM;
937: goto done;
938: }
939: memset(msg, 0, sizeof(*msg));
940:
941: msg->header.opcode = NNPFS_MSG_SYMLINK;
942: msg->parent_handle = xn->handle;
943: vattr2xfs_attr(vap, &msg->attr);
944: msg->cred.uid = cred->cr_uid;
945: msg->cred.pag = xfs_get_pag(cred);
946: if (strlcpy (msg->contents, target, sizeof(msg->contents)) >= NNPFS_MAX_SYMLINK_CONTENT) {
947: error = ENAMETOOLONG;
948: goto done;
949: }
950: if (strlcpy(msg->name, name, sizeof(msg->name)) >= NNPFS_MAX_NAME) {
951: error = ENAMETOOLONG;
952: goto done;
953: }
954: error = xfs_message_rpc(xfsp->fd, &msg->header, sizeof(*msg), proc);
955: if (error == 0)
956: error = ((struct xfs_message_wakeup *) msg)->error;
957:
958: done:
959: free(msg, M_TEMP);
960: return error;
961: }
962:
963: int
964: xfs_readlink_common(struct vnode *vp, struct uio *uiop, struct ucred *cred)
965: {
966: int error = 0;
967:
968: NNPFSDEB(XDEBVNOPS, ("xfs_readlink\n"));
969:
970: #ifdef HAVE_FREEBSD_THREAD
971: error = xfs_data_valid(vp, cred, xfs_uio_to_thread(uiop), NNPFS_DATA_R,
972: xfs_uio_end_length(uiop));
973: #else
974: error = xfs_data_valid(vp, cred, xfs_uio_to_proc(uiop), NNPFS_DATA_R,
975: xfs_uio_end_length(uiop));
976: #endif
977: if (error == 0) {
978: struct vnode *t = DATA_FROM_VNODE(vp);
979:
980: #ifdef HAVE_FREEBSD_THREAD
981: xfs_vfs_readlock(t, xfs_uio_to_thread(uiop));
982: xfs_vop_read(t, uiop, 0, cred, error);
983: xfs_vfs_unlock(t, xfs_uio_to_thread(uiop));
984: #else
985: xfs_vfs_readlock(t, xfs_uio_to_proc(uiop));
986: xfs_vop_read(t, uiop, 0, cred, error);
987: xfs_vfs_unlock(t, xfs_uio_to_proc(uiop));
988: #endif
989: }
990: return error;
991: }
992:
993: int
994: xfs_inactive_common(struct vnode *vp, d_thread_t *p)
995: {
996: int error;
997: struct xfs_node *xn = VNODE_TO_XNODE(vp);
998:
999: NNPFSDEB(XDEBVNOPS, ("xfs_inactive, %lx\n",
1000: (unsigned long)vp));
1001:
1002: /*
1003: * This seems rather bogus, but sometimes we get an already
1004: * cleaned node to be made inactive. Just ignoring it seems safe.
1005: */
1006:
1007: if (xn == NULL) {
1008: NNPFSDEB(XDEBVNOPS, ("xfs_inactive: clean node\n"));
1009: return 0;
1010: }
1011:
1012: /* xn->wr_cred not set -> NOCRED */
1013:
1014: if (vp->v_type == VREG)
1015: xfs_pushdirty(vp, xn->wr_cred, p);
1016:
1017: error = xfs_fsync_common(vp, xn->wr_cred, /* XXX */ 0, p);
1018: if (error) {
1019: printf ("xfs_inactive: failed writing back data: %d\n", error);
1020: xn->flags &= ~NNPFS_DATA_DIRTY;
1021: }
1022:
1023: /* If this node is no longer valid, recycle immediately. */
1024: if (!NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_R | NNPFS_ATTR_W)
1025: || (xn->flags & NNPFS_STALE) == NNPFS_STALE)
1026: {
1027: #ifndef __osf__
1028: xfs_vfs_unlock(vp, p);
1029: NNPFSDEB(XDEBVNOPS, ("xfs_inactive: vrecycle\n"));
1030: vrecycle(vp, p);
1031: #else /* __osf__ */
1032: NNPFSDEB(XDEBVNOPS, ("xfs_inactive: vp = %lx vp->v_usecount= %d\n",
1033: (unsigned long)vp, vp?vp->v_usecount:0));
1034: #endif /* __osf__ */
1035: } else {
1036: #ifndef __osf__
1037: xfs_vfs_unlock(vp, p);
1038: #endif
1039: xn->flags &= ~NNPFS_STALE;
1040: }
1041:
1042: NNPFSDEB(XDEBVNOPS, ("return: xfs_inactive\n"));
1043:
1044: return 0;
1045: }
1046:
1047: int
1048: xfs_reclaim_common(struct vnode *vp)
1049: {
1050: struct xfs_message_inactivenode msg;
1051: struct xfs *xfsp = NNPFS_FROM_VNODE(vp);
1052: struct xfs_node *xn = VNODE_TO_XNODE(vp);
1053:
1054: NNPFSDEB(XDEBVNOPS, ("xfs_reclaim: %lx\n",
1055: (unsigned long)vp));
1056:
1057: NNPFS_TOKEN_CLEAR(xn,
1058: ~0,
1059: NNPFS_OPEN_MASK | NNPFS_ATTR_MASK |
1060: NNPFS_DATA_MASK | NNPFS_LOCK_MASK);
1061: /* Release, data if we still have it. */
1062: if (DATA_FROM_XNODE(xn) != 0) {
1063: vrele(DATA_FROM_XNODE(xn));
1064: DATA_FROM_XNODE(xn) = 0;
1065: }
1066:
1067: xfs_remove_node(&xfsp->nodehead, xn);
1068:
1069: msg.header.opcode = NNPFS_MSG_INACTIVENODE;
1070: msg.handle = xn->handle;
1071: msg.flag = NNPFS_NOREFS | NNPFS_DELETE;
1072: xfs_message_send(xfsp->fd, &msg.header, sizeof(msg));
1073:
1074: xfs_dnlc_purge(vp);
1075: free_xfs_node(xn);
1076: return 0;
1077: }
1078:
1079: /*
1080: *
1081: */
1082:
1083: #if 0
1084:
1085: int
1086: xfs_advlock_common(struct vnode *dvp,
1087: int locktype,
1088: unsigned long lockid, /* XXX this good ? */
1089: struct ucred *cred)
1090: {
1091: struct xfs *xfsp = NNPFS_FROM_VNODE(dvp);
1092: struct xfs_node *xn = VNODE_TO_XNODE(dvp);
1093: int error = 0;
1094:
1095: NNPFSDEB(XDEBVNOPS, ("xfs_advlock\n"));
1096: {
1097: struct xfs_message_advlock msg;
1098:
1099: msg.header.opcode = NNPFS_MSG_ADVLOCK;
1100: msg.handle = xn->handle;
1101: msg.locktype = locktype;
1102: msg.lockid = lockid;
1103:
1104: if (cred != NOCRED) {
1105: msg.cred.uid = cred->cr_uid;
1106: msg.cred.pag = xfs_get_pag(cred);
1107: } else {
1108: msg.cred.uid = 0;
1109: msg.cred.pag = NNPFS_ANONYMOUSID;
1110: }
1111: error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), p);
1112: if (error == 0)
1113: error = ((struct xfs_message_wakeup *) & msg)->error;
1114: }
1115:
1116: if (error == 0) {
1117:
1118: /* sleep until woken */
1119:
1120: } else {
1121:
1122: /* die */
1123: }
1124:
1125: return error;
1126: }
1127:
1128: #endif
1129:
1130: /*
1131: *
1132: */
1133:
1134: void
1135: xfs_printnode_common (struct vnode *vp)
1136: {
1137: struct xfs_node *xn = VNODE_TO_XNODE(vp);
1138:
1139: printf ("xnode: fid: %d.%d.%d.%d\n",
1140: xn->handle.a, xn->handle.b, xn->handle.c, xn->handle.d);
1141: printf ("\tattr: %svalid\n",
1142: NNPFS_TOKEN_GOT(xn, NNPFS_ATTR_VALID) ? "": "in");
1143: printf ("\tdata: %svalid\n",
1144: NNPFS_TOKEN_GOT(xn, NNPFS_DATA_VALID) ? "": "in");
1145: printf ("\tflags: 0x%x\n", xn->flags);
1146: printf ("\toffset: %d\n", xn->offset);
1147: }
CVSweb