Whamcloud - gitweb
LU-8424 osd-zfs: ZFS macro DN_MAX_BONUSLEN is deprecated
[fs/lustre-release.git] / lustre / osd-zfs / osd_xattr.c
index 777fdb0..9c2bac9 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, 2014, Intel Corporation.
+ * Copyright (c) 2012, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -108,9 +104,9 @@ static inline int __osd_xattr_cache(const struct lu_env *env,
                                    struct osd_object *obj)
 {
        LASSERT(obj->oo_sa_xattr == NULL);
-       LASSERT(obj->oo_db != NULL);
+       LASSERT(obj->oo_dn != NULL);
 
-       return __osd_xattr_load(osd_obj2dev(obj), obj->oo_db->db_object,
+       return __osd_xattr_load(osd_obj2dev(obj), obj->oo_dn->dn_object,
                                &obj->oo_sa_xattr);
 }
 
@@ -151,8 +147,8 @@ int __osd_xattr_get_large(const struct lu_env *env, struct osd_device *osd,
                          uint64_t xattr, struct lu_buf *buf,
                          const char *name, int *sizep)
 {
-       dmu_buf_t       *xa_data_db;
-       sa_handle_t     *sa_hdl = NULL;
+       dnode_t         *xa_data_dn;
+       sa_handle_t *sa_hdl = NULL;
        uint64_t         xa_data_obj, size;
        int              rc;
 
@@ -166,7 +162,7 @@ int __osd_xattr_get_large(const struct lu_env *env, struct osd_device *osd,
        if (rc)
                return rc;
 
-       rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj, &xa_data_db);
+       rc = __osd_obj2dnode(env, osd->od_os, xa_data_obj, &xa_data_dn);
        if (rc)
                return rc;
 
@@ -196,13 +192,13 @@ int __osd_xattr_get_large(const struct lu_env *env, struct osd_device *osd,
                goto out;
        }
 
-       rc = -dmu_read(osd->od_os, xa_data_db->db_object, 0,
+       rc = -dmu_read(osd->od_os, xa_data_dn->dn_object, 0,
                        size, buf->lb_buf, DMU_READ_PREFETCH);
 
 out:
        sa_handle_destroy(sa_hdl);
 out_rele:
-       dmu_buf_rele(xa_data_db, FTAG);
+       osd_dnode_rele(xa_data_dn);
 
        return rc;
 }
@@ -229,6 +225,9 @@ int __osd_xattr_get(const struct lu_env *env, struct osd_object *obj,
 {
        int rc;
 
+       if (unlikely(!dt_object_exists(&obj->oo_dt) || obj->oo_destroyed))
+               return -ENOENT;
+
        /* check SA_ZPL_DXATTR first then fallback to directory xattr */
        rc = __osd_sa_xattr_get(env, obj, buf, name, sizep);
        if (rc != -ENOENT)
@@ -245,18 +244,17 @@ int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
        int                 rc, size = 0;
        ENTRY;
 
-       LASSERT(obj->oo_db != NULL);
+       LASSERT(obj->oo_dn != NULL);
        LASSERT(osd_invariant(obj));
-       LASSERT(dt_object_exists(dt));
 
        if (!osd_obj2dev(obj)->od_posix_acl &&
-           (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
-            strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
+           (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 ||
+            strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
                RETURN(-EOPNOTSUPP);
 
-       down(&obj->oo_guard);
+       down_read(&obj->oo_guard);
        rc = __osd_xattr_get(env, obj, buf, name, &size);
-       up(&obj->oo_guard);
+       up_read(&obj->oo_guard);
 
        if (rc == -ENOENT)
                rc = -ENODATA;
@@ -265,36 +263,18 @@ int osd_xattr_get(const struct lu_env *env, struct dt_object *dt,
        RETURN(rc);
 }
 
-void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
-                            int vallen, const char *name,
-                            struct osd_thandle *oh)
+/* the function is used to declare EAs when SA is not supported */
+void __osd_xattr_declare_legacy(const struct lu_env *env,
+                               struct osd_object *obj,
+                               int vallen, const char *name,
+                               struct osd_thandle *oh)
 {
        struct osd_device *osd = osd_obj2dev(obj);
-       dmu_buf_t         *db = obj->oo_db;
-       dmu_tx_t          *tx = oh->ot_tx;
-       uint64_t           xa_data_obj;
-       int                rc = 0;
-       int                here;
-
-       here = dt_object_exists(&obj->oo_dt);
-
-       /* object may be not yet created */
-       if (here) {
-               LASSERT(db);
-               LASSERT(obj->oo_sa_hdl);
-               /* we might just update SA_ZPL_DXATTR */
-               dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
-
-               if (obj->oo_xattr == ZFS_NO_OBJECT)
-                       rc = -ENOENT;
-       }
+       dmu_tx_t *tx = oh->ot_tx;
+       uint64_t xa_data_obj;
+       int rc;
 
-       if (!here || rc == -ENOENT) {
-               /* we'll be updating SA_ZPL_XATTR */
-               if (here) {
-                       LASSERT(obj->oo_sa_hdl);
-                       dmu_tx_hold_sa(tx, obj->oo_sa_hdl, 1);
-               }
+       if (obj->oo_xattr == ZFS_NO_OBJECT) {
                /* xattr zap + entry */
                dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, TRUE, (char *) name);
                /* xattr value obj */
@@ -313,7 +293,6 @@ void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
                dmu_tx_hold_bonus(tx, xa_data_obj);
                dmu_tx_hold_free(tx, xa_data_obj, vallen, DMU_OBJECT_END);
                dmu_tx_hold_write(tx, xa_data_obj, 0, vallen);
-               return;
        } else if (rc == -ENOENT) {
                /*
                 * Entry doesn't exist, we need to create a new one and a new
@@ -323,11 +302,45 @@ void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
                dmu_tx_hold_zap(tx, obj->oo_xattr, TRUE, (char *) name);
                dmu_tx_hold_sa_create(tx, ZFS_SA_BASE_ATTR_SIZE);
                dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0, vallen);
+       }
+}
+
+void __osd_xattr_declare_set(const struct lu_env *env, struct osd_object *obj,
+                            int vallen, const char *name,
+                            struct osd_thandle *oh)
+{
+       dmu_tx_t *tx = oh->ot_tx;
+       int bonuslen;
+
+       if (unlikely(obj->oo_destroyed))
+               return;
+
+       if (unlikely(!osd_obj2dev(obj)->od_xattr_in_sa)) {
+               __osd_xattr_declare_legacy(env, obj, vallen, name, oh);
                return;
        }
 
-       /* An error happened */
-       tx->tx_err = -rc;
+       /* declare EA in SA */
+       if (dt_object_exists(&obj->oo_dt)) {
+               LASSERT(obj->oo_sa_hdl);
+               /* XXX: it should be possible to skip spill
+                * declaration if specific EA is part of
+                * bonus and doesn't grow */
+               dmu_tx_hold_spill(tx, obj->oo_dn->dn_object);
+               return;
+       }
+
+       bonuslen = osd_obj_bonuslen(obj);
+
+       /* the object doesn't exist, but we've declared bonus
+        * in osd_declare_object_create() yet */
+       if (obj->oo_ea_in_bonus > bonuslen) {
+               /* spill has been declared already */
+       } else if (obj->oo_ea_in_bonus + vallen > bonuslen) {
+               /* we're about to exceed bonus, let's declare spill */
+               dmu_tx_hold_spill(tx, DMU_NEW_OBJECT);
+       }
+       obj->oo_ea_in_bonus += vallen;
 }
 
 int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
@@ -341,9 +354,9 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
        LASSERT(handle != NULL);
        oh = container_of0(handle, struct osd_thandle, ot_super);
 
-       down(&obj->oo_guard);
+       down_read(&obj->oo_guard);
        __osd_xattr_declare_set(env, obj, buf->lb_len, name, oh);
-       up(&obj->oo_guard);
+       up_read(&obj->oo_guard);
 
        RETURN(0);
 }
@@ -356,8 +369,7 @@ int osd_declare_xattr_set(const struct lu_env *env, struct dt_object *dt,
  *
  * No locking is done here.
  */
-static int
-__osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
+int __osd_sa_xattr_update(const struct lu_env *env, struct osd_object *obj,
                      struct osd_thandle *oh)
 {
        struct osd_device *osd = osd_obj2dev(obj);
@@ -474,8 +486,8 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
                struct osd_thandle *oh)
 {
        struct osd_device *osd = osd_obj2dev(obj);
-       dmu_buf_t         *xa_zap_db = NULL;
-       dmu_buf_t         *xa_data_db = NULL;
+       dnode_t *xa_zap_dn = NULL;
+       dnode_t *xa_data_dn = NULL;
        uint64_t           xa_data_obj;
        sa_handle_t       *sa_hdl = NULL;
        dmu_tx_t          *tx = oh->ot_tx;
@@ -489,12 +501,11 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
 
                la->la_valid = LA_MODE;
                la->la_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
-               rc = __osd_zap_create(env, osd, &xa_zap_db, tx, la,
-                                     obj->oo_db->db_object, 0);
+               rc = __osd_zap_create(env, osd, &xa_zap_dn, tx, la, 0);
                if (rc)
                        return rc;
 
-               obj->oo_xattr = xa_zap_db->db_object;
+               obj->oo_xattr = xa_zap_dn->dn_object;
                rc = osd_object_sa_update(obj, SA_ZPL_XATTR(osd),
                                &obj->oo_xattr, 8, oh);
                if (rc)
@@ -512,8 +523,7 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
                 * Entry already exists.
                 * We'll truncate the existing object.
                 */
-               rc = __osd_obj2dbuf(env, osd->od_os, xa_data_obj,
-                                       &xa_data_db);
+               rc = __osd_obj2dnode(env, osd->od_os, xa_data_obj, &xa_data_dn);
                if (rc)
                        goto out;
 
@@ -526,7 +536,7 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
                if (rc)
                        goto out_sa;
 
-               rc = -dmu_free_range(osd->od_os, xa_data_db->db_object,
+               rc = -dmu_free_range(osd->od_os, xa_data_dn->dn_object,
                                     0, DMU_OBJECT_END, tx);
                if (rc)
                        goto out_sa;
@@ -545,11 +555,10 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
 
                la->la_valid = LA_MODE;
                la->la_mode = S_IFREG | S_IRUGO | S_IWUSR;
-               rc = __osd_object_create(env, obj, &xa_data_db, tx, la,
-                                        obj->oo_xattr);
+               rc = __osd_object_create(env, obj, &xa_data_dn, tx, la);
                if (rc)
                        goto out;
-               xa_data_obj = xa_data_db->db_object;
+               xa_data_obj = xa_data_dn->dn_object;
 
                rc = -sa_handle_get(osd->od_os, xa_data_obj, NULL,
                                        SA_HDL_PRIVATE, &sa_hdl);
@@ -574,10 +583,10 @@ __osd_xattr_set(const struct lu_env *env, struct osd_object *obj,
 out_sa:
        sa_handle_destroy(sa_hdl);
 out:
-       if (xa_data_db != NULL)
-               dmu_buf_rele(xa_data_db, FTAG);
-       if (xa_zap_db != NULL)
-               dmu_buf_rele(xa_zap_db, FTAG);
+       if (xa_data_dn != NULL)
+               osd_dnode_rele(xa_data_dn);
+       if (xa_zap_dn != NULL)
+               osd_dnode_rele(xa_zap_dn);
 
        return rc;
 }
@@ -593,25 +602,19 @@ int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
 
        LASSERT(handle != NULL);
        LASSERT(osd_invariant(obj));
-       LASSERT(dt_object_exists(dt));
-       LASSERT(obj->oo_db);
 
        if (!osd_obj2dev(obj)->od_posix_acl &&
-           (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
-            strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
+           (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 ||
+            strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
                RETURN(-EOPNOTSUPP);
 
-       if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_LINKEA_OVERFLOW) &&
-           strcmp(name, XATTR_NAME_LINK) == 0)
-               RETURN(-ENOSPC);
-
        oh = container_of0(handle, struct osd_thandle, ot_super);
 
-       down(&obj->oo_guard);
+       down_write(&obj->oo_guard);
        CDEBUG(D_INODE, "Setting xattr %s with size %d\n",
                name, (int)buf->lb_len);
        rc = osd_xattr_set_internal(env, obj, buf, name, fl, oh);
-       up(&obj->oo_guard);
+       up_write(&obj->oo_guard);
 
        RETURN(rc);
 }
@@ -660,22 +663,22 @@ int osd_declare_xattr_del(const struct lu_env *env, struct dt_object *dt,
        ENTRY;
 
        LASSERT(handle != NULL);
-       LASSERT(dt_object_exists(dt));
        LASSERT(osd_invariant(obj));
 
        oh = container_of0(handle, struct osd_thandle, ot_super);
        LASSERT(oh->ot_tx != NULL);
-       LASSERT(obj->oo_db != NULL);
+       LASSERT(obj->oo_dn != NULL);
 
-       down(&obj->oo_guard);
-       __osd_xattr_declare_del(env, obj, name, oh);
-       up(&obj->oo_guard);
+       down_read(&obj->oo_guard);
+       if (likely(dt_object_exists(&obj->oo_dt) && !obj->oo_destroyed))
+               __osd_xattr_declare_del(env, obj, name, oh);
+       up_read(&obj->oo_guard);
 
        RETURN(0);
 }
 
-int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
-                      const char *name, struct osd_thandle *oh)
+static int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
+                             const char *name, struct osd_thandle *oh)
 {
        int rc;
 
@@ -691,13 +694,16 @@ int __osd_sa_xattr_del(const struct lu_env *env, struct osd_object *obj,
        return rc;
 }
 
-int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
-                   const char *name, struct osd_thandle *oh)
+static int __osd_xattr_del(const struct lu_env *env, struct osd_object *obj,
+                          const char *name, struct osd_thandle *oh)
 {
        struct osd_device *osd = osd_obj2dev(obj);
        uint64_t           xa_data_obj;
        int                rc;
 
+       if (unlikely(!dt_object_exists(&obj->oo_dt) || obj->oo_destroyed))
+               return -ENOENT;
+
        /* try remove xattr from SA at first */
        rc = __osd_sa_xattr_del(env, obj, name, oh);
        if (rc != -ENOENT)
@@ -734,20 +740,20 @@ int osd_xattr_del(const struct lu_env *env, struct dt_object *dt,
        ENTRY;
 
        LASSERT(handle != NULL);
-       LASSERT(obj->oo_db != NULL);
+       LASSERT(obj->oo_dn != NULL);
        LASSERT(osd_invariant(obj));
        LASSERT(dt_object_exists(dt));
        oh = container_of0(handle, struct osd_thandle, ot_super);
        LASSERT(oh->ot_tx != NULL);
 
        if (!osd_obj2dev(obj)->od_posix_acl &&
-           (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
-            strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
+           (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 ||
+            strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
                RETURN(-EOPNOTSUPP);
 
-       down(&obj->oo_guard);
+       down_write(&obj->oo_guard);
        rc = __osd_xattr_del(env, obj, name, oh);
-       up(&obj->oo_guard);
+       up_write(&obj->oo_guard);
 
        RETURN(rc);
 }
@@ -836,7 +842,7 @@ int osd_xattrs_destroy(const struct lu_env *env,
 
        rc = -dmu_object_free(osd->od_os, obj->oo_xattr, tx);
        if (rc)
-               CERROR("%s: free xattr "LPU64" failed: rc = %d\n",
+               CERROR("%s: free xattr %llu failed: rc = %d\n",
                       osd->od_svname, obj->oo_xattr, rc);
 
        return rc;
@@ -862,8 +868,8 @@ osd_sa_xattr_list(const struct lu_env *env, struct osd_object *obj,
                const char *name = nvpair_name(nvp);
 
                if (!osd_obj2dev(obj)->od_posix_acl &&
-                   (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0 ||
-                    strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0))
+                   (strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 ||
+                    strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0))
                        continue;
 
                len = strlen(name);
@@ -888,11 +894,11 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
        int                    rc, counted;
        ENTRY;
 
-       LASSERT(obj->oo_db != NULL);
+       LASSERT(obj->oo_dn != NULL);
        LASSERT(osd_invariant(obj));
        LASSERT(dt_object_exists(dt));
 
-       down(&obj->oo_guard);
+       down_read(&obj->oo_guard);
 
        rc = osd_sa_xattr_list(env, obj, lb);
        if (rc < 0)
@@ -910,8 +916,8 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
 
        while ((rc = -zap_cursor_retrieve(zc, za)) == 0) {
                if (!osd_obj2dev(obj)->od_posix_acl &&
-                   (strcmp(za->za_name, POSIX_ACL_XATTR_ACCESS) == 0 ||
-                    strcmp(za->za_name, POSIX_ACL_XATTR_DEFAULT) == 0)) {
+                   (strcmp(za->za_name, XATTR_NAME_POSIX_ACL_ACCESS) == 0 ||
+                    strcmp(za->za_name, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) {
                        zap_cursor_advance(zc);
                        continue;
                }
@@ -919,7 +925,7 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
                rc = strlen(za->za_name);
                if (lb->lb_buf != NULL) {
                        if (counted + rc + 1 > lb->lb_len)
-                               RETURN(-ERANGE);
+                               GOTO(out_fini, rc = -ERANGE);
 
                        memcpy(lb->lb_buf + counted, za->za_name, rc + 1);
                }
@@ -936,7 +942,7 @@ int osd_xattr_list(const struct lu_env *env, struct dt_object *dt,
 out_fini:
        osd_zap_cursor_fini(zc);
 out:
-       up(&obj->oo_guard);
+       up_read(&obj->oo_guard);
        RETURN(rc);
 
 }