tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: extended attributes
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
manu%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index