Whamcloud - gitweb
LU-6101 osd: zfs-osd should convert hash
[fs/lustre-release.git] / lustre / osd-zfs / osd_index.c
index 2f420a9..b498b23 100644 (file)
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
- */
-/*
- * Copyright (c) 2012, 2013, Intel Corporation.
- * Use is subject to license terms.
+ *
+ * Copyright (c) 2012, 2014, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -140,7 +138,8 @@ static inline void osd_obj_cursor_init_serialized(zap_cursor_t *zc,
                                                 uint64_t dirhash)
 {
        struct osd_device *d = osd_obj2dev(o);
-       zap_cursor_init_serialized(zc, d->od_os, o->oo_db->db_object, dirhash);
+       osd_zap_cursor_init_serialized(zc, d->od_os,
+                                      o->oo_db->db_object, dirhash);
 }
 
 static inline int osd_obj_cursor_init(zap_cursor_t **zc, struct osd_object *o,
@@ -169,11 +168,24 @@ static struct dt_it *osd_index_it_init(const struct lu_env *env,
        LASSERT(osd_object_is_zap(obj->oo_db));
        LASSERT(info);
 
-       it = &info->oti_it_zap;
+       if (info->oti_it_inline) {
+               OBD_ALLOC_PTR(it);
+               if (it == NULL)
+                       RETURN(ERR_PTR(-ENOMEM));
+       } else {
+               it = &info->oti_it_zap;
+               info->oti_it_inline = 1;
+       }
 
        rc = osd_obj_cursor_init(&it->ozi_zc, obj, 0);
-       if (rc != 0)
+       if (rc != 0) {
+               if (it != &info->oti_it_zap)
+                       OBD_FREE_PTR(it);
+               else
+                       info->oti_it_inline = 0;
+
                RETURN(ERR_PTR(rc));
+       }
 
        it->ozi_obj   = obj;
        it->ozi_capa  = capa;
@@ -185,8 +197,9 @@ static struct dt_it *osd_index_it_init(const struct lu_env *env,
 
 static void osd_index_it_fini(const struct lu_env *env, struct dt_it *di)
 {
-       struct osd_zap_it *it = (struct osd_zap_it *)di;
-       struct osd_object *obj;
+       struct osd_thread_info  *info   = osd_oti_get(env);
+       struct osd_zap_it       *it     = (struct osd_zap_it *)di;
+       struct osd_object       *obj;
        ENTRY;
 
        LASSERT(it);
@@ -196,6 +209,10 @@ static void osd_index_it_fini(const struct lu_env *env, struct dt_it *di)
 
        osd_zap_cursor_fini(it->ozi_zc);
        lu_object_put(env, &obj->oo_dt.do_lu);
+       if (it != &info->oti_it_zap)
+               OBD_FREE_PTR(it);
+       else
+               info->oti_it_inline = 0;
 
        EXIT;
 }
@@ -422,16 +439,20 @@ static int osd_declare_dir_insert(const struct lu_env *env,
 {
        struct osd_object  *obj = osd_dt_obj(dt);
        struct osd_thandle *oh;
+       uint64_t object;
        ENTRY;
 
        LASSERT(th != NULL);
        oh = container_of0(th, struct osd_thandle, ot_super);
 
-       LASSERT(obj->oo_db);
-       LASSERT(osd_object_is_zap(obj->oo_db));
+       /* This is for inserting dot/dotdot for new created dir. */
+       if (obj->oo_db == NULL)
+               object = DMU_NEW_OBJECT;
+       else
+               object = obj->oo_db->db_object;
 
-       dmu_tx_hold_bonus(oh->ot_tx, obj->oo_db->db_object);
-       dmu_tx_hold_zap(oh->ot_tx, obj->oo_db->db_object, TRUE, (char *)key);
+       dmu_tx_hold_bonus(oh->ot_tx, object);
+       dmu_tx_hold_zap(oh->ot_tx, object, TRUE, (char *)key);
 
        RETURN(0);
 }
