Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/ufs Improve UFS1 extended attributes usability



details:   https://anonhg.NetBSD.org/src/rev/95f08a5dacf0
branches:  trunk
changeset: 766096:95f08a5dacf0
user:      manu <manu%NetBSD.org@localhost>
date:      Wed Jun 15 12:54:32 2011 +0000

description:
Improve UFS1 extended attributes usability
- autocreate attribute backing file for new attributes
- autoload attributes when issuing extattrctl start
- when autoloading attributes, do not display garbage warning when looking
up entries that got ENOENT

diffstat:

 sys/ufs/ufs/ufs_extattr.c |  167 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 160 insertions(+), 7 deletions(-)

diffs (232 lines):

diff -r 7261eed594cc -r 95f08a5dacf0 sys/ufs/ufs/ufs_extattr.c
--- a/sys/ufs/ufs/ufs_extattr.c Wed Jun 15 10:02:24 2011 +0000
+++ b/sys/ufs/ufs/ufs_extattr.c Wed Jun 15 12:54:32 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ufs_extattr.c,v 1.30 2011/06/12 03:36:02 rmind Exp $   */
+/*     $NetBSD: ufs_extattr.c,v 1.31 2011/06/15 12:54:32 manu Exp $    */
 
 /*-
  * Copyright (c) 1999-2002 Robert N. M. Watson
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.30 2011/06/12 03:36:02 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.31 2011/06/15 12:54:32 manu Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ffs.h"
@@ -99,6 +99,8 @@
                    struct lwp *l);
 static int     ufs_extattr_rm(struct vnode *vp, int attrnamespace,
                    const char *name, kauth_cred_t cred, struct lwp *l);
+static struct ufs_extattr_list_entry *ufs_extattr_find_attr(struct ufsmount *,
+                   int, const char *);
 
 /*
  * Per-FS attribute lock protecting attribute operations.
@@ -147,6 +149,142 @@
        return (1);
 }
 
+#ifdef UFS_EXTATTR_AUTOCREATE
+/*
+ * Autocreate an attribute storage
+ */
+static struct ufs_extattr_list_entry *
+ufs_extattr_autocreate_attr(struct vnode *vp, int attrnamespace,
+    const char *attrname, struct lwp *l)
+{
+       struct mount *mp = vp->v_mount;
+       struct ufsmount *ump = VFSTOUFS(mp);
+       struct vnode *backing_vp;
+       struct nameidata nd;
+       struct pathbuf *pb;
+       char *path;
+       struct ufs_extattr_fileheader uef;
+       struct ufs_extattr_list_entry *uele;
+       int error;
+
+       path = PNBUF_GET();
+
+       /* 
+        * We only support system and user namespace autocreation
+        */ 
+       switch (attrnamespace) {
+       case EXTATTR_NAMESPACE_SYSTEM:
+               (void)snprintf(path, PATH_MAX, "%s/%s/%s/%s", 
+                              mp->mnt_stat.f_mntonname,
+                              UFS_EXTATTR_FSROOTSUBDIR,
+                              UFS_EXTATTR_SUBDIR_SYSTEM,
+                              attrname);
+               break;
+       case EXTATTR_NAMESPACE_USER:
+               (void)snprintf(path, PATH_MAX, "%s/%s/%s/%s", 
+                              mp->mnt_stat.f_mntonname,
+                              UFS_EXTATTR_FSROOTSUBDIR,
+                              UFS_EXTATTR_SUBDIR_USER,
+                              attrname);
+               break;
+       default:
+               PNBUF_PUT(path);
+               return NULL;
+               break;
+       }
+
+       /*
+        * When setting attribute on the root vnode, we get it 
+        * already locked, and vn_open/namei/VFS_ROOT will try to
+        * look it, causing a panic. Unlock it first.
+        */ 
+       if (vp->v_vflag && VV_ROOT) {
+               KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+               VOP_UNLOCK(vp);
+       }
+       KASSERT(VOP_ISLOCKED(vp) == 0);
+
+       pb = pathbuf_create(path);
+       NDINIT(&nd, CREATE, LOCKPARENT, pb);
+       
+       error = vn_open(&nd, O_CREAT|O_RDWR, 0600);
+
+       /*
+        * Reacquire the lock on the vnode if it was root.
+        */
+       KASSERT(VOP_ISLOCKED(vp) == 0);
+       if (vp->v_vflag && VV_ROOT)
+               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+       KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+
+       if (error != 0) {
+               pathbuf_destroy(pb);
+               PNBUF_PUT(path);
+               return NULL;
+       }
+
+       KASSERT(nd.ni_vp != NULL);
+       KASSERT(VOP_ISLOCKED(nd.ni_vp) == LK_EXCLUSIVE);
+       KASSERT(VOP_ISLOCKED(nd.ni_dvp) == 0);
+
+       /*
+        * backing_vp is the backing store. 
+        */     
+       backing_vp = nd.ni_vp;
+       pathbuf_destroy(pb);
+       PNBUF_PUT(path);
+
+       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);
+
+       VOP_UNLOCK(backing_vp);
+
+       if (error != 0) {
+               printf("%s: write uef header failed for %s, error = %d\n", 
+                      __func__, attrname, error);
+               vn_close(backing_vp, FREAD|FWRITE, l->l_cred);
+               return NULL;
+       }
+
+       /*
+        * ufs_extattr_enable_with_open increases the vnode reference
+        * count. Not sure why, but do the same here.
+        */
+       vref(vp);
+
+       /*
+        * Now enable attribute. 
+        */
+       error = ufs_extattr_enable(ump,attrnamespace, attrname, backing_vp, 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;
+       }
+
+       uele = ufs_extattr_find_attr(ump, attrnamespace, attrname);
+       if (uele == NULL) {
+               printf("%s: atttribute %s created but not found!\n",
+                      __func__, attrname);
+               vn_close(backing_vp, FREAD|FWRITE, l->l_cred);
+               return NULL;
+       }
+
+       printf("%s: EA backing store autocreated for %s\n",
+              mp->mnt_stat.f_mntonname, attrname);
+
+       return uele;
+}
+#endif /* UFS_EXTATTR_AUTOCREATE */
+
 /*
  * Locate an attribute given a name and mountpoint.
  * Must be holding uepm lock for the mount point.
@@ -354,6 +492,7 @@
     int attrnamespace, struct lwp *l)
 {
        struct vop_readdir_args vargs;
+       struct statvfs *sbp = &ump->um_mountp->mnt_stat;
        struct dirent *dp, *edp;
        struct vnode *attr_vp;
        struct uio auio;
@@ -408,7 +547,9 @@
                                goto next;
                        error = ufs_extattr_lookup(dvp, LOCKPARENT,
                            dp->d_name, &attr_vp, l);
-                       if (error) {
+                       if (error == ENOENT) {
+                               goto next; /* keep silent */
+                       } else if (error) {
                                printf("ufs_extattr_iterate_directory: lookup "
                                    "%s %d\n", dp->d_name, error);
                        } else if (attr_vp == dvp) {
@@ -423,9 +564,9 @@
                                        printf("ufs_extattr_iterate_directory: "
                                            "enable %s %d\n", dp->d_name,
                                            error);
-                               } else if (1 || bootverbose) {
-                                       printf("UFS autostarted EA %s\n",
-                                           dp->d_name);
+                               } else if (bootverbose) {
+                                       printf("%s: EA %s loaded\n",
+                                              sbp->f_mntonname, dp->d_name);
                                }
                        }
  next:
@@ -738,7 +879,11 @@
                if (attrname != NULL)
                        return (EINVAL);
 
+#ifdef UFS_EXTATTR_AUTOSTART
+               error = ufs_extattr_autostart(mp, l);
+#else
                error = ufs_extattr_start(mp, l);
+#endif
                return (error);
                
        case UFS_EXTATTR_CMD_STOP:
@@ -1061,8 +1206,16 @@
                return (error);
 
        attribute = ufs_extattr_find_attr(ump, attrnamespace, name);
-       if (!attribute)
+       if (!attribute) {
+#ifdef UFS_EXTATTR_AUTOCREATE
+               attribute =  ufs_extattr_autocreate_attr(vp, attrnamespace, 
+                                                        name, l);
+               if  (!attribute)
+                       return (ENOATTR);
+#else /* UFS_EXTATTR_AUTOCREATE */
                return (ENOATTR);
+#endif /* UFS_EXTATTR_AUTOCREATE */
+       }
 
        /*
         * Early rejection of invalid offsets/length.



Home | Main Index | Thread Index | Old Index