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, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
30 * Copyright (c) 2011, 2013, Intel Corporation.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/fld/fld_index.c
38 * Author: WangDi <wangdi@clusterfs.com>
39 * Author: Yury Umanets <umka@clusterfs.com>
42 #define DEBUG_SUBSYSTEM S_FLD
44 # include <linux/libcfs/libcfs.h>
45 # include <linux/module.h>
46 # include <linux/jbd.h>
49 #include <obd_class.h>
50 #include <lustre_ver.h>
51 #include <obd_support.h>
52 #include <lprocfs_status.h>
54 #include <dt_object.h>
55 #include <md_object.h>
56 #include <lustre_mdc.h>
57 #include <lustre_fid.h>
58 #include <lustre_fld.h>
59 #include "fld_internal.h"
61 const char fld_index_name
[] = "fld";
63 static const struct lu_seq_range IGIF_FLD_RANGE
= {
64 .lsr_start
= FID_SEQ_IGIF
,
65 .lsr_end
= FID_SEQ_IGIF_MAX
+ 1,
67 .lsr_flags
= LU_SEQ_RANGE_MDT
70 static const struct lu_seq_range DOT_LUSTRE_FLD_RANGE
= {
71 .lsr_start
= FID_SEQ_DOT_LUSTRE
,
72 .lsr_end
= FID_SEQ_DOT_LUSTRE
+ 1,
74 .lsr_flags
= LU_SEQ_RANGE_MDT
77 static const struct lu_seq_range ROOT_FLD_RANGE
= {
78 .lsr_start
= FID_SEQ_ROOT
,
79 .lsr_end
= FID_SEQ_ROOT
+ 1,
81 .lsr_flags
= LU_SEQ_RANGE_MDT
84 const struct dt_index_features fld_index_features
= {
85 .dif_flags
= DT_IND_UPDATE
,
86 .dif_keysize_min
= sizeof(seqno_t
),
87 .dif_keysize_max
= sizeof(seqno_t
),
88 .dif_recsize_min
= sizeof(struct lu_seq_range
),
89 .dif_recsize_max
= sizeof(struct lu_seq_range
),
93 extern struct lu_context_key fld_thread_key
;
95 int fld_declare_index_create(const struct lu_env
*env
,
96 struct lu_server_fld
*fld
,
97 const struct lu_seq_range
*new_range
,
100 struct lu_seq_range
*tmp
;
101 struct lu_seq_range
*range
;
102 struct fld_thread_info
*info
;
107 info
= lu_context_key_get(&env
->le_ctx
, &fld_thread_key
);
108 range
= &info
->fti_lrange
;
109 tmp
= &info
->fti_irange
;
110 memset(range
, 0, sizeof(*range
));
112 rc
= fld_index_lookup(env
, fld
, new_range
->lsr_start
, range
);
114 /* In case of duplicate entry, the location must be same */
115 LASSERT((range_compare_loc(new_range
, range
) == 0));
116 GOTO(out
, rc
= -EEXIST
);
120 CERROR("%s: lookup range "DRANGE
" error: rc = %d\n",
121 fld
->lsf_name
, PRANGE(range
), rc
);
125 /* Check for merge case, since the fld entry can only be increamental,
126 * so we will only check whether it can be merged from the left. */
127 if (new_range
->lsr_start
== range
->lsr_end
&& range
->lsr_end
!= 0 &&
128 range_compare_loc(new_range
, range
) == 0) {
129 range_cpu_to_be(tmp
, range
);
130 rc
= dt_declare_delete(env
, fld
->lsf_obj
,
131 (struct dt_key
*)&tmp
->lsr_start
, th
);
133 CERROR("%s: declare record "DRANGE
" failed: rc = %d\n",
134 fld
->lsf_name
, PRANGE(range
), rc
);
137 memcpy(tmp
, new_range
, sizeof(*new_range
));
138 tmp
->lsr_start
= range
->lsr_start
;
140 memcpy(tmp
, new_range
, sizeof(*new_range
));
143 range_cpu_to_be(tmp
, tmp
);
144 rc
= dt_declare_insert(env
, fld
->lsf_obj
, (struct dt_rec
*)tmp
,
145 (struct dt_key
*)&tmp
->lsr_start
, th
);
151 * insert range in fld store.
153 * \param range range to be inserted
154 * \param th transaction for this operation as it could compound
160 * The whole fld index insertion is protected by seq->lss_mutex (see
161 * seq_server_alloc_super), i.e. only one thread will access fldb each
162 * time, so we do not need worry the fld file and cache will being
163 * changed between declare and create.
164 * Because the fld entry can only be increamental, so we will only check
165 * whether it can be merged from the left.
167 int fld_index_create(const struct lu_env
*env
, struct lu_server_fld
*fld
,
168 const struct lu_seq_range
*new_range
, struct thandle
*th
)
170 struct lu_seq_range
*range
;
171 struct lu_seq_range
*tmp
;
172 struct fld_thread_info
*info
;
175 struct fld_cache_entry
*flde
;
178 info
= lu_context_key_get(&env
->le_ctx
, &fld_thread_key
);
180 LASSERT(mutex_is_locked(&fld
->lsf_lock
));
182 range
= &info
->fti_lrange
;
183 memset(range
, 0, sizeof(*range
));
184 tmp
= &info
->fti_irange
;
185 rc
= fld_index_lookup(env
, fld
, new_range
->lsr_start
, range
);
187 rc
= rc
== 0 ? -EEXIST
: rc
;
191 if (new_range
->lsr_start
== range
->lsr_end
&& range
->lsr_end
!= 0 &&
192 range_compare_loc(new_range
, range
) == 0) {
193 range_cpu_to_be(tmp
, range
);
194 rc
= dt_delete(env
, fld
->lsf_obj
,
195 (struct dt_key
*)&tmp
->lsr_start
, th
,
199 memcpy(tmp
, new_range
, sizeof(*new_range
));
200 tmp
->lsr_start
= range
->lsr_start
;
203 memcpy(tmp
, new_range
, sizeof(*new_range
));
206 range_cpu_to_be(tmp
, tmp
);
207 rc
= dt_insert(env
, fld
->lsf_obj
, (struct dt_rec
*)tmp
,
208 (struct dt_key
*)&tmp
->lsr_start
, th
, BYPASS_CAPA
, 1);
210 CERROR("%s: insert range "DRANGE
" failed: rc = %d\n",
211 fld
->lsf_name
, PRANGE(new_range
), rc
);
215 flde
= fld_cache_entry_create(new_range
);
217 GOTO(out
, rc
= PTR_ERR(flde
));
219 write_lock(&fld
->lsf_cache
->fci_lock
);
221 fld_cache_delete_nolock(fld
->lsf_cache
, new_range
);
222 rc
= fld_cache_insert_nolock(fld
->lsf_cache
, flde
);
223 write_unlock(&fld
->lsf_cache
->fci_lock
);
231 * lookup range for a seq passed. note here we only care about the start/end,
232 * caller should handle the attached location data (flags, index).
234 * \param seq seq for lookup.
235 * \param range result of lookup.
237 * \retval 0 found, \a range is the matched range;
238 * \retval -ENOENT not found, \a range is the left-side range;
239 * \retval -ve other error;
241 int fld_index_lookup(const struct lu_env
*env
, struct lu_server_fld
*fld
,
242 seqno_t seq
, struct lu_seq_range
*range
)
244 struct lu_seq_range
*fld_rec
;
245 struct fld_thread_info
*info
;
250 info
= lu_context_key_get(&env
->le_ctx
, &fld_thread_key
);
251 fld_rec
= &info
->fti_rec
;
253 rc
= fld_cache_lookup(fld
->lsf_cache
, seq
, fld_rec
);
256 if (range_within(range
, seq
))
262 CDEBUG(D_INFO
, "%s: lookup seq = "LPX64
" range : "DRANGE
" rc = %d\n",
263 fld
->lsf_name
, seq
, PRANGE(range
), rc
);
268 int fld_insert_entry(const struct lu_env
*env
,
269 struct lu_server_fld
*fld
,
270 const struct lu_seq_range
*range
)
276 th
= dt_trans_create(env
, lu2dt_dev(fld
->lsf_obj
->do_lu
.lo_dev
));
280 rc
= fld_declare_index_create(env
, fld
, range
, th
);
287 rc
= dt_trans_start_local(env
, lu2dt_dev(fld
->lsf_obj
->do_lu
.lo_dev
),
292 rc
= fld_index_create(env
, fld
, range
, th
);
296 dt_trans_stop(env
, lu2dt_dev(fld
->lsf_obj
->do_lu
.lo_dev
), th
);
299 EXPORT_SYMBOL(fld_insert_entry
);
301 static int fld_insert_special_entries(const struct lu_env
*env
,
302 struct lu_server_fld
*fld
)
306 rc
= fld_insert_entry(env
, fld
, &IGIF_FLD_RANGE
);
310 rc
= fld_insert_entry(env
, fld
, &DOT_LUSTRE_FLD_RANGE
);
314 rc
= fld_insert_entry(env
, fld
, &ROOT_FLD_RANGE
);
319 int fld_index_init(const struct lu_env
*env
, struct lu_server_fld
*fld
,
320 struct dt_device
*dt
)
322 struct dt_object
*dt_obj
= NULL
;
324 struct lu_attr
*attr
= NULL
;
325 struct lu_seq_range
*range
= NULL
;
326 struct fld_thread_info
*info
;
327 struct dt_object_format dof
;
329 const struct dt_it_ops
*iops
;
333 info
= lu_context_key_get(&env
->le_ctx
, &fld_thread_key
);
334 LASSERT(info
!= NULL
);
336 lu_local_obj_fid(&fid
, FLD_INDEX_OID
);
341 memset(attr
, 0, sizeof(*attr
));
342 attr
->la_valid
= LA_MODE
;
343 attr
->la_mode
= S_IFREG
| 0666;
344 dof
.dof_type
= DFT_INDEX
;
345 dof
.u
.dof_idx
.di_feat
= &fld_index_features
;
347 dt_obj
= dt_find_or_create(env
, dt
, &fid
, &dof
, attr
);
348 if (IS_ERR(dt_obj
)) {
349 rc
= PTR_ERR(dt_obj
);
350 CERROR("%s: Can't find \"%s\" obj %d\n", fld
->lsf_name
,
356 fld
->lsf_obj
= dt_obj
;
357 rc
= dt_obj
->do_ops
->do_index_try(env
, dt_obj
, &fld_index_features
);
359 CERROR("%s: File \"%s\" is not an index: rc = %d!\n",
360 fld
->lsf_name
, fld_index_name
, rc
);
364 range
= &info
->fti_rec
;
365 /* Load fld entry to cache */
366 iops
= &dt_obj
->do_index_ops
->dio_it
;
367 it
= iops
->init(env
, dt_obj
, 0, NULL
);
369 GOTO(out
, rc
= PTR_ERR(it
));
371 rc
= iops
->load(env
, it
, 0);
373 GOTO(out_it_fini
, rc
);
376 /* Load FLD entry into server cache */
378 rc
= iops
->rec(env
, it
, (struct dt_rec
*)range
, 0);
380 GOTO(out_it_put
, rc
);
381 LASSERT(range
!= NULL
);
382 range_be_to_cpu(range
, range
);
383 rc
= fld_cache_insert(fld
->lsf_cache
, range
);
385 GOTO(out_it_put
, rc
);
386 rc
= iops
->next(env
, it
);
390 /* Note: fld_insert_entry will detect whether these
391 * special entries already exist inside FLDB */
392 mutex_lock(&fld
->lsf_lock
);
393 rc
= fld_insert_special_entries(env
, fld
);
394 mutex_unlock(&fld
->lsf_lock
);
396 CERROR("%s: insert special entries failed!: rc = %d\n",
398 GOTO(out_it_put
, rc
);
411 lu_object_put(env
, &dt_obj
->do_lu
);
417 void fld_index_fini(const struct lu_env
*env
, struct lu_server_fld
*fld
)
420 if (fld
->lsf_obj
!= NULL
) {
421 if (!IS_ERR(fld
->lsf_obj
))
422 lu_object_put(env
, &fld
->lsf_obj
->do_lu
);