Module Name: src Committed By: pooka Date: Fri May 21 10:16:54 UTC 2010
Modified Files: src/sys/fs/puffs: puffs_msgif.h puffs_vfsops.c puffs_vnops.c Log Message: Support extended attributes. To generate a diff of this commit: cvs rdiff -u -r1.70 -r1.71 src/sys/fs/puffs/puffs_msgif.h cvs rdiff -u -r1.87 -r1.88 src/sys/fs/puffs/puffs_vfsops.c cvs rdiff -u -r1.144 -r1.145 src/sys/fs/puffs/puffs_vnops.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/fs/puffs/puffs_msgif.h diff -u src/sys/fs/puffs/puffs_msgif.h:1.70 src/sys/fs/puffs/puffs_msgif.h:1.71 --- src/sys/fs/puffs/puffs_msgif.h:1.70 Thu May 20 12:09:45 2010 +++ src/sys/fs/puffs/puffs_msgif.h Fri May 21 10:16:54 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_msgif.h,v 1.70 2010/05/20 12:09:45 pooka Exp $ */ +/* $NetBSD: puffs_msgif.h,v 1.71 2010/05/21 10:16:54 pooka Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -69,7 +69,8 @@ PUFFS_VFS_INIT, PUFFS_VFS_DONE, PUFFS_VFS_SNAPSHOT, PUFFS_VFS_EXTATTRCTL, PUFFS_VFS_SUSPEND }; -#define PUFFS_VFS_MAX PUFFS_VFS_EXTATTRCTL /* XXX: NOT TRUE!! */ +#define PUFFS_VFS_SPARE 0 +#define PUFFS_VFS_MAX (PUFFS_VFS_EXTATTRCTL+PUFFS_VFS_SPARE) /* moreXXX: we don't need everything here either */ enum { @@ -88,9 +89,10 @@ PUFFS_VN_ADVLOCK, PUFFS_VN_LEASE, PUFFS_VN_WHITEOUT, PUFFS_VN_GETPAGES, PUFFS_VN_PUTPAGES, PUFFS_VN_GETEXTATTR, PUFFS_VN_LISTEXTATTR, PUFFS_VN_OPENEXTATTR, PUFFS_VN_DELETEEXTATTR, - PUFFS_VN_SETEXTATTR + PUFFS_VN_SETEXTATTR /* PUFFS_VN_CLOSEEXTATTR */ }; -#define PUFFS_VN_MAX PUFFS_VN_SETEXTATTR +#define PUFFS_VN_SPARE 0 +#define PUFFS_VN_MAX (PUFFS_VN_SETEXTATTR+PUFFS_VN_SPARE) /* * These signal invalid parameters the file system returned. @@ -102,6 +104,10 @@ }; #define PUFFS_ERR_MAX PUFFS_ERR_VPTOFH +/* trick to avoid protocol bump */ +#define PUFFS_ERR_GETEXTATTR PUFFS_ERR_ERROR +#define PUFFS_ERR_LISTEXTATTR PUFFS_ERR_ERROR + #define PUFFSDEVELVERS 0x80000000 #define PUFFSVERSION 29 #define PUFFSNAMESIZE 32 @@ -247,6 +253,8 @@ #define PUFFS_MSG_MAXSIZE 2*MAXPHYS #define PUFFS_MSGSTRUCT_MAX 4096 /* XXX: approxkludge */ +#define PUFFS_EXTNAMELEN NAME_MAX /* currently same as EXTATTR_MAXNAMELEN */ + #define PUFFS_TOMOVE(a,b) (MIN((a), b->pmp_msg_maxsize - PUFFS_MSGSTRUCT_MAX)) /* puffs struct componentname built by kernel */ @@ -327,6 +335,17 @@ #define PUFFS_SUSPEND_RESUME 2 #define PUFFS_SUSPEND_ERROR 3 +#define PUFFS_EXTATTRCTL_HASNODE 0x01 +#define PUFFS_EXTATTRCTL_HASATTRNAME 0x02 +struct puffs_vfsmsg_extattrctl { + struct puffs_req pvfsr_pr; + + int pvfsr_cmd; /* OUT */ + int pvfsr_attrnamespace; /* OUT */ + int pvfsr_flags; /* OUT */ + char pvfsr_attrname[PUFFS_EXTNAMELEN]; /* OUT */ +}; + /* * aux structures for vnode operations. */ @@ -571,6 +590,54 @@ struct puffs_kcred pvnr_cn_cred; /* OUT */ }; +struct puffs_vnmsg_getextattr { + struct puffs_req pvn_pr; + + int pvnr_attrnamespace; /* OUT */ + char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ + + struct puffs_kcred pvnr_cred; /* OUT */ + size_t pvnr_datasize; /* IN */ + + size_t pvnr_resid; /* IN/OUT */ + uint8_t pvnr_data[0] /* IN */ + __aligned(ALIGNBYTES+1); +}; + +struct puffs_vnmsg_setextattr { + struct puffs_req pvn_pr; + + int pvnr_attrnamespace; /* OUT */ + char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ + + struct puffs_kcred pvnr_cred; /* OUT */ + + size_t pvnr_resid; /* IN/OUT */ + uint8_t pvnr_data[0] /* OUT */ + __aligned(ALIGNBYTES+1); +}; + +struct puffs_vnmsg_listextattr { + struct puffs_req pvn_pr; + + int pvnr_attrnamespace; /* OUT */ + + struct puffs_kcred pvnr_cred; /* OUT */ + size_t pvnr_datasize; /* IN */ + + size_t pvnr_resid; /* IN/OUT */ + uint8_t pvnr_data[0] /* IN */ + __aligned(ALIGNBYTES+1); +}; + +struct puffs_vnmsg_deleteextattr { + struct puffs_req pvn_pr; + + int pvnr_attrnamespace; /* OUT */ + char pvnr_attrname[PUFFS_EXTNAMELEN];/* OUT */ + + struct puffs_kcred pvnr_cred; /* OUT */ +}; /* * For cache reports. Everything is always out-out-out, no replies Index: src/sys/fs/puffs/puffs_vfsops.c diff -u src/sys/fs/puffs/puffs_vfsops.c:1.87 src/sys/fs/puffs/puffs_vfsops.c:1.88 --- src/sys/fs/puffs/puffs_vfsops.c:1.87 Wed Feb 17 14:32:08 2010 +++ src/sys/fs/puffs/puffs_vfsops.c Fri May 21 10:16:54 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vfsops.c,v 1.87 2010/02/17 14:32:08 pooka Exp $ */ +/* $NetBSD: puffs_vfsops.c,v 1.88 2010/05/21 10:16:54 pooka Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.87 2010/02/17 14:32:08 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.88 2010/05/21 10:16:54 pooka Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -758,6 +758,56 @@ return EOPNOTSUPP; } +int +puffs_vfsop_extattrctl(struct mount *mp, int cmd, struct vnode *vp, + int attrnamespace, const char *attrname) +{ + PUFFS_MSG_VARS(vfs, extattrctl); + struct puffs_mount *pmp = MPTOPUFFSMP(mp); + struct puffs_node *pnp; + puffs_cookie_t pnc; + int error, flags; + + if (vp) { + /* doesn't make sense for puffs servers */ + if (vp->v_mount != mp) + return EXDEV; + pnp = vp->v_data; + pnc = pnp->pn_cookie; + flags = PUFFS_EXTATTRCTL_HASNODE; + } else { + pnp = pnc = NULL; + flags = 0; + } + + PUFFS_MSG_ALLOC(vfs, extattrctl); + extattrctl_msg->pvfsr_cmd = cmd; + extattrctl_msg->pvfsr_attrnamespace = attrnamespace; + extattrctl_msg->pvfsr_flags = flags; + if (attrname) { + strlcpy(extattrctl_msg->pvfsr_attrname, attrname, + sizeof(extattrctl_msg->pvfsr_attrname)); + extattrctl_msg->pvfsr_flags |= PUFFS_EXTATTRCTL_HASATTRNAME; + } + puffs_msg_setinfo(park_extattrctl, + PUFFSOP_VFS, PUFFS_VFS_EXTATTRCTL, pnc); + + puffs_msg_enqueue(pmp, park_extattrctl); + if (vp) { + mutex_enter(&pnp->pn_mtx); + puffs_referencenode(pnp); + mutex_exit(&pnp->pn_mtx); + VOP_UNLOCK(vp, 0); + } + error = puffs_msg_wait2(pmp, park_extattrctl, pnp, NULL); + PUFFS_MSG_RELEASE(extattrctl); + if (vp) { + puffs_releasenode(pnp); + } + + return checkerr(pmp, error, __func__); +} + const struct vnodeopv_desc * const puffs_vnodeopv_descs[] = { &puffs_vnodeop_opv_desc, &puffs_specop_opv_desc, @@ -784,7 +834,7 @@ puffs_vfsop_done, /* done */ NULL, /* mountroot */ puffs_vfsop_snapshot, /* snapshot */ - vfs_stdextattrctl, /* extattrctl */ + puffs_vfsop_extattrctl, /* extattrctl */ (void *)eopnotsupp, /* suspendctl */ genfs_renamelock_enter, genfs_renamelock_exit, Index: src/sys/fs/puffs/puffs_vnops.c diff -u src/sys/fs/puffs/puffs_vnops.c:1.144 src/sys/fs/puffs/puffs_vnops.c:1.145 --- src/sys/fs/puffs/puffs_vnops.c:1.144 Mon Mar 29 13:11:33 2010 +++ src/sys/fs/puffs/puffs_vnops.c Fri May 21 10:16:54 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: puffs_vnops.c,v 1.144 2010/03/29 13:11:33 pooka Exp $ */ +/* $NetBSD: puffs_vnops.c,v 1.145 2010/05/21 10:16:54 pooka Exp $ */ /* * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.144 2010/03/29 13:11:33 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.145 2010/05/21 10:16:54 pooka Exp $"); #include <sys/param.h> #include <sys/buf.h> @@ -82,6 +82,10 @@ int puffs_vnop_mmap(void *); int puffs_vnop_getpages(void *); int puffs_vnop_abortop(void *); +int puffs_vnop_getextattr(void *); +int puffs_vnop_setextattr(void *); +int puffs_vnop_listextattr(void *); +int puffs_vnop_deleteextattr(void *); int puffs_vnop_spec_read(void *); int puffs_vnop_spec_write(void *); @@ -134,7 +138,14 @@ { &vop_bwrite_desc, genfs_nullop }, /* REAL bwrite */ { &vop_mmap_desc, puffs_vnop_mmap }, /* REAL mmap */ { &vop_poll_desc, puffs_vnop_poll }, /* REAL poll */ - + { &vop_getextattr_desc, puffs_vnop_getextattr }, /* getextattr */ + { &vop_setextattr_desc, puffs_vnop_setextattr }, /* setextattr */ + { &vop_listextattr_desc, puffs_vnop_listextattr }, /* listextattr */ + { &vop_deleteextattr_desc, puffs_vnop_deleteextattr },/* deleteextattr */ +#if 0 + { &vop_openextattr_desc, puffs_vnop_checkop }, /* openextattr */ + { &vop_closeextattr_desc, puffs_vnop_checkop }, /* closeextattr */ +#endif { &vop_kqfilter_desc, genfs_eopnotsupp }, /* kqfilter XXX */ { NULL, NULL } }; @@ -185,13 +196,13 @@ { &vop_bwrite_desc, vn_bwrite }, /* bwrite */ { &vop_getpages_desc, spec_getpages }, /* genfs_getpages */ { &vop_putpages_desc, spec_putpages }, /* genfs_putpages */ + { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */ + { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */ + { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */ + { &vop_deleteextattr_desc, puffs_vnop_checkop },/* deleteextattr */ #if 0 { &vop_openextattr_desc, _openextattr }, /* openextattr */ { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */ - { &vop_getextattr_desc, _getextattr }, /* getextattr */ - { &vop_setextattr_desc, _setextattr }, /* setextattr */ - { &vop_listextattr_desc, _listextattr }, /* listextattr */ - { &vop_deleteextattr_desc, _deleteextattr }, /* deleteextattr */ #endif { NULL, NULL } }; @@ -244,11 +255,11 @@ #if 0 { &vop_openextattr_desc, _openextattr }, /* openextattr */ { &vop_closeextattr_desc, _closeextattr }, /* closeextattr */ - { &vop_getextattr_desc, _getextattr }, /* getextattr */ - { &vop_setextattr_desc, _setextattr }, /* setextattr */ - { &vop_listextattr_desc, _listextattr }, /* listextattr */ - { &vop_deleteextattr_desc, _deleteextattr }, /* deleteextattr */ #endif + { &vop_getextattr_desc, puffs_vnop_checkop }, /* getextattr */ + { &vop_setextattr_desc, puffs_vnop_checkop }, /* setextattr */ + { &vop_listextattr_desc, puffs_vnop_checkop }, /* listextattr */ + { &vop_deleteextattr_desc, puffs_vnop_checkop }, /* deleteextattr */ { NULL, NULL } }; const struct vnodeopv_desc puffs_fifoop_opv_desc = @@ -365,6 +376,10 @@ CHECKOP_NOTSUPP(PRINT); CHECKOP_NOTSUPP(PATHCONF); CHECKOP_NOTSUPP(ADVLOCK); + CHECKOP_NOTSUPP(GETEXTATTR); + CHECKOP_NOTSUPP(SETEXTATTR); + CHECKOP_NOTSUPP(LISTEXTATTR); + CHECKOP_NOTSUPP(DELETEEXTATTR); CHECKOP_SUCCESS(ACCESS); CHECKOP_SUCCESS(CLOSE); @@ -2582,6 +2597,241 @@ } /* + * Extended attribute support. + */ + +int +puffs_vnop_getextattr(void *v) +{ + struct vop_getextattr_args /* + struct vnode *a_vp; + int a_attrnamespace; + const char *a_name; + struct uio *a_uio; + size_t *a_size; + kauth_cred_t a_cred; + }; */ *ap = v; + PUFFS_MSG_VARS(vn, getextattr); + struct vnode *vp = ap->a_vp; + struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); + int attrnamespace = ap->a_attrnamespace; + const char *name = ap->a_name; + struct uio *uio = ap->a_uio; + size_t *sizep = ap->a_size; + size_t tomove, resid; + int error; + + if (uio) + resid = uio->uio_resid; + else + resid = 0; + + tomove = PUFFS_TOMOVE(resid, pmp); + if (tomove != resid) { + error = E2BIG; + goto out; + } + + puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_getextattr) + tomove, + &park_getextattr, (void *)&getextattr_msg, 1); + + getextattr_msg->pvnr_attrnamespace = attrnamespace; + strlcpy(getextattr_msg->pvnr_attrname, name, + sizeof(getextattr_msg->pvnr_attrname)); + puffs_credcvt(&getextattr_msg->pvnr_cred, ap->a_cred); + if (sizep) + getextattr_msg->pvnr_datasize = 1; + getextattr_msg->pvnr_resid = tomove; + + puffs_msg_setinfo(park_getextattr, + PUFFSOP_VN, PUFFS_VN_GETEXTATTR, VPTOPNC(vp)); + puffs_msg_setdelta(park_getextattr, tomove); + PUFFS_MSG_ENQUEUEWAIT2(pmp, park_getextattr, vp->v_data, NULL, error); + + error = checkerr(pmp, error, __func__); + if (error) + goto out; + + resid = getextattr_msg->pvnr_resid; + if (resid > tomove) { + puffs_senderr(pmp, PUFFS_ERR_GETEXTATTR, E2BIG, + "resid grew", VPTOPNC(vp)); + error = EPROTO; + goto out; + } + + if (sizep) + *sizep = getextattr_msg->pvnr_datasize; + if (uio) + error = uiomove(getextattr_msg->pvnr_data, tomove - resid, uio); + + out: + PUFFS_MSG_RELEASE(getextattr); + return error; +} + +int +puffs_vnop_setextattr(void *v) +{ + struct vop_setextattr_args /* { + struct vnode *a_vp; + int a_attrnamespace; + const char *a_name; + struct uio *a_uio; + kauth_cred_t a_cred; + }; */ *ap = v; + PUFFS_MSG_VARS(vn, setextattr); + struct vnode *vp = ap->a_vp; + struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); + int attrnamespace = ap->a_attrnamespace; + const char *name = ap->a_name; + struct uio *uio = ap->a_uio; + size_t tomove, resid; + int error; + + if (uio) + resid = uio->uio_resid; + else + resid = 0; + + tomove = PUFFS_TOMOVE(resid, pmp); + if (tomove != resid) { + error = E2BIG; + goto out; + } + + puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_setextattr) + tomove, + &park_setextattr, (void *)&setextattr_msg, 1); + + setextattr_msg->pvnr_attrnamespace = attrnamespace; + strlcpy(setextattr_msg->pvnr_attrname, name, + sizeof(setextattr_msg->pvnr_attrname)); + puffs_credcvt(&setextattr_msg->pvnr_cred, ap->a_cred); + setextattr_msg->pvnr_resid = tomove; + + if (uio) { + error = uiomove(setextattr_msg->pvnr_data, tomove, uio); + if (error) + goto out; + } + + puffs_msg_setinfo(park_setextattr, + PUFFSOP_VN, PUFFS_VN_SETEXTATTR, VPTOPNC(vp)); + PUFFS_MSG_ENQUEUEWAIT2(pmp, park_setextattr, vp->v_data, NULL, error); + + error = checkerr(pmp, error, __func__); + if (error) + goto out; + + if (setextattr_msg->pvnr_resid != 0) + error = EIO; + + out: + PUFFS_MSG_RELEASE(setextattr); + + return error; +} + +int +puffs_vnop_listextattr(void *v) +{ + struct vop_listextattr_args /* { + struct vnode *a_vp; + int a_attrnamespace; + struct uio *a_uio; + size_t *a_size; + kauth_cred_t a_cred; + }; */ *ap = v; + PUFFS_MSG_VARS(vn, listextattr); + struct vnode *vp = ap->a_vp; + struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); + int attrnamespace = ap->a_attrnamespace; + struct uio *uio = ap->a_uio; + size_t *sizep = ap->a_size; + size_t tomove, resid; + int error; + + if (uio) + resid = uio->uio_resid; + else + resid = 0; + + tomove = PUFFS_TOMOVE(resid, pmp); + if (tomove != resid) { + error = E2BIG; + goto out; + } + + puffs_msgmem_alloc(sizeof(struct puffs_vnmsg_listextattr) + tomove, + &park_listextattr, (void *)&listextattr_msg, 1); + + listextattr_msg->pvnr_attrnamespace = attrnamespace; + puffs_credcvt(&listextattr_msg->pvnr_cred, ap->a_cred); + listextattr_msg->pvnr_resid = tomove; + if (sizep) + listextattr_msg->pvnr_datasize = 1; + + puffs_msg_setinfo(park_listextattr, + PUFFSOP_VN, PUFFS_VN_LISTEXTATTR, VPTOPNC(vp)); + puffs_msg_setdelta(park_listextattr, tomove); + PUFFS_MSG_ENQUEUEWAIT2(pmp, park_listextattr, vp->v_data, NULL, error); + + error = checkerr(pmp, error, __func__); + if (error) + goto out; + + resid = listextattr_msg->pvnr_resid; + if (resid > tomove) { + puffs_senderr(pmp, PUFFS_ERR_LISTEXTATTR, E2BIG, + "resid grew", VPTOPNC(vp)); + error = EPROTO; + goto out; + } + + if (sizep) + *sizep = listextattr_msg->pvnr_datasize; + if (uio) + error = uiomove(listextattr_msg->pvnr_data, tomove-resid, uio); + + out: + PUFFS_MSG_RELEASE(listextattr); + return error; +} + +int +puffs_vnop_deleteextattr(void *v) +{ + struct vop_deleteextattr_args /* { + struct vnode *a_vp; + int a_attrnamespace; + const char *a_name; + kauth_cred_t a_cred; + }; */ *ap = v; + PUFFS_MSG_VARS(vn, deleteextattr); + struct vnode *vp = ap->a_vp; + struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); + int attrnamespace = ap->a_attrnamespace; + const char *name = ap->a_name; + int error; + + PUFFS_MSG_ALLOC(vn, deleteextattr); + deleteextattr_msg->pvnr_attrnamespace = attrnamespace; + strlcpy(deleteextattr_msg->pvnr_attrname, name, + sizeof(deleteextattr_msg->pvnr_attrname)); + puffs_credcvt(&deleteextattr_msg->pvnr_cred, ap->a_cred); + + puffs_msg_setinfo(park_deleteextattr, + PUFFSOP_VN, PUFFS_VN_DELETEEXTATTR, VPTOPNC(vp)); + PUFFS_MSG_ENQUEUEWAIT2(pmp, park_deleteextattr, + vp->v_data, NULL, error); + + error = checkerr(pmp, error, __func__); + + PUFFS_MSG_RELEASE(deleteextattr); + return error; +} + +/* * spec & fifo. These call the miscfs spec and fifo vectors, but issue * FAF update information for the puffs node first. */