On Tue, Jun 07, 2011 at 08:07:02AM +0000, Emmanuel Dreyfus wrote: [autocreate extended attribute backend] > Such a behavior could be triggered by a new kernel option such > as UFS_EXTATTR_AUTOCREATE. It could hold the default size for autocreated > attributes. (e.g.: options UFS_EXTATTR_AUTOCREATE=1024 to get 1024 bytes > long attributes).
Here is a patch that implements this option. Is it reasonable to commit it? Index: sys/ufs/ufs/ufs_extattr.c =================================================================== RCS file: /cvsroot/src/sys/ufs/ufs/ufs_extattr.c,v retrieving revision 1.29 diff -U4 -r1.29 ufs_extattr.c --- src/sys/ufs/ufs/ufs_extattr.c 10 May 2011 08:29:32 -0000 1.29 +++ src/sys/ufs/ufs/ufs_extattr.c 9 Jun 2011 16:32:12 -0000 @@ -146,8 +146,121 @@ return (0); return (1); } +#ifdef UFS_EXTATTR_AUTOCREATE +static struct ufs_extattr_list_entry *ufs_extattr_find_attr(struct ufsmount *, + int, const char *); +/* + * Autocreate an attribute storage + */ +static struct ufs_extattr_list_entry * +ufs_extattr_autocreate_attr(struct ufsmount *ump, int attrnamespace, + const char *attrname, struct lwp *l) +{ + struct vnode *backing_vp; + struct statvfs sbp; + struct pathbuf *pb; + struct nameidata nd; + char path[PATH_MAX + 1]; + struct ufs_extattr_fileheader uef; + int error; + + /* + * Get filesystem informations and root + */ + error = vfs_busy(ump->um_mountp, NULL); + if (error != 0) { + printf("%s: vfs_busy() returned %d\n", __func__, error); + return NULL; + } + + error = VFS_STATVFS(ump->um_mountp, &sbp); + vfs_unbusy(ump->um_mountp, false, NULL); + if (error != 0) { + printf("%s: VFS_STATVFS() returned %d\n", __func__, error); + return NULL; + } + + /* + * We only support system and user namespace autocreation + */ + switch (attrnamespace) { + case EXTATTR_NAMESPACE_SYSTEM: + (void)snprintf(path, PATH_MAX, "%s/%s/%s/%s", + sbp.f_mntonname, + UFS_EXTATTR_FSROOTSUBDIR, + UFS_EXTATTR_SUBDIR_SYSTEM, + attrname); + break; + case EXTATTR_NAMESPACE_USER: + (void)snprintf(path, PATH_MAX, "%s/%s/%s/%s", + sbp.f_mntonname, + UFS_EXTATTR_FSROOTSUBDIR, + UFS_EXTATTR_SUBDIR_USER, + attrname); + break; + default: + return NULL; + break; + } + + if ((pb = pathbuf_create(path)) == NULL) { + printf("%s: pathbuf_create(\"%s\") failed\n", __func__, path); + return NULL; + } + + NDINIT(&nd, CREATE, 0, pb); + + if ((error = vn_open(&nd, O_CREAT|O_RDWR, 0600)) != 0) { + pathbuf_destroy(pb); + return NULL; + } + + pathbuf_destroy(pb); + KASSERT(nd.ni_vp != NULL); + KASSERT(VOP_ISLOCKED(nd.ni_vp) == LK_EXCLUSIVE); + + /* + * backing_vp is the backing store. + */ + backing_vp = nd.ni_vp; + + uef.uef_magic = UFS_EXTATTR_MAGIC; + uef.uef_version = UFS_EXTATTR_VERSION; + uef.uef_size = UFS_EXTATTR_AUTOCREATE; + + error = vn_rdwr(UIO_WRITE, backing_vp, &uef, sizeof(uef), 0, + UIO_SYSSPACE, IO_NODELOCKED|IO_APPEND, + l->l_cred, NULL, l); + if (error != 0) { + printf("%s: write uef header failed for %s, error = %d\n", + __func__, attrname, error); + VOP_UNLOCK(nd.ni_vp); + vn_close(backing_vp, FREAD|FWRITE, l->l_cred); + return NULL; + } + + /* + * Now enable attribute. + */ + error = ufs_extattr_enable_with_open(ump, backing_vp, attrnamespace, + attrname, l); + KASSERT(VOP_ISLOCKED(backing_vp) == 0); + + if (error != 0) { + printf("%s: enable %s failed, error %d\n", + __func__, attrname, error); + vn_close(backing_vp, FREAD|FWRITE, l->l_cred); + return NULL; + } + + vn_close(backing_vp, FREAD|FWRITE, l->l_cred); + + return ufs_extattr_find_attr(ump, attrnamespace, attrname); +} +#endif /* UFS_EXTATTR_AUTOCREATE */ + /* * Locate an attribute given a name and mountpoint. * Must be holding uepm lock for the mount point. */ @@ -1060,10 +1173,18 @@ if (error) return (error); attribute = ufs_extattr_find_attr(ump, attrnamespace, name); - if (!attribute) + if (!attribute) { +#ifdef UFS_EXTATTR_AUTOCREATE + attribute = ufs_extattr_autocreate_attr(ump, attrnamespace, + name, l); + if (!attribute) + return (ENOATTR); +#else /* UFS_EXTATTR_AUTOCREATE */ return (ENOATTR); +#endif /* UFS_EXTATTR_AUTOCREATE */ + } /* * Early rejection of invalid offsets/length. * Reject: any offset but 0 (replace) -- Emmanuel Dreyfus m...@netbsd.org