@@ -505,7 +526,7 @@ static inline void osd_object_put(const struct lu_env *env,
 }
 
 static int osd_seq_exists(const struct lu_env *env, struct osd_device *osd,
-                         obd_seq seq)
+                         u64 seq)
 {
        struct lu_seq_range     *range = &osd_oti_get(env)->oti_seq_range;
        struct seq_server_site  *ss = osd_seq_site(osd);
@@ -615,12 +636,25 @@ static int osd_dir_insert(const struct lu_env *env, struct dt_object *dt,
                                 * during iteration */
                                GOTO(out, rc = 0);
                        } else if (name[1] == '.' && name[2] == 0) {
+                               if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_BAD_PARENT)) {
+                                       struct lu_fid tfid = *fid;
+
+                                       osd_object_put(env, child);
+                                       tfid.f_oid--;
+                                       child = osd_object_find(env, dt, &tfid);
+                                       if (IS_ERR(child))
+                                               RETURN(PTR_ERR(child));
+
+                                       LASSERT(child->oo_db);
+                               }
+
                                /* update parent dnode in the child.
                                 * later it will be used to generate ".." */
                                rc = osd_object_sa_update(parent,
                                                 SA_ZPL_PARENT(osd),
                                                 &child->oo_db->db_object,
                                                 8, oh);
+
                                GOTO(out, rc);
                        }
                }
@@ -636,6 +670,12 @@ static int osd_dir_insert(const struct lu_env *env, struct dt_object *dt,
        rc = -zap_add(osd->od_os, parent->oo_db->db_object,
                      (char *)key, 8, sizeof(oti->oti_zde) / 8,
                      (void *)&oti->oti_zde, oh->ot_tx);
+       if (unlikely(rc == -EEXIST &&
+                    name[0] == '.' && name[1] == '.' && name[2] == 0))
+               /* Update (key,oid) in ZAP */
+               rc = -zap_update(osd->od_os, parent->oo_db->db_object,
+                               (char *)key, 8, sizeof(oti->oti_zde) / 8,
+                               (void *)&oti->oti_zde, oh->ot_tx);
 
 out:
        if (child != NULL)
@@ -824,6 +864,8 @@ static int osd_dir_it_next(const struct lu_env *env, struct dt_it *di)
        zap_attribute_t   *za = &osd_oti_get(env)->oti_za;
        int                rc;
 
+       ENTRY;
+
        /* temp. storage should be enough for any key supported by ZFS */
        CLASSERT(sizeof(za->za_name) <= sizeof(it->ozi_name));
 
@@ -836,9 +878,10 @@ static int osd_dir_it_next(const struct lu_env *env, struct dt_it *di)
                it->ozi_pos++;
                if (it->ozi_pos <=2)
                        RETURN(0);
-       }
 
-       zap_cursor_advance(it->ozi_zc);
+       } else {
+               zap_cursor_advance(it->ozi_zc);
+       }
 
        /*
         * According to current API we need to return error if its last entry.
@@ -928,14 +971,11 @@ static int osd_dir_it_rec(const struct lu_env *env, const struct dt_it *di,
                osd_it_append_attrs(lde, attr, 2, IFTODT(S_IFDIR));
                lde->lde_reclen = cpu_to_le16(lu_dirent_calc_size(2, attr));
                rc = osd_find_parent_fid(env, &it->ozi_obj->oo_dt, &lde->lde_fid);
-               /*
-                * early Orion code was not setting LinkEA, so it's possible
-                * some setups still have objects with no LinkEA set.
-                * but at that time .. was a real record in the directory
-                * so we should try to lookup .. in ZAP
-                */
-               if (rc != -ENOENT)
-                       GOTO(out, rc);
+
+               /* ENOENT happens at the root of filesystem so ignore it */
+               if (rc == -ENOENT)
+                       rc = 0;
+               GOTO(out, rc);
        }
 
        LASSERT(lde);
@@ -981,7 +1021,8 @@ static int osd_dir_it_rec_size(const struct lu_env *env, const struct dt_it *di,
 {
        struct osd_zap_it   *it = (struct osd_zap_it *)di;
        zap_attribute_t     *za = &osd_oti_get(env)->oti_za;
-       int                  rc, namelen = 0;
+       size_t               namelen = 0;
+       int                  rc;
        ENTRY;
 
        if (it->ozi_pos <= 1)
@@ -1063,7 +1104,7 @@ static int osd_dir_it_load(const struct lu_env *env,
        RETURN(rc);
 }
 
-static struct dt_index_operations osd_dir_ops = {
+struct dt_index_operations osd_dir_ops = {
        .dio_lookup         = osd_dir_lookup,
        .dio_declare_insert = osd_declare_dir_insert,
        .dio_insert         = osd_dir_insert,