diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 1999-04-30 01:59:03 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 1999-04-30 01:59:03 +0000 |
commit | b0d7a6a83d7eaa1e9a526c576527d81957b28268 (patch) | |
tree | 0baa2e9e6f6c86554b23b30e24ff2c2801debe48 /sys/xfs/xfs_vnodeops-common.c | |
parent | 55728d80a6017f4e7da4b56865862c70d4d75897 (diff) |
Import of xfs from arla-0.35.7
Diffstat (limited to 'sys/xfs/xfs_vnodeops-common.c')
-rw-r--r-- | sys/xfs/xfs_vnodeops-common.c | 948 |
1 files changed, 948 insertions, 0 deletions
diff --git a/sys/xfs/xfs_vnodeops-common.c b/sys/xfs/xfs_vnodeops-common.c new file mode 100644 index 00000000000..fee9b17acc8 --- /dev/null +++ b/sys/xfs/xfs_vnodeops-common.c @@ -0,0 +1,948 @@ +/* + * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * XFS operations. + */ + +#include <xfs/xfs_locl.h> +#include <xfs/xfs_message.h> +#include <xfs/xfs_common.h> +#include <xfs/xfs_fs.h> +#include <xfs/xfs_dev.h> +#include <xfs/xfs_deb.h> +#include <xfs/xfs_syscalls.h> +#include <xfs/xfs_vnodeops.h> + +RCSID("$Id: xfs_vnodeops-common.c,v 1.1 1999/04/30 01:59:01 art Exp $"); + +int +xfs_open_valid(struct vnode * vp, struct ucred * cred, u_int tok) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + XFSDEB(XDEBVFOPS, ("xfs_open_valid\n")); + + do { + if (!XFS_TOKEN_GOT(xn, tok)) { + struct xfs_message_open msg; + + msg.header.opcode = XFS_MSG_OPEN; + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + msg.handle = xn->handle; + msg.tokens = tok; + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } else { + goto done; + } + } while (error == 0); + +done: + XFSDEB(XDEBVFOPS, ("xfs_open_valid: error = %d\n", error)); + + return error; +} + +int +xfs_attr_valid(struct vnode * vp, struct ucred * cred, u_int tok) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + pag_t pag = xfs_get_pag(cred); + + do { + if (!XFS_TOKEN_GOT(xn, tok)) { + struct xfs_message_getattr msg; + + msg.header.opcode = XFS_MSG_GETATTR; + msg.cred.uid = cred->cr_uid; + msg.cred.pag = pag; + msg.handle = xn->handle; + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } else { + goto done; + } + } while (error == 0); + +done: + return error; +} + +int +xfs_fetch_rights(struct vnode * vp, struct ucred * cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + pag_t pag = xfs_get_pag(cred); + + do { + if (!xfs_has_pag(xn, pag)) { + struct xfs_message_getattr msg; + + msg.header.opcode = XFS_MSG_GETATTR; + msg.cred.uid = cred->cr_uid; + msg.cred.pag = pag; + msg.handle = xn->handle; + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } else { + goto done; + } + } while (error == 0); + +done: + + return error; +} + +int +xfs_data_valid(struct vnode * vp, struct ucred * cred, u_int tok) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + do { + if (!XFS_TOKEN_GOT(xn, tok)) { + struct xfs_message_getdata msg; + + msg.header.opcode = XFS_MSG_GETDATA; + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + msg.handle = xn->handle; + msg.tokens = tok; + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } else { + goto done; + } + } while (error == 0); + +done: + return error; +} + +static int +do_fsync(struct xfs * xfsp, + struct xfs_node * xn, + struct ucred * cred, + u_int flag) +{ + int error; + struct xfs_message_putdata msg; + + msg.header.opcode = XFS_MSG_PUTDATA; + if (cred != NOCRED) { + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + msg.handle = xn->handle; + vattr2xfs_attr(&xn->attr, &msg.attr); + msg.flag = flag; + + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + + if (error == 0) + xn->flags &= ~XFS_DATA_DIRTY; + + return error; +} + +int +xfs_fsync_common(struct vnode *vp, struct ucred *cred, + int waitfor, struct proc *proc) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_fsync: %p\n", vp)); + + /* + * It seems that fsync is sometimes called after reclaiming a node. + * In that case we just look happy. + */ + + if (xn == NULL) { + printf("XFS PANIC WARNING! xfs_fsync called after reclaiming!\n"); + return 0; + } + + if (xn->flags & XFS_DATA_DIRTY) + error = do_fsync(xfsp, xn, cred, XFS_WRITE); + + return error; +} + +int +xfs_close_common(struct vnode *vp, int fflag, + struct proc *proc, struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_close cred = %p\n", cred)); + + if (fflag & FWRITE && xn->flags & XFS_DATA_DIRTY) + error = do_fsync(xfsp, xn, cred, XFS_WRITE); + + return error; +} + +int +xfs_read_common(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) +{ + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_read\n")); + + error = xfs_data_valid(vp, cred, XFS_DATA_R); + + if (error == 0) { + struct vnode *t = DATA_FROM_VNODE(vp); + + xfs_vfs_readlock(t, xfs_uio_to_proc(uio)); +#ifdef __osf__ + VOP_READ(t, uio, ioflag, cred, error); +#else /* __osf__ */ + error = VOP_READ(t, uio, ioflag, cred); +#endif /* __osf__ */ + xfs_vfs_unlock(t, xfs_uio_to_proc(uio)); + } + return error; +} + +int +xfs_write_common(struct vnode *vp, struct uio *uiop, int ioflag, struct ucred *cred) +{ + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_write\n")); + + error = xfs_data_valid(vp, cred, XFS_DATA_W); + + if (error == 0) { + struct xfs_node *xn = VNODE_TO_XNODE(vp); + struct vnode *t = DATA_FROM_XNODE(xn); + struct vattr sub_attr; + int error2 = 0; + + xfs_vfs_writelock(t, xfs_uio_to_proc(uiop)); +#ifdef __osf__ + VOP_WRITE(t, uiop, ioflag, cred, error); + VNODE_TO_XNODE(vp)->flags |= XFS_DATA_DIRTY; + VOP_GETATTR(t, &sub_attr, cred, error2); +#else /* __osf__ */ + error = VOP_WRITE(t, uiop, ioflag, cred); + VNODE_TO_XNODE(vp)->flags |= XFS_DATA_DIRTY; + error2 = VOP_GETATTR(t, &sub_attr, cred, uiop->uio_procp); +#endif /* __osf__ */ + + if (error2 == 0) { + xn->attr.va_size = sub_attr.va_size; + xn->attr.va_mtime = sub_attr.va_mtime; +#ifdef HAVE_KERNEL_VNODE_PAGER_SETSIZE + vnode_pager_setsize(vp, sub_attr.va_size); +#endif + } + xfs_vfs_unlock(t, xfs_uio_to_proc(uiop)); + } + + return error; +} + +int +xfs_getattr_common(struct vnode *vp, struct vattr *vap, struct ucred *cred) +{ + int error = 0; + + struct xfs_node *xn = VNODE_TO_XNODE(vp); + + XFSDEB(XDEBVNOPS, ("xfs_getattr\n")); + + error = xfs_attr_valid(vp, cred, XFS_ATTR_R); + if (error == 0) + *vap = xn->attr; + return error; +} + +int +xfs_setattr_common(struct vnode *vp, struct vattr *vap, struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_setattr\n")); + +#define CHECK_XFSATTR(A, cast) (vap->A == cast VNOVAL || vap->A == xn->attr.A) + if (CHECK_XFSATTR(va_mode,(mode_t)) && + CHECK_XFSATTR(va_nlink,) && + CHECK_XFSATTR(va_size,) && + CHECK_XFSATTR(va_uid,) && + CHECK_XFSATTR(va_gid,) && + CHECK_XFSATTR(va_mtime.tv_sec,) && + CHECK_XFSATTR(va_fileid,) && + CHECK_XFSATTR(va_type,)) + return 0; /* Nothing to do */ +#undef CHECK_XFSATTR + + if (XFS_TOKEN_GOT(xn, XFS_ATTR_W)) { + /* Update attributes and mark them dirty. */ + VNODE_TO_XNODE(vp)->flags |= XFS_ATTR_DIRTY; + error = EINVAL; /* XXX not yet implemented */ + goto done; + } else { + struct xfs_message_putattr msg; + + msg.header.opcode = XFS_MSG_PUTATTR; + if (cred != NOCRED) { + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + msg.handle = xn->handle; + vattr2xfs_attr(vap, &msg.attr); + + XFS_TOKEN_CLEAR(xn, XFS_ATTR_VALID, XFS_ATTR_MASK); + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } + +done: + return error; +} + +static int +check_rights (u_char rights, int mode) +{ + int error = 0; + + if (mode & VREAD) + if ((rights & XFS_RIGHT_R) == 0) + error = EACCES; + if (mode & VWRITE) + if ((rights & XFS_RIGHT_W) == 0) + error = EACCES; + if (mode & VEXEC) + if ((rights & XFS_RIGHT_X) == 0) + error = EACCES; + return error; +} + +int +xfs_access_common(struct vnode *vp, int mode, struct ucred *cred) +{ + int error = 0; + pag_t pag = xfs_get_pag(cred); + + XFSDEB(XDEBVNOPS, ("xfs_access mode = 0%o\n", mode)); + + error = xfs_attr_valid(vp, cred, XFS_ATTR_R); + if (error == 0) { + struct xfs_node *xn = VNODE_TO_XNODE(vp); + int i; + + error = check_rights (xn->anonrights, mode); + + if (error == 0) + goto done; + + XFSDEB(XDEBVNOPS, ("xfs_access anonaccess failed\n")); + + xfs_fetch_rights(vp, cred); /* ignore error */ + + error = EACCES; /* default to EACCES if pag isn't in xn->id */ + + for (i = 0; i < MAXRIGHTS; i++) + if (xn->id[i] == pag) { + error = check_rights (xn->rights[i], mode); + break; + } + } + +done: + XFSDEB(XDEBVNOPS, ("xfs_access(0%o) = %d\n", mode, error)); + + return error; +} + +int +xfs_lookup_common(struct vnode *dvp, + xfs_componentname *cnp, + struct vnode **vpp) +{ + struct xfs_message_getnode msg; + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *d = VNODE_TO_XNODE(dvp); + int error = 0; + struct proc *proc = xfs_cnp_to_proc(cnp); + struct ucred *cred = xfs_proc_to_cred(proc); + + *vpp = NULL; + + if (dvp->v_type != VDIR) + return ENOTDIR; + + again: + + do { +#ifdef __osf__ + VOP_ACCESS(dvp, VEXEC, cred, error); +#else + error = VOP_ACCESS(dvp, VEXEC, cred, xfs_cnp_to_proc(cnp)); +#endif + if (error != 0) + goto done; + + error = xfs_dnlc_lookup(dvp, cnp, vpp); + if (error == 0) { + + /* + * Doesn't quite work. + */ + +#if 0 + if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) + && (cnp->cn_flags & ISLASTCN)) { + error = EJUSTRETURN; + goto done; + } +#endif + + msg.header.opcode = XFS_MSG_GETNODE; + if (cnp->cn_cred != NOCRED) { + msg.cred.uid = cnp->cn_cred->cr_uid; + msg.cred.pag = xfs_get_pag(cnp->cn_cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + msg.parent_handle = d->handle; + + bcopy(cnp->cn_nameptr, msg.name, cnp->cn_namelen); + msg.name[cnp->cn_namelen] = '\0'; + + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + if(error == ENOENT && cnp->cn_nameiop != CREATE) { + XFSDEB(XDEBVNOPS, ("xfs_lookup: neg cache %p (%s, %ld)\n", + dvp, + cnp->cn_nameptr, cnp->cn_namelen)); + xfs_dnlc_enter (dvp, cnp, NULL); + } + } else if (error == -1) { + if (xfs_do_vget(*vpp, LK_EXCLUSIVE, xfs_cnp_to_proc(cnp))) + goto again; + error = 0; + goto done; + } + } while (error == 0); + +done: + return error; +} + +int +xfs_lookup_name(struct vnode *dvp, + const char *name, + struct proc *proc, + struct ucred *cred, + struct vnode **vpp) +{ + xfs_componentname cn; + + xfs_cnp_init (&cn, name, NULL, dvp, proc, cred, CREATE); + return xfs_lookup_common (dvp, &cn, vpp); +} + +int +xfs_create_common(struct vnode *dvp, + const char *name, + struct vattr *vap, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_create: (%s)\n", name)); + { + struct xfs_message_create msg; + + msg.header.opcode = XFS_MSG_CREATE; + msg.parent_handle = xn->handle; + strncpy(msg.name, name, 256); + vattr2xfs_attr(vap, &msg.attr); + + msg.mode = 0; /* XXX - mode */ + if (cred != NOCRED) { + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } + +#if 0 + if (error == EEXIST) + error = 0; +#endif + + return error; +} + +int +xfs_remove_common(struct vnode *dvp, + struct vnode *vp, + const char *name, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + struct xfs_message_remove msg; + int error; + + XFSDEB(XDEBVNOPS, ("xfs_remove: %s\n", name)); + + msg.header.opcode = XFS_MSG_REMOVE; + msg.parent_handle = xn->handle; + strncpy(msg.name, name, 256); + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) &msg)->error; + + if (error == 0) + xfs_dnlc_purge (vp); + +#if !defined(__FreeBSD__) || __FreeBSD_version < 300000 + if (dvp == vp) + vrele(vp); + else + vput(vp); + vput(dvp); +#endif + + return error; +} + +int +xfs_rename_common(struct vnode *fdvp, + struct vnode *fvp, + const char *fname, + struct vnode *tdvp, + struct vnode *tvp, + const char *tname, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(fdvp); + int error; + + XFSDEB(XDEBVNOPS, ("xfs_rename: %s %s\n", fname, tname)); + + if ((fvp->v_mount != tdvp->v_mount) + || (tvp && (fvp->v_mount != tvp->v_mount))) { + return EXDEV; + } + + { + struct xfs_message_rename msg; + + msg.header.opcode = XFS_MSG_RENAME; + msg.old_parent_handle = VNODE_TO_XNODE(fdvp)->handle; + strncpy(msg.old_name, fname, 256); + msg.new_parent_handle = VNODE_TO_XNODE(tdvp)->handle; + strncpy(msg.new_name, tname, 256); + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) &msg)->error; + + } + + XFSDEB(XDEBVNOPS, ("xfs_rename: error = %d\n", error)); + + return error; +} + +int +xfs_mkdir_common(struct vnode *dvp, + const char *name, + struct vattr *vap, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_mkdir: %s\n", name)); + { + struct xfs_message_mkdir msg; + + msg.header.opcode = XFS_MSG_MKDIR; + msg.parent_handle = xn->handle; + strncpy(msg.name, name, 256); + vattr2xfs_attr(vap, &msg.attr); + if (cred != NOCRED) { + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } + + return error; +} + +int +xfs_rmdir_common(struct vnode *dvp, + struct vnode *vp, + const char *name, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + struct xfs_message_rmdir msg; + int error; + + XFSDEB(XDEBVNOPS, ("xfs_rmdir: %s\n", name)); + + msg.header.opcode = XFS_MSG_RMDIR; + msg.parent_handle = xn->handle; + strncpy(msg.name, name, 256); + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) &msg)->error; + + if (error == 0) + xfs_dnlc_purge (vp); + +#if !defined(__FreeBSD__) || __FreeBSD_version < 300000 + if (dvp == vp) + vrele(vp); + else + vput(vp); + vput(dvp); +#endif + + return error; +} + +int +xfs_readdir_common(struct vnode *vp, + struct uio *uiop, + struct ucred *cred, + int *eofflag) +{ + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_readdir\n")); + + if(eofflag) + *eofflag = 0; + error = xfs_data_valid(vp, cred, XFS_DATA_R); + if (error == 0) { + struct vnode *t = DATA_FROM_VNODE(vp); + + xfs_vfs_readlock(t, xfs_uio_to_proc(uiop)); +#ifdef __osf__ + VOP_READ(t, uiop, 0, cred, error); +#else + error = VOP_READ(t, uiop, 0, cred); +#endif + if(eofflag) + *eofflag = VNODE_TO_XNODE(vp)->attr.va_size <= uiop->uio_offset; + xfs_vfs_unlock(t, xfs_uio_to_proc(uiop)); + } + return error; +} + +int +xfs_link_common(struct vnode *dvp, + struct vnode *vp, + const char *name, + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + struct xfs_node *xn2 = VNODE_TO_XNODE(vp); + struct xfs_message_link msg; + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_link: %s\n", name)); + + msg.header.opcode = XFS_MSG_LINK; + msg.parent_handle = xn->handle; + msg.from_handle = xn2->handle; + strncpy(msg.name, name, 256); + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + + return error; +} + +int +xfs_symlink_common(struct vnode *dvp, + struct vnode **vpp, + const char *name, + struct proc *proc, + struct ucred *cred, + struct vattr *vap, + char *target) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + struct xfs_message_symlink msg; + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_symlink: %s\n", name)); + + msg.header.opcode = XFS_MSG_SYMLINK; + msg.parent_handle = xn->handle; + strncpy(msg.name, name, sizeof(msg.name)); + msg.name[sizeof(msg.name) - 1] = '\0'; + vattr2xfs_attr(vap, &msg.attr); + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + strncpy (msg.contents, target, sizeof(msg.contents)); + msg.contents[sizeof(msg.contents) - 1] = '\0'; + + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + + if (error == 0) { + error = xfs_lookup_name(dvp, name, proc, cred, vpp); + if (error == 0) + vput (*vpp); + } + +#if !defined(__FreeBSD__) || __FreeBSD_version < 300000 + vput(dvp); +#endif + + return error; +} + +int +xfs_readlink_common(struct vnode *vp, struct uio *uiop, struct ucred *cred) +{ + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_readlink\n")); + + error = xfs_data_valid(vp, cred, XFS_DATA_R); + if (error == 0) { + struct vnode *t = DATA_FROM_VNODE(vp); + + xfs_vfs_readlock(t, xfs_uio_to_proc(uiop)); +#ifdef __osf__ + VOP_READ(t, uiop, 0, cred, error); +#else + error = VOP_READ(t, uiop, 0, cred); +#endif + xfs_vfs_unlock(t, xfs_uio_to_proc(uiop)); + } + return error; +} + +int +xfs_inactive_common(struct vnode *vp, struct proc *p) +{ + struct xfs_message_inactivenode msg; + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + + XFSDEB(XDEBVNOPS, ("xfs_inactive, %p\n", vp)); + + /* + * This seems rather bogus, but sometimes we get an already + * cleaned node to be made inactive. Just ignoring it seems safe. + */ + + if (xn == NULL) { + XFSDEB(XDEBVNOPS, ("xfs_inactive: clean node\n")); + return 0; + } + + xn->tokens = 0; + msg.header.opcode = XFS_MSG_INACTIVENODE; + msg.handle = xn->handle; + msg.flag = XFS_NOREFS; + xfs_message_send(xfsp->fd, &msg.header, sizeof(msg)); + +#ifndef __osf__ + xfs_vfs_unlock(vp, p); +#else + /* XXX ? */ +#endif + + XFSDEB(XDEBVNOPS, ("return: xfs_inactive\n")); + + return 0; +} + +int +xfs_reclaim_common(struct vnode *vp) +{ + struct xfs_message_inactivenode msg; + struct xfs *xfsp = XFS_FROM_VNODE(vp); + struct xfs_node *xn = VNODE_TO_XNODE(vp); + + XFSDEB(XDEBVNOPS, ("xfs_reclaim: %p\n", vp)); + + msg.header.opcode = XFS_MSG_INACTIVENODE; + msg.handle = xn->handle; + msg.flag = XFS_NOREFS | XFS_DELETE; + xfs_message_send(xfsp->fd, &msg.header, sizeof(msg)); + + xfs_dnlc_purge(vp); + free_xfs_node(xn); + + return 0; +} + +/* + * + */ + +#if 0 + +int +xfs_advlock_common(struct vnode *dvp, + int locktype, + unsigned long lockid, /* XXX this good ? */ + struct ucred *cred) +{ + struct xfs *xfsp = XFS_FROM_VNODE(dvp); + struct xfs_node *xn = VNODE_TO_XNODE(dvp); + int error = 0; + + XFSDEB(XDEBVNOPS, ("xfs_advlock\n")); + { + struct xfs_message_advlock msg; + + msg.header.opcode = XFS_MSG_ADVLOCK; + msg.handle = xn->handle; + msg.locktype = locktype; + msg.lockid = lockid; + + if (cred != NOCRED) { + msg.cred.uid = cred->cr_uid; + msg.cred.pag = xfs_get_pag(cred); + } else { + msg.cred.uid = 0; + msg.cred.pag = XFS_ANONYMOUSID; + } + error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg)); + if (error == 0) + error = ((struct xfs_message_wakeup *) & msg)->error; + } + + if (error == 0) { + + /* sleep until woken */ + + } else { + + /* die */ + } + + return error; +} + +#endif + +/* + * + */ + +void +xfs_printnode_common (struct vnode *vp) +{ + struct xfs_node *xn = VNODE_TO_XNODE(vp); + + printf ("xnode: fid: %d.%d.%d.%d\n", + xn->handle.a, xn->handle.b, xn->handle.c, xn->handle.d); + printf ("\tattr: %svalid\n", + XFS_TOKEN_GOT(xn, XFS_ATTR_VALID) ? "": "in"); + printf ("\tdata: %svalid\n", + XFS_TOKEN_GOT(xn, XFS_DATA_VALID) ? "": "in"); + printf ("\tflags: 0x%x\n", xn->flags); +} |