Whamcloud - gitweb
LU-12631 llite: report latency for filesystem ops
[fs/lustre-release.git] / lustre / llite / xattr.c
index 243219b..6cfad04 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/xattr.h>
+#ifdef HAVE_LINUX_SELINUX_IS_ENABLED
 #include <linux/selinux.h>
+#endif
 
 #define DEBUG_SUBSYSTEM S_LLITE
 
 #include <obd_support.h>
 #include <lustre_dlm.h>
-#include <lustre_ver.h>
 #include <lustre_eacl.h>
+#include <lustre_swab.h>
 
 #include "llite_internal.h"
 
+#ifndef HAVE_XATTR_HANDLER_NAME
+static inline const char *xattr_prefix(const struct xattr_handler *handler)
+{
+       return handler->prefix;
+}
+#endif
+
+#ifdef HAVE_LINUX_SELINUX_IS_ENABLED
+# define test_xattr_is_selinux_disabled(handler, name) \
+               ((handler)->flags == XATTR_SECURITY_T && \
+               !selinux_is_enabled() && \
+               strcmp((name), "selinux") == 0)
+#else
+# define test_xattr_is_selinux_disabled(handler, name) \
+               ((handler)->flags == XATTR_SECURITY_T && \
+               strcmp((name), "selinux") == 0)
+#endif
+
 const struct xattr_handler *get_xattr_type(const char *name)
 {
-       int i = 0;
+       int i;
 
-       while (ll_xattr_handlers[i]) {
-               size_t len = strlen(ll_xattr_handlers[i]->prefix);
+       for (i = 0; ll_xattr_handlers[i]; i++) {
+               const char *prefix = xattr_prefix(ll_xattr_handlers[i]);
+               size_t prefix_len = strlen(prefix);
 
-               if (!strncmp(ll_xattr_handlers[i]->prefix, name, len))
+               if (!strncmp(prefix, name, prefix_len))
                        return ll_xattr_handlers[i];
-               i++;
        }
+
        return NULL;
 }
 
@@ -91,17 +112,18 @@ static int ll_xattr_set_common(const struct xattr_handler *handler,
        struct ptlrpc_request *req = NULL;
        const char *pv = value;
        char *fullname;
+       ktime_t kstart = ktime_get();
        u64 valid;
        int rc;
        ENTRY;
 
-       if (flags == XATTR_REPLACE) {
-               ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_REMOVEXATTR, 1);
+       /* When setxattr() is called with a size of 0 the value is
+        * unconditionally replaced by "". When removexattr() is
+        * called we get a NULL value and XATTR_REPLACE for flags. */
+       if (!value && flags == XATTR_REPLACE)
                valid = OBD_MD_FLXATTRRM;
-       } else {
-               ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_SETXATTR, 1);
+       else
                valid = OBD_MD_FLXATTR;
-       }
 
        /* FIXME: enable IMA when the conditions are ready */
        if (handler->flags == XATTR_SECURITY_T &&
@@ -114,11 +136,7 @@ static int ll_xattr_set_common(const struct xattr_handler *handler,
 
        if ((handler->flags == XATTR_ACL_ACCESS_T ||
             handler->flags == XATTR_ACL_DEFAULT_T) &&
-#ifdef HAVE_INODE_OWNER_OR_CAPABLE
            !inode_owner_or_capable(inode))
-#else
-           !is_owner_or_cap(inode))
-#endif
                RETURN(-EPERM);
 
        /* b10667: ignore lustre special xattr for now */
@@ -128,8 +146,7 @@ static int ll_xattr_set_common(const struct xattr_handler *handler,
                RETURN(0);
 
        /* LU-549:  Disable security.selinux when selinux is disabled */
-       if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() &&
-           strcmp(name, "selinux") == 0)
+       if (test_xattr_is_selinux_disabled(handler, name))
                RETURN(-EOPNOTSUPP);
 
        /*
@@ -141,22 +158,27 @@ static int ll_xattr_set_common(const struct xattr_handler *handler,
                        RETURN(-EPERM);
        }
 
-       fullname = kasprintf(GFP_KERNEL, "%s%s", handler->prefix, name);
+       fullname = kasprintf(GFP_KERNEL, "%s%s", xattr_prefix(handler), name);
        if (!fullname)
                RETURN(-ENOMEM);
 
        rc = md_setxattr(sbi->ll_md_exp, ll_inode2fid(inode), valid, fullname,
-                        pv, size, 0, flags, ll_i2suppgid(inode), &req);
+                        pv, size, flags, ll_i2suppgid(inode), &req);
        kfree(fullname);
        if (rc) {
                if (rc == -EOPNOTSUPP && handler->flags == XATTR_USER_T) {
                        LCONSOLE_INFO("Disabling user_xattr feature because it is not supported on the server\n");
-                        sbi->ll_flags &= ~LL_SBI_USER_XATTR;
-                }
+                       sbi->ll_flags &= ~LL_SBI_USER_XATTR;
+               }
                RETURN(rc);
-        }
+       }
+
+       ptlrpc_req_finished(req);
+
+       ll_stats_ops_tally(ll_i2sbi(inode), valid == OBD_MD_FLXATTRRM ?
+                               LPROC_LL_REMOVEXATTR : LPROC_LL_SETXATTR,
+                          ktime_us_delta(ktime_get(), kstart));
 
-        ptlrpc_req_finished(req);
        RETURN(0);
 }
 
@@ -300,6 +322,11 @@ static int ll_xattr_set(const struct xattr_handler *handler,
                        const char *name, const void *value, size_t size,
                        int flags)
 {
+       ktime_t kstart = ktime_get();
+       int op_type = flags == XATTR_REPLACE ? LPROC_LL_REMOVEXATTR :
+                                              LPROC_LL_SETXATTR;
+       int rc;
+
        LASSERT(inode);
        LASSERT(name);
 
@@ -308,21 +335,22 @@ static int ll_xattr_set(const struct xattr_handler *handler,
 
        /* lustre/trusted.lov.xxx would be passed through xattr API */
        if (!strcmp(name, "lov")) {
-               int op_type = flags == XATTR_REPLACE ? LPROC_LL_REMOVEXATTR :
-                                                      LPROC_LL_SETXATTR;
-
-               ll_stats_ops_tally(ll_i2sbi(inode), op_type, 1);
-
-               return ll_setstripe_ea(dentry, (struct lov_user_md *)value,
+               rc = ll_setstripe_ea(dentry, (struct lov_user_md *)value,
                                       size);
+               ll_stats_ops_tally(ll_i2sbi(inode), op_type,
+                                  ktime_us_delta(ktime_get(), kstart));
+               return rc;
        } else if (!strcmp(name, "lma") || !strcmp(name, "link")) {
-               int op_type = flags == XATTR_REPLACE ? LPROC_LL_REMOVEXATTR :
-                                                      LPROC_LL_SETXATTR;
-
-               ll_stats_ops_tally(ll_i2sbi(inode), op_type, 1);
+               ll_stats_ops_tally(ll_i2sbi(inode), op_type,
+                                  ktime_us_delta(ktime_get(), kstart));
                return 0;
        }
 
+       if (strncmp(name, "lov.", 4) == 0 &&
+           (__swab32(((struct lov_user_md *)value)->lmm_magic) &
+           le32_to_cpu(LOV_MAGIC_MASK)) == le32_to_cpu(LOV_MAGIC_MAGIC))
+               lustre_swab_lov_user_md((struct lov_user_md *)value, 0);
+
        return ll_xattr_set_common(handler, dentry, inode, name, value, size,
                                   flags);
 }
@@ -333,7 +361,6 @@ int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer,
        struct ll_inode_info *lli = ll_i2info(inode);
         struct ll_sb_info *sbi = ll_i2sbi(inode);
         struct ptlrpc_request *req = NULL;
-        struct mdt_body *body;
         void *xdata;
        int rc;
        ENTRY;
@@ -360,35 +387,25 @@ int ll_xattr_list(struct inode *inode, const char *name, int type, void *buffer,
                }
        } else {
 getxattr_nocache:
-               rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode),
-                                valid, name, NULL, 0, size, 0, &req);
+               rc = md_getxattr(sbi->ll_md_exp, ll_inode2fid(inode), valid,
+                                name, size, &req);
                if (rc < 0)
                        GOTO(out_xattr, rc);
 
