Whamcloud - gitweb
LU-10565 osd: unify interface for vfs
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_compat.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  *
32  * lustre/osd/osd_compat.c
33  *
34  * on-disk structure for managing /O
35  *
36  * Author: Alex Zhuravlev <bzzz@whamcloud.com>
37  */
38
39 /* prerequisite for linux/xattr.h */
40 #include <linux/types.h>
41 /* prerequisite for linux/xattr.h */
42 #include <linux/fs.h>
43 /* XATTR_{REPLACE,CREATE} */
44 #include <linux/xattr.h>
45
46 /*
47  * struct OBD_{ALLOC,FREE}*()
48  * OBD_FAIL_CHECK
49  */
50 #include <obd_support.h>
51
52 #include "osd_internal.h"
53 #include "osd_oi.h"
54
55 static void osd_push_ctxt(const struct osd_device *dev,
56                           struct lvfs_run_ctxt *newctxt,
57                           struct lvfs_run_ctxt *save)
58 {
59         OBD_SET_CTXT_MAGIC(newctxt);
60         newctxt->pwdmnt = dev->od_mnt;
61         newctxt->pwd = dev->od_mnt->mnt_root;
62         newctxt->fs = get_ds();
63         newctxt->umask = current_umask();
64         newctxt->dt = NULL;
65
66         push_ctxt(save, newctxt);
67 }
68
69 /* utility to make a directory */
70 static struct dentry *
71 simple_mkdir(const struct lu_env *env, struct osd_device *osd,
72              struct dentry *dir, const struct lu_fid *fid,
73              const char *name, __u32 compat, int mode, bool *created)
74 {
75         struct osd_thread_info *info = osd_oti_get(env);
76         struct lu_fid *tfid = &info->oti_fid3;
77         struct inode *inode;
78         struct dentry *dchild;
79         int err = 0;
80         ENTRY;
81
82         // ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
83         CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name);
84         dchild = ll_lookup_one_len(name, dir, strlen(name));
85         if (IS_ERR(dchild))
86                 RETURN(dchild);
87
88         inode = dchild->d_inode;
89         if (inode) {
90                 struct lustre_mdt_attrs *lma = &info->oti_ost_attrs.loa_lma;
91                 int old_mode = inode->i_mode;
92
93                 if (created)
94                         *created = false;
95
96                 if (!S_ISDIR(old_mode)) {
97                         CERROR("found %s (%lu/%u) is mode %o\n", name,
98                                inode->i_ino, inode->i_generation, old_mode);
99                         GOTO(out_err, err = -ENOTDIR);
100                 }
101
102                 if (unlikely(osd->od_dt_dev.dd_rdonly))
103                         RETURN(dchild);
104
105                 /* Fixup directory permissions if necessary */
106                 if ((old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
107                         CDEBUG(D_CONFIG,
108                                "fixing permissions on %s from %o to %o\n",
109                                name, old_mode, mode);
110                         inode->i_mode = (mode & S_IALLUGO) |
111                                         (old_mode & ~S_IALLUGO);
112                         mark_inode_dirty(inode);
113                 }
114
115                 err = osd_get_lma(info, inode, &info->oti_obj_dentry,
116                                   &info->oti_ost_attrs);
117                 if (err == -ENODATA)
118                         goto set_fid;
119
120                 if (err)
121                         GOTO(out_err, err);
122
123                 if ((fid && !lu_fid_eq(fid, &lma->lma_self_fid)) ||
124                     lma->lma_compat != compat)
125                         goto set_fid;
126
127                 RETURN(dchild);
128         }
129
130         err = vfs_mkdir(dir->d_inode, dchild, mode);
131         if (err)
132                 GOTO(out_err, err);
133
134         inode = dchild->d_inode;
135         if (created)
136                 *created = true;
137
138 set_fid:
139         if (fid)
140                 *tfid = *fid;
141         else
142                 lu_igif_build(tfid, inode->i_ino, inode->i_generation);
143         err = osd_ea_fid_set(info, inode, tfid, compat, 0);
144         if (err)
145                 GOTO(out_err, err);
146
147         RETURN(dchild);
148
149 out_err:
150         dput(dchild);
151         return ERR_PTR(err);
152 }
153
154 static int osd_last_rcvd_subdir_count(struct osd_device *osd)
155 {
156         struct lr_server_data lsd;
157         struct dentry        *dlast;
158         loff_t                off;
159         int                   rc = 0;
160         int                   count = OBJ_SUBDIR_COUNT;
161
162         ENTRY;
163
164         dlast = ll_lookup_one_len(LAST_RCVD, osd_sb(osd)->s_root,
165                                   strlen(LAST_RCVD));
166         if (IS_ERR(dlast))
167                 return PTR_ERR(dlast);
168         else if (dlast->d_inode == NULL)
169                 goto out;
170
171         off = 0;
172         rc = osd_ldiskfs_read(dlast->d_inode, &lsd, sizeof(lsd), &off);
173         if (rc == sizeof(lsd)) {
174                 CDEBUG(D_INFO, "read last_rcvd header, uuid = %s, "
175                        "subdir count = %d\n", lsd.lsd_uuid,
176                        lsd.lsd_subdir_count);
177                 if (le16_to_cpu(lsd.lsd_subdir_count) > 0)
178                         count = le16_to_cpu(lsd.lsd_subdir_count);
179         } else if (rc != 0) {
180                 CERROR("Can't read last_rcvd file, rc = %d\n", rc);
181                 if (rc > 0)
182                         rc = -EFAULT;
183                 dput(dlast);
184                 return rc;
185         }
186 out:
187         dput(dlast);
188         LASSERT(count > 0);
189         return count;
190 }
191
192 static int osd_mdt_init(const struct lu_env *env, struct osd_device *dev)
193 {
194         struct lvfs_run_ctxt    new;
195         struct lvfs_run_ctxt    save;
196         struct dentry           *parent;
197         struct osd_mdobj_map    *omm;
198         struct dentry           *d;
199         struct osd_thread_info  *info = osd_oti_get(env);
200         struct lu_fid           *fid = &info->oti_fid3;
201         int                     rc = 0;
202         ENTRY;
203
204         OBD_ALLOC_PTR(dev->od_mdt_map);
205         if (dev->od_mdt_map == NULL)
206                 RETURN(-ENOMEM);
207
208         omm = dev->od_mdt_map;
209
210         parent = osd_sb(dev)->s_root;
211         osd_push_ctxt(dev, &new, &save);
212
213         lu_local_obj_fid(fid, REMOTE_PARENT_DIR_OID);
214         d = simple_mkdir(env, dev, parent, fid, REMOTE_PARENT_DIR,
215                          LMAC_NOT_IN_OI, 0755, NULL);
216         if (IS_ERR(d))
217                 GOTO(cleanup, rc = PTR_ERR(d));
218
219         omm->omm_remote_parent = d;
220
221         GOTO(cleanup, rc = 0);
222
223 cleanup:
224         pop_ctxt(&save, &new);
225         if (rc) {
226                 if (omm->omm_remote_parent != NULL)
227                         dput(omm->omm_remote_parent);
228                 OBD_FREE_PTR(omm);
229                 dev->od_mdt_map = NULL;
230         }
231         return rc;
232 }
233
234 static void osd_mdt_fini(struct osd_device *osd)
235 {
236         struct osd_mdobj_map *omm = osd->od_mdt_map;
237
238         if (omm == NULL)
239                 return;
240
241         if (omm->omm_remote_parent)
242                 dput(omm->omm_remote_parent);
243
244         OBD_FREE_PTR(omm);
245         osd->od_ost_map = NULL;
246 }
247
248 int osd_add_to_remote_parent(const struct lu_env *env, struct osd_device *osd,
249                              struct osd_object *obj, struct osd_thandle *oh)
250 {
251         struct osd_mdobj_map    *omm = osd->od_mdt_map;
252         struct osd_thread_info  *oti = osd_oti_get(env);
253         struct lustre_mdt_attrs *lma = &oti->oti_ost_attrs.loa_lma;
254         char                    *name = oti->oti_name;
255         struct osd_thread_info  *info = osd_oti_get(env);
256         struct dentry           *dentry;
257         struct dentry           *parent;
258         int                     rc;
259
260         if (OBD_FAIL_CHECK(OBD_FAIL_LFSCK_NO_AGENTENT))
261                 RETURN(0);
262
263         /* Set REMOTE_PARENT in lma, so other process like unlink or lfsck
264          * can identify this object quickly */
265         rc = osd_get_lma(oti, obj->oo_inode, &oti->oti_obj_dentry,
266                          &oti->oti_ost_attrs);
267         if (rc)
268                 RETURN(rc);
269
270         lma->lma_incompat |= LMAI_REMOTE_PARENT;
271         lustre_lma_swab(lma);
272         rc = __osd_xattr_set(oti, obj->oo_inode, XATTR_NAME_LMA, lma,
273                              sizeof(*lma), XATTR_REPLACE);
274         if (rc)
275                 RETURN(rc);
276
277         parent = omm->omm_remote_parent;
278         sprintf(name, DFID_NOBRACE, PFID(lu_object_fid(&obj->oo_dt.do_lu)));
279         dentry = osd_child_dentry_by_inode(env, parent->d_inode,
280                                            name, strlen(name));
281         inode_lock(parent->d_inode);
282         rc = osd_ldiskfs_add_entry(info, osd, oh->ot_handle, dentry,
283                                    obj->oo_inode, NULL);
284         if (!rc && S_ISDIR(obj->oo_inode->i_mode))
285                 ldiskfs_inc_count(oh->ot_handle, parent->d_inode);
286         else if (unlikely(rc == -EEXIST))
287                 rc = 0;
288         if (!rc)
289                 lu_object_set_agent_entry(&obj->oo_dt.do_lu);
290         CDEBUG(D_INODE, "%s: create agent entry for %s: rc = %d\n",
291                osd_name(osd), name, rc);
292         mark_inode_dirty(parent->d_inode);
293         inode_unlock(parent->d_inode);
294         RETURN(rc);
295 }
296
297 int osd_delete_from_remote_parent(const struct lu_env *env,
298                                   struct osd_device *osd,
299                                   struct osd_object *obj,
300                                   struct osd_thandle *oh, bool destroy)
301 {
302         struct osd_mdobj_map       *omm = osd->od_mdt_map;
303         struct osd_thread_info     *oti = osd_oti_get(env);
304         struct lustre_mdt_attrs    *lma = &oti->oti_ost_attrs.loa_lma;
305         char                       *name = oti->oti_name;
306         struct dentry              *dentry;
307         struct dentry              *parent;
308         struct ldiskfs_dir_entry_2 *de;
309         struct buffer_head         *bh;
310         int                        rc;
311
312         parent = omm->omm_remote_parent;
313         sprintf(name, DFID_NOBRACE, PFID(lu_object_fid(&obj->oo_dt.do_lu)));
314         dentry = osd_child_dentry_by_inode(env, parent->d_inode,
315                                            name, strlen(name));
316         inode_lock(parent->d_inode);
317         bh = osd_ldiskfs_find_entry(parent->d_inode, &dentry->d_name, &de,
318                                     NULL, NULL);
319         if (IS_ERR(bh)) {
320                 inode_unlock(parent->d_inode);
321                 rc = PTR_ERR(bh);
322                 if (unlikely(rc == -ENOENT))
323                         rc = 0;
324         } else {
325                 rc = ldiskfs_delete_entry(oh->ot_handle, parent->d_inode,
326                                           de, bh);
327                 if (!rc && S_ISDIR(obj->oo_inode->i_mode))
328                         ldiskfs_dec_count(oh->ot_handle, parent->d_inode);
329                 mark_inode_dirty(parent->d_inode);
330                 inode_unlock(parent->d_inode);
331                 brelse(bh);
332                 CDEBUG(D_INODE, "%s: remove agent entry for %s: rc = %d\n",
333                        osd_name(osd), name, rc);
334         }
335
336         if (destroy || rc) {
337                 if (!rc)
338                         lu_object_clear_agent_entry(&obj->oo_dt.do_lu);
339
340                 RETURN(rc);
341         }
342
343         rc = osd_get_lma(oti, obj->oo_inode, &oti->oti_obj_dentry,
344                          &oti->oti_ost_attrs);
345         if (rc)
346                 RETURN(rc);
347
348         /* Get rid of REMOTE_PARENT flag from incompat */
349         lma->lma_incompat &= ~LMAI_REMOTE_PARENT;
350         lustre_lma_swab(lma);
351         rc = __osd_xattr_set(oti, obj->oo_inode, XATTR_NAME_LMA, lma,
352                              sizeof(*lma), XATTR_REPLACE);
353         if (!rc)
354                 lu_object_clear_agent_entry(&obj->oo_dt.do_lu);
355         RETURN(rc);
356 }
357
358 int osd_lookup_in_remote_parent(struct osd_thread_info *oti,
359                                 struct osd_device *osd,
360                                 const struct lu_fid *fid,
361                                 struct osd_inode_id *id)
362 {
363         struct osd_mdobj_map        *omm = osd->od_mdt_map;
364         char                        *name = oti->oti_name;
365         struct dentry               *parent;
366         struct dentry               *dentry;
367         struct ldiskfs_dir_entry_2 *de;
368         struct buffer_head         *bh;
369         int                         rc;
370         ENTRY;
371
372         if (unlikely(osd->od_is_ost))
373                 RETURN(-ENOENT);
374
375         parent = omm->omm_remote_parent;
376         sprintf(name, DFID_NOBRACE, PFID(fid));
377         dentry = osd_child_dentry_by_inode(oti->oti_env, parent->d_inode,
378                                            name, strlen(name));
379         inode_lock(parent->d_inode);
380         bh = osd_ldiskfs_find_entry(parent->d_inode, &dentry->d_name, &de,
381                                     NULL, NULL);
382         if (IS_ERR(bh)) {
383                 rc = PTR_ERR(bh);
384         } else {
385                 struct inode *inode;
386
387                 osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
388                 brelse(bh);
389                 inode = osd_iget(oti, osd, id);
390                 if (IS_ERR(inode)) {
391                         rc = PTR_ERR(inode);
392                         if (rc == -ESTALE)
393                                 rc = -ENOENT;
394                 } else {
395                         iput(inode);
396                         rc = 0;
397                 }
398         }
399         inode_unlock(parent->d_inode);
400         if (rc == 0)
401                 osd_add_oi_cache(oti, osd, id, fid);
402         RETURN(rc);
403 }
404
405 /*
406  * directory structure on legacy OST:
407  *
408  * O/<seq>/d0-31/<objid>
409  * O/<seq>/LAST_ID
410  * last_rcvd
411  * LAST_GROUP
412  * CONFIGS
413  *
414  */
415 static int osd_ost_init(const struct lu_env *env, struct osd_device *dev)
416 {
417         struct lvfs_run_ctxt new;
418         struct lvfs_run_ctxt save;
419         struct dentry *d;
420         int rc;
421         bool created = false;
422         ENTRY;
423
424         OBD_ALLOC_PTR(dev->od_ost_map);
425         if (dev->od_ost_map == NULL)
426                 RETURN(-ENOMEM);
427
428         /* to get subdir count from last_rcvd */
429         rc = osd_last_rcvd_subdir_count(dev);
430         if (rc < 0)
431                 GOTO(cleanup_alloc, rc);
432
433         dev->od_ost_map->om_subdir_count = rc;
434         INIT_LIST_HEAD(&dev->od_ost_map->om_seq_list);
435         rwlock_init(&dev->od_ost_map->om_seq_list_lock);
436         mutex_init(&dev->od_ost_map->om_dir_init_mutex);
437
438         osd_push_ctxt(dev, &new, &save);
439         d = simple_mkdir(env, dev, osd_sb(dev)->s_root, NULL, "O",
440                          LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0755, &created);
441         if (IS_ERR(d))
442                 GOTO(cleanup_ctxt, rc = PTR_ERR(d));
443
444         if (created)
445                 /* It is quite probably that the device is new formatted. */
446                 dev->od_maybe_new = 1;
447
448         dev->od_ost_map->om_root = d;
449
450         pop_ctxt(&save, &new);
451         RETURN(0);
452
453 cleanup_ctxt:
454         pop_ctxt(&save, &new);
455 cleanup_alloc:
456         OBD_FREE_PTR(dev->od_ost_map);
457         return rc;
458 }
459
460 static void osd_seq_free(struct osd_obj_seq *osd_seq)
461 {
462         int j;
463
464         if (osd_seq->oos_dirs) {
465                 for (j = 0; j < osd_seq->oos_subdir_count; j++) {
466                         if (osd_seq->oos_dirs[j])
467                                 dput(osd_seq->oos_dirs[j]);
468                 }
469                 OBD_FREE(osd_seq->oos_dirs,
470                          sizeof(struct dentry *) * osd_seq->oos_subdir_count);
471         }
472
473         if (osd_seq->oos_root)
474                 dput(osd_seq->oos_root);
475
476         OBD_FREE_PTR(osd_seq);
477 }
478
479 static void osd_ost_fini(struct osd_device *osd)
480 {
481         struct osd_obj_seq    *osd_seq;
482         struct osd_obj_seq    *tmp;
483         struct osd_obj_map    *map = osd->od_ost_map;
484         ENTRY;
485
486         if (map == NULL)
487                 return;
488
489         write_lock(&map->om_seq_list_lock);
490         list_for_each_entry_safe(osd_seq, tmp, &map->om_seq_list,
491                                  oos_seq_list) {
492                 list_del_init(&osd_seq->oos_seq_list);
493                 write_unlock(&map->om_seq_list_lock);
494                 osd_seq_free(osd_seq);
495                 write_lock(&map->om_seq_list_lock);
496         }
497         write_unlock(&map->om_seq_list_lock);
498         if (map->om_root)
499                 dput(map->om_root);
500         OBD_FREE_PTR(map);
501         osd->od_ost_map = NULL;
502         EXIT;
503 }
504
505 static int osd_index_backup_dir_init(const struct lu_env *env,
506                                      struct osd_device *dev)
507 {
508         struct lu_fid *fid = &osd_oti_get(env)->oti_fid;
509         struct lvfs_run_ctxt new;
510         struct lvfs_run_ctxt save;
511         struct dentry *dentry;
512         int rc = 0;
513         ENTRY;
514
515         lu_local_obj_fid(fid, INDEX_BACKUP_OID);
516         osd_push_ctxt(dev, &new, &save);
517         dentry = simple_mkdir(env, dev, osd_sb(dev)->s_root, fid,
518                               INDEX_BACKUP_DIR, LMAC_NOT_IN_OI, 0755, NULL);
519         if (IS_ERR(dentry)) {
520                 rc = PTR_ERR(dentry);
521         } else {
522                 dev->od_index_backup_inode = igrab(dentry->d_inode);
523                 dput(dentry);
524         }
525         pop_ctxt(&save, &new);
526
527         RETURN(rc);
528 }
529
530 static void osd_index_backup_dir_fini(struct osd_device *dev)
531 {
532         if (dev->od_index_backup_inode) {
533                 iput(dev->od_index_backup_inode);
534                 dev->od_index_backup_inode = NULL;
535         }
536 }
537
538 int osd_obj_map_init(const struct lu_env *env, struct osd_device *dev)
539 {
540         int rc;
541         bool mdt_init = false;
542         ENTRY;
543
544         rc = osd_ost_init(env, dev);
545         if (rc)
546                 RETURN(rc);
547
548         if (!dev->od_is_ost) {
549                 rc = osd_mdt_init(env, dev);
550                 if (rc) {
551                         osd_ost_fini(dev);
552                         RETURN(rc);
553                 }
554
555                 mdt_init = true;
556         }
557
558         rc = osd_index_backup_dir_init(env, dev);
559         if (rc) {
560                 osd_ost_fini(dev);
561                 if (mdt_init)
562                         osd_mdt_fini(dev);
563         }
564
565         RETURN(rc);
566 }
567
568 static struct osd_obj_seq *osd_seq_find_locked(struct osd_obj_map *map, u64 seq)
569 {
570         struct osd_obj_seq *osd_seq;
571
572         list_for_each_entry(osd_seq, &map->om_seq_list, oos_seq_list) {
573                 if (osd_seq->oos_seq == seq)
574                         return osd_seq;
575         }
576         return NULL;
577 }
578
579 static struct osd_obj_seq *osd_seq_find(struct osd_obj_map *map, u64 seq)
580 {
581         struct osd_obj_seq *osd_seq;
582
583         read_lock(&map->om_seq_list_lock);
584         osd_seq = osd_seq_find_locked(map, seq);
585         read_unlock(&map->om_seq_list_lock);
586         return osd_seq;
587 }
588
589 void osd_obj_map_fini(struct osd_device *dev)
590 {
591         osd_index_backup_dir_fini(dev);
592         osd_ost_fini(dev);
593         osd_mdt_fini(dev);
594 }
595
596 /**
597  * Update the specified OI mapping.
598  *
599  * \retval   1, changed nothing
600  * \retval   0, changed successfully
601  * \retval -ve, on error
602  */
603 static int osd_obj_update_entry(struct osd_thread_info *info,
604                                 struct osd_device *osd,
605                                 struct dentry *dir, const char *name,
606                                 const struct lu_fid *fid,
607                                 const struct osd_inode_id *id,
608                                 handle_t *th)
609 {
610         struct inode               *parent = dir->d_inode;
611         struct dentry              *child;
612         struct ldiskfs_dir_entry_2 *de;
613         struct buffer_head         *bh;
614         struct inode               *inode;
615         struct dentry              *dentry = &info->oti_obj_dentry;
616         struct osd_inode_id        *oi_id  = &info->oti_id3;
617         struct lustre_mdt_attrs    *lma    = &info->oti_ost_attrs.loa_lma;
618         struct lu_fid              *oi_fid = &lma->lma_self_fid;
619         int                         rc;
620         ENTRY;
621
622         LASSERT(th != NULL);
623         LASSERT(th->h_transaction != NULL);
624
625         child = &info->oti_child_dentry;
626         child->d_parent = dir;
627         child->d_name.hash = 0;
628         child->d_name.name = name;
629         child->d_name.len = strlen(name);
630
631         ll_vfs_dq_init(parent);
632         inode_lock(parent);
633         bh = osd_ldiskfs_find_entry(parent, &child->d_name, &de, NULL, NULL);
634         if (IS_ERR(bh))
635                 GOTO(out, rc = PTR_ERR(bh));
636
637         if (le32_to_cpu(de->inode) == id->oii_ino)
638                 GOTO(out, rc = 1);
639
640         osd_id_gen(oi_id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
641         inode = osd_iget(info, osd, oi_id);
642         if (IS_ERR(inode)) {
643                 rc = PTR_ERR(inode);
644                 if (rc == -ENOENT || rc == -ESTALE)
645                         goto update;
646                 GOTO(out, rc);
647         }
648
649         /* The EA inode should NOT be in OI, old OI scrub may added
650          * such OI mapping by wrong, replace it. */
651         if (unlikely(osd_is_ea_inode(inode))) {
652                 iput(inode);
653                 goto update;
654         }
655
656         rc = osd_get_lma(info, inode, dentry, &info->oti_ost_attrs);
657         if (rc == -ENODATA) {
658                 rc = osd_get_idif(info, inode, dentry, oi_fid);
659                 if (rc > 0 || rc == -ENODATA) {
660                         oi_fid = NULL;
661                         rc = 0;
662                 }
663         }
664         iput(inode);
665
666         if (rc != 0)
667                 GOTO(out, rc);
668
669         /* If the OST-object has neither FID-in-LMA nor FID-in-ff, it is
670          * either a crashed object or a uninitialized one. Replace it. */
671         if (oi_fid != NULL && lu_fid_eq(fid, oi_fid)) {
672                 CERROR("%s: the FID "DFID" is used by two objects: "
673                        "%u/%u %u/%u\n", osd_name(osd), PFID(fid),
674                        oi_id->oii_ino, oi_id->oii_gen,
675                        id->oii_ino, id->oii_gen);
676                 GOTO(out, rc = -EEXIST);
677         }
678
679         if (fid_is_idif(fid) && oi_fid != NULL && fid_is_idif(oi_fid)) {
680                 __u32 idx1 = fid_idif_ost_idx(fid);
681                 __u32 idx2 = fid_idif_ost_idx(oi_fid);
682                 struct ost_id *ostid = &info->oti_ostid;
683                 struct lu_fid *tfid = &info->oti_fid3;
684
685                 LASSERTF(idx1 == 0 || idx1 == osd->od_index,
686                          "invalid given FID "DFID", not match the "
687                          "device index %u\n", PFID(fid), osd->od_index);
688
689                 if (idx1 != idx2) {
690                         if (idx1 == 0 && idx2 == osd->od_index) {
691                                 fid_to_ostid(fid, ostid);
692                                 ostid_to_fid(tfid, ostid, idx2);
693                                 if (lu_fid_eq(tfid, oi_fid)) {
694                                         CERROR("%s: the FID "DFID" is used by "
695                                                "two objects(2): %u/%u %u/%u\n",
696                                                osd_name(osd), PFID(fid),
697                                                oi_id->oii_ino, oi_id->oii_gen,
698                                                id->oii_ino, id->oii_gen);
699
700                                         GOTO(out, rc = -EEXIST);
701                                 }
702                         } else if (idx2 == 0 && idx1 == osd->od_index) {
703                                 fid_to_ostid(oi_fid, ostid);
704                                 ostid_to_fid(tfid, ostid, idx1);
705                                 if (lu_fid_eq(tfid, fid)) {
706                                         CERROR("%s: the FID "DFID" is used by "
707                                                "two objects(2): %u/%u %u/%u\n",
708                                                osd_name(osd), PFID(fid),
709                                                oi_id->oii_ino, oi_id->oii_gen,
710                                                id->oii_ino, id->oii_gen);
711
712                                         GOTO(out, rc = -EEXIST);
713                                 }
714                         }
715                 }
716         }
717
718 update:
719         /* There may be temporary inconsistency: On one hand, the new
720          * object may be referenced by multiple entries, which is out
721          * of our control unless we traverse the whole /O completely,
722          * which is non-flat order and inefficient, should be avoided;
723          * On the other hand, the old object may become orphan if it
724          * is still valid. Since it was referenced by an invalid entry,
725          * making it as invisible temporary may be not worse. OI scrub
726          * will process it later. */
727         rc = ldiskfs_journal_get_write_access(th, bh);
728         if (rc != 0)
729                 GOTO(out, rc);
730
731         de->inode = cpu_to_le32(id->oii_ino);
732         rc = ldiskfs_handle_dirty_metadata(th, NULL, bh);
733
734         GOTO(out, rc);
735
736 out:
737         if (!IS_ERR(bh))
738                 brelse(bh);
739         inode_unlock(parent);
740         return rc;
741 }
742
743 static int osd_obj_del_entry(struct osd_thread_info *info,
744                              struct osd_device *osd,
745                              struct dentry *dird, char *name,
746                              handle_t *th)
747 {
748         struct ldiskfs_dir_entry_2 *de;
749         struct buffer_head         *bh;
750         struct dentry              *child;
751         struct inode               *dir = dird->d_inode;
752         int                         rc;
753         ENTRY;
754
755         LASSERT(th != NULL);
756         LASSERT(th->h_transaction != NULL);
757
758
759         child = &info->oti_child_dentry;
760         child->d_name.hash = 0;
761         child->d_name.name = name;
762         child->d_name.len = strlen(name);
763         child->d_parent = dird;
764         child->d_inode = NULL;
765
766         ll_vfs_dq_init(dir);
767         inode_lock(dir);
768         bh = osd_ldiskfs_find_entry(dir, &child->d_name, &de, NULL, NULL);
769         if (IS_ERR(bh)) {
770                 rc = PTR_ERR(bh);
771         } else {
772                 rc = ldiskfs_delete_entry(th, dir, de, bh);
773                 brelse(bh);
774         }
775         inode_unlock(dir);
776
777         RETURN(rc);
778 }
779
780 static int osd_obj_add_entry(struct osd_thread_info *info,
781                              struct osd_device *osd,
782                              struct dentry *dir, char *name,
783                              const struct osd_inode_id *id,
784                              handle_t *th)
785 {
786         struct dentry *child;
787         struct inode *inode;
788         int rc;
789
790         ENTRY;
791
792         if (OBD_FAIL_CHECK(OBD_FAIL_OSD_COMPAT_NO_ENTRY))
793                 RETURN(0);
794
795         LASSERT(th != NULL);
796         LASSERT(th->h_transaction != NULL);
797
798         inode = info->oti_inode;
799         if (unlikely(inode == NULL)) {
800                 struct ldiskfs_inode_info *lii;
801                 OBD_ALLOC_PTR(lii);
802                 if (lii == NULL)
803                         RETURN(-ENOMEM);
804                 inode = info->oti_inode = &lii->vfs_inode;
805         }
806
807         inode->i_sb = osd_sb(osd);
808         osd_id_to_inode(inode, id);
809         inode->i_mode = S_IFREG; /* for type in ldiskfs dir entry */
810
811         child = &info->oti_child_dentry;
812         child->d_name.hash = 0;
813         child->d_name.name = name;
814         child->d_name.len = strlen(name);
815         child->d_parent = dir;
816         child->d_inode = inode;
817
818         if (OBD_FAIL_CHECK(OBD_FAIL_OSD_COMPAT_INVALID_ENTRY))
819                 inode->i_ino++;
820
821         ll_vfs_dq_init(dir->d_inode);
822         inode_lock(dir->d_inode);
823         rc = osd_ldiskfs_add_entry(info, osd, th, child, inode, NULL);
824         inode_unlock(dir->d_inode);
825
826         RETURN(rc);
827 }
828
829 /**
830  * Use %llu for legacy OST sequences, but use %llx for new
831  * sequences names, so that the O/{seq}/dN/{oid} more closely
832  * follows the DFID/PFID format. This makes it easier to map from
833  * debug messages to objects in the future, and the legacy space
834  * of FID_SEQ_OST_MDT0 will be unused in the future.
835  **/
836 static inline void osd_seq_name(char *seq_name, size_t name_size, u64 seq)
837 {
838         snprintf(seq_name, name_size,
839                  (fid_seq_is_rsvd(seq) ||
840                   fid_seq_is_mdt0(seq)) ? "%llu" : "%llx",
841                  fid_seq_is_idif(seq) ? 0 : seq);
842 }
843
844 static inline void osd_oid_name(char *name, size_t name_size,
845                                 const struct lu_fid *fid, u64 id)
846 {
847         snprintf(name, name_size,
848                  (fid_seq_is_rsvd(fid_seq(fid)) ||
849                   fid_seq_is_mdt0(fid_seq(fid)) ||
850                   fid_seq_is_idif(fid_seq(fid))) ? "%llu" : "%llx", id);
851 }
852
853 /* external locking is required */
854 static int osd_seq_load_locked(struct osd_thread_info *info,
855                                struct osd_device *osd,
856                                struct osd_obj_seq *osd_seq)
857 {
858         struct osd_obj_map  *map = osd->od_ost_map;
859         struct dentry       *seq_dir;
860         int                 rc = 0;
861         int                 i;
862         char                dir_name[32];
863         ENTRY;
864
865         if (osd_seq->oos_root != NULL)
866                 RETURN(0);
867
868         LASSERT(map);
869         LASSERT(map->om_root);
870
871         osd_seq_name(dir_name, sizeof(dir_name), osd_seq->oos_seq);
872
873         seq_dir = simple_mkdir(info->oti_env, osd, map->om_root, NULL, dir_name,
874                                LMAC_NOT_IN_OI | LMAC_FID_ON_OST, 0755, NULL);
875         if (IS_ERR(seq_dir))
876                 GOTO(out_err, rc = PTR_ERR(seq_dir));
877         else if (seq_dir->d_inode == NULL)
878                 GOTO(out_put, rc = -EFAULT);
879
880         osd_seq->oos_root = seq_dir;
881
882         LASSERT(osd_seq->oos_dirs == NULL);
883         OBD_ALLOC(osd_seq->oos_dirs,
884                   sizeof(seq_dir) * osd_seq->oos_subdir_count);
885         if (osd_seq->oos_dirs == NULL)
886                 GOTO(out_put, rc = -ENOMEM);
887
888         for (i = 0; i < osd_seq->oos_subdir_count; i++) {
889                 struct dentry   *dir;
890
891                 snprintf(dir_name, sizeof(dir_name), "d%u", i);
892                 dir = simple_mkdir(info->oti_env, osd, osd_seq->oos_root, NULL,
893                                    dir_name, LMAC_NOT_IN_OI | LMAC_FID_ON_OST,
894                                    0700, NULL);
895                 if (IS_ERR(dir)) {
896                         GOTO(out_free, rc = PTR_ERR(dir));
897                 } else if (dir->d_inode == NULL) {
898                         dput(dir);
899                         GOTO(out_free, rc = -EFAULT);
900                 }
901
902                 osd_seq->oos_dirs[i] = dir;
903         }
904
905         if (rc != 0) {
906 out_free:
907                 for (i = 0; i < osd_seq->oos_subdir_count; i++) {
908                         if (osd_seq->oos_dirs[i] != NULL)
909                                 dput(osd_seq->oos_dirs[i]);
910                 }
911                 OBD_FREE(osd_seq->oos_dirs,
912                          sizeof(seq_dir) * osd_seq->oos_subdir_count);
913 out_put:
914                 dput(seq_dir);
915                 osd_seq->oos_root = NULL;
916         }
917 out_err:
918         RETURN(rc);
919 }
920
921 static struct osd_obj_seq *osd_seq_load(struct osd_thread_info *info,
922                                         struct osd_device *osd, u64 seq)
923 {
924         struct osd_obj_map      *map;
925         struct osd_obj_seq      *osd_seq;
926         int                     rc = 0;
927         ENTRY;
928
929         map = osd->od_ost_map;
930         LASSERT(map);
931         LASSERT(map->om_root);
932
933         osd_seq = osd_seq_find(map, seq);
934         if (likely(osd_seq != NULL))
935                 RETURN(osd_seq);
936
937         /* Serializing init process */
938         mutex_lock(&map->om_dir_init_mutex);
939
940         /* Check whether the seq has been added */
941         read_lock(&map->om_seq_list_lock);
942         osd_seq = osd_seq_find_locked(map, seq);
943         if (osd_seq != NULL) {
944                 read_unlock(&map->om_seq_list_lock);
945                 GOTO(cleanup, rc = 0);
946         }
947         read_unlock(&map->om_seq_list_lock);
948
949         OBD_ALLOC_PTR(osd_seq);
950         if (osd_seq == NULL)
951                 GOTO(cleanup, rc = -ENOMEM);
952
953         INIT_LIST_HEAD(&osd_seq->oos_seq_list);
954         osd_seq->oos_seq = seq;
955         /* Init subdir count to be 32, but each seq can have
956          * different subdir count */
957         osd_seq->oos_subdir_count = map->om_subdir_count;
958         rc = osd_seq_load_locked(info, osd, osd_seq);
959         if (rc != 0)
960                 GOTO(cleanup, rc);
961
962         write_lock(&map->om_seq_list_lock);
963         list_add(&osd_seq->oos_seq_list, &map->om_seq_list);
964         write_unlock(&map->om_seq_list_lock);
965
966 cleanup:
967         mutex_unlock(&map->om_dir_init_mutex);
968         if (rc != 0) {
969                 if (osd_seq != NULL)
970                         OBD_FREE_PTR(osd_seq);
971                 RETURN(ERR_PTR(rc));
972         }
973
974         RETURN(osd_seq);
975 }
976
977 int osd_obj_map_lookup(struct osd_thread_info *info, struct osd_device *dev,
978                        const struct lu_fid *fid, struct osd_inode_id *id)
979 {
980         struct osd_obj_map              *map;
981         struct osd_obj_seq              *osd_seq;
982         struct dentry                   *d_seq;
983         struct dentry                   *child;
984         struct ost_id                   *ostid = &info->oti_ostid;
985         int                             dirn;
986         char                            name[32];
987         struct ldiskfs_dir_entry_2      *de;
988         struct buffer_head              *bh;
989         struct inode                    *dir;
990         struct inode                    *inode;
991         ENTRY;
992
993         /* on the very first lookup we find and open directories */
994
995         map = dev->od_ost_map;
996         LASSERT(map);
997         LASSERT(map->om_root);
998
999         fid_to_ostid(fid, ostid);
1000         osd_seq = osd_seq_load(info, dev, ostid_seq(ostid));
1001         if (IS_ERR(osd_seq))
1002                 RETURN(PTR_ERR(osd_seq));
1003
1004         dirn = ostid_id(ostid) & (osd_seq->oos_subdir_count - 1);
1005         d_seq = osd_seq->oos_dirs[dirn];
1006         LASSERT(d_seq);
1007
1008         osd_oid_name(name, sizeof(name), fid, ostid_id(ostid));
1009
1010         child = &info->oti_child_dentry;
1011         child->d_parent = d_seq;
1012         child->d_name.hash = 0;
1013         child->d_name.name = name;
1014         /* XXX: we can use rc from sprintf() instead of strlen() */
1015         child->d_name.len = strlen(name);
1016
1017         dir = d_seq->d_inode;
1018         inode_lock(dir);
1019         bh = osd_ldiskfs_find_entry(dir, &child->d_name, &de, NULL, NULL);
1020         inode_unlock(dir);
1021
1022         if (IS_ERR(bh))
1023                 RETURN(PTR_ERR(bh));
1024
1025         osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
1026         brelse(bh);
1027
1028         inode = osd_iget(info, dev, id);
1029         if (IS_ERR(inode)) {
1030                 int rc = PTR_ERR(inode);
1031
1032                 RETURN(rc == -ENOENT ? -ESTALE : rc);
1033         }
1034
1035         iput(inode);
1036         RETURN(0);
1037 }
1038
1039 int osd_obj_map_insert(struct osd_thread_info *info,
1040                        struct osd_device *osd,
1041                        const struct lu_fid *fid,
1042                        const struct osd_inode_id *id,
1043                        handle_t *th)
1044 {
1045         struct osd_obj_map      *map;
1046         struct osd_obj_seq      *osd_seq;
1047         struct dentry           *d;
1048         struct ost_id           *ostid = &info->oti_ostid;
1049         u64                      oid;
1050         int                     dirn, rc = 0;
1051         char                    name[32];
1052         ENTRY;
1053
1054         map = osd->od_ost_map;
1055         LASSERT(map);
1056
1057         /* map fid to seq:objid */
1058         fid_to_ostid(fid, ostid);
1059
1060         oid = ostid_id(ostid);
1061         osd_seq = osd_seq_load(info, osd, ostid_seq(ostid));
1062         if (IS_ERR(osd_seq))
1063                 RETURN(PTR_ERR(osd_seq));
1064
1065         dirn = oid & (osd_seq->oos_subdir_count - 1);
1066         d = osd_seq->oos_dirs[dirn];
1067         LASSERT(d);
1068
1069         osd_oid_name(name, sizeof(name), fid, oid);
1070
1071 again:
1072         rc = osd_obj_add_entry(info, osd, d, name, id, th);
1073         if (rc == -EEXIST) {
1074                 rc = osd_obj_update_entry(info, osd, d, name, fid, id, th);
1075                 if (unlikely(rc == -ENOENT))
1076                         goto again;
1077
1078                 if (unlikely(rc == 1))
1079                         RETURN(0);
1080         }
1081
1082         RETURN(rc);
1083 }
1084
1085 int osd_obj_map_delete(struct osd_thread_info *info, struct osd_device *osd,
1086                        const struct lu_fid *fid, handle_t *th)
1087 {
1088         struct osd_obj_map      *map;
1089         struct osd_obj_seq      *osd_seq;
1090         struct dentry           *d;
1091         struct ost_id           *ostid = &info->oti_ostid;
1092         int                     dirn, rc = 0;
1093         char                    name[32];
1094         ENTRY;
1095
1096         map = osd->od_ost_map;
1097         LASSERT(map);
1098
1099         /* map fid to seq:objid */
1100         fid_to_ostid(fid, ostid);
1101
1102         osd_seq = osd_seq_load(info, osd, ostid_seq(ostid));
1103         if (IS_ERR(osd_seq))
1104                 GOTO(cleanup, rc = PTR_ERR(osd_seq));
1105
1106         dirn = ostid_id(ostid) & (osd_seq->oos_subdir_count - 1);
1107         d = osd_seq->oos_dirs[dirn];
1108         LASSERT(d);
1109
1110         osd_oid_name(name, sizeof(name), fid, ostid_id(ostid));
1111         rc = osd_obj_del_entry(info, osd, d, name, th);
1112 cleanup:
1113         RETURN(rc);
1114 }
1115
1116 int osd_obj_map_update(struct osd_thread_info *info,
1117                        struct osd_device *osd,
1118                        const struct lu_fid *fid,
1119                        const struct osd_inode_id *id,
1120                        handle_t *th)
1121 {
1122         struct osd_obj_seq      *osd_seq;
1123         struct dentry           *d;
1124         struct ost_id           *ostid = &info->oti_ostid;
1125         int                     dirn, rc = 0;
1126         char                    name[32];
1127         ENTRY;
1128
1129         fid_to_ostid(fid, ostid);
1130         osd_seq = osd_seq_load(info, osd, ostid_seq(ostid));
1131         if (IS_ERR(osd_seq))
1132                 RETURN(PTR_ERR(osd_seq));
1133
1134         dirn = ostid_id(ostid) & (osd_seq->oos_subdir_count - 1);
1135         d = osd_seq->oos_dirs[dirn];
1136         LASSERT(d);
1137
1138         osd_oid_name(name, sizeof(name), fid, ostid_id(ostid));
1139         rc = osd_obj_update_entry(info, osd, d, name, fid, id, th);
1140
1141         RETURN(rc);
1142 }
1143
1144 int osd_obj_map_recover(struct osd_thread_info *info,
1145                         struct osd_device *osd,
1146                         struct inode *src_parent,
1147                         struct dentry *src_child,
1148                         const struct lu_fid *fid)
1149 {
1150         struct osd_obj_seq         *osd_seq;
1151         struct dentry              *tgt_parent;
1152         struct dentry              *tgt_child = &info->oti_child_dentry;
1153         struct inode               *dir;
1154         struct inode               *inode     = src_child->d_inode;
1155         struct ost_id              *ostid     = &info->oti_ostid;
1156         handle_t                   *jh;
1157         struct ldiskfs_dir_entry_2 *de;
1158         struct buffer_head         *bh;
1159         char                        name[32];
1160         int                         dirn;
1161         int                         rc        = 0;
1162         ENTRY;
1163
1164         if (fid_is_last_id(fid)) {
1165                 osd_seq = osd_seq_load(info, osd, fid_seq(fid));
1166                 if (IS_ERR(osd_seq))
1167                         RETURN(PTR_ERR(osd_seq));
1168
1169                 tgt_parent = osd_seq->oos_root;
1170                 tgt_child->d_name.name = "LAST_ID";
1171                 tgt_child->d_name.len = strlen("LAST_ID");
1172         } else {
1173                 fid_to_ostid(fid, ostid);
1174                 osd_seq = osd_seq_load(info, osd, ostid_seq(ostid));
1175                 if (IS_ERR(osd_seq))
1176                         RETURN(PTR_ERR(osd_seq));
1177
1178                 dirn = ostid_id(ostid) & (osd_seq->oos_subdir_count - 1);
1179                 tgt_parent = osd_seq->oos_dirs[dirn];
1180                 osd_oid_name(name, sizeof(name), fid, ostid_id(ostid));
1181                 tgt_child->d_name.name = name;
1182                 tgt_child->d_name.len = strlen(name);
1183         }
1184         LASSERT(tgt_parent != NULL);
1185
1186         dir = tgt_parent->d_inode;
1187         tgt_child->d_name.hash = 0;
1188         tgt_child->d_parent = tgt_parent;
1189         tgt_child->d_inode = inode;
1190
1191         /* The non-initialized src_child may be destroyed. */
1192         jh = osd_journal_start_sb(osd_sb(osd), LDISKFS_HT_MISC,
1193                                 osd_dto_credits_noquota[DTO_INDEX_DELETE] +
1194                                 osd_dto_credits_noquota[DTO_INDEX_INSERT] +
1195                                 osd_dto_credits_noquota[DTO_OBJECT_DELETE]);
1196         if (IS_ERR(jh))
1197                 RETURN(PTR_ERR(jh));
1198
1199         ll_vfs_dq_init(src_parent);
1200         ll_vfs_dq_init(dir);
1201
1202         inode_lock(src_parent);
1203         inode_lock(dir);
1204         bh = osd_ldiskfs_find_entry(dir, &tgt_child->d_name, &de, NULL, NULL);
1205         if (!IS_ERR(bh)) {
1206                 /* XXX: If some other object occupied the same slot. And If such
1207                  *      inode is zero-sized and with SUID+SGID, then means it is
1208                  *      a new created one. Maybe we can remove it and insert the
1209                  *      original one back to the /O/<seq>/d<x>. But there are
1210                  *      something to be considered:
1211                  *
1212                  *      1) The OST-object under /lost+found has crashed LMA.
1213                  *         So it should not conflict with the current one.
1214                  *
1215                  *      2) There are race conditions that: someone may just want
1216                  *         to modify the current one. Even if the OI scrub takes
1217                  *         the object lock when remove the current one, it still
1218                  *         cause the modification to be lost becasue the target
1219                  *         has been removed when the RPC service thread waiting
1220                  *         for the lock.
1221                  *
1222                  *      So keep it there before we have suitable solution. */
1223                 brelse(bh);
1224                 inode_unlock(dir);
1225                 inode_unlock(src_parent);
1226                 ldiskfs_journal_stop(jh);
1227
1228                 rc = -EEXIST;
1229                 /* If the src object has never been modified, then remove it. */
1230                 if (inode->i_size == 0 && inode->i_mode & S_ISUID &&
1231                     inode->i_mode & S_ISGID) {
1232                         rc = ll_vfs_unlink(src_parent, src_child);
1233                         if (unlikely(rc == -ENOENT))
1234                                 rc = 0;
1235                 }
1236                 RETURN(rc);
1237         }
1238
1239         bh = osd_ldiskfs_find_entry(src_parent, &src_child->d_name, &de,
1240                                     NULL, NULL);
1241         if (unlikely(IS_ERR(bh)))
1242                 GOTO(unlock, rc = PTR_ERR(bh));
1243
1244         rc = ldiskfs_delete_entry(jh, src_parent, de, bh);
1245         brelse(bh);
1246         if (rc != 0)
1247                 GOTO(unlock, rc);
1248
1249         rc = osd_ldiskfs_add_entry(info, osd, jh, tgt_child, inode, NULL);
1250
1251         GOTO(unlock, rc);
1252
1253 unlock:
1254         inode_unlock(dir);
1255         inode_unlock(src_parent);
1256         ldiskfs_journal_stop(jh);
1257         return rc;
1258 }
1259
1260 static struct dentry *
1261 osd_object_spec_find(struct osd_thread_info *info, struct osd_device *osd,
1262                      const struct lu_fid *fid, char **name)
1263 {
1264         struct dentry *root = ERR_PTR(-ENOENT);
1265
1266         if (fid_is_last_id(fid)) {
1267                 struct osd_obj_seq *osd_seq;
1268
1269                 /* on creation of LAST_ID we create O/<seq> hierarchy */
1270                 osd_seq = osd_seq_load(info, osd, fid_seq(fid));
1271                 if (IS_ERR(osd_seq))
1272                         RETURN((struct dentry *)osd_seq);
1273
1274                 *name = "LAST_ID";
1275                 root = osd_seq->oos_root;
1276         } else {
1277                 *name = osd_lf_fid2name(fid);
1278                 if (*name == NULL)
1279                         CWARN("UNKNOWN COMPAT FID "DFID"\n", PFID(fid));
1280                 else if ((*name)[0])
1281                         root = osd_sb(osd)->s_root;
1282         }
1283
1284         return root;
1285 }
1286
1287 int osd_obj_spec_update(struct osd_thread_info *info, struct osd_device *osd,
1288                         const struct lu_fid *fid, const struct osd_inode_id *id,
1289                         handle_t *th)
1290 {
1291         struct dentry   *root;
1292         char            *name = NULL;
1293         int              rc;
1294         ENTRY;
1295
1296         root = osd_object_spec_find(info, osd, fid, &name);
1297         if (!IS_ERR(root)) {
1298                 rc = osd_obj_update_entry(info, osd, root, name, fid, id, th);
1299         } else {
1300                 rc = PTR_ERR(root);
1301                 if (rc == -ENOENT)
1302                         rc = 1;
1303         }
1304
1305         RETURN(rc);
1306 }
1307
1308 int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
1309                         const struct lu_fid *fid, const struct osd_inode_id *id,
1310                         handle_t *th)
1311 {
1312         struct dentry   *root;
1313         char            *name = NULL;
1314         int              rc;
1315         ENTRY;
1316
1317         root = osd_object_spec_find(info, osd, fid, &name);
1318         if (!IS_ERR(root)) {
1319                 rc = osd_obj_add_entry(info, osd, root, name, id, th);
1320         } else {
1321                 rc = PTR_ERR(root);
1322                 if (rc == -ENOENT)
1323                         rc = 0;
1324         }
1325
1326         RETURN(rc);
1327 }
1328
1329 int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd,
1330                         const struct lu_fid *fid, struct osd_inode_id *id)
1331 {
1332         struct dentry   *root;
1333         struct dentry   *dentry;
1334         struct inode    *inode;
1335         char            *name = NULL;
1336         int             rc = -ENOENT;
1337         ENTRY;
1338
1339         if (fid_is_last_id(fid)) {
1340                 struct osd_obj_seq *osd_seq;
1341
1342                 osd_seq = osd_seq_load(info, osd, fid_seq(fid));
1343                 if (IS_ERR(osd_seq))
1344                         RETURN(PTR_ERR(osd_seq));
1345                 root = osd_seq->oos_root;
1346                 name = "LAST_ID";
1347         } else {
1348                 root = osd_sb(osd)->s_root;
1349                 name = osd_lf_fid2name(fid);
1350                 if (name == NULL || strlen(name) == 0)
1351                         RETURN(-ENOENT);
1352         }
1353
1354         dentry = ll_lookup_one_len(name, root, strlen(name));
1355         if (!IS_ERR(dentry)) {
1356                 inode = dentry->d_inode;
1357                 if (inode) {
1358                         if (is_bad_inode(inode)) {
1359                                 rc = -EIO;
1360                         } else {
1361                                 osd_id_gen(id, inode->i_ino,
1362                                            inode->i_generation);
1363                                 rc = 0;
1364                         }
1365                 }
1366                 /* if dentry is accessible after osd_compat_spec_insert it
1367                  * will still contain NULL inode, so don't keep it in cache */
1368                 d_invalidate(dentry);
1369                 dput(dentry);
1370         }
1371
1372         RETURN(rc);
1373 }