4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License version 2 for more details. A copy is
14 * included in the COPYING file that accompanied this code.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Copyright (c) 2014, Intel Corporation.
26 * lustre/lfsck/lfsck_striped_dir.c
28 * Author: Fan, Yong <fan.yong@intel.com>
31 #define DEBUG_SUBSYSTEM S_LFSCK
33 #include <lustre/lustre_idl.h>
34 #include <lu_object.h>
35 #include <dt_object.h>
36 #include <md_object.h>
37 #include <lustre_fid.h>
38 #include <lustre_lib.h>
39 #include <lustre_net.h>
40 #include <lustre_lmv.h>
41 #include <lustre/lustre_user.h>
43 #include "lfsck_internal.h"
45 void lfsck_lmv_put(const struct lu_env *env, struct lfsck_lmv *llmv)
47 if (llmv != NULL && atomic_dec_and_test(&llmv->ll_ref)) {
48 if (llmv->ll_lslr != NULL)
49 OBD_FREE_LARGE(llmv->ll_lslr,
50 sizeof(struct lfsck_slave_lmv_rec) *
51 llmv->ll_stripes_allocated);
57 static inline bool lfsck_is_valid_slave_lmv(struct lmv_mds_md_v1 *lmv)
59 return lmv->lmv_stripe_count >= 1 &&
60 lmv->lmv_stripe_count <= LFSCK_LMV_MAX_STRIPES &&
61 lmv->lmv_stripe_count > lmv->lmv_master_mdt_index &&
62 lmv_is_known_hash_type(lmv->lmv_hash_type);
65 int lfsck_read_stripe_lmv(const struct lu_env *env, struct dt_object *obj,
66 struct lmv_mds_md_v1 *lmv)
68 struct dt_object *bottom;
71 /* Currently, we only store the LMV header on disk. It is the LOD's
72 * duty to iterate the master MDT-object's directory to compose the
73 * integrated LMV EA. But here, we only want to load the LMV header,
74 * so we need to bypass LOD to avoid unnecessary iteration in LOD. */
75 bottom = lu2dt(container_of0(obj->do_lu.lo_header->loh_layers.prev,
76 struct lu_object, lo_linkage));
77 if (unlikely(bottom == NULL))
80 dt_read_lock(env, bottom, 0);
81 rc = dt_xattr_get(env, bottom, lfsck_buf_get(env, lmv, sizeof(*lmv)),
82 XATTR_NAME_LMV, BYPASS_CAPA);
83 dt_read_unlock(env, bottom);
84 if (rc != sizeof(*lmv))
85 return rc > 0 ? -EINVAL : rc;
87 lfsck_lmv_header_le_to_cpu(lmv, lmv);
88 if ((lmv->lmv_magic == LMV_MAGIC &&
89 !(lmv->lmv_hash_type & LMV_HASH_FLAG_MIGRATION)) ||
90 (lmv->lmv_magic == LMV_MAGIC_STRIPE &&
91 !(lmv->lmv_hash_type & LMV_HASH_FLAG_DEAD)))
98 * Parse the shard's index from the given shard name.
100 * The valid shard name/type should be:
101 * 1) The type must be S_IFDIR
102 * 2) The name should be $FID:$index
103 * 3) the index should within valid range.
105 * \param[in] env pointer to the thread context
106 * \param[in] name the shard name
107 * \param[in] namelen the name length
108 * \param[in] type the entry's type
109 * \param[in] fid the entry's FID
111 * \retval zero or positive number for the index from the name
112 * \retval negative error number on failure
114 int lfsck_shard_name_to_index(const struct lu_env *env, const char *name,
115 int namelen, __u16 type, const struct lu_fid *fid)
117 char *name2 = lfsck_env_info(env)->lti_tmpbuf2;
124 LASSERT(name != name2);
126 len = snprintf(name2, sizeof(lfsck_env_info(env)->lti_tmpbuf2),
128 if (namelen < len + 1 || memcmp(name, name2, len) != 0)
132 if (!isdigit(name[len]))
135 idx = idx * 10 + name[len++] - '0';
136 } while (len < namelen);
138 if (idx >= LFSCK_LMV_MAX_STRIPES)
144 bool lfsck_is_valid_slave_name_entry(const struct lu_env *env,
145 struct lfsck_lmv *llmv,
146 const char *name, int namelen)
148 struct lmv_mds_md_v1 *lmv;
151 if (llmv == NULL || !llmv->ll_lmv_slave || !llmv->ll_lmv_verified)
155 idx = lmv_name_to_stripe_index(lmv->lmv_hash_type,
156 lmv->lmv_stripe_count,
158 if (unlikely(idx != lmv->lmv_master_mdt_index))
165 * Check whether the given name is a valid entry under the @parent.
167 * If the @parent is a striped directory then the @child should one
168 * shard of the striped directory, its name should be $FID:$index.
170 * If the @parent is a shard of a striped directory, then the name hash
171 * should match the MDT, otherwise it is invalid.
173 * \param[in] env pointer to the thread context
174 * \param[in] parent the parent directory
175 * \param[in] child the child object to be checked
176 * \param[in] cname the name for the @child in the parent directory
178 * \retval positive number for invalid name entry
179 * \retval 0 if the name is valid or uncertain
180 * \retval negative error number on failure
182 int lfsck_namespace_check_name(const struct lu_env *env,
183 struct dt_object *parent,
184 struct dt_object *child,
185 const struct lu_name *cname)
187 struct lmv_mds_md_v1 *lmv = &lfsck_env_info(env)->lti_lmv;
191 rc = lfsck_read_stripe_lmv(env, parent, lmv);
193 RETURN(rc == -ENODATA ? 0 : rc);
195 if (lmv->lmv_magic == LMV_MAGIC_STRIPE) {
196 if (!lfsck_is_valid_slave_lmv(lmv))
199 idx = lmv_name_to_stripe_index(lmv->lmv_hash_type,
200 lmv->lmv_stripe_count,
203 if (unlikely(idx != lmv->lmv_master_mdt_index))
205 } else if (lfsck_shard_name_to_index(env, cname->ln_name,
206 cname->ln_namelen, lfsck_object_type(child),
207 lfsck_dto2fid(child)) < 0) {
214 int lfsck_namespace_verify_stripe_slave(const struct lu_env *env,
215 struct lfsck_component *com,
216 struct dt_object *obj,
217 struct lfsck_lmv *llmv)