-               body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
-               LASSERT(body);
-
                /* only detect the xattr size */
                if (size == 0)
-                       GOTO(out, rc = body->mbo_eadatasize);
+                       GOTO(out, rc);
 
-               if (size < body->mbo_eadatasize) {
-                       CERROR("server bug: replied size %u > %u\n",
-                               body->mbo_eadatasize, (int)size);
+               if (size < rc)
                        GOTO(out, rc = -ERANGE);
-               }
-
-               if (body->mbo_eadatasize == 0)
-                       GOTO(out, rc = -ENODATA);
 
                /* do not need swab xattr data */
                xdata = req_capsule_server_sized_get(&req->rq_pill, &RMF_EADATA,
-                                                       body->mbo_eadatasize);
+                                                    rc);
                if (!xdata)
-                       GOTO(out, rc = -EFAULT);
+                       GOTO(out, rc = -EPROTO);
 
-               memcpy(buffer, xdata, body->mbo_eadatasize);
-               rc = body->mbo_eadatasize;
+               memcpy(buffer, xdata, rc);
        }
 
        EXIT;
@@ -396,13 +413,13 @@ getxattr_nocache:
 out_xattr:
        if (rc == -EOPNOTSUPP && type == XATTR_USER_T) {
                LCONSOLE_INFO("%s: disabling user_xattr feature because "
-                               "it is not supported on the server: rc = %d\n",
-                               ll_get_fsname(inode->i_sb, NULL, 0), rc);
+                             "it is not supported on the server: rc = %d\n",
+                             sbi->ll_fsname, rc);
                sbi->ll_flags &= ~LL_SBI_USER_XATTR;
        }
 out:
         ptlrpc_req_finished(req);
