Whamcloud - gitweb
LU-2158 lvfs: move ldiskfs only functions to osd-ldiskfs
[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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/osd/osd_compat.c
37  *
38  * on-disk structure for managing /O
39  *
40  * Author: Alex Zhuravlev <bzzz@whamcloud.com>
41  */
42
43 /* LUSTRE_VERSION_CODE */
44 #include <lustre_ver.h>
45 /* prerequisite for linux/xattr.h */
46 #include <linux/types.h>
47 /* prerequisite for linux/xattr.h */
48 #include <linux/fs.h>
49
50 /*
51  * struct OBD_{ALLOC,FREE}*()
52  * OBD_FAIL_CHECK
53  */
54 #include <obd_support.h>
55
56 #include "osd_internal.h"
57 #include "osd_oi.h"
58
59 static void osd_push_ctxt(const struct osd_device *dev,
60                           struct lvfs_run_ctxt *newctxt,
61                           struct lvfs_run_ctxt *save)
62 {
63         OBD_SET_CTXT_MAGIC(newctxt);
64         newctxt->pwdmnt = dev->od_mnt;
65         newctxt->pwd = dev->od_mnt->mnt_root;
66         newctxt->fs = get_ds();
67
68         push_ctxt(save, newctxt, NULL);
69 }
70
71 static void osd_pop_ctxt(const struct osd_device *dev,
72                          struct lvfs_run_ctxt *new,
73                          struct lvfs_run_ctxt *save)
74 {
75         pop_ctxt(save, new, NULL);
76 }
77
78 /* utility to make a directory */
79 static struct dentry *simple_mkdir(struct dentry *dir, struct vfsmount *mnt,
80                                    const char *name, int mode, int fix)
81 {
82         struct dentry *dchild;
83         int err = 0;
84         ENTRY;
85
86         // ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
87         CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name);
88         dchild = ll_lookup_one_len(name, dir, strlen(name));
89         if (IS_ERR(dchild))
90                 GOTO(out_up, dchild);
91
92         if (dchild->d_inode) {
93                 int old_mode = dchild->d_inode->i_mode;
94                 if (!S_ISDIR(old_mode)) {
95                         CERROR("found %s (%lu/%u) is mode %o\n", name,
96                                dchild->d_inode->i_ino,
97                                dchild->d_inode->i_generation, old_mode);
98                         GOTO(out_err, err = -ENOTDIR);
99                 }
100
101                 /* Fixup directory permissions if necessary */
102                 if (fix && (old_mode & S_IALLUGO) != (mode & S_IALLUGO)) {
103                         CDEBUG(D_CONFIG,
104                                "fixing permissions on %s from %o to %o\n",
105                                name, old_mode, mode);
106                         dchild->d_inode->i_mode = (mode & S_IALLUGO) |
107                                                   (old_mode & ~S_IALLUGO);
108                         mark_inode_dirty(dchild->d_inode);
109                 }
110                 GOTO(out_up, dchild);
111         }
112
113         err = ll_vfs_mkdir(dir->d_inode, dchild, mnt, mode);
114         if (err)
115                 GOTO(out_err, err);
116
117         RETURN(dchild);
118
119 out_err:
120         dput(dchild);
121         dchild = ERR_PTR(err);
122 out_up:
123         return dchild;
124 }
125
126 int osd_last_rcvd_subdir_count(struct osd_device *osd)
127 {
128         struct lr_server_data lsd;
129         struct dentry        *dlast;
130         loff_t                off;
131         int                   rc = 0;
132         int                   count = FILTER_SUBDIR_COUNT;
133
134         ENTRY;
135
136         dlast = ll_lookup_one_len(LAST_RCVD, osd_sb(osd)->s_root,
137                                   strlen(LAST_RCVD));
138         if (IS_ERR(dlast))
139                 return PTR_ERR(dlast);
140         else if (dlast->d_inode == NULL)
141                 goto out;
142
143         off = 0;
144         rc = osd_ldiskfs_read(dlast->d_inode, &lsd, sizeof(lsd), &off);
145         if (rc == sizeof(lsd)) {
146                 CDEBUG(D_INFO, "read last_rcvd header, uuid = %s, "
147                        "subdir count = %d\n", lsd.lsd_uuid,
148                        lsd.lsd_subdir_count);
149                 if (le16_to_cpu(lsd.lsd_subdir_count) > 0)
150                         count = le16_to_cpu(lsd.lsd_subdir_count);
151         } else if (rc != 0) {
152                 CERROR("Can't read last_rcvd file, rc = %d\n", rc);
153                 if (rc > 0)
154                         rc = -EFAULT;
155                 dput(dlast);
156                 return rc;
157         }
158 out:
159         dput(dlast);
160         LASSERT(count > 0);
161         return count;
162 }
163
164 /*
165  * directory structure on legacy MDT:
166  *
167  * REM_OBJ_DIR/ per mdt
168  * AGENT_OBJ_DIR/ per mdt
169  *
170  */
171 static const char remote_obj_dir[] = "REM_OBJ_DIR";
172 static const char agent_obj_dir[] = "AGENT_OBJ_DIR";
173 int osd_mdt_init(struct osd_device *dev)
174 {
175         struct lvfs_run_ctxt  new;
176         struct lvfs_run_ctxt  save;
177         struct dentry   *parent;
178         struct osd_mdobj_map *omm;
179         struct dentry   *d;
180         int                rc = 0;
181         ENTRY;
182
183         OBD_ALLOC_PTR(dev->od_mdt_map);
184         if (dev->od_mdt_map == NULL)
185                 RETURN(-ENOMEM);
186
187         omm = dev->od_mdt_map;
188
189         LASSERT(dev->od_fsops);
190
191         parent = osd_sb(dev)->s_root;
192         osd_push_ctxt(dev, &new, &save);
193
194         d = simple_mkdir(parent, dev->od_mnt, agent_obj_dir,
195                          0755, 1);
196         if (IS_ERR(d))
197                 GOTO(cleanup, rc = PTR_ERR(d));
198
199         omm->omm_agent_dentry = d;
200
201 cleanup:
202         pop_ctxt(&save, &new, NULL);
203         if (rc) {
204                 if (omm->omm_agent_dentry != NULL)
205                         dput(omm->omm_agent_dentry);
206                 OBD_FREE_PTR(omm);
207                 dev->od_mdt_map = NULL;
208         }
209         RETURN(rc);
210 }
211
212 static void osd_mdt_fini(struct osd_device *osd)
213 {
214         struct osd_mdobj_map *omm = osd->od_mdt_map;
215
216         if (omm == NULL)
217                 return;
218
219         if (omm->omm_agent_dentry)
220                 dput(omm->omm_agent_dentry);
221
222         OBD_FREE_PTR(omm);
223         osd->od_ost_map = NULL;
224 }
225
226 int osd_add_to_agent(const struct lu_env *env, struct osd_device *osd,
227                      struct osd_object *obj, struct osd_thandle *oh)
228 {
229         struct osd_mdobj_map    *omm = osd->od_mdt_map;
230         struct osd_thread_info  *oti = osd_oti_get(env);
231         char                    *name = oti->oti_name;
232         struct dentry           *agent;
233         struct dentry           *parent;
234         int                     rc;
235
236         parent = omm->omm_agent_dentry;
237         sprintf(name, DFID_NOBRACE, PFID(lu_object_fid(&obj->oo_dt.do_lu)));
238         agent = osd_child_dentry_by_inode(env, parent->d_inode,
239                                           name, strlen(name));
240         mutex_lock(&parent->d_inode->i_mutex);
241         rc = osd_ldiskfs_add_entry(oh->ot_handle, agent, obj->oo_inode, NULL);
242         LASSERTF(parent->d_inode->i_nlink > 1, "%s: agent inode nlink %d",
243                  osd_name(osd), parent->d_inode->i_nlink);
244         parent->d_inode->i_nlink++;
245         mark_inode_dirty(parent->d_inode);
246         mutex_unlock(&parent->d_inode->i_mutex);
247         RETURN(rc);
248 }
249
250 int osd_delete_from_agent(const struct lu_env *env, struct osd_device *osd,
251                           struct osd_object *obj, struct osd_thandle *oh)
252 {
253         struct osd_mdobj_map       *omm = osd->od_mdt_map;
254         struct osd_thread_info     *oti = osd_oti_get(env);
255         char                       *name = oti->oti_name;
256         struct dentry              *agent;
257         struct dentry              *parent;
258         struct ldiskfs_dir_entry_2 *de;
259         struct buffer_head         *bh;
260         int                        rc;
261
262         parent = omm->omm_agent_dentry;
263         sprintf(name, DFID_NOBRACE, PFID(lu_object_fid(&obj->oo_dt.do_lu)));
264         agent = osd_child_dentry_by_inode(env, parent->d_inode,
265                                           name, strlen(name));
266         mutex_lock(&parent->d_inode->i_mutex);
267         bh = osd_ldiskfs_find_entry(parent->d_inode, agent, &de, NULL);
268         if (bh == NULL) {
269                 mutex_unlock(&parent->d_inode->i_mutex);
270                 RETURN(-ENOENT);
271         }
272         rc = ldiskfs_delete_entry(oh->ot_handle, parent->d_inode, de, bh);
273         LASSERTF(parent->d_inode->i_nlink > 1, "%s: agent inode nlink %d",
274                  osd_name(osd), parent->d_inode->i_nlink);
275         parent->d_inode->i_nlink--;
276         mark_inode_dirty(parent->d_inode);
277         mutex_unlock(&parent->d_inode->i_mutex);
278         brelse(bh);
279         RETURN(rc);
280 }
281
282 /*
283  * directory structure on legacy OST:
284  *
285  * O/<seq>/d0-31/<objid>
286  * O/<seq>/LAST_ID
287  * last_rcvd
288  * LAST_GROUP
289  * CONFIGS
290  *
291  */
292 int osd_ost_init(struct osd_device *dev)
293 {
294         struct lvfs_run_ctxt  new;
295         struct lvfs_run_ctxt  save;
296         struct dentry        *rootd = osd_sb(dev)->s_root;
297         struct dentry        *d;
298         int                   rc;
299         ENTRY;
300
301         OBD_ALLOC_PTR(dev->od_ost_map);
302         if (dev->od_ost_map == NULL)
303                 RETURN(-ENOMEM);
304
305         /* to get subdir count from last_rcvd */
306         rc = osd_last_rcvd_subdir_count(dev);
307         if (rc < 0) {
308                 OBD_FREE_PTR(dev->od_ost_map);
309                 RETURN(rc);
310         }
311
312         dev->od_ost_map->om_subdir_count = rc;
313         rc = 0;
314
315         CFS_INIT_LIST_HEAD(&dev->od_ost_map->om_seq_list);
316         rwlock_init(&dev->od_ost_map->om_seq_list_lock);
317         sema_init(&dev->od_ost_map->om_dir_init_sem, 1);
318
319         LASSERT(dev->od_fsops);
320         osd_push_ctxt(dev, &new, &save);
321
322         d = simple_mkdir(rootd, dev->od_mnt, "O", 0755, 1);
323         if (IS_ERR(d))
324                 GOTO(cleanup, rc = PTR_ERR(d));
325
326         ldiskfs_set_inode_state(d->d_inode, LDISKFS_STATE_LUSTRE_NO_OI);
327         dev->od_ost_map->om_root = d;
328
329 cleanup:
330         osd_pop_ctxt(dev, &new, &save);
331         if (IS_ERR(d)) {
332                 OBD_FREE_PTR(dev->od_ost_map);
333                 RETURN(PTR_ERR(d));
334         }
335
336         RETURN(rc);
337 }
338
339 static void osd_seq_free(struct osd_obj_map *map,
340                          struct osd_obj_seq *osd_seq)
341 {
342         int j;
343
344         cfs_list_del_init(&osd_seq->oos_seq_list);
345
346         if (osd_seq->oos_dirs) {
347                 for (j = 0; j < osd_seq->oos_subdir_count; j++) {
348                         if (osd_seq->oos_dirs[j])
349                                 dput(osd_seq->oos_dirs[j]);
350                 }
351                 OBD_FREE(osd_seq->oos_dirs,
352                          sizeof(struct dentry *) * osd_seq->oos_subdir_count);
353         }
354
355         if (osd_seq->oos_root)
356                 dput(osd_seq->oos_root);
357
358         OBD_FREE_PTR(osd_seq);
359 }
360
361 static void osd_ost_fini(struct osd_device *osd)
362 {
363         struct osd_obj_seq    *osd_seq;
364         struct osd_obj_seq    *tmp;
365         struct osd_obj_map    *map = osd->od_ost_map;
366         ENTRY;
367
368         if (map == NULL)
369                 return;
370
371         write_lock(&map->om_seq_list_lock);
372         cfs_list_for_each_entry_safe(osd_seq, tmp,
373                                      &map->om_seq_list,
374                                      oos_seq_list) {
375                 osd_seq_free(map, osd_seq);
376         }
377         write_unlock(&map->om_seq_list_lock);
378         if (map->om_root)
379                 dput(map->om_root);
380         OBD_FREE_PTR(map);
381         osd->od_ost_map = NULL;
382         EXIT;
383 }
384
385 int osd_obj_map_init(struct osd_device *dev)
386 {
387         int rc;
388         ENTRY;
389
390         /* prepare structures for OST */
391         rc = osd_ost_init(dev);
392         if (rc)
393                 RETURN(rc);
394
395         /* prepare structures for MDS */
396         rc = osd_mdt_init(dev);
397
398         RETURN(rc);
399 }
400
401 struct osd_obj_seq *osd_seq_find_locked(struct osd_obj_map *map, obd_seq seq)
402 {
403         struct osd_obj_seq *osd_seq;
404
405         cfs_list_for_each_entry(osd_seq, &map->om_seq_list, oos_seq_list) {
406                 if (osd_seq->oos_seq == seq)
407                         return osd_seq;
408         }
409         return NULL;
410 }
411
412 struct osd_obj_seq *osd_seq_find(struct osd_obj_map *map, obd_seq seq)
413 {
414         struct osd_obj_seq *osd_seq;
415
416         read_lock(&map->om_seq_list_lock);
417         osd_seq = osd_seq_find_locked(map, seq);
418         read_unlock(&map->om_seq_list_lock);
419         return osd_seq;
420 }
421
422 void osd_obj_map_fini(struct osd_device *dev)
423 {
424         osd_ost_fini(dev);
425         osd_mdt_fini(dev);
426 }
427
428 static int osd_obj_del_entry(struct osd_thread_info *info,
429                              struct osd_device *osd,
430                              struct dentry *dird, char *name,
431                              struct thandle *th)
432 {
433         struct ldiskfs_dir_entry_2 *de;
434         struct buffer_head         *bh;
435         struct osd_thandle         *oh;
436         struct dentry              *child;
437         struct inode               *dir = dird->d_inode;
438         int                         rc;
439         ENTRY;
440
441         oh = container_of(th, struct osd_thandle, ot_super);
442         LASSERT(oh->ot_handle != NULL);
443         LASSERT(oh->ot_handle->h_transaction != NULL);
444
445
446         child = &info->oti_child_dentry;
447         child->d_name.hash = 0;
448         child->d_name.name = name;
449         child->d_name.len = strlen(name);
450         child->d_parent = dird;
451         child->d_inode = NULL;
452
453         ll_vfs_dq_init(dir);
454         mutex_lock(&dir->i_mutex);
455         rc = -ENOENT;
456         bh = osd_ldiskfs_find_entry(dir, child, &de, NULL);
457         if (bh) {
458                 rc = ldiskfs_delete_entry(oh->ot_handle, dir, de, bh);
459                 brelse(bh);
460         }
461         mutex_unlock(&dir->i_mutex);
462
463         RETURN(rc);
464 }
465
466 int osd_obj_add_entry(struct osd_thread_info *info,
467                       struct osd_device *osd,
468                       struct dentry *dir, char *name,
469                       const struct osd_inode_id *id,
470                       struct thandle *th)
471 {
472         struct osd_thandle *oh;
473         struct dentry *child;
474         struct inode *inode;
475         int rc;
476
477         ENTRY;
478
479         oh = container_of(th, struct osd_thandle, ot_super);
480         LASSERT(oh->ot_handle != NULL);
481         LASSERT(oh->ot_handle->h_transaction != NULL);
482
483         inode = &info->oti_inode;
484         inode->i_sb = osd_sb(osd);
485         osd_id_to_inode(inode, id);
486         inode->i_mode = S_IFREG; /* for type in ldiskfs dir entry */
487
488         child = &info->oti_child_dentry;
489         child->d_name.hash = 0;
490         child->d_name.name = name;
491         child->d_name.len = strlen(name);
492         child->d_parent = dir;
493         child->d_inode = inode;
494
495         ll_vfs_dq_init(dir->d_inode);
496         mutex_lock(&dir->d_inode->i_mutex);
497         rc = osd_ldiskfs_add_entry(oh->ot_handle, child, inode, NULL);
498         mutex_unlock(&dir->d_inode->i_mutex);
499
500         RETURN(rc);
501 }
502
503 /**
504  * Use LPU64 for legacy OST sequences, but use LPX64i for new
505  * sequences names, so that the O/{seq}/dN/{oid} more closely
506  * follows the DFID/PFID format. This makes it easier to map from
507  * debug messages to objects in the future, and the legacy space
508  * of FID_SEQ_OST_MDT0 will be unused in the future.
509  **/
510 static inline void osd_seq_name(char *seq_name, obd_seq seq)
511 {
512         sprintf(seq_name, (fid_seq_is_rsvd(seq) ||
513                            fid_seq_is_mdt0(seq)) ? LPU64 : LPX64i,
514                 fid_seq_is_idif(seq) ? 0 : seq);
515 }
516
517 static inline void osd_oid_name(char *name, const struct lu_fid *fid, obd_id id)
518 {
519         sprintf(name, (fid_seq_is_rsvd(fid_seq(fid)) ||
520                 fid_seq_is_mdt0(fid_seq(fid)) ||
521                 fid_seq_is_idif(fid_seq(fid))) ? LPU64 : LPX64i, id);
522 }
523
524 /* external locking is required */
525 static int osd_seq_load_locked(struct osd_device *osd,
526                                struct osd_obj_seq *osd_seq)
527 {
528         struct osd_obj_map  *map = osd->od_ost_map;
529         struct dentry       *seq_dir;
530         int                 rc = 0;
531         int                 i;
532         char                seq_name[32];
533         ENTRY;
534
535         if (osd_seq->oos_root != NULL)
536                 RETURN(0);
537
538         LASSERT(map);
539         LASSERT(map->om_root);
540
541         osd_seq_name(seq_name, osd_seq->oos_seq);
542
543         seq_dir = simple_mkdir(map->om_root, osd->od_mnt, seq_name, 0755, 1);
544         if (IS_ERR(seq_dir))
545                 GOTO(out_err, rc = PTR_ERR(seq_dir));
546         else if (seq_dir->d_inode == NULL)
547                 GOTO(out_put, rc = -EFAULT);
548
549         ldiskfs_set_inode_state(seq_dir->d_inode, LDISKFS_STATE_LUSTRE_NO_OI);
550         osd_seq->oos_root = seq_dir;
551
552         LASSERT(osd_seq->oos_dirs == NULL);
553         OBD_ALLOC(osd_seq->oos_dirs,
554                   sizeof(seq_dir) * osd_seq->oos_subdir_count);
555         if (osd_seq->oos_dirs == NULL)
556                 GOTO(out_put, rc = -ENOMEM);
557
558         for (i = 0; i < osd_seq->oos_subdir_count; i++) {
559                 struct dentry   *dir;
560                 char         name[32];
561
562                 sprintf(name, "d%u", i);
563                 dir = simple_mkdir(osd_seq->oos_root, osd->od_mnt, name,
564                                    0700, 1);
565                 if (IS_ERR(dir)) {
566                         rc = PTR_ERR(dir);
567                 } else if (dir->d_inode) {
568                         ldiskfs_set_inode_state(dir->d_inode,
569                                                 LDISKFS_STATE_LUSTRE_NO_OI);
570                         osd_seq->oos_dirs[i] = dir;
571                         rc = 0;
572                 } else {
573                         LBUG();
574                 }
575         }
576
577         if (rc != 0)
578                 osd_seq_free(map, osd_seq);
579 out_put:
580         if (rc != 0) {
581                 dput(seq_dir);
582                 osd_seq->oos_root = NULL;
583         }
584 out_err:
585         RETURN(rc);
586 }
587
588 struct osd_obj_seq *osd_seq_load(struct osd_device *osd, obd_seq seq)
589 {
590         struct osd_obj_map      *map;
591         struct osd_obj_seq      *osd_seq;
592         int                     rc = 0;
593         ENTRY;
594
595         map = osd->od_ost_map;
596         LASSERT(map);
597         LASSERT(map->om_root);
598
599         osd_seq = osd_seq_find(map, seq);
600         if (likely(osd_seq != NULL))
601                 RETURN(osd_seq);
602
603         /* Serializing init process */
604         down(&map->om_dir_init_sem);
605
606         /* Check whether the seq has been added */
607         read_lock(&map->om_seq_list_lock);
608         osd_seq = osd_seq_find_locked(map, seq);
609         if (osd_seq != NULL) {
610                 read_unlock(&map->om_seq_list_lock);
611                 GOTO(cleanup, rc = 0);
612         }
613         read_unlock(&map->om_seq_list_lock);
614
615         OBD_ALLOC_PTR(osd_seq);
616         if (osd_seq == NULL)
617                 GOTO(cleanup, rc = -ENOMEM);
618
619         CFS_INIT_LIST_HEAD(&osd_seq->oos_seq_list);
620         osd_seq->oos_seq = seq;
621         /* Init subdir count to be 32, but each seq can have
622          * different subdir count */
623         osd_seq->oos_subdir_count = map->om_subdir_count;
624         rc = osd_seq_load_locked(osd, osd_seq);
625         if (rc != 0)
626                 GOTO(cleanup, rc);
627
628         write_lock(&map->om_seq_list_lock);
629         cfs_list_add(&osd_seq->oos_seq_list, &map->om_seq_list);
630         write_unlock(&map->om_seq_list_lock);
631
632 cleanup:
633         up(&map->om_dir_init_sem);
634         if (rc != 0) {
635                 if (osd_seq != NULL)
636                         OBD_FREE_PTR(osd_seq);
637                 RETURN(ERR_PTR(rc));
638         }
639
640         RETURN(osd_seq);
641 }
642
643 int osd_obj_map_lookup(struct osd_thread_info *info, struct osd_device *dev,
644                        const struct lu_fid *fid, struct osd_inode_id *id)
645 {
646         struct osd_obj_map              *map;
647         struct osd_obj_seq              *osd_seq;
648         struct dentry                   *d_seq;
649         struct dentry                   *child;
650         struct ost_id                   *ostid = &info->oti_ostid;
651         int                             dirn;
652         char                            name[32];
653         struct ldiskfs_dir_entry_2      *de;
654         struct buffer_head              *bh;
655         struct inode                    *dir;
656         struct inode                    *inode;
657         ENTRY;
658
659         /* on the very first lookup we find and open directories */
660
661         map = dev->od_ost_map;
662         LASSERT(map);
663         LASSERT(map->om_root);
664
665         fid_ostid_pack(fid, ostid);
666         osd_seq = osd_seq_load(dev, ostid->oi_seq);
667         if (IS_ERR(osd_seq))
668                 RETURN(PTR_ERR(osd_seq));
669
670         dirn = ostid->oi_id & (osd_seq->oos_subdir_count - 1);
671         d_seq = osd_seq->oos_dirs[dirn];
672         LASSERT(d_seq);
673
674         osd_oid_name(name, fid, ostid->oi_id);
675
676         child = &info->oti_child_dentry;
677         child->d_parent = d_seq;
678         child->d_name.hash = 0;
679         child->d_name.name = name;
680         /* XXX: we can use rc from sprintf() instead of strlen() */
681         child->d_name.len = strlen(name);
682
683         dir = d_seq->d_inode;
684         mutex_lock(&dir->i_mutex);
685         bh = osd_ldiskfs_find_entry(dir, child, &de, NULL);
686         mutex_unlock(&dir->i_mutex);
687
688         if (bh == NULL)
689                 RETURN(-ENOENT);
690
691         osd_id_gen(id, le32_to_cpu(de->inode), OSD_OII_NOGEN);
692         brelse(bh);
693
694         inode = osd_iget(info, dev, id);
695         if (IS_ERR(inode))
696                 RETURN(PTR_ERR(inode));
697
698         iput(inode);
699         RETURN(0);
700 }
701
702 int osd_obj_map_insert(struct osd_thread_info *info,
703                        struct osd_device *osd,
704                        const struct lu_fid *fid,
705                        const struct osd_inode_id *id,
706                        struct thandle *th)
707 {
708         struct osd_obj_map      *map;
709         struct osd_obj_seq      *osd_seq;
710         struct dentry           *d;
711         struct ost_id           *ostid = &info->oti_ostid;
712         int                     dirn, rc = 0;
713         char                    name[32];
714         ENTRY;
715
716         map = osd->od_ost_map;
717         LASSERT(map);
718
719         /* map fid to seq:objid */
720         fid_ostid_pack(fid, ostid);
721
722         osd_seq = osd_seq_load(osd, ostid->oi_seq);
723         if (IS_ERR(osd_seq))
724                 RETURN(PTR_ERR(osd_seq));
725
726         dirn = ostid->oi_id & (osd_seq->oos_subdir_count - 1);
727         d = osd_seq->oos_dirs[dirn];
728         LASSERT(d);
729
730         osd_oid_name(name, fid, ostid->oi_id);
731         rc = osd_obj_add_entry(info, osd, d, name, id, th);
732
733         RETURN(rc);
734 }
735
736 int osd_obj_map_delete(struct osd_thread_info *info, struct osd_device *osd,
737                        const struct lu_fid *fid, struct thandle *th)
738 {
739         struct osd_obj_map      *map;
740         struct osd_obj_seq      *osd_seq;
741         struct dentry           *d;
742         struct ost_id           *ostid = &info->oti_ostid;
743         int                     dirn, rc = 0;
744         char                    name[32];
745         ENTRY;
746
747         map = osd->od_ost_map;
748         LASSERT(map);
749
750         /* map fid to seq:objid */
751         fid_ostid_pack(fid, ostid);
752
753         osd_seq = osd_seq_load(osd, ostid->oi_seq);
754         if (IS_ERR(osd_seq))
755                 GOTO(cleanup, rc = PTR_ERR(osd_seq));
756
757         dirn = ostid->oi_id & (osd_seq->oos_subdir_count - 1);
758         d = osd_seq->oos_dirs[dirn];
759         LASSERT(d);
760
761         osd_oid_name(name, fid, ostid->oi_id);
762         rc = osd_obj_del_entry(info, osd, d, name, th);
763 cleanup:
764         RETURN(rc);
765 }
766
767 int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
768                         const struct lu_fid *fid,
769                         const struct osd_inode_id *id,
770                         struct thandle *th)
771 {
772         struct osd_obj_map      *map = osd->od_ost_map;
773         struct dentry           *root = osd_sb(osd)->s_root;
774         char                    *name;
775         int                     rc = 0;
776         ENTRY;
777
778         if (fid_is_last_id(fid)) {
779                 struct osd_obj_seq      *osd_seq;
780
781                 /* on creation of LAST_ID we create O/<seq> hierarchy */
782                 LASSERT(map);
783                 osd_seq = osd_seq_load(osd, fid_seq(fid));
784                 if (IS_ERR(osd_seq))
785                         RETURN(PTR_ERR(osd_seq));
786                 rc = osd_obj_add_entry(info, osd, osd_seq->oos_root,
787                                        "LAST_ID", id, th);
788         } else {
789                 name = osd_lf_fid2name(fid);
790                 if (name == NULL)
791                         CWARN("UNKNOWN COMPAT FID "DFID"\n", PFID(fid));
792                 else if (name[0])
793                         rc = osd_obj_add_entry(info, osd, root, name, id, th);
794         }
795
796         RETURN(rc);
797 }
798
799 int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd,
800                         const struct lu_fid *fid, struct osd_inode_id *id)
801 {
802         struct dentry   *root;
803         struct dentry   *dentry;
804         struct inode    *inode;
805         char            *name;
806         int             rc = -ENOENT;
807         ENTRY;
808
809         if (fid_is_last_id(fid)) {
810                 struct osd_obj_seq *osd_seq;
811
812                 osd_seq = osd_seq_load(osd, fid_seq(fid));
813                 if (IS_ERR(osd_seq))
814                         RETURN(PTR_ERR(osd_seq));
815                 root = osd_seq->oos_root;
816                 name = "LAST_ID";
817         } else {
818                 root = osd_sb(osd)->s_root;
819                 name = osd_lf_fid2name(fid);
820                 if (name == NULL || strlen(name) == 0)
821                         RETURN(-ENOENT);
822         }
823
824         dentry = ll_lookup_one_len(name, root, strlen(name));
825         if (!IS_ERR(dentry)) {
826                 inode = dentry->d_inode;
827                 if (inode) {
828                         if (is_bad_inode(inode)) {
829                                 rc = -EIO;
830                         } else {
831                                 osd_id_gen(id, inode->i_ino,
832                                            inode->i_generation);
833                                 rc = 0;
834                         }
835                 }
836                 /* if dentry is accessible after osd_compat_spec_insert it
837                  * will still contain NULL inode, so don't keep it in cache */
838                 d_invalidate(dentry);
839                 dput(dentry);
840         }
841
842         RETURN(rc);
843 }