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