-        return rc;
+       RETURN(rc);
 }
 
 static int ll_xattr_get_common(const struct xattr_handler *handler,
@@ -411,21 +428,21 @@ static int ll_xattr_get_common(const struct xattr_handler *handler,
                               const char *name, void *buffer, size_t size)
 {
        struct ll_sb_info *sbi = ll_i2sbi(inode);
+       ktime_t kstart = ktime_get();
        char *fullname;
        int rc;
 
-       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR, 1);
+       ENTRY;
 
        rc = xattr_type_filter(sbi, handler);
        if (rc)
                RETURN(rc);
 
        /* LU-549:  Disable security.selinux when selinux is disabled */
-       if (handler->flags == XATTR_SECURITY_T && !selinux_is_enabled() &&
-           !strcmp(name, "selinux"))
+       if (test_xattr_is_selinux_disabled(handler, name))
                RETURN(-EOPNOTSUPP);
 
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
        /* posix acl is under protection of LOOKUP lock. when calling to this,
         * we just have path resolution to the target inode, so we have great
         * chance that cached ACL is uptodate.
@@ -449,14 +466,17 @@ static int ll_xattr_get_common(const struct xattr_handler *handler,
                RETURN(-ENODATA);
 #endif
 
-       fullname = kasprintf(GFP_KERNEL, "%s%s", handler->prefix, name);
+       fullname = kasprintf(GFP_KERNEL, "%s%s", xattr_prefix(handler), name);
        if (!fullname)
                RETURN(-ENOMEM);
 
        rc = ll_xattr_list(inode, fullname, handler->flags, buffer, size,
                           OBD_MD_FLXATTR);
        kfree(fullname);
-       return rc;
+       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_GETXATTR,
+                          ktime_us_delta(ktime_get(), kstart));
+
+       RETURN(rc);
 }
 
 static ssize_t ll_getxattr_lov(struct inode *inode, void *buf, size_t buf_size)
@@ -499,10 +519,26 @@ static ssize_t ll_getxattr_lov(struct inode *inode, void *buf, size_t buf_size)
                 * recognizing layout gen as stripe offset when the
                 * file is restored. See LU-2809.
                 */
-               if (((struct lov_mds_md *)buf)->lmm_magic == LOV_MAGIC_COMP_V1)
+               if ((((struct lov_mds_md *)buf)->lmm_magic &
+                   __swab32(LOV_MAGIC_MAGIC)) == __swab32(LOV_MAGIC_MAGIC))
+                       lustre_swab_lov_user_md((struct lov_user_md *)buf,
+                                               cl.cl_size);
+
+               switch (((struct lov_mds_md *)buf)->lmm_magic) {
+               case LOV_MAGIC_V1:
+               case LOV_MAGIC_V3:
+               case LOV_MAGIC_SPECIFIC:
+                       ((struct lov_mds_md *)buf)->lmm_layout_gen = 0;
+                       break;
+               case LOV_MAGIC_COMP_V1:
+               case LOV_MAGIC_FOREIGN:
                        goto out_env;
+               default:
+                       CERROR("Invalid LOV magic %08x\n",
+                              ((struct lov_mds_md *)buf)->lmm_magic);
+                       GOTO(out_env, rc = -EINVAL);
+               }
 
-               ((struct lov_mds_md *)buf)->lmm_layout_gen = 0;
 out_env:
                cl_env_put(env, &refcheck);
 
@@ -529,7 +565,7 @@ out_req:
                if (req)
                        ptlrpc_req_finished(req);
 
-               return rc;
+               RETURN(rc);
        } else {
                RETURN(-ENODATA);
        }
