1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2012, 2017, Intel Corporation.
8 * This file is part of Lustre, http://www.lustre.org/
10 * Local storage for file/objects with fid generation. Works on top of OSD.
12 * Author: Mikhail Pershin <mike.pershin@intel.com>
15 #define DEBUG_SUBSYSTEM S_CLASS
17 #include "local_storage.h"
19 /* all initialized local storages on this node are linked on this */
20 static LIST_HEAD(ls_list_head);
21 static DEFINE_MUTEX(ls_list_mutex);
23 static int ls_object_init(const struct lu_env *env, struct lu_object *o,
24 const struct lu_object_conf *unused)
27 struct lu_object *below;
28 struct lu_device *under;
32 ls = container_of(o->lo_dev, struct ls_device, ls_top_dev.dd_lu_dev);
33 under = &ls->ls_osd->dd_lu_dev;
34 below = under->ld_ops->ldo_object_alloc(env, o->lo_header, under);
38 lu_object_add(o, below);
43 static void ls_object_free(const struct lu_env *env, struct lu_object *o)
45 struct ls_object *obj = lu2ls_obj(o);
46 struct lu_object_header *h = o->lo_header;
48 dt_object_fini(&obj->ls_obj);
49 lu_object_header_fini(h);
50 OBD_FREE_RCU(obj, sizeof(*obj), ls_header.loh_rcu);
53 static const struct lu_object_operations ls_lu_obj_ops = {
54 .loo_object_init = ls_object_init,
55 .loo_object_free = ls_object_free,
58 static struct lu_object *ls_object_alloc(const struct lu_env *env,
59 const struct lu_object_header *_h,
62 struct lu_object_header *h;
73 lu_object_header_init(h);
74 dt_object_init(&o->ls_obj, h, d);
75 lu_object_add_top(h, l);
77 l->lo_ops = &ls_lu_obj_ops;
85 static const struct lu_device_operations ls_lu_dev_ops = {
86 .ldo_object_alloc = ls_object_alloc
89 static const struct lu_device_type_operations ls_device_type_ops = {
94 static struct lu_device_type ls_lu_type = {
95 .ldt_name = "local_storage",
96 .ldt_ops = &ls_device_type_ops,
100 struct ls_device *ls_device_init(struct dt_device *dev)
102 struct ls_device *ls;
108 GOTO(out_ls, ls = ERR_PTR(-ENOMEM));
110 kref_init(&ls->ls_refcount);
111 INIT_LIST_HEAD(&ls->ls_los_list);
112 mutex_init(&ls->ls_los_mutex);
116 LASSERT(dev->dd_lu_dev.ld_site);
117 lu_device_init(&ls->ls_top_dev.dd_lu_dev, &ls_lu_type);
118 ls->ls_top_dev.dd_lu_dev.ld_ops = &ls_lu_dev_ops;
119 ls->ls_top_dev.dd_lu_dev.ld_site = dev->dd_lu_dev.ld_site;
121 /* finally add ls to the list */
122 list_add(&ls->ls_linkage, &ls_list_head);
127 struct ls_device *ls_device_find_or_init(struct dt_device *dev)
129 struct ls_device *ls, *ret = NULL;
133 mutex_lock(&ls_list_mutex);
135 list_for_each_entry(ls, &ls_list_head, ls_linkage) {
136 if (ls->ls_osd == dev) {
137 kref_get(&ls->ls_refcount);
146 /* not found, then create */
147 ls = ls_device_init(dev);
149 mutex_unlock(&ls_list_mutex);
153 static void ls_device_put_free(struct kref *kref)
155 struct ls_device *ls = container_of(kref, struct ls_device,
158 LASSERT(list_empty(&ls->ls_los_list));
159 list_del(&ls->ls_linkage);
160 mutex_unlock(&ls_list_mutex);
163 void ls_device_put(const struct lu_env *env, struct ls_device *ls)
166 if (kref_put_mutex(&ls->ls_refcount, ls_device_put_free,
168 lu_site_purge(env, ls->ls_top_dev.dd_lu_dev.ld_site, ~0);
169 lu_device_fini(&ls->ls_top_dev.dd_lu_dev);
175 * local file fid generation
177 int local_object_fid_generate(const struct lu_env *env,
178 struct local_oid_storage *los,
181 LASSERT(los->los_dev);
182 LASSERT(los->los_obj);
186 /* to make it unique after reboot we store
187 * the latest generated fid atomically with
188 * object creation see local_object_create() */
190 mutex_lock(&los->los_id_lock);
191 fid->f_seq = los->los_seq;
192 fid->f_oid = ++los->los_last_oid;
194 mutex_unlock(&los->los_id_lock);
199 int local_object_declare_create(const struct lu_env *env,
200 struct local_oid_storage *los,
201 struct dt_object *o, struct lu_attr *attr,
202 struct dt_object_format *dof,
205 struct dt_thread_info *dti = dt_info(env);
210 /* update fid generation file */
212 LASSERT(dt_object_exists(los->los_obj));
213 dti->dti_lb.lb_buf = NULL;
214 dti->dti_lb.lb_len = sizeof(struct los_ondisk);
215 rc = dt_declare_record_write(env, los->los_obj,
216 &dti->dti_lb, 0, th);
221 rc = dt_declare_create(env, o, attr, NULL, dof, th);
225 dti->dti_lb.lb_buf = NULL;
226 dti->dti_lb.lb_len = sizeof(dti->dti_lma);
227 rc = dt_declare_xattr_set(env, o, NULL, &dti->dti_lb, XATTR_NAME_LMA, 0,
233 int local_object_create(const struct lu_env *env,
234 struct local_oid_storage *los,
235 struct dt_object *o, struct lu_attr *attr,
236 struct dt_object_format *dof, struct thandle *th)
238 struct dt_thread_info *dti = dt_info(env);
244 rc = dt_create(env, o, attr, NULL, dof, th);
251 LASSERT(los->los_obj);
252 LASSERT(dt_object_exists(los->los_obj));
254 /* many threads can be updated this, serialize
255 * them here to avoid the race where one thread
256 * takes the value first, but writes it last */
257 mutex_lock(&los->los_id_lock);
259 /* update local oid number on disk so that
260 * we know the last one used after reboot */
261 lastid = cpu_to_le64(los->los_last_oid);
264 dti->dti_lb.lb_buf = &lastid;
265 dti->dti_lb.lb_len = sizeof(lastid);
266 rc = dt_record_write(env, los->los_obj, &dti->dti_lb, &dti->dti_off,
268 mutex_unlock(&los->los_id_lock);
274 * Create local named object (file, directory or index) in parent directory.
276 static struct dt_object *__local_file_create(const struct lu_env *env,
277 const struct lu_fid *fid,
278 struct local_oid_storage *los,
279 struct ls_device *ls,
280 struct dt_object *parent,
282 struct lu_attr *attr,
283 struct dt_object_format *dof)
285 struct dt_thread_info *dti = dt_info(env);
286 struct lu_object_conf *conf = &dti->dti_conf;
287 struct dt_insert_rec *rec = &dti->dti_dt_rec;
288 struct dt_object *dto;
292 /* We know that the target object does not exist, to be created,
293 * then give some hints - LOC_F_NEW to help low layer to handle
294 * that efficiently and properly. */
295 memset(conf, 0, sizeof(*conf));
296 conf->loc_flags = LOC_F_NEW;
297 dto = ls_locate(env, ls, fid, conf);
298 if (unlikely(IS_ERR(dto)))
301 LASSERT(dto != NULL);
302 if (dt_object_exists(dto))
303 GOTO(out, rc = -EEXIST);
305 th = dt_trans_create(env, ls->ls_osd);
307 GOTO(out, rc = PTR_ERR(th));
309 rc = local_object_declare_create(env, los, dto, attr, dof, th);
311 GOTO(trans_stop, rc);
313 if (dti->dti_dof.dof_type == DFT_DIR) {
314 rc = dt_declare_ref_add(env, dto, th);
316 GOTO(trans_stop, rc);
318 rc = dt_declare_ref_add(env, parent, th);
320 GOTO(trans_stop, rc);
324 rec->rec_type = attr->la_mode & S_IFMT;
325 rc = dt_declare_insert(env, parent, (const struct dt_rec *)rec,
326 (const struct dt_key *)name, th);
328 GOTO(trans_stop, rc);
330 if (dti->dti_dof.dof_type == DFT_DIR) {
331 if (!dt_try_as_dir(env, dto, false))
332 GOTO(trans_stop, rc = -ENOTDIR);
334 rec->rec_type = S_IFDIR;
336 rc = dt_declare_insert(env, dto, (const struct dt_rec *)rec,
337 (const struct dt_key *)".", th);
339 GOTO(trans_stop, rc);
341 rec->rec_fid = lu_object_fid(&parent->do_lu);
342 rc = dt_declare_insert(env, dto, (const struct dt_rec *)rec,
343 (const struct dt_key *)"..", th);
345 GOTO(trans_stop, rc);
347 rc = dt_declare_ref_add(env, dto, th);
349 GOTO(trans_stop, rc);
352 rc = dt_trans_start_local(env, ls->ls_osd, th);
354 GOTO(trans_stop, rc);
356 dt_write_lock(env, dto, DT_SRC_CHILD);
357 if (dt_object_exists(dto))
358 GOTO(unlock, rc = 0);
360 CDEBUG(D_OTHER, "create new object "DFID"\n",
361 PFID(lu_object_fid(&dto->do_lu)));
362 rc = local_object_create(env, los, dto, attr, dof, th);
365 LASSERT(dt_object_exists(dto));
367 if (dti->dti_dof.dof_type == DFT_DIR) {
369 rec->rec_type = S_IFDIR;
371 /* Add "." and ".." for newly created dir */
372 rc = dt_insert(env, dto, (const struct dt_rec *)rec,
373 (const struct dt_key *)".", th);
377 dt_ref_add(env, dto, th);
378 rec->rec_fid = lu_object_fid(&parent->do_lu);
379 rc = dt_insert(env, dto, (const struct dt_rec *)rec,
380 (const struct dt_key *)"..", th);
386 rec->rec_type = dto->do_lu.lo_header->loh_attr;
387 dt_write_lock(env, parent, DT_SRC_PARENT);
388 rc = dt_insert(env, parent, (const struct dt_rec *)rec,
389 (const struct dt_key *)name, th);
390 if (dti->dti_dof.dof_type == DFT_DIR)
391 dt_ref_add(env, parent, th);
392 dt_write_unlock(env, parent);
397 dt_destroy(env, dto, th);
399 dt_write_unlock(env, dto);
401 dt_trans_stop(env, ls->ls_osd, th);
404 dt_object_put_nocache(env, dto);
410 struct dt_object *local_file_find(const struct lu_env *env,
411 struct local_oid_storage *los,
412 struct dt_object *parent,
415 struct dt_thread_info *dti = dt_info(env);
416 struct dt_object *dto;
421 rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
423 dto = ls_locate(env, dt2ls_dev(los->los_dev),
424 &dti->dti_fid, NULL);
430 EXPORT_SYMBOL(local_file_find);
433 * Look up and create (if it does not exist) a local named file or directory in
436 struct dt_object *local_file_find_or_create(const struct lu_env *env,
437 struct local_oid_storage *los,
438 struct dt_object *parent,
439 const char *name, __u32 mode)
441 struct dt_thread_info *dti = dt_info(env);
442 struct dt_object *dto;
445 dto = local_file_find(env, los, parent, name);
446 if (!IS_ERR(dto) || PTR_ERR(dto) != -ENOENT)
449 rc = local_object_fid_generate(env, los, &dti->dti_fid);
453 /* create the object */
454 dti->dti_attr.la_valid = LA_MODE;
455 dti->dti_attr.la_mode = mode;
456 dti->dti_dof.dof_type = dt_mode_to_dft(mode & S_IFMT);
457 dto = __local_file_create(env, &dti->dti_fid, los,
458 dt2ls_dev(los->los_dev), parent, name,
459 &dti->dti_attr, &dti->dti_dof);
462 EXPORT_SYMBOL(local_file_find_or_create);
464 struct dt_object *local_file_find_or_create_with_fid(const struct lu_env *env,
465 struct dt_device *dt,
466 const struct lu_fid *fid,
467 struct dt_object *parent,
471 struct dt_thread_info *dti = dt_info(env);
472 struct dt_object *dto;
477 rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
479 dto = dt_locate(env, dt, &dti->dti_fid);
480 } else if (rc != -ENOENT) {
483 struct ls_device *ls;
485 ls = ls_device_find_or_init(dt);
489 /* create the object */
490 dti->dti_attr.la_valid = LA_MODE;
491 dti->dti_attr.la_mode = mode;
492 dti->dti_dof.dof_type = dt_mode_to_dft(mode & S_IFMT);
493 dto = __local_file_create(env, fid, NULL, ls, parent,
494 name, &dti->dti_attr,
496 /* ls_device_put() will finalize the ls device, we
497 * have to open the object in other device stack */
499 dti->dti_fid = dto->do_lu.lo_header->loh_fid;
500 dt_object_put_nocache(env, dto);
501 dto = dt_locate(env, dt, &dti->dti_fid);
503 ls_device_put(env, ls);
508 EXPORT_SYMBOL(local_file_find_or_create_with_fid);
511 * Look up and create (if it does not exist) a local named index file in parent
514 struct dt_object *local_index_find_or_create(const struct lu_env *env,
515 struct local_oid_storage *los,
516 struct dt_object *parent,
517 const char *name, __u32 mode,
518 const struct dt_index_features *ft)
520 struct dt_thread_info *dti = dt_info(env);
521 struct dt_object *dto;
526 rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
528 /* name is found, get the object */
529 dto = ls_locate(env, dt2ls_dev(los->los_dev),
530 &dti->dti_fid, NULL);
531 } else if (rc != -ENOENT) {
534 rc = local_object_fid_generate(env, los, &dti->dti_fid);
538 /* create the object */
539 dti->dti_attr.la_valid = LA_MODE;
540 dti->dti_attr.la_mode = mode;
541 dti->dti_dof.dof_type = DFT_INDEX;
542 dti->dti_dof.u.dof_idx.di_feat = ft;
543 dto = __local_file_create(env, &dti->dti_fid, los,
544 dt2ls_dev(los->los_dev),
545 parent, name, &dti->dti_attr,
552 EXPORT_SYMBOL(local_index_find_or_create);
555 local_index_find_or_create_with_fid(const struct lu_env *env,
556 struct dt_device *dt,
557 const struct lu_fid *fid,
558 struct dt_object *parent,
559 const char *name, __u32 mode,
560 const struct dt_index_features *ft)
562 struct dt_thread_info *dti = dt_info(env);
563 struct dt_object *dto;
568 rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
570 /* name is found, get the object */
571 if (!lu_fid_eq(fid, &dti->dti_fid))
572 dto = ERR_PTR(-EINVAL);
574 dto = dt_locate(env, dt, fid);
575 } else if (rc != -ENOENT) {
578 struct ls_device *ls;
580 ls = ls_device_find_or_init(dt);
584 /* create the object */
585 dti->dti_attr.la_valid = LA_MODE;
586 dti->dti_attr.la_mode = mode;
587 dti->dti_dof.dof_type = DFT_INDEX;
588 dti->dti_dof.u.dof_idx.di_feat = ft;
589 dto = __local_file_create(env, fid, NULL, ls, parent,
590 name, &dti->dti_attr,
592 /* ls_device_put() will finalize the ls device, we
593 * have to open the object in other device stack */
595 dti->dti_fid = dto->do_lu.lo_header->loh_fid;
596 dt_object_put_nocache(env, dto);
597 dto = dt_locate(env, dt, &dti->dti_fid);
599 ls_device_put(env, ls);
604 EXPORT_SYMBOL(local_index_find_or_create_with_fid);
606 static int local_object_declare_unlink(const struct lu_env *env,
607 struct dt_device *dt,
609 struct dt_object *c, const char *name,
614 rc = dt_declare_delete(env, p, (const struct dt_key *)name, th);
618 if (S_ISDIR(p->do_lu.lo_header->loh_attr)) {
619 rc = dt_declare_ref_del(env, p, th);
624 rc = dt_declare_ref_del(env, c, th);
628 return dt_declare_destroy(env, c, th);
631 int local_object_unlink(const struct lu_env *env, struct dt_device *dt,
632 struct dt_object *parent, const char *name)
634 struct dt_thread_info *dti = dt_info(env);
635 struct dt_object *dto;
641 rc = dt_lookup_dir(env, parent, name, &dti->dti_fid);
647 dto = dt_locate(env, dt, &dti->dti_fid);
648 if (unlikely(IS_ERR(dto)))
649 RETURN(PTR_ERR(dto));
651 th = dt_trans_create(env, dt);
653 GOTO(out, rc = PTR_ERR(th));
655 rc = local_object_declare_unlink(env, dt, parent, dto, name, th);
659 rc = dt_trans_start_local(env, dt, th);
663 if (S_ISDIR(dto->do_lu.lo_header->loh_attr)) {
664 dt_write_lock(env, parent, 0);
665 rc = dt_ref_del(env, parent, th);
666 dt_write_unlock(env, parent);
671 dt_write_lock(env, dto, 0);
672 rc = dt_delete(env, parent, (struct dt_key *)name, th);
676 rc = dt_ref_del(env, dto, th);
678 struct dt_insert_rec *rec = &dti->dti_dt_rec;
680 rec->rec_fid = &dti->dti_fid;
681 rec->rec_type = dto->do_lu.lo_header->loh_attr;
682 rc = dt_insert(env, parent, (const struct dt_rec *)rec,
683 (const struct dt_key *)name, th);
687 rc = dt_destroy(env, dto, th);
689 dt_write_unlock(env, dto);
691 dt_trans_stop(env, dt, th);
693 dt_object_put_nocache(env, dto);
696 EXPORT_SYMBOL(local_object_unlink);
698 struct local_oid_storage *dt_los_find(struct ls_device *ls, __u64 seq)
700 struct local_oid_storage *los, *ret = NULL;
702 list_for_each_entry(los, &ls->ls_los_list, los_list) {
703 if (los->los_seq == seq) {
704 atomic_inc(&los->los_refcount);
712 void dt_los_put(struct local_oid_storage *los)
714 /* should never happen, only local_oid_storage_fini should
715 * drop refcount to zero
717 LASSERT(!atomic_dec_and_test(&los->los_refcount));
720 /* after Lustre 2.3 release there may be old file to store last generated FID
721 * If such file exists then we have to read its content
723 static int lastid_compat_check(const struct lu_env *env, struct dt_device *dev,
724 __u64 lastid_seq, __u32 *first_oid,
725 struct ls_device *ls)
727 struct dt_thread_info *dti = dt_info(env);
728 struct dt_object *root = NULL;
729 struct los_ondisk losd;
730 struct dt_object *o = NULL;
733 rc = dt_root_get(env, dev, &dti->dti_fid);
737 root = ls_locate(env, ls, &dti->dti_fid, NULL);
739 return PTR_ERR(root);
741 /* find old last_id file */
742 snprintf(dti->dti_buf, sizeof(dti->dti_buf), "seq-%#llx-lastid",
744 rc = dt_lookup_dir(env, root, dti->dti_buf, &dti->dti_fid);
745 dt_object_put_nocache(env, root);
747 /* old llog lastid accessed by FID only */
748 if (lastid_seq != FID_SEQ_LLOG)
750 dti->dti_fid.f_seq = FID_SEQ_LLOG;
751 dti->dti_fid.f_oid = 1;
752 dti->dti_fid.f_ver = 0;
753 o = ls_locate(env, ls, &dti->dti_fid, NULL);
757 if (!dt_object_exists(o)) {
758 dt_object_put_nocache(env, o);
761 CDEBUG(D_INFO, "Found old llog lastid file\n");
765 CDEBUG(D_INFO, "Found old lastid file for sequence %#llx\n",
767 o = ls_locate(env, ls, &dti->dti_fid, NULL);
771 /* let's read seq-NNNNNN-lastid file value */
772 LASSERT(dt_object_exists(o));
774 dti->dti_lb.lb_buf = &losd;
775 dti->dti_lb.lb_len = sizeof(losd);
776 dt_read_lock(env, o, 0);
777 rc = dt_record_read(env, o, &dti->dti_lb, &dti->dti_off);
778 dt_read_unlock(env, o);
779 if (rc == 0 && le32_to_cpu(losd.lso_magic) != LOS_MAGIC) {
780 CERROR("%s: wrong content of seq-%#llx-lastid file, magic %x\n",
781 o->do_lu.lo_dev->ld_obd->obd_name, lastid_seq,
782 le32_to_cpu(losd.lso_magic));
785 CERROR("%s: failed to read seq-%#llx-lastid: rc = %d\n",
786 o->do_lu.lo_dev->ld_obd->obd_name, lastid_seq, rc);
788 dt_object_put_nocache(env, o);
790 *first_oid = le32_to_cpu(losd.lso_next_oid);
796 * Initialize local OID storage for required sequence.
797 * That may be needed for services that uses local files and requires
798 * dynamic OID allocation for them.
800 * Per each sequence we have an object with 'first_fid' identificator
801 * containing the counter for OIDs of locally created files with that
804 * It is used now by llog subsystem and MGS for NID tables
806 * Function gets first_fid to create counter object.
807 * All dynamic fids will be generated with the same sequence and incremented
810 * Returned local_oid_storage is in-memory representaion of OID storage
812 int local_oid_storage_init(const struct lu_env *env, struct dt_device *dev,
813 const struct lu_fid *first_fid,
814 struct local_oid_storage **los)
816 struct dt_thread_info *dti = dt_info(env);
817 struct ls_device *ls;
819 struct dt_object *o = NULL;
821 __u32 first_oid = fid_oid(first_fid);
826 ls = ls_device_find_or_init(dev);
830 mutex_lock(&ls->ls_los_mutex);
831 *los = dt_los_find(ls, fid_seq(first_fid));
835 /* not found, then create */
838 GOTO(out, rc = -ENOMEM);
840 atomic_set(&(*los)->los_refcount, 1);
841 mutex_init(&(*los)->los_id_lock);
842 (*los)->los_dev = &ls->ls_top_dev;
843 kref_get(&ls->ls_refcount);
844 list_add(&(*los)->los_list, &ls->ls_los_list);
846 /* Use {seq, 0, 0} to create the LAST_ID file for every
847 * sequence. OIDs start at LUSTRE_FID_INIT_OID.
849 dti->dti_fid.f_seq = fid_seq(first_fid);
850 dti->dti_fid.f_oid = LUSTRE_FID_LASTID_OID;
851 dti->dti_fid.f_ver = 0;
852 o = ls_locate(env, ls, &dti->dti_fid, NULL);
854 GOTO(out_los, rc = PTR_ERR(o));
856 if (!dt_object_exists(o)) {
857 rc = lastid_compat_check(env, dev, fid_seq(first_fid),
862 th = dt_trans_create(env, dev);
864 GOTO(out_los, rc = PTR_ERR(th));
866 dti->dti_attr.la_valid = LA_MODE | LA_TYPE;
867 dti->dti_attr.la_mode = S_IFREG | S_IRUGO | S_IWUSR;
868 dti->dti_dof.dof_type = dt_mode_to_dft(S_IFREG);
870 rc = dt_declare_create(env, o, &dti->dti_attr, NULL,
875 lastid = cpu_to_le64(first_oid);
878 dti->dti_lb.lb_buf = &lastid;
879 dti->dti_lb.lb_len = sizeof(lastid);
880 rc = dt_declare_record_write(env, o, &dti->dti_lb, dti->dti_off,
885 rc = dt_trans_start_local(env, dev, th);
889 dt_write_lock(env, o, 0);
890 if (dt_object_exists(o))
891 GOTO(out_lock, rc = 0);
893 rc = dt_create(env, o, &dti->dti_attr, NULL, &dti->dti_dof,
898 rc = dt_record_write(env, o, &dti->dti_lb, &dti->dti_off, th);
902 dt_write_unlock(env, o);
904 dt_trans_stop(env, dev, th);
907 dti->dti_lb.lb_buf = &lastid;
908 dti->dti_lb.lb_len = sizeof(lastid);
909 dt_read_lock(env, o, 0);
910 rc = dt_record_read(env, o, &dti->dti_lb, &dti->dti_off);
911 dt_read_unlock(env, o);
912 if (rc == 0 && le64_to_cpu(lastid) > OBIF_MAX_OID) {
913 CERROR("%s: bad oid %llu is read from LAST_ID\n",
914 o->do_lu.lo_dev->ld_obd->obd_name,
915 le64_to_cpu(lastid));
921 list_del(&(*los)->los_list);
922 ls_device_put(env, ls);
925 if (o != NULL && !IS_ERR(o))
926 dt_object_put_nocache(env, o);
928 (*los)->los_seq = fid_seq(first_fid);
929 (*los)->los_last_oid = le64_to_cpu(lastid);
931 /* Read value should not be less than initial one
932 * but possible after upgrade from older fs.
933 * In this case just switch to the first_oid in memory and
934 * it will be updated on disk with first object generated */
935 if ((*los)->los_last_oid < first_oid)
936 (*los)->los_last_oid = first_oid;
939 mutex_unlock(&ls->ls_los_mutex);
940 ls_device_put(env, ls);
943 EXPORT_SYMBOL(local_oid_storage_init);
945 void local_oid_storage_fini(const struct lu_env *env,
946 struct local_oid_storage *los)
948 struct ls_device *ls;
951 LASSERT(los->los_dev);
952 ls = dt2ls_dev(los->los_dev);
954 /* Take the mutex before decreasing the reference to avoid race
955 * conditions as described in LU-4721. */
956 mutex_lock(&ls->ls_los_mutex);
957 if (!atomic_dec_and_test(&los->los_refcount)) {
958 mutex_unlock(&ls->ls_los_mutex);
963 dt_object_put_nocache(env, los->los_obj);
964 list_del(&los->los_list);
966 mutex_unlock(&ls->ls_los_mutex);
967 ls_device_put(env, ls);
969 EXPORT_SYMBOL(local_oid_storage_fini);