Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Nov 2003 11:20:08 -0800 (PST)
From:      Chris Vance <cvance@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 42151 for review
Message-ID:  <200311121920.hACJK8Tp010264@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <vfs/vfs_journal.h>
 
+#include <hfs/hfs_extattr.h>
 #include <hfs/hfs_format.h>
 #include <hfs/hfs_catalog.h>
 #include <hfs/hfs_cnode.h>
@@ -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 <sys/dirent.h>
 #include <sys/extattr.h>
 #include <sys/sysctl.h>
+#include <sys/ubc.h>
 
+#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) ====



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200311121920.hACJK8Tp010264>