@@ -558,6 +594,7 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 {
        struct inode *inode = dentry->d_inode;
        struct ll_sb_info *sbi = ll_i2sbi(inode);
+       ktime_t kstart = ktime_get();
        char *xattr_name;
        ssize_t rc, rc2;
        size_t len, rem;
@@ -567,8 +604,6 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
        CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p)\n",
               PFID(ll_inode2fid(inode)), inode);
 
-       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR, 1);
-
        rc = ll_xattr_list(inode, NULL, XATTR_OTHER_T, buffer, size,
                           OBD_MD_FLXATTRLS);
        if (rc < 0)
@@ -580,7 +615,7 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
         * exists.
         */
        if (!size)
-               RETURN(rc + sizeof(XATTR_LUSTRE_LOV));
+               goto out;
 
        xattr_name = buffer;
        rem = rc;
@@ -614,6 +649,10 @@ ssize_t ll_listxattr(struct dentry *dentry, char *buffer, size_t size)
 
        memcpy(buffer + rc, XATTR_LUSTRE_LOV, sizeof(XATTR_LUSTRE_LOV));
 
+out:
+       ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_LISTXATTR,
+                          ktime_us_delta(ktime_get(), kstart));
+
        RETURN(rc + sizeof(XATTR_LUSTRE_LOV));
 }
 
@@ -760,7 +799,11 @@ static const struct xattr_handler ll_security_xattr_handler = {
 };
 
 static const struct xattr_handler ll_acl_access_xattr_handler = {
+#ifdef HAVE_XATTR_HANDLER_NAME
+       .name = XATTR_NAME_POSIX_ACL_ACCESS,
+#else
        .prefix = XATTR_NAME_POSIX_ACL_ACCESS,
+#endif
        .flags = XATTR_ACL_ACCESS_T,
 #if defined(HAVE_XATTR_HANDLER_SIMPLIFIED)
        .get = ll_xattr_get_common_4_3,
@@ -775,7 +818,11 @@ static const struct xattr_handler ll_acl_access_xattr_handler = {
 };
 
 static const struct xattr_handler ll_acl_default_xattr_handler = {
+#ifdef HAVE_XATTR_HANDLER_NAME
+       .name = XATTR_NAME_POSIX_ACL_DEFAULT,
+#else
        .prefix = XATTR_NAME_POSIX_ACL_DEFAULT,
+#endif
        .flags = XATTR_ACL_DEFAULT_T,
 #if defined(HAVE_XATTR_HANDLER_SIMPLIFIED)
        .get = ll_xattr_get_common_4_3,
@@ -808,7 +855,7 @@ const struct xattr_handler *ll_xattr_handlers[] = {
        &ll_user_xattr_handler,
        &ll_trusted_xattr_handler,
        &ll_security_xattr_handler,
-#ifdef CONFIG_FS_POSIX_ACL
+#ifdef CONFIG_LUSTRE_FS_POSIX_ACL
        &ll_acl_access_xattr_handler,
        &ll_acl_default_xattr_handler,
 #endif