From owner-p4-projects@FreeBSD.ORG Wed Nov 12 11:20:12 2003 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 805A916A4D0; Wed, 12 Nov 2003 11:20:12 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 59B3816A4CE for ; Wed, 12 Nov 2003 11:20:12 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3073243F85 for ; Wed, 12 Nov 2003 11:20:11 -0800 (PST) (envelope-from cvance@nailabs.com) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.9/8.12.9) with ESMTP id hACJKBXJ010267 for ; Wed, 12 Nov 2003 11:20:11 -0800 (PST) (envelope-from cvance@nailabs.com) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.9/8.12.9/Submit) id hACJK8Tp010264 for perforce@freebsd.org; Wed, 12 Nov 2003 11:20:08 -0800 (PST) (envelope-from cvance@nailabs.com) Date: Wed, 12 Nov 2003 11:20:08 -0800 (PST) Message-Id: <200311121920.hACJK8Tp010264@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to cvance@nailabs.com using -f From: Chris Vance To: Perforce Change Reviews Subject: PERFORCE change 42151 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Nov 2003 19:20:12 -0000 http://perforce.freebsd.org/chv.cgi?CH=42151 Change 42151 by cvance@cvance_osx_laptop on 2003/11/12 11:20:04 Come another step closer to HFS extended attributes mostly by removing '#if 0' from the extattr hfs syscall implementations (except extattrctl) and adding autostart code and supporting functions This code is mostly untested. All I'll promise is that it won't hurt you if you don't run it. Certainly don't create .attribute directories/backing files and expect the autostart to do anything other than panic. Affected files ... .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs.h#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_extattr.c#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_extattr.h#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_vfsops.c#2 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_vnops.c#3 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/sys/malloc.h#6 edit .. //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/vfs/vfs_syscalls.c#9 edit Differences ... ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs.h#2 (text+ko) ==== @@ -38,6 +38,7 @@ #include +#include #include #include #include @@ -177,6 +178,7 @@ } vfsVCB_t; +struct hfs_extattr_per_mount hfs_extattr; /* This structure describes the HFS specific mount structure data. */ typedef struct hfsmount { @@ -206,6 +208,9 @@ /* simple lock for shared meta renaming */ simple_lock_data_t hfs_renamelock; + /* extended attributes */ + struct hfs_extattr_per_mount hfs_extattr; + /* HFS Specific */ struct vfsVCB hfs_vcb; struct cat_desc hfs_privdir_desc; ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_extattr.c#2 (text+ko) ==== @@ -52,11 +52,579 @@ #include #include #include +#include +#include "hfs_extattr.h" +#include "hfs.h" #ifdef HFS_EXTATTR /* + * Lock functions copied/ported From FreeBSD 5.1, including comments... + * + * Per-FS attribute lock protecting attribute operations. + * XXX Right now there is a lot of lock contention due to having a single + * lock per-FS; really, this should be far more fine-grained. + */ +static void +hfs_extattr_uepm_lock(struct hfsmount *hfsmp, struct proc *p) +{ + + /* Ideally, LK_CANRECURSE would not be used, here. */ + lockmgr(&hfsmp->hfs_extattr.uepm_lock, LK_EXCLUSIVE | LK_RETRY | + LK_CANRECURSE, 0, p); +} + +static void +hfs_extattr_uepm_unlock(struct hfsmount *hfsmp, struct proc *p) +{ + + lockmgr(&hfsmp->hfs_extattr.uepm_lock, LK_RELEASE, 0, p); +} + +/* + * Determine whether the name passed is a valid name for an actual + * attribute. + * + * Invalid currently consists of: + * NULL pointer for attrname + * zero-length attrname (used to retrieve application attribute list) + */ +static int +hfs_extattr_valid_attrname(int attrnamespace, const char *attrname) +{ + + if (attrname == NULL) + return (0); + if (strlen(attrname) == 0) + return (0); + return (1); +} + +/* + * Locate an attribute given a name and mountpoint. + * Must be holding uepm lock for the mount point. + */ +static struct hfs_extattr_list_entry * +hfs_extattr_find_attr(struct hfsmount *hfsmp, int attrnamespace, + const char *attrname) +{ + struct hfs_extattr_list_entry *search_attribute; + + for (search_attribute = LIST_FIRST(&hfsmp->hfs_extattr.uepm_list); + search_attribute; + search_attribute = LIST_NEXT(search_attribute, uele_entries)) { + if (!(strncmp(attrname, search_attribute->uele_attrname, + HFS_EXTATTR_MAXEXTATTRNAME)) && + (attrnamespace == search_attribute->uele_attrnamespace)) { + return (search_attribute); + } + } + + return (0); +} + + +/* + * Destroy per-FS structures supporting extended attributes. Assumes + * that EAs have already been stopped, and will panic if not. + */ +void +hfs_extattr_uepm_destroy(struct hfs_extattr_per_mount *uepm, struct proc *p) +{ + + if (!(uepm->uepm_flags & HFS_EXTATTR_UEPM_INITIALIZED)) + panic("hfs_extattr_uepm_destroy: not initialized"); + + if ((uepm->uepm_flags & HFS_EXTATTR_UEPM_STARTED)) + panic("Hfs_extattr_uepm_destroy: called while still started"); + + simple_lock(&mountlist_slock); + uepm->uepm_flags &= ~HFS_EXTATTR_UEPM_INITIALIZED; + lockmgr(&uepm->uepm_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, + &mountlist_slock, p); +} + +/* + * Start extended attribute support on an FS. + */ +int +hfs_extattr_start(struct mount *mp, struct proc *p) +{ + struct hfsmount *hfsmp = VFSTOHFS(mp); + int error = 0; + + hfs_extattr_uepm_lock(hfsmp, p); + + if (!(hfsmp->hfs_extattr.uepm_flags & HFS_EXTATTR_UEPM_INITIALIZED)) { + error = EOPNOTSUPP; + goto unlock; + } + if (hfsmp->hfs_extattr.uepm_flags & HFS_EXTATTR_UEPM_STARTED) { + error = EBUSY; + goto unlock; + } + + hfsmp->hfs_extattr.uepm_flags |= HFS_EXTATTR_UEPM_STARTED; + crhold(p->p_ucred); + hfsmp->hfs_extattr.uepm_ucred = p->p_ucred; + + unlock: + hfs_extattr_uepm_unlock(hfsmp, p); + + return (error); +} + +/* + * Helper routine: given a locked parent directory and filename, return + * the locked vnode of the inode associated with the name. Will not + * follow symlinks, may return any type of vnode. Lock on parent will + * be released even in the event of a failure. In the event that the + * target is the parent (i.e., "."), there will be two references and + * one lock, requiring the caller to possibly special-case. + */ +#define UE_GETDIR_LOCKPARENT 1 +#define UE_GETDIR_LOCKPARENT_DONT 2 +static int +hfs_extattr_lookup(struct vnode *start_dvp, int lockparent, char *dirname, + struct vnode **vp, struct proc *p) +{ + struct vop_cachedlookup_args vargs; + struct componentname cnp; + struct vnode *target_vp; + int error; + + bzero(&cnp, sizeof(cnp)); + cnp.cn_nameiop = LOOKUP; + cnp.cn_flags = ISLASTCN; + if (lockparent == UE_GETDIR_LOCKPARENT) + cnp.cn_flags |= LOCKPARENT; + cnp.cn_proc = p; + cnp.cn_cred = p->p_ucred; + MALLOC_ZONE(cnp.cn_pnbuf, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK); + cnp.cn_pnlen = MAXPATHLEN; + cnp.cn_nameptr = cnp.cn_pnbuf; + error = copystr(dirname, cnp.cn_pnbuf, MAXPATHLEN, + (size_t *) &cnp.cn_namelen); + if (error) { + if (lockparent == UE_GETDIR_LOCKPARENT_DONT) { + VOP_UNLOCK(start_dvp, 0, p); + } + _FREE_ZONE(cnp.cn_pnbuf, cnp.cn_pnlen, M_NAMEI); + printf("hfs_extattr_lookup: copystr failed\n"); + return (error); + } + cnp.cn_namelen--; /* trim nul termination */ + vargs.a_desc = NULL; + vargs.a_dvp = start_dvp; + vargs.a_vpp = &target_vp; + vargs.a_cnp = &cnp; + error = hfs_lookup(&vargs); + _FREE_ZONE(cnp.cn_pnbuf, cnp.cn_pnlen, M_NAMEI); + if (error) { + /* + * Error condition, may have to release the lock on the parent + * if hfs_lookup() didn't. + */ + if (lockparent == UE_GETDIR_LOCKPARENT_DONT) + VOP_UNLOCK(start_dvp, 0, p); + + /* + * Check that hfs_lookup() didn't release the lock when we + * didn't want it to. + */ + if (lockparent == UE_GETDIR_LOCKPARENT) + panic("hfs_extattr_lookup: lockparent but PDIRUNLOCK"); + + return (error); + } +/* + if (target_vp == start_dvp) + panic("hfs_extattr_lookup: target_vp == start_dvp"); +*/ + + if (target_vp != start_dvp && + (lockparent == UE_GETDIR_LOCKPARENT_DONT)) + panic("hfs_extattr_lookup: !lockparent but !PDIRUNLOCK"); + + if (lockparent == UE_GETDIR_LOCKPARENT) + panic("hfs_extattr_lookup: lockparent but PDIRUNLOCK"); + + /* printf("hfs_extattr_lookup: success\n"); */ + *vp = target_vp; + return (0); +} + +/* + * Enable a named attribute on the specified filesystem; provide an + * unlocked backing vnode to hold the attribute data. + */ +static int +hfs_extattr_enable(struct hfsmount *hfsmp, int attrnamespace, + const char *attrname, struct vnode *backing_vnode, struct proc *p) +{ + struct hfs_extattr_list_entry *attribute; + struct iovec aiov; + struct uio auio; + int error = 0; + + if (!hfs_extattr_valid_attrname(attrnamespace, attrname)) + return (EINVAL); + if (backing_vnode->v_type != VREG) + return (EINVAL); + + MALLOC(attribute, struct hfs_extattr_list_entry *, + sizeof(struct hfs_extattr_list_entry), M_EXTATTR, M_WAITOK); + if (attribute == NULL) + return (ENOMEM); + + if (!(hfsmp->hfs_extattr.uepm_flags & HFS_EXTATTR_UEPM_STARTED)) { + error = ENOTSUP; + goto free_exit; + } + + if (hfs_extattr_find_attr(hfsmp, attrnamespace, attrname)) { + error = EEXIST; + goto free_exit; + } + + strncpy(attribute->uele_attrname, attrname, + HFS_EXTATTR_MAXEXTATTRNAME); + attribute->uele_attrnamespace = attrnamespace; + bzero(&attribute->uele_fileheader, + sizeof(struct hfs_extattr_fileheader)); + + attribute->uele_backing_vnode = backing_vnode; + + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = (caddr_t) &attribute->uele_fileheader; + aiov.iov_len = sizeof(struct hfs_extattr_fileheader); + auio.uio_resid = sizeof(struct hfs_extattr_fileheader); + auio.uio_offset = (off_t) 0; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_procp = p; + + VOP_LEASE(backing_vnode, p, p->p_ucred, LEASE_WRITE); + vn_lock(backing_vnode, LK_SHARED | LK_RETRY, p); + error = VOP_READ(backing_vnode, &auio, IO_NODELOCKED, + hfsmp->hfs_extattr.uepm_ucred); + + if (error) + goto unlock_free_exit; + + if (auio.uio_resid != 0) { + printf("hfs_extattr_enable: malformed attribute header\n"); + error = EINVAL; + goto unlock_free_exit; + } + + if (attribute->uele_fileheader.uef_magic != HFS_EXTATTR_MAGIC) { + printf("hfs_extattr_enable: invalid attribute header magic\n"); + error = EINVAL; + goto unlock_free_exit; + } + + if (attribute->uele_fileheader.uef_version != HFS_EXTATTR_VERSION) { + printf("hfs_extattr_enable: incorrect attribute header " + "version\n"); + error = EINVAL; + goto unlock_free_exit; + } + + backing_vnode->v_flag |= VSYSTEM; + LIST_INSERT_HEAD(&hfsmp->hfs_extattr.uepm_list, attribute, + uele_entries); + + VOP_UNLOCK(backing_vnode, 0, p); + return (0); + +unlock_free_exit: + VOP_UNLOCK(backing_vnode, 0, p); + +free_exit: + FREE(attribute, M_EXTATTR); + return (error); +} + +/* + * Enable an EA using the passed filesystem, backing vnode, attribute name, + * namespace, and proc. Will perform a VOP_OPEN() on the vp, so expects vp + * to be locked when passed in. The vnode will be returned unlocked, + * regardless of success/failure of the function. As a result, the caller + * will always need to vrele(), but not vput(). + */ +static int +hfs_extattr_enable_with_open(struct hfsmount *hfsmp, struct vnode *vp, + int attrnamespace, const char *attrname, struct proc *p) +{ + int error; + + if (UBCINFOEXISTS(vp) && !ubc_hold(vp)) { + error = ENOENT; + VOP_UNLOCK(vp, 0, p); + return error; + } + + error = VOP_OPEN(vp, FREAD|FWRITE, p->p_ucred, p); + if (error) { + ubc_rele(vp); + printf("hfs_extattr_enable_with_open.VOP_OPEN(): failed " + "with %d\n", error); + VOP_UNLOCK(vp, 0, p); + return (error); + } + + if(++vp->v_writecount <= 0) + panic("hfs_extattr_enable_with_open:v_writecount"); + + vref(vp); + + VOP_UNLOCK(vp, 0, p); + + error = hfs_extattr_enable(hfsmp, attrnamespace, attrname, vp, p); + if (error != 0) + vn_close(vp, FREAD|FWRITE, p->p_ucred, p); + return (error); +} + +/* + * Given a locked directory vnode, iterate over the names in the directory + * and use hfs_extattr_lookup() to retrieve locked vnodes of potential + * attribute files. Then invoke hfs_extattr_enable_with_open() on each + * to attempt to start the attribute. Leaves the directory locked on + * exit. + */ + +/* + * Defining DIRBLKSIZ as the same value as ufs can't possibly be right + * reading the comments prior to hfs_readdir() shows the confusion. + */ +#define DIRBLKSIZ 1024 +static int +hfs_extattr_iterate_directory(struct hfsmount *hfsmp, struct vnode *dvp, + int attrnamespace, struct proc *p) +{ + struct vop_readdir_args vargs; + struct dirent *dp, *edp; + struct vnode *attr_vp; + struct uio auio; + struct iovec aiov; + char *dirbuf; + int error, eofflag = 0; + + if (dvp->v_type != VDIR) + return (ENOTDIR); + + MALLOC(dirbuf, char *, DIRBLKSIZ, M_TEMP, M_WAITOK); + + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_procp = p; + auio.uio_offset = 0; + + vargs.a_desc = NULL; + vargs.a_vp = dvp; + vargs.a_uio = &auio; + vargs.a_cred = p->p_ucred; + vargs.a_eofflag = &eofflag; + vargs.a_ncookies = NULL; + vargs.a_cookies = NULL; + + while (!eofflag) { + auio.uio_resid = DIRBLKSIZ; + aiov.iov_base = dirbuf; + aiov.iov_len = DIRBLKSIZ; + error = hfs_readdir(&vargs); + if (error) { + printf("hfs_extattr_iterate_directory: hfs_readdir " + "%d\n", error); + return (error); + } + + edp = (struct dirent *)&dirbuf[DIRBLKSIZ]; + for (dp = (struct dirent *)dirbuf; dp < edp; ) { +#if (BYTE_ORDER == LITTLE_ENDIAN) + dp->d_type = dp->d_namlen; + dp->d_namlen = 0; +#else + dp->d_type = 0; +#endif + if (dp->d_reclen == 0) + break; + error = hfs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT, + dp->d_name, &attr_vp, p); + if (error) { + printf("hfs_extattr_iterate_directory: lookup " + "%s %d\n", dp->d_name, error); + } else if (attr_vp == dvp) { + vrele(attr_vp); + } else if (attr_vp->v_type != VREG) { + vput(attr_vp); + } else { + error = hfs_extattr_enable_with_open(hfsmp, + attr_vp, attrnamespace, dp->d_name, p); + vrele(attr_vp); + if (error) { + printf("hfs_extattr_iterate_directory: " + "enable %s %d\n", dp->d_name, + error); + } else { + printf("HFS autostarted EA %s\n", + dp->d_name); + } + } + dp = (struct dirent *) ((char *)dp + dp->d_reclen); + if (dp >= edp) + break; + } + } + FREE(dirbuf, M_TEMP); + + return (0); +} + + +/* + * Auto-start of extended attributes, to be executed (optionally) at + * mount-time. + */ +int +hfs_extattr_autostart(struct mount *mp, struct proc *p) +{ + + printf("hfs_extattr_autostart called\n"); + struct vnode *rvp, *attr_dvp, *attr_system_dvp, *attr_user_dvp; + int error; + + /* + * Does HFS_EXTATTR_FSROOTSUBDIR exist off the filesystem root? + * If so, automatically start EA's. + */ + error = VFS_ROOT(mp, &rvp); + if (error) { + printf("hfs_extattr_autostart.VFS_ROOT() returned %d\n", + error); + return (error); + } + + error = hfs_extattr_lookup(rvp, UE_GETDIR_LOCKPARENT_DONT, + HFS_EXTATTR_FSROOTSUBDIR, &attr_dvp, p); + if (error) { + /* rvp ref'd but now unlocked */ + vrele(rvp); + return (error); + } + if (rvp == attr_dvp) { + /* Should never happen. */ + vrele(attr_dvp); + vput(rvp); + return (EINVAL); + } + vrele(rvp); + + if (attr_dvp->v_type != VDIR) { + printf("hfs_extattr_autostart: %s != VDIR\n", + HFS_EXTATTR_FSROOTSUBDIR); + goto return_vput_attr_dvp; + } + + error = hfs_extattr_start(mp, p); + if (error) { + printf("hfs_extattr_autostart: hfs_extattr_start failed (%d)\n", + error); + goto return_vput_attr_dvp; + } + + /* + * Look for two subdirectories: HFS_EXTATTR_SUBDIR_SYSTEM, + * HFS_EXTATTR_SUBDIR_USER. For each, iterate over the sub-directory, + * and start with appropriate type. Failures in either don't + * result in an over-all failure. attr_dvp is left locked to + * be cleaned up on exit. + */ + error = hfs_extattr_lookup(attr_dvp, UE_GETDIR_LOCKPARENT, + HFS_EXTATTR_SUBDIR_SYSTEM, &attr_system_dvp, p); + if (!error) { + error = hfs_extattr_iterate_directory(VFSTOHFS(mp), + attr_system_dvp, EXTATTR_NAMESPACE_SYSTEM, p); + if (error) + printf("hfs_extattr_iterate_directory returned %d\n", + error); + vput(attr_system_dvp); + } + + error = hfs_extattr_lookup(attr_dvp, UE_GETDIR_LOCKPARENT, + HFS_EXTATTR_SUBDIR_USER, &attr_user_dvp, p); + if (!error) { + error = hfs_extattr_iterate_directory(VFSTOHFS(mp), + attr_user_dvp, EXTATTR_NAMESPACE_USER, p); + if (error) + printf("hfs_extattr_iterate_directory returned %d\n", + error); + vput(attr_user_dvp); + } + + /* Mask startup failures in sub-directories. */ + error = 0; + +return_vput_attr_dvp: + vput(attr_dvp); + + return (error); +} + +/* + * Stop extended attribute support on an FS. + */ +int +hfs_extattr_stop(struct mount *mp, struct proc *p) +{ + + printf("hfs_extattr_stop called\n"); + return (0); +} + +/* + * Real work associated with retrieving a named attribute--assumes that + * the attribute lock has already been grabbed. + */ +static int +hfs_extattr_get(struct vnode *vp, int attrnamespace, const char *name, + struct uio *uio, size_t *size, struct ucred *cred, struct proc *p) +{ + + return (ENOTSUP); +} + +/* + * Real work associated with setting a vnode's extended attributes; + * assumes that the attribute lock has already been grabbed. + */ +static int +hfs_extattr_set(struct vnode *vp, int attrnamespace, const char *name, + struct uio *uio, struct ucred *cred, struct proc *p) +{ + + return (ENOTSUP); +} + +/* + * Real work associated with removing an extended attribute from a vnode. + * Assumes the attribute lock has already been grabbed. + */ +static int +hfs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name, + struct ucred *cred, struct proc *p) +{ + + return (ENOTSUP); +} + +/* * Vnode operating to retrieve a named extended attribute. */ int @@ -73,22 +641,20 @@ }; */ { - printf("hfs_getextattr called\n"); - return (ENOTSUP); -#if 0 struct mount *mp = ap->a_vp->v_mount; - struct ufsmount *ump = VFSTOUFS(mp); + struct hfsmount *hfsmp = VTOHFS(ap->a_vp); int error; - hfs_extattr_uepm_lock(ump, ap->a_td); + printf("hfs_getextattr called\n"); + + hfs_extattr_uepm_lock(hfsmp, ap->a_p); error = hfs_extattr_get(ap->a_vp, ap->a_attrnamespace, ap->a_name, - ap->a_uio, ap->a_size, ap->a_cred, ap->a_td); + ap->a_uio, ap->a_size, ap->a_cred, ap->a_p); - hfs_extattr_uepm_unlock(ump, ap->a_td); + hfs_extattr_uepm_unlock(hfsmp, ap->a_p); return (error); -#endif } /* @@ -107,15 +673,13 @@ }; */ { - printf("hfs_setextattr called\n"); - return (ENOTSUP); -#if 0 struct mount *mp = ap->a_vp->v_mount; - struct ufsmount *ump = VFSTOUFS(mp); + struct hfsmount *hfsmp = VTOHFS(ap->a_vp); int error; - hfs_extattr_uepm_lock(ump, ap->a_td); + printf("hfs_setextattr called\n"); + hfs_extattr_uepm_lock(hfsmp, ap->a_p); /* * XXX: No longer a supported way to delete extended attributes. @@ -124,12 +688,11 @@ return (EINVAL); error = hfs_extattr_set(ap->a_vp, ap->a_attrnamespace, ap->a_name, - ap->a_uio, ap->a_cred, ap->a_td); + ap->a_uio, ap->a_cred, ap->a_p); - hfs_extattr_uepm_unlock(ump, ap->a_td); + hfs_extattr_uepm_unlock(hfsmp, ap->a_p); return (error); -#endif } /* @@ -147,24 +710,22 @@ }; */ { - printf("hfs_deleteextattr called\n"); - return (ENOTSUP); -#if 0 struct mount *mp = ap->a_vp->v_mount; - struct ufsmount *ump = VFSTOUFS(mp); + struct hfsmount *hfsmp = VTOHFS(ap->a_vp); int error; - hfs_extattr_uepm_lock(ump, ap->a_td); + printf("hfs_deleteextattr called\n"); + hfs_extattr_uepm_lock(hfsmp, ap->a_p); error = hfs_extattr_rm(ap->a_vp, ap->a_attrnamespace, ap->a_name, - ap->a_cred, ap->a_td); + ap->a_cred, ap->a_p); - hfs_extattr_uepm_unlock(ump, ap->a_td); + hfs_extattr_uepm_unlock(hfsmp, ap->a_p); return (error); -#endif } + #endif /* !HFS_EXTATTR */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_extattr.h#2 (text+ko) ==== @@ -68,7 +68,7 @@ /* data follows the header */ }; -#ifdef _KERNEL +#ifdef KERNEL #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_EXTATTR); @@ -84,17 +84,19 @@ struct vnode *uele_backing_vnode; }; +struct lock__bsd__; struct lock; struct ucred; struct hfs_extattr_per_mount { - struct lock uepm_lock; + struct lock__bsd__ uepm_lock; struct hfs_extattr_list_head uepm_list; struct ucred *uepm_ucred; int uepm_flags; }; void hfs_extattr_uepm_init(struct hfs_extattr_per_mount *uepm); -void hfs_extattr_uepm_destroy(struct hfs_extattr_per_mount *uepm); +void hfs_extattr_uepm_destroy(struct hfs_extattr_per_mount *uepm, + struct proc *p); int hfs_extattr_start(struct mount *mp, struct proc *p); int hfs_extattr_autostart(struct mount *mp, struct proc *p); int hfs_extattr_stop(struct mount *mp, struct proc *p); @@ -105,6 +107,6 @@ int hfs_setextattr(struct vop_setextattr_args *ap); void hfs_extattr_vnode_inactive(struct vnode *vp, struct proc *p); -#endif /* !_KERNEL */ +#endif /* !KERNEL */ #endif /* !_HFS_HFS_EXTATTR_H_ */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_vfsops.c#2 (text+ko) ==== @@ -88,6 +88,7 @@ #include "hfs_cnode.h" #include "hfs_dbg.h" #include "hfs_endian.h" +#include "hfs_extattr.h" #include "hfs_quota.h" #include "hfscommon/headers/FileMgrInternal.h" @@ -1151,6 +1152,20 @@ (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT, 0); } FREE(mdbp, M_TEMP); + +#ifdef HFS_EXTATTR + /* + * + * Auto-starting does the following: + * - check for /.attribute in the fs, and extattr_start if so + * - for each file in .attribute, enable that file with + * an attribute of the same name. + * Not clear how to report errors -- probably eat them. + * This would all happen while the filesystem was busy/not + * available, so would effectively be "atomic". + */ + (void) hfs_extattr_autostart(mp, p); +#endif /* !HFS_EXTATTR */ return (0); error_exit: @@ -1208,6 +1223,16 @@ force = 1; } +#ifdef UFS_EXTATTR + if ((error = hfs_extattr_stop(mp, p))) { + if (error != ENOTSUP) + printf("hfs_unmount: hfs_extattr_stop returned %d\n", + error); + } else { + hfs_extattr_uepm_destroy(&hfsmp->hfs_extattr, p); + } +#endif + if ((retval = hfs_flushfiles(mp, flags, p)) && !force) return (retval); ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/hfs/hfs_vnops.c#3 (text+ko) ==== @@ -2547,7 +2547,7 @@ OUT int *ncookies; INOUT u_long **cookies; */ -static int +int hfs_readdir(ap) struct vop_readdir_args /* { struct vnode *vp; ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/sys/malloc.h#6 (text+ko) ==== @@ -170,7 +170,7 @@ #define M_MACPIPELABEL 93 #define M_MACTEMP 94 #define M_SBUF 95 -#define M_HFS_EXTATTR 96 +#define M_EXTATTR 96 #define M_LAST 97 /* Must be last type + 1 */ /* Strings corresponding to types of memory */ ==== //depot/projects/trustedbsd/sedarwin/apsl/xnu/bsd/vfs/vfs_syscalls.c#9 (text+ko) ====