Whamcloud - gitweb
27367ecb4f8f6f0450594fa041c4a142c0123c6f
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
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_handler.c
37  *
38  * Top-level entry points into osd module
39  *
40  * Author: Nikita Danilov <nikita@clusterfs.com>
41  *         Pravin Shelar <pravin.shelar@sun.com> : Added fid in dirent
42  */
43
44 #ifndef EXPORT_SYMTAB
45 # define EXPORT_SYMTAB
46 #endif
47 #define DEBUG_SUBSYSTEM S_MDS
48
49 #include <linux/module.h>
50
51 /* LUSTRE_VERSION_CODE */
52 #include <lustre_ver.h>
53 /* prerequisite for linux/xattr.h */
54 #include <linux/types.h>
55 /* prerequisite for linux/xattr.h */
56 #include <linux/fs.h>
57 /* XATTR_{REPLACE,CREATE} */
58 #include <linux/xattr.h>
59 /* simple_mkdir() */
60 #include <lvfs.h>
61
62 /*
63  * struct OBD_{ALLOC,FREE}*()
64  * OBD_FAIL_CHECK
65  */
66 #include <obd_support.h>
67 /* struct ptlrpc_thread */
68 #include <lustre_net.h>
69
70 /* fid_is_local() */
71 #include <lustre_fid.h>
72
73 #include "osd_internal.h"
74 #include "osd_igif.h"
75
76 /* llo_* api support */
77 #include <md_object.h>
78
79 static const char dot[] = ".";
80 static const char dotdot[] = "..";
81 static const char remote_obj_dir[] = "REM_OBJ_DIR";
82
83 struct osd_directory {
84         struct iam_container od_container;
85         struct iam_descr     od_descr;
86 };
87
88 struct osd_object {
89         struct dt_object       oo_dt;
90         /**
91          * Inode for file system object represented by this osd_object. This
92          * inode is pinned for the whole duration of lu_object life.
93          *
94          * Not modified concurrently (either setup early during object
95          * creation, or assigned by osd_object_create() under write lock).
96          */
97         struct inode          *oo_inode;
98         /**
99          * to protect index ops.
100          */
101         cfs_rw_semaphore_t     oo_ext_idx_sem;
102         cfs_rw_semaphore_t     oo_sem;
103         struct osd_directory  *oo_dir;
104         /** protects inode attributes. */
105         cfs_spinlock_t         oo_guard;
106         /**
107          * Following two members are used to indicate the presence of dot and
108          * dotdot in the given directory. This is required for interop mode
109          * (b11826).
110          */
111         int                    oo_compat_dot_created;
112         int                    oo_compat_dotdot_created;
113
114         const struct lu_env   *oo_owner;
115 #ifdef CONFIG_LOCKDEP
116         struct lockdep_map     oo_dep_map;
117 #endif
118 };
119
120 static const struct lu_object_operations      osd_lu_obj_ops;
121 static const struct lu_device_operations      osd_lu_ops;
122 static       struct lu_context_key            osd_key;
123 static const struct dt_object_operations      osd_obj_ops;
124 static const struct dt_object_operations      osd_obj_ea_ops;
125 static const struct dt_body_operations        osd_body_ops;
126 static const struct dt_index_operations       osd_index_iam_ops;
127 static const struct dt_index_operations       osd_index_ea_ops;
128
129 struct osd_thandle {
130         struct thandle          ot_super;
131         handle_t               *ot_handle;
132         struct journal_callback ot_jcb;
133         /* Link to the device, for debugging. */
134         struct lu_ref_link     *ot_dev_link;
135
136 #if OSD_THANDLE_STATS
137         /** time when this handle was allocated */
138         cfs_time_t oth_alloced;
139
140         /** time when this thanle was started */
141         cfs_time_t oth_started;
142 #endif
143 };
144
145 /*
146  * Helpers.
147  */
148 static int lu_device_is_osd(const struct lu_device *d)
149 {
150         return ergo(d != NULL && d->ld_ops != NULL, d->ld_ops == &osd_lu_ops);
151 }
152
153 static struct osd_device *osd_dt_dev(const struct dt_device *d)
154 {
155         LASSERT(lu_device_is_osd(&d->dd_lu_dev));
156         return container_of0(d, struct osd_device, od_dt_dev);
157 }
158
159 static struct osd_device *osd_dev(const struct lu_device *d)
160 {
161         LASSERT(lu_device_is_osd(d));
162         return osd_dt_dev(container_of0(d, struct dt_device, dd_lu_dev));
163 }
164
165 static struct osd_device *osd_obj2dev(const struct osd_object *o)
166 {
167         return osd_dev(o->oo_dt.do_lu.lo_dev);
168 }
169
170 static struct super_block *osd_sb(const struct osd_device *dev)
171 {
172         return dev->od_mount->lmi_mnt->mnt_sb;
173 }
174
175 static int osd_object_is_root(const struct osd_object *obj)
176 {
177         return osd_sb(osd_obj2dev(obj))->s_root->d_inode == obj->oo_inode;
178 }
179
180 static struct osd_object *osd_obj(const struct lu_object *o)
181 {
182         LASSERT(lu_device_is_osd(o->lo_dev));
183         return container_of0(o, struct osd_object, oo_dt.do_lu);
184 }
185
186 static struct osd_object *osd_dt_obj(const struct dt_object *d)
187 {
188         return osd_obj(&d->do_lu);
189 }
190
191 static struct lu_device *osd2lu_dev(struct osd_device *osd)
192 {
193         return &osd->od_dt_dev.dd_lu_dev;
194 }
195
196 static journal_t *osd_journal(const struct osd_device *dev)
197 {
198         return LDISKFS_SB(osd_sb(dev))->s_journal;
199 }
200
201 static int osd_has_index(const struct osd_object *obj)
202 {
203         return obj->oo_dt.do_index_ops != NULL;
204 }
205
206 static int osd_object_invariant(const struct lu_object *l)
207 {
208         return osd_invariant(osd_obj(l));
209 }
210
211 #ifdef HAVE_QUOTA_SUPPORT
212 static inline void
213 osd_push_ctxt(const struct lu_env *env, struct osd_ctxt *save)
214 {
215         struct md_ucred    *uc = md_ucred(env);
216         struct cred        *tc;
217
218         LASSERT(uc != NULL);
219
220         save->oc_uid = current_fsuid();
221         save->oc_gid = current_fsgid();
222         save->oc_cap = current_cap();
223         if ((tc = prepare_creds())) {
224                 tc->fsuid         = uc->mu_fsuid;
225                 tc->fsgid         = uc->mu_fsgid;
226                 commit_creds(tc);
227         }
228         /* XXX not suboptimal */
229         cfs_curproc_cap_unpack(uc->mu_cap);
230 }
231
232 static inline void
233 osd_pop_ctxt(struct osd_ctxt *save)
234 {
235         struct cred *tc;
236
237         if ((tc = prepare_creds())) {
238                 tc->fsuid         = save->oc_uid;
239                 tc->fsgid         = save->oc_gid;
240                 tc->cap_effective = save->oc_cap;
241                 commit_creds(tc);
242         }
243 }
244 #endif
245
246 static inline struct osd_thread_info *osd_oti_get(const struct lu_env *env)
247 {
248         return lu_context_key_get(&env->le_ctx, &osd_key);
249 }
250
251 /*
252  * Concurrency: doesn't matter
253  */
254 static int osd_read_locked(const struct lu_env *env, struct osd_object *o)
255 {
256         return osd_oti_get(env)->oti_r_locks > 0;
257 }
258
259 /*
260  * Concurrency: doesn't matter
261  */
262 static int osd_write_locked(const struct lu_env *env, struct osd_object *o)
263 {
264         struct osd_thread_info *oti = osd_oti_get(env);
265         return oti->oti_w_locks > 0 && o->oo_owner == env;
266 }
267
268 /*
269  * Concurrency: doesn't access mutable data
270  */
271 static int osd_root_get(const struct lu_env *env,
272                         struct dt_device *dev, struct lu_fid *f)
273 {
274         struct inode *inode;
275
276         inode = osd_sb(osd_dt_dev(dev))->s_root->d_inode;
277         LU_IGIF_BUILD(f, inode->i_ino, inode->i_generation);
278         return 0;
279 }
280
281 /*
282  * OSD object methods.
283  */
284
285 /*
286  * Concurrency: no concurrent access is possible that early in object
287  * life-cycle.
288  */
289 static struct lu_object *osd_object_alloc(const struct lu_env *env,
290                                           const struct lu_object_header *hdr,
291                                           struct lu_device *d)
292 {
293         struct osd_object *mo;
294
295         OBD_ALLOC_PTR(mo);
296         if (mo != NULL) {
297                 struct lu_object *l;
298
299                 l = &mo->oo_dt.do_lu;
300                 dt_object_init(&mo->oo_dt, NULL, d);
301                 if (osd_dev(d)->od_iop_mode)
302                         mo->oo_dt.do_ops = &osd_obj_ea_ops;
303                 else
304                         mo->oo_dt.do_ops = &osd_obj_ops;
305
306                 l->lo_ops = &osd_lu_obj_ops;
307                 cfs_init_rwsem(&mo->oo_sem);
308                 cfs_init_rwsem(&mo->oo_ext_idx_sem);
309                 cfs_spin_lock_init(&mo->oo_guard);
310                 return l;
311         } else
312                 return NULL;
313 }
314
315 /*
316  * retrieve object from backend ext fs.
317  **/
318 static struct inode *osd_iget(struct osd_thread_info *info,
319                               struct osd_device *dev,
320                               const struct osd_inode_id *id)
321 {
322         struct inode *inode = NULL;
323
324 #ifdef HAVE_EXT4_LDISKFS
325         inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
326         if (IS_ERR(inode))
327         /* Newer kernels return an error instead of a NULL pointer */
328                 inode = NULL;
329 #else
330         inode = iget(osd_sb(dev), id->oii_ino);
331 #endif
332         if (inode == NULL) {
333                 CERROR("no inode\n");
334                 inode = ERR_PTR(-EACCES);
335         } else if (id->oii_gen != OSD_OII_NOGEN &&
336                    inode->i_generation != id->oii_gen) {
337                 iput(inode);
338                 inode = ERR_PTR(-ESTALE);
339         } else if (inode->i_nlink == 0) {
340                 /* due to parallel readdir and unlink,
341                 * we can have dead inode here. */
342                 CWARN("stale inode\n");
343                 make_bad_inode(inode);
344                 iput(inode);
345                 inode = ERR_PTR(-ESTALE);
346         } else if (is_bad_inode(inode)) {
347                 CERROR("bad inode %lx\n",inode->i_ino);
348                 iput(inode);
349                 inode = ERR_PTR(-ENOENT);
350         }
351         return inode;
352 }
353
354 static int osd_fid_lookup(const struct lu_env *env,
355                           struct osd_object *obj, const struct lu_fid *fid)
356 {
357         struct osd_thread_info *info;
358         struct lu_device       *ldev = obj->oo_dt.do_lu.lo_dev;
359         struct osd_device      *dev;
360         struct osd_inode_id    *id;
361         struct osd_oi          *oi;
362         struct inode           *inode;
363         int                     result;
364
365         LINVRNT(osd_invariant(obj));
366         LASSERT(obj->oo_inode == NULL);
367         LASSERT(fid_is_sane(fid) || osd_fid_is_root(fid));
368         /*
369          * This assertion checks that osd layer sees only local
370          * fids. Unfortunately it is somewhat expensive (does a
371          * cache-lookup). Disabling it for production/acceptance-testing.
372          */
373         LASSERT(1 || fid_is_local(env, ldev->ld_site, fid));
374
375         ENTRY;
376
377         info = osd_oti_get(env);
378         dev  = osd_dev(ldev);
379         id   = &info->oti_id;
380         oi   = &dev->od_oi;
381
382         if (OBD_FAIL_CHECK(OBD_FAIL_OST_ENOENT))
383                 RETURN(-ENOENT);
384
385         result = osd_oi_lookup(info, oi, fid, id);
386         if (result == 0) {
387                 inode = osd_iget(info, dev, id);
388                 if (!IS_ERR(inode)) {
389                         obj->oo_inode = inode;
390                         LASSERT(obj->oo_inode->i_sb == osd_sb(dev));
391                         if (dev->od_iop_mode) {
392                                 obj->oo_compat_dot_created = 1;
393                                 obj->oo_compat_dotdot_created = 1;
394                         }
395                         result = 0;
396                 } else
397                         /*
398                          * If fid wasn't found in oi, inode-less object is
399                          * created, for which lu_object_exists() returns
400                          * false. This is used in a (frequent) case when
401                          * objects are created as locking anchors or
402                          * place holders for objects yet to be created.
403                          */
404                         result = PTR_ERR(inode);
405         } else if (result == -ENOENT)
406                 result = 0;
407         LINVRNT(osd_invariant(obj));
408
409         RETURN(result);
410 }
411
412 /*
413  * Concurrency: shouldn't matter.
414  */
415 static void osd_object_init0(struct osd_object *obj)
416 {
417         LASSERT(obj->oo_inode != NULL);
418         obj->oo_dt.do_body_ops = &osd_body_ops;
419         obj->oo_dt.do_lu.lo_header->loh_attr |=
420                 (LOHA_EXISTS | (obj->oo_inode->i_mode & S_IFMT));
421 }
422
423 /*
424  * Concurrency: no concurrent access is possible that early in object
425  * life-cycle.
426  */
427 static int osd_object_init(const struct lu_env *env, struct lu_object *l,
428                            const struct lu_object_conf *unused)
429 {
430         struct osd_object *obj = osd_obj(l);
431         int result;
432
433         LINVRNT(osd_invariant(obj));
434
435         result = osd_fid_lookup(env, obj, lu_object_fid(l));
436         if (result == 0) {
437                 if (obj->oo_inode != NULL)
438                         osd_object_init0(obj);
439         }
440         LINVRNT(osd_invariant(obj));
441         return result;
442 }
443
444 /*
445  * Concurrency: no concurrent access is possible that late in object
446  * life-cycle.
447  */
448 static void osd_object_free(const struct lu_env *env, struct lu_object *l)
449 {
450         struct osd_object *obj = osd_obj(l);
451
452         LINVRNT(osd_invariant(obj));
453
454         dt_object_fini(&obj->oo_dt);
455         OBD_FREE_PTR(obj);
456 }
457
458 /**
459  * IAM Iterator
460  */
461 static struct iam_path_descr *osd_it_ipd_get(const struct lu_env *env,
462                                              const struct iam_container *bag)
463 {
464         return bag->ic_descr->id_ops->id_ipd_alloc(bag,
465                                            osd_oti_get(env)->oti_it_ipd);
466 }
467
468 static struct iam_path_descr *osd_idx_ipd_get(const struct lu_env *env,
469                                               const struct iam_container *bag)
470 {
471         return bag->ic_descr->id_ops->id_ipd_alloc(bag,
472                                            osd_oti_get(env)->oti_idx_ipd);
473 }
474
475 static void osd_ipd_put(const struct lu_env *env,
476                         const struct iam_container *bag,
477                         struct iam_path_descr *ipd)
478 {
479         bag->ic_descr->id_ops->id_ipd_free(ipd);
480 }
481
482 /*
483  * Concurrency: no concurrent access is possible that late in object
484  * life-cycle.
485  */
486 static void osd_index_fini(struct osd_object *o)
487 {
488         struct iam_container *bag;
489
490         if (o->oo_dir != NULL) {
491                 bag = &o->oo_dir->od_container;
492                 if (o->oo_inode != NULL) {
493                         if (bag->ic_object == o->oo_inode)
494                                 iam_container_fini(bag);
495                 }
496                 OBD_FREE_PTR(o->oo_dir);
497                 o->oo_dir = NULL;
498         }
499 }
500
501 /*
502  * Concurrency: no concurrent access is possible that late in object
503  * life-cycle (for all existing callers, that is. New callers have to provide
504  * their own locking.)
505  */
506 static int osd_inode_unlinked(const struct inode *inode)
507 {
508         return inode->i_nlink == 0;
509 }
510
511 enum {
512         OSD_TXN_OI_DELETE_CREDITS    = 20,
513         OSD_TXN_INODE_DELETE_CREDITS = 20
514 };
515
516 /*
517  * Journal
518  */
519
520 #if OSD_THANDLE_STATS
521 /**
522  * Set time when the handle is allocated
523  */
524 static void osd_th_alloced(struct osd_thandle *oth)
525 {
526         oth->oth_alloced = cfs_time_current();
527 }
528
529 /**
530  * Set time when the handle started
531  */
532 static void osd_th_started(struct osd_thandle *oth)
533 {
534         oth->oth_started = cfs_time_current();
535 }
536
537 /**
538  * Helper function to convert time interval to microseconds packed in
539  * long int (default time units for the counter in "stats" initialized
540  * by lu_time_init() )
541  */
542 static long interval_to_usec(cfs_time_t start, cfs_time_t end)
543 {
544         struct timeval val;
545
546         cfs_duration_usec(cfs_time_sub(end, start), &val);
547         return val.tv_sec * 1000000 + val.tv_usec;
548 }
549
550 /**
551  * Check whether the we deal with this handle for too long.
552  */
553 static void __osd_th_check_slow(void *oth, struct osd_device *dev,
554                                 cfs_time_t alloced, cfs_time_t started,
555                                 cfs_time_t closed)
556 {
557         cfs_time_t now = cfs_time_current();
558
559         LASSERT(dev != NULL);
560
561         lprocfs_counter_add(dev->od_stats, LPROC_OSD_THANDLE_STARTING,
562                             interval_to_usec(alloced, started));
563         lprocfs_counter_add(dev->od_stats, LPROC_OSD_THANDLE_OPEN,
564                             interval_to_usec(started, closed));
565         lprocfs_counter_add(dev->od_stats, LPROC_OSD_THANDLE_CLOSING,
566                             interval_to_usec(closed, now));
567
568         if (cfs_time_before(cfs_time_add(alloced, cfs_time_seconds(30)), now)) {
569                 CWARN("transaction handle %p was open for too long: "
570                       "now "CFS_TIME_T" ,"
571                       "alloced "CFS_TIME_T" ,"
572                       "started "CFS_TIME_T" ,"
573                       "closed "CFS_TIME_T"\n",
574                       oth, now, alloced, started, closed);
575                 libcfs_debug_dumpstack(NULL);
576         }
577 }
578
579 #define OSD_CHECK_SLOW_TH(oth, dev, expr)                               \
580 {                                                                       \
581         cfs_time_t __closed = cfs_time_current();                       \
582         cfs_time_t __alloced = oth->oth_alloced;                        \
583         cfs_time_t __started = oth->oth_started;                        \
584                                                                         \
585         expr;                                                           \
586         __osd_th_check_slow(oth, dev, __alloced, __started, __closed);  \
587 }
588
589 #else /* OSD_THANDLE_STATS */
590
591 #define osd_th_alloced(h)                  do {} while(0)
592 #define osd_th_started(h)                  do {} while(0)
593 #define OSD_CHECK_SLOW_TH(oth, dev, expr)  expr
594
595 #endif /* OSD_THANDLE_STATS */
596
597 /*
598  * Concurrency: doesn't access mutable data.
599  */
600 static int osd_param_is_sane(const struct osd_device *dev,
601                              const struct txn_param *param)
602 {
603         return param->tp_credits <= osd_journal(dev)->j_max_transaction_buffers;
604 }
605
606 /*
607  * Concurrency: shouldn't matter.
608  */
609 static void osd_trans_commit_cb(struct journal_callback *jcb, int error)
610 {
611         struct osd_thandle *oh = container_of0(jcb, struct osd_thandle, ot_jcb);
612         struct thandle     *th  = &oh->ot_super;
613         struct dt_device   *dev = th->th_dev;
614         struct lu_device   *lud = &dev->dd_lu_dev;
615
616         LASSERT(dev != NULL);
617         LASSERT(oh->ot_handle == NULL);
618
619         if (error) {
620                 CERROR("transaction @0x%p commit error: %d\n", th, error);
621         } else {
622                 struct lu_env *env = &osd_dt_dev(dev)->od_env_for_commit;
623                 /*
624                  * This od_env_for_commit is only for commit usage.  see
625                  * "struct dt_device"
626                  */
627                 lu_context_enter(&env->le_ctx);
628                 dt_txn_hook_commit(env, th);
629                 lu_context_exit(&env->le_ctx);
630         }
631
632         lu_ref_del_at(&lud->ld_reference, oh->ot_dev_link, "osd-tx", th);
633         lu_device_put(lud);
634         th->th_dev = NULL;
635
636         lu_context_exit(&th->th_ctx);
637         lu_context_fini(&th->th_ctx);
638         OBD_FREE_PTR(oh);
639 }
640
641 /*
642  * Concurrency: shouldn't matter.
643  */
644 static struct thandle *osd_trans_start(const struct lu_env *env,
645                                        struct dt_device *d,
646                                        struct txn_param *p)
647 {
648         struct osd_device  *dev = osd_dt_dev(d);
649         handle_t           *jh;
650         struct osd_thandle *oh;
651         struct thandle     *th;
652         int hook_res;
653
654         ENTRY;
655
656         hook_res = dt_txn_hook_start(env, d, p);
657         if (hook_res != 0)
658                 RETURN(ERR_PTR(hook_res));
659
660         if (osd_param_is_sane(dev, p)) {
661                 OBD_ALLOC_GFP(oh, sizeof *oh, CFS_ALLOC_IO);
662                 if (oh != NULL) {
663                         struct osd_thread_info *oti = osd_oti_get(env);
664
665                         /*
666                          * XXX temporary stuff. Some abstraction layer should
667                          * be used.
668                          */
669                         oti->oti_dev = dev;
670                         osd_th_alloced(oh);
671                         jh = ldiskfs_journal_start_sb(osd_sb(dev), p->tp_credits);
672                         osd_th_started(oh);
673                         if (!IS_ERR(jh)) {
674                                 oh->ot_handle = jh;
675                                 th = &oh->ot_super;
676                                 th->th_dev = d;
677                                 th->th_result = 0;
678                                 jh->h_sync = p->tp_sync;
679                                 lu_device_get(&d->dd_lu_dev);
680                                 oh->ot_dev_link = lu_ref_add
681                                         (&d->dd_lu_dev.ld_reference,
682                                          "osd-tx", th);
683                                 /* add commit callback */
684                                 lu_context_init(&th->th_ctx, LCT_TX_HANDLE);
685                                 lu_context_enter(&th->th_ctx);
686                                 osd_journal_callback_set(jh, osd_trans_commit_cb,
687                                                          (struct journal_callback *)&oh->ot_jcb);
688                                         LASSERT(oti->oti_txns == 0);
689                                         LASSERT(oti->oti_r_locks == 0);
690                                         LASSERT(oti->oti_w_locks == 0);
691                                         oti->oti_txns++;
692                         } else {
693                                 OBD_FREE_PTR(oh);
694                                 th = (void *)jh;
695                         }
696                 } else
697                         th = ERR_PTR(-ENOMEM);
698         } else {
699                 CERROR("Invalid transaction parameters\n");
700                 th = ERR_PTR(-EINVAL);
701         }
702
703         RETURN(th);
704 }
705
706 /*
707  * Concurrency: shouldn't matter.
708  */
709 static void osd_trans_stop(const struct lu_env *env, struct thandle *th)
710 {
711         int result;
712         struct osd_thandle *oh;
713         struct osd_thread_info *oti = osd_oti_get(env);
714
715         ENTRY;
716
717         oh = container_of0(th, struct osd_thandle, ot_super);
718         if (oh->ot_handle != NULL) {
719                 handle_t *hdl = oh->ot_handle;
720
721                 LASSERT(oti->oti_txns == 1);
722                 oti->oti_txns--;
723                 LASSERT(oti->oti_r_locks == 0);
724                 LASSERT(oti->oti_w_locks == 0);
725                 result = dt_txn_hook_stop(env, th);
726                 if (result != 0)
727                         CERROR("Failure in transaction hook: %d\n", result);
728                 oh->ot_handle = NULL;
729                 OSD_CHECK_SLOW_TH(oh, oti->oti_dev,
730                                   result = ldiskfs_journal_stop(hdl));
731                 if (result != 0)
732                         CERROR("Failure to stop transaction: %d\n", result);
733         }
734         EXIT;
735 }
736
737 /*
738  * Concurrency: no concurrent access is possible that late in object
739  * life-cycle.
740  */
741 static int osd_inode_remove(const struct lu_env *env, struct osd_object *obj)
742 {
743         const struct lu_fid    *fid = lu_object_fid(&obj->oo_dt.do_lu);
744         struct osd_device      *osd = osd_obj2dev(obj);
745         struct osd_thread_info *oti = osd_oti_get(env);
746         struct txn_param       *prm = &oti->oti_txn;
747         struct lu_env          *env_del_obj = &oti->oti_obj_delete_tx_env;
748         struct thandle         *th;
749         int result;
750
751         lu_env_init(env_del_obj, LCT_DT_THREAD);
752         txn_param_init(prm, OSD_TXN_OI_DELETE_CREDITS +
753                             OSD_TXN_INODE_DELETE_CREDITS);
754         th = osd_trans_start(env_del_obj, &osd->od_dt_dev, prm);
755         if (!IS_ERR(th)) {
756                 result = osd_oi_delete(osd_oti_get(env_del_obj),
757                                        &osd->od_oi, fid, th);
758                 osd_trans_stop(env_del_obj, th);
759         } else
760                 result = PTR_ERR(th);
761
762         lu_env_fini(env_del_obj);
763         return result;
764 }
765
766 /*
767  * Called just before object is freed. Releases all resources except for
768  * object itself (that is released by osd_object_free()).
769  *
770  * Concurrency: no concurrent access is possible that late in object
771  * life-cycle.
772  */
773 static void osd_object_delete(const struct lu_env *env, struct lu_object *l)
774 {
775         struct osd_object *obj   = osd_obj(l);
776         struct inode      *inode = obj->oo_inode;
777
778         LINVRNT(osd_invariant(obj));
779
780         /*
781          * If object is unlinked remove fid->ino mapping from object index.
782          */
783
784         osd_index_fini(obj);
785         if (inode != NULL) {
786                 int result;
787
788                 if (osd_inode_unlinked(inode)) {
789                         result = osd_inode_remove(env, obj);
790                         if (result != 0)
791                                 LU_OBJECT_DEBUG(D_ERROR, env, l,
792                                                 "Failed to cleanup: %d\n",
793                                                 result);
794                 }
795
796                 iput(inode);
797                 obj->oo_inode = NULL;
798         }
799 }
800
801 /*
802  * Concurrency: ->loo_object_release() is called under site spin-lock.
803  */
804 static void osd_object_release(const struct lu_env *env,
805                                struct lu_object *l)
806 {
807         struct osd_object *o = osd_obj(l);
808
809         LASSERT(!lu_object_is_dying(l->lo_header));
810         if (o->oo_inode != NULL && osd_inode_unlinked(o->oo_inode))
811                 cfs_set_bit(LU_OBJECT_HEARD_BANSHEE, &l->lo_header->loh_flags);
812 }
813
814 /*
815  * Concurrency: shouldn't matter.
816  */
817 static int osd_object_print(const struct lu_env *env, void *cookie,
818                             lu_printer_t p, const struct lu_object *l)
819 {
820         struct osd_object *o = osd_obj(l);
821         struct iam_descr  *d;
822
823         if (o->oo_dir != NULL)
824                 d = o->oo_dir->od_container.ic_descr;
825         else
826                 d = NULL;
827         return (*p)(env, cookie, LUSTRE_OSD_NAME"-object@%p(i:%p:%lu/%u)[%s]",
828                     o, o->oo_inode,
829                     o->oo_inode ? o->oo_inode->i_ino : 0UL,
830                     o->oo_inode ? o->oo_inode->i_generation : 0,
831                     d ? d->id_ops->id_name : "plain");
832 }
833
834 /*
835  * Concurrency: shouldn't matter.
836  */
837 int osd_statfs(const struct lu_env *env, struct dt_device *d,
838                cfs_kstatfs_t *sfs)
839 {
840         struct osd_device *osd = osd_dt_dev(d);
841         struct super_block *sb = osd_sb(osd);
842         int result = 0;
843
844         cfs_spin_lock(&osd->od_osfs_lock);
845         /* cache 1 second */
846         if (cfs_time_before_64(osd->od_osfs_age, cfs_time_shift_64(-1))) {
847                 result = ll_do_statfs(sb, &osd->od_kstatfs);
848                 if (likely(result == 0)) /* N.B. statfs can't really fail */
849                         osd->od_osfs_age = cfs_time_current_64();
850         }
851
852         if (likely(result == 0))
853                 *sfs = osd->od_kstatfs;
854         cfs_spin_unlock(&osd->od_osfs_lock);
855
856         return result;
857 }
858
859 /*
860  * Concurrency: doesn't access mutable data.
861  */
862 static void osd_conf_get(const struct lu_env *env,
863                          const struct dt_device *dev,
864                          struct dt_device_param *param)
865 {
866         /*
867          * XXX should be taken from not-yet-existing fs abstraction layer.
868          */
869         param->ddp_max_name_len  = LDISKFS_NAME_LEN;
870         param->ddp_max_nlink     = LDISKFS_LINK_MAX;
871         param->ddp_block_shift   = osd_sb(osd_dt_dev(dev))->s_blocksize_bits;
872 }
873
874 /**
875  * Helper function to get and fill the buffer with input values.
876  */
877 static struct lu_buf *osd_buf_get(const struct lu_env *env, void *area, ssize_t len)
878 {
879         struct lu_buf *buf;
880
881         buf = &osd_oti_get(env)->oti_buf;
882         buf->lb_buf = area;
883         buf->lb_len = len;
884         return buf;
885 }
886
887 /*
888  * Concurrency: shouldn't matter.
889  */
890 static int osd_sync(const struct lu_env *env, struct dt_device *d)
891 {
892         CDEBUG(D_HA, "syncing OSD %s\n", LUSTRE_OSD_NAME);
893         return ldiskfs_force_commit(osd_sb(osd_dt_dev(d)));
894 }
895
896 /**
897  * Start commit for OSD device.
898  *
899  * An implementation of dt_commit_async method for OSD device.
900  * Asychronously starts underlayng fs sync and thereby a transaction
901  * commit.
902  *
903  * \param env environment
904  * \param d dt device
905  *
906  * \see dt_device_operations
907  */
908 static int osd_commit_async(const struct lu_env *env,
909                             struct dt_device *d)
910 {
911         struct super_block *s = osd_sb(osd_dt_dev(d));
912         ENTRY;
913
914         CDEBUG(D_HA, "async commit OSD %s\n", LUSTRE_OSD_NAME);
915         RETURN(s->s_op->sync_fs(s, 0));
916 }
917
918 /*
919  * Concurrency: shouldn't matter.
920  */
921 lvfs_sbdev_type fsfilt_ldiskfs_journal_sbdev(struct super_block *);
922
923 static void osd_ro(const struct lu_env *env, struct dt_device *d)
924 {
925         ENTRY;
926
927         CERROR("*** setting device %s read-only ***\n", LUSTRE_OSD_NAME);
928
929         __lvfs_set_rdonly(lvfs_sbdev(osd_sb(osd_dt_dev(d))),
930                           fsfilt_ldiskfs_journal_sbdev(osd_sb(osd_dt_dev(d))));
931         EXIT;
932 }
933
934
935 /*
936  * Concurrency: serialization provided by callers.
937  */
938 static int osd_init_capa_ctxt(const struct lu_env *env, struct dt_device *d,
939                               int mode, unsigned long timeout, __u32 alg,
940                               struct lustre_capa_key *keys)
941 {
942         struct osd_device *dev = osd_dt_dev(d);
943         ENTRY;
944
945         dev->od_fl_capa = mode;
946         dev->od_capa_timeout = timeout;
947         dev->od_capa_alg = alg;
948         dev->od_capa_keys = keys;
949         RETURN(0);
950 }
951
952 /**
953  * Concurrency: serialization provided by callers.
954  */
955 static void osd_init_quota_ctxt(const struct lu_env *env, struct dt_device *d,
956                                struct dt_quota_ctxt *ctxt, void *data)
957 {
958         struct obd_device *obd = (void *)ctxt;
959         struct vfsmount *mnt = (struct vfsmount *)data;
960         ENTRY;
961
962         obd->u.obt.obt_sb = mnt->mnt_root->d_inode->i_sb;
963         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
964         obd->obd_lvfs_ctxt.pwdmnt = mnt;
965         obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
966         obd->obd_lvfs_ctxt.fs = get_ds();
967
968         EXIT;
969 }
970
971 /**
972  * Note: we do not count into QUOTA here.
973  * If we mount with --data_journal we may need more.
974  */
975 static const int osd_dto_credits_noquota[DTO_NR] = {
976         /**
977          * Insert/Delete.
978          * INDEX_EXTRA_TRANS_BLOCKS(8) +
979          * SINGLEDATA_TRANS_BLOCKS(8)
980          * XXX Note: maybe iam need more, since iam have more level than
981          *           EXT3 htree.
982          */
983         [DTO_INDEX_INSERT]  = 16,
984         [DTO_INDEX_DELETE]  = 16,
985         /**
986          * Unused now
987          */
988         [DTO_IDNEX_UPDATE]  = 16,
989         /**
990          * Create a object. The same as create object in EXT3.
991          * DATA_TRANS_BLOCKS(14) +
992          * INDEX_EXTRA_BLOCKS(8) +
993          * 3(inode bits, groups, GDT)
994          */
995         [DTO_OBJECT_CREATE] = 25,
996         /**
997          * Unused now
998          */
999         [DTO_OBJECT_DELETE] = 25,
1000         /**
1001          * Attr set credits.
1002          * 3(inode bits, group, GDT)
1003          */
1004         [DTO_ATTR_SET_BASE] = 3,
1005         /**
1006          * Xattr set. The same as xattr of EXT3.
1007          * DATA_TRANS_BLOCKS(14)
1008          * XXX Note: in original MDS implmentation INDEX_EXTRA_TRANS_BLOCKS
1009          * are also counted in. Do not know why?
1010          */
1011         [DTO_XATTR_SET]     = 14,
1012         [DTO_LOG_REC]       = 14,
1013         /**
1014          * creadits for inode change during write.
1015          */
1016         [DTO_WRITE_BASE]    = 3,
1017         /**
1018          * credits for single block write.
1019          */
1020         [DTO_WRITE_BLOCK]   = 14,
1021         /**
1022          * Attr set credits for chown.
1023          * This is extra credits for setattr, and it is null without quota
1024          */
1025         [DTO_ATTR_SET_CHOWN]= 0
1026 };
1027
1028 /**
1029  * Note: we count into QUOTA here.
1030  * If we mount with --data_journal we may need more.
1031  */
1032 static const int osd_dto_credits_quota[DTO_NR] = {
1033         /**
1034          * INDEX_EXTRA_TRANS_BLOCKS(8) +
1035          * SINGLEDATA_TRANS_BLOCKS(8) +
1036          * 2 * QUOTA_TRANS_BLOCKS(2)
1037          */
1038         [DTO_INDEX_INSERT]  = 20,
1039         /**
1040          * INDEX_EXTRA_TRANS_BLOCKS(8) +
1041          * SINGLEDATA_TRANS_BLOCKS(8) +
1042          * 2 * QUOTA_TRANS_BLOCKS(2)
1043          */
1044         [DTO_INDEX_DELETE]  = 20,
1045         /**
1046          * Unused now.
1047          */
1048         [DTO_IDNEX_UPDATE]  = 16,
1049         /*
1050          * Create a object. Same as create object in EXT3 filesystem.
1051          * DATA_TRANS_BLOCKS(16) +
1052          * INDEX_EXTRA_BLOCKS(8) +
1053          * 3(inode bits, groups, GDT) +
1054          * 2 * QUOTA_INIT_BLOCKS(25)
1055          */
1056         [DTO_OBJECT_CREATE] = 77,
1057         /*
1058          * Unused now.
1059          * DATA_TRANS_BLOCKS(16) +
1060          * INDEX_EXTRA_BLOCKS(8) +
1061          * 3(inode bits, groups, GDT) +
1062          * QUOTA(?)
1063          */
1064         [DTO_OBJECT_DELETE] = 27,
1065         /**
1066          * Attr set credits.
1067          * 3 (inode bit, group, GDT) +
1068          */
1069         [DTO_ATTR_SET_BASE] = 3,
1070         /**
1071          * Xattr set. The same as xattr of EXT3.
1072          * DATA_TRANS_BLOCKS(16)
1073          * XXX Note: in original MDS implmentation INDEX_EXTRA_TRANS_BLOCKS are
1074          *           also counted in. Do not know why?
1075          */
1076         [DTO_XATTR_SET]     = 16,
1077         [DTO_LOG_REC]       = 16,
1078         /**
1079          * creadits for inode change during write.
1080          */
1081         [DTO_WRITE_BASE]    = 3,
1082         /**
1083          * credits for single block write.
1084          */
1085         [DTO_WRITE_BLOCK]   = 16,
1086         /**
1087          * Attr set credits for chown.
1088          * It is added to already set setattr credits
1089          * 2 * QUOTA_INIT_BLOCKS(25) +
1090          * 2 * QUOTA_DEL_BLOCKS(9)
1091          */
1092         [DTO_ATTR_SET_CHOWN]= 68,
1093 };
1094
1095 static int osd_credit_get(const struct lu_env *env, struct dt_device *d,
1096                           enum dt_txn_op op)
1097 {
1098         LASSERT(ARRAY_SIZE(osd_dto_credits_noquota) ==
1099                 ARRAY_SIZE(osd_dto_credits_quota));
1100         LASSERT(0 <= op && op < ARRAY_SIZE(osd_dto_credits_noquota));
1101 #ifdef HAVE_QUOTA_SUPPORT
1102         if (test_opt(osd_sb(osd_dt_dev(d)), QUOTA))
1103                 return osd_dto_credits_quota[op];
1104         else
1105 #endif
1106                 return osd_dto_credits_noquota[op];
1107 }
1108
1109 static const struct dt_device_operations osd_dt_ops = {
1110         .dt_root_get       = osd_root_get,
1111         .dt_statfs         = osd_statfs,
1112         .dt_trans_start    = osd_trans_start,
1113         .dt_trans_stop     = osd_trans_stop,
1114         .dt_conf_get       = osd_conf_get,
1115         .dt_sync           = osd_sync,
1116         .dt_ro             = osd_ro,
1117         .dt_commit_async   = osd_commit_async,
1118         .dt_credit_get     = osd_credit_get,
1119         .dt_init_capa_ctxt = osd_init_capa_ctxt,
1120         .dt_init_quota_ctxt= osd_init_quota_ctxt,
1121 };
1122
1123 static void osd_object_read_lock(const struct lu_env *env,
1124                                  struct dt_object *dt, unsigned role)
1125 {
1126         struct osd_object *obj = osd_dt_obj(dt);
1127         struct osd_thread_info *oti = osd_oti_get(env);
1128
1129         LINVRNT(osd_invariant(obj));
1130
1131         LASSERT(obj->oo_owner != env);
1132         cfs_down_read_nested(&obj->oo_sem, role);
1133
1134         LASSERT(obj->oo_owner == NULL);
1135         oti->oti_r_locks++;
1136 }
1137
1138 static void osd_object_write_lock(const struct lu_env *env,
1139                                   struct dt_object *dt, unsigned role)
1140 {
1141         struct osd_object *obj = osd_dt_obj(dt);
1142         struct osd_thread_info *oti = osd_oti_get(env);
1143
1144         LINVRNT(osd_invariant(obj));
1145
1146         LASSERT(obj->oo_owner != env);
1147         cfs_down_write_nested(&obj->oo_sem, role);
1148
1149         LASSERT(obj->oo_owner == NULL);
1150         obj->oo_owner = env;
1151         oti->oti_w_locks++;
1152 }
1153
1154 static void osd_object_read_unlock(const struct lu_env *env,
1155                                    struct dt_object *dt)
1156 {
1157         struct osd_object *obj = osd_dt_obj(dt);
1158         struct osd_thread_info *oti = osd_oti_get(env);
1159
1160         LINVRNT(osd_invariant(obj));
1161
1162         LASSERT(oti->oti_r_locks > 0);
1163         oti->oti_r_locks--;
1164         cfs_up_read(&obj->oo_sem);
1165 }
1166
1167 static void osd_object_write_unlock(const struct lu_env *env,
1168                                     struct dt_object *dt)
1169 {
1170         struct osd_object *obj = osd_dt_obj(dt);
1171         struct osd_thread_info *oti = osd_oti_get(env);
1172
1173         LINVRNT(osd_invariant(obj));
1174
1175         LASSERT(obj->oo_owner == env);
1176         LASSERT(oti->oti_w_locks > 0);
1177         oti->oti_w_locks--;
1178         obj->oo_owner = NULL;
1179         cfs_up_write(&obj->oo_sem);
1180 }
1181
1182 static int osd_object_write_locked(const struct lu_env *env,
1183                                    struct dt_object *dt)
1184 {
1185         struct osd_object *obj = osd_dt_obj(dt);
1186
1187         LINVRNT(osd_invariant(obj));
1188
1189         return obj->oo_owner == env;
1190 }
1191
1192 static int capa_is_sane(const struct lu_env *env,
1193                         struct osd_device *dev,
1194                         struct lustre_capa *capa,
1195                         struct lustre_capa_key *keys)
1196 {
1197         struct osd_thread_info *oti = osd_oti_get(env);
1198         struct lustre_capa *tcapa = &oti->oti_capa;
1199         struct obd_capa *oc;
1200         int i, rc = 0;
1201         ENTRY;
1202
1203         oc = capa_lookup(dev->od_capa_hash, capa, 0);
1204         if (oc) {
1205                 if (capa_is_expired(oc)) {
1206                         DEBUG_CAPA(D_ERROR, capa, "expired");
1207                         rc = -ESTALE;
1208                 }
1209                 capa_put(oc);
1210                 RETURN(rc);
1211         }
1212
1213         if (capa_is_expired_sec(capa)) {
1214                 DEBUG_CAPA(D_ERROR, capa, "expired");
1215                 RETURN(-ESTALE);
1216         }
1217
1218         cfs_spin_lock(&capa_lock);
1219         for (i = 0; i < 2; i++) {
1220                 if (keys[i].lk_keyid == capa->lc_keyid) {
1221                         oti->oti_capa_key = keys[i];
1222                         break;
1223                 }
1224         }
1225         cfs_spin_unlock(&capa_lock);
1226
1227         if (i == 2) {
1228                 DEBUG_CAPA(D_ERROR, capa, "no matched capa key");
1229                 RETURN(-ESTALE);
1230         }
1231
1232         rc = capa_hmac(tcapa->lc_hmac, capa, oti->oti_capa_key.lk_key);
1233         if (rc)
1234                 RETURN(rc);
1235
1236         if (memcmp(tcapa->lc_hmac, capa->lc_hmac, sizeof(capa->lc_hmac))) {
1237                 DEBUG_CAPA(D_ERROR, capa, "HMAC mismatch");
1238                 RETURN(-EACCES);
1239         }
1240
1241         oc = capa_add(dev->od_capa_hash, capa);
1242         capa_put(oc);
1243
1244         RETURN(0);
1245 }
1246
1247 static int osd_object_auth(const struct lu_env *env, struct dt_object *dt,
1248                            struct lustre_capa *capa, __u64 opc)
1249 {
1250         const struct lu_fid *fid = lu_object_fid(&dt->do_lu);
1251         struct osd_device *dev = osd_dev(dt->do_lu.lo_dev);
1252         struct md_capainfo *ci;
1253         int rc;
1254
1255         if (!dev->od_fl_capa)
1256                 return 0;
1257
1258         if (capa == BYPASS_CAPA)
1259                 return 0;
1260
1261         ci = md_capainfo(env);
1262         if (unlikely(!ci))
1263                 return 0;
1264
1265         if (ci->mc_auth == LC_ID_NONE)
1266                 return 0;
1267
1268         if (!capa) {
1269                 CERROR("no capability is provided for fid "DFID"\n", PFID(fid));
1270                 return -EACCES;
1271         }
1272
1273         if (!lu_fid_eq(fid, &capa->lc_fid)) {
1274                 DEBUG_CAPA(D_ERROR, capa, "fid "DFID" mismatch with",
1275                            PFID(fid));
1276                 return -EACCES;
1277         }
1278
1279         if (!capa_opc_supported(capa, opc)) {
1280                 DEBUG_CAPA(D_ERROR, capa, "opc "LPX64" not supported by", opc);
1281                 return -EACCES;
1282         }
1283
1284         if ((rc = capa_is_sane(env, dev, capa, dev->od_capa_keys))) {
1285                 DEBUG_CAPA(D_ERROR, capa, "insane (rc %d)", rc);
1286                 return -EACCES;
1287         }
1288
1289         return 0;
1290 }
1291
1292 static struct timespec *osd_inode_time(const struct lu_env *env,
1293                                        struct inode *inode, __u64 seconds)
1294 {
1295         struct osd_thread_info *oti = osd_oti_get(env);
1296         struct timespec        *t   = &oti->oti_time;
1297
1298         t->tv_sec  = seconds;
1299         t->tv_nsec = 0;
1300         *t = timespec_trunc(*t, get_sb_time_gran(inode->i_sb));
1301         return t;
1302 }
1303
1304
1305 static void osd_inode_getattr(const struct lu_env *env,
1306                               struct inode *inode, struct lu_attr *attr)
1307 {
1308         attr->la_valid      |= LA_ATIME | LA_MTIME | LA_CTIME | LA_MODE |
1309                                LA_SIZE | LA_BLOCKS | LA_UID | LA_GID |
1310                                LA_FLAGS | LA_NLINK | LA_RDEV | LA_BLKSIZE;
1311
1312         attr->la_atime      = LTIME_S(inode->i_atime);
1313         attr->la_mtime      = LTIME_S(inode->i_mtime);
1314         attr->la_ctime      = LTIME_S(inode->i_ctime);
1315         attr->la_mode       = inode->i_mode;
1316         attr->la_size       = i_size_read(inode);
1317         attr->la_blocks     = inode->i_blocks;
1318         attr->la_uid        = inode->i_uid;
1319         attr->la_gid        = inode->i_gid;
1320         attr->la_flags      = LDISKFS_I(inode)->i_flags;
1321         attr->la_nlink      = inode->i_nlink;
1322         attr->la_rdev       = inode->i_rdev;
1323         attr->la_blksize    = ll_inode_blksize(inode);
1324         attr->la_blkbits    = inode->i_blkbits;
1325 }
1326
1327 static int osd_attr_get(const struct lu_env *env,
1328                         struct dt_object *dt,
1329                         struct lu_attr *attr,
1330                         struct lustre_capa *capa)
1331 {
1332         struct osd_object *obj = osd_dt_obj(dt);
1333
1334         LASSERT(dt_object_exists(dt));
1335         LINVRNT(osd_invariant(obj));
1336
1337         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_READ))
1338                 return -EACCES;
1339
1340         cfs_spin_lock(&obj->oo_guard);
1341         osd_inode_getattr(env, obj->oo_inode, attr);
1342         cfs_spin_unlock(&obj->oo_guard);
1343         return 0;
1344 }
1345
1346 static int osd_inode_setattr(const struct lu_env *env,
1347                              struct inode *inode, const struct lu_attr *attr)
1348 {
1349         __u64 bits;
1350
1351         bits = attr->la_valid;
1352
1353         LASSERT(!(bits & LA_TYPE)); /* Huh? You want too much. */
1354
1355 #ifdef HAVE_QUOTA_SUPPORT
1356         if ((bits & LA_UID && attr->la_uid != inode->i_uid) ||
1357             (bits & LA_GID && attr->la_gid != inode->i_gid)) {
1358                 struct osd_ctxt *save = &osd_oti_get(env)->oti_ctxt;
1359                 struct iattr iattr;
1360                 int rc;
1361
1362                 iattr.ia_valid = 0;
1363                 if (bits & LA_UID)
1364                         iattr.ia_valid |= ATTR_UID;
1365                 if (bits & LA_GID)
1366                         iattr.ia_valid |= ATTR_GID;
1367                 iattr.ia_uid = attr->la_uid;
1368                 iattr.ia_gid = attr->la_gid;
1369                 osd_push_ctxt(env, save);
1370                 rc = ll_vfs_dq_transfer(inode, &iattr) ? -EDQUOT : 0;
1371                 osd_pop_ctxt(save);
1372                 if (rc != 0)
1373                         return rc;
1374         }
1375 #endif
1376
1377         if (bits & LA_ATIME)
1378                 inode->i_atime  = *osd_inode_time(env, inode, attr->la_atime);
1379         if (bits & LA_CTIME)
1380                 inode->i_ctime  = *osd_inode_time(env, inode, attr->la_ctime);
1381         if (bits & LA_MTIME)
1382                 inode->i_mtime  = *osd_inode_time(env, inode, attr->la_mtime);
1383         if (bits & LA_SIZE) {
1384                 LDISKFS_I(inode)->i_disksize = attr->la_size;
1385                 i_size_write(inode, attr->la_size);
1386         }
1387
1388 #if 0
1389         /* OSD should not change "i_blocks" which is used by quota.
1390          * "i_blocks" should be changed by ldiskfs only. */
1391         if (bits & LA_BLOCKS)
1392                 inode->i_blocks = attr->la_blocks;
1393 #endif
1394         if (bits & LA_MODE)
1395                 inode->i_mode   = (inode->i_mode & S_IFMT) |
1396                         (attr->la_mode & ~S_IFMT);
1397         if (bits & LA_UID)
1398                 inode->i_uid    = attr->la_uid;
1399         if (bits & LA_GID)
1400                 inode->i_gid    = attr->la_gid;
1401         if (bits & LA_NLINK)
1402                 inode->i_nlink  = attr->la_nlink;
1403         if (bits & LA_RDEV)
1404                 inode->i_rdev   = attr->la_rdev;
1405
1406         if (bits & LA_FLAGS)
1407                 inode->i_flags = ll_ext_to_inode_flags(attr->la_flags);
1408         return 0;
1409 }
1410
1411 static int osd_attr_set(const struct lu_env *env,
1412                         struct dt_object *dt,
1413                         const struct lu_attr *attr,
1414                         struct thandle *handle,
1415                         struct lustre_capa *capa)
1416 {
1417         struct osd_object *obj = osd_dt_obj(dt);
1418         int rc;
1419
1420         LASSERT(handle != NULL);
1421         LASSERT(dt_object_exists(dt));
1422         LASSERT(osd_invariant(obj));
1423
1424         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_WRITE))
1425                 return -EACCES;
1426
1427         cfs_spin_lock(&obj->oo_guard);
1428         rc = osd_inode_setattr(env, obj->oo_inode, attr);
1429         cfs_spin_unlock(&obj->oo_guard);
1430
1431         if (!rc)
1432                 mark_inode_dirty(obj->oo_inode);
1433         return rc;
1434 }
1435
1436 /*
1437  * Object creation.
1438  *
1439  * XXX temporary solution.
1440  */
1441 static int osd_create_pre(struct osd_thread_info *info, struct osd_object *obj,
1442                           struct lu_attr *attr, struct thandle *th)
1443 {
1444         return 0;
1445 }
1446
1447 static int osd_create_post(struct osd_thread_info *info, struct osd_object *obj,
1448                            struct lu_attr *attr, struct thandle *th)
1449 {
1450         osd_object_init0(obj);
1451         return 0;
1452 }
1453
1454 static struct dentry * osd_child_dentry_get(const struct lu_env *env,
1455                                             struct osd_object *obj,
1456                                             const char *name,
1457                                             const int namelen)
1458 {
1459         struct osd_thread_info *info   = osd_oti_get(env);
1460         struct dentry *child_dentry = &info->oti_child_dentry;
1461         struct dentry *obj_dentry = &info->oti_obj_dentry;
1462
1463         obj_dentry->d_inode = obj->oo_inode;
1464         obj_dentry->d_sb = osd_sb(osd_obj2dev(obj));
1465         obj_dentry->d_name.hash = 0;
1466
1467         child_dentry->d_name.hash = 0;
1468         child_dentry->d_parent = obj_dentry;
1469         child_dentry->d_name.name = name;
1470         child_dentry->d_name.len = namelen;
1471         return child_dentry;
1472 }
1473
1474
1475 static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj,
1476                       cfs_umode_t mode,
1477                       struct dt_allocation_hint *hint,
1478                       struct thandle *th)
1479 {
1480         int result;
1481         struct osd_device  *osd = osd_obj2dev(obj);
1482         struct osd_thandle *oth;
1483         struct dt_object   *parent;
1484         struct inode       *inode;
1485 #ifdef HAVE_QUOTA_SUPPORT
1486         struct osd_ctxt    *save = &info->oti_ctxt;
1487 #endif
1488
1489         LINVRNT(osd_invariant(obj));
1490         LASSERT(obj->oo_inode == NULL);
1491
1492         oth = container_of(th, struct osd_thandle, ot_super);
1493         LASSERT(oth->ot_handle->h_transaction != NULL);
1494
1495         if (hint && hint->dah_parent)
1496                 parent = hint->dah_parent;
1497         else
1498                 parent = osd->od_obj_area;
1499
1500         LASSERT(parent != NULL);
1501         LASSERT(osd_dt_obj(parent)->oo_inode->i_op != NULL);
1502
1503 #ifdef HAVE_QUOTA_SUPPORT
1504         osd_push_ctxt(info->oti_env, save);
1505 #endif
1506         inode = ldiskfs_create_inode(oth->ot_handle,
1507                                      osd_dt_obj(parent)->oo_inode, mode);
1508 #ifdef HAVE_QUOTA_SUPPORT
1509         osd_pop_ctxt(save);
1510 #endif
1511         if (!IS_ERR(inode)) {
1512                 obj->oo_inode = inode;
1513                 result = 0;
1514         } else
1515                 result = PTR_ERR(inode);
1516         LINVRNT(osd_invariant(obj));
1517         return result;
1518 }
1519
1520 enum {
1521         OSD_NAME_LEN = 255
1522 };
1523
1524 static int osd_mkdir(struct osd_thread_info *info, struct osd_object *obj,
1525                      struct lu_attr *attr,
1526                      struct dt_allocation_hint *hint,
1527                      struct dt_object_format *dof,
1528                      struct thandle *th)
1529 {
1530         int result;
1531         struct osd_thandle *oth;
1532         struct osd_device *osd = osd_obj2dev(obj);
1533         __u32 mode = (attr->la_mode & (S_IFMT | S_IRWXUGO | S_ISVTX));
1534
1535         LASSERT(S_ISDIR(attr->la_mode));
1536
1537         oth = container_of(th, struct osd_thandle, ot_super);
1538         LASSERT(oth->ot_handle->h_transaction != NULL);
1539         result = osd_mkfile(info, obj, mode, hint, th);
1540         if (result == 0 && osd->od_iop_mode == 0) {
1541                 LASSERT(obj->oo_inode != NULL);
1542                 /*
1543                  * XXX uh-oh... call low-level iam function directly.
1544                  */
1545
1546                 result = iam_lvar_create(obj->oo_inode, OSD_NAME_LEN, 4,
1547                                          sizeof (struct osd_fid_pack),
1548                                          oth->ot_handle);
1549         }
1550         return result;
1551 }
1552
1553 static int osd_mk_index(struct osd_thread_info *info, struct osd_object *obj,
1554                         struct lu_attr *attr,
1555                         struct dt_allocation_hint *hint,
1556                         struct dt_object_format *dof,
1557                         struct thandle *th)
1558 {
1559         int result;
1560         struct osd_thandle *oth;
1561         const struct dt_index_features *feat = dof->u.dof_idx.di_feat;
1562
1563         __u32 mode = (attr->la_mode & (S_IFMT | S_IRWXUGO | S_ISVTX));
1564
1565         LASSERT(S_ISREG(attr->la_mode));
1566
1567         oth = container_of(th, struct osd_thandle, ot_super);
1568         LASSERT(oth->ot_handle->h_transaction != NULL);
1569
1570         result = osd_mkfile(info, obj, mode, hint, th);
1571         if (result == 0) {
1572                 LASSERT(obj->oo_inode != NULL);
1573                 if (feat->dif_flags & DT_IND_VARKEY)
1574                         result = iam_lvar_create(obj->oo_inode,
1575                                                  feat->dif_keysize_max,
1576                                                  feat->dif_ptrsize,
1577                                                  feat->dif_recsize_max,
1578                                                  oth->ot_handle);
1579                 else
1580                         result = iam_lfix_create(obj->oo_inode,
1581                                                  feat->dif_keysize_max,
1582                                                  feat->dif_ptrsize,
1583                                                  feat->dif_recsize_max,
1584                                                  oth->ot_handle);
1585
1586         }
1587         return result;
1588 }
1589
1590 static int osd_mkreg(struct osd_thread_info *info, struct osd_object *obj,
1591                      struct lu_attr *attr,
1592                      struct dt_allocation_hint *hint,
1593                      struct dt_object_format *dof,
1594                      struct thandle *th)
1595 {
1596         LASSERT(S_ISREG(attr->la_mode));
1597         return osd_mkfile(info, obj, (attr->la_mode &
1598                                (S_IFMT | S_IRWXUGO | S_ISVTX)), hint, th);
1599 }
1600
1601 static int osd_mksym(struct osd_thread_info *info, struct osd_object *obj,
1602                      struct lu_attr *attr,
1603                      struct dt_allocation_hint *hint,
1604                      struct dt_object_format *dof,
1605                      struct thandle *th)
1606 {
1607         LASSERT(S_ISLNK(attr->la_mode));
1608         return osd_mkfile(info, obj, (attr->la_mode &
1609                               (S_IFMT | S_IRWXUGO | S_ISVTX)), hint, th);
1610 }
1611
1612 static int osd_mknod(struct osd_thread_info *info, struct osd_object *obj,
1613                      struct lu_attr *attr,
1614                      struct dt_allocation_hint *hint,
1615                      struct dt_object_format *dof,
1616                      struct thandle *th)
1617 {
1618         cfs_umode_t mode = attr->la_mode & (S_IFMT | S_IRWXUGO | S_ISVTX);
1619         int result;
1620
1621         LINVRNT(osd_invariant(obj));
1622         LASSERT(obj->oo_inode == NULL);
1623         LASSERT(S_ISCHR(mode) || S_ISBLK(mode) ||
1624                 S_ISFIFO(mode) || S_ISSOCK(mode));
1625
1626         result = osd_mkfile(info, obj, mode, hint, th);
1627         if (result == 0) {
1628                 LASSERT(obj->oo_inode != NULL);
1629                 init_special_inode(obj->oo_inode, mode, attr->la_rdev);
1630         }
1631         LINVRNT(osd_invariant(obj));
1632         return result;
1633 }
1634
1635 typedef int (*osd_obj_type_f)(struct osd_thread_info *, struct osd_object *,
1636                               struct lu_attr *,
1637                               struct dt_allocation_hint *hint,
1638                               struct dt_object_format *dof,
1639                               struct thandle *);
1640
1641 static osd_obj_type_f osd_create_type_f(enum dt_format_type type)
1642 {
1643         osd_obj_type_f result;
1644
1645         switch (type) {
1646         case DFT_DIR:
1647                 result = osd_mkdir;
1648                 break;
1649         case DFT_REGULAR:
1650                 result = osd_mkreg;
1651                 break;
1652         case DFT_SYM:
1653                 result = osd_mksym;
1654                 break;
1655         case DFT_NODE:
1656                 result = osd_mknod;
1657                 break;
1658         case DFT_INDEX:
1659                 result = osd_mk_index;
1660                 break;
1661
1662         default:
1663                 LBUG();
1664                 break;
1665         }
1666         return result;
1667 }
1668
1669
1670 static void osd_ah_init(const struct lu_env *env, struct dt_allocation_hint *ah,
1671                         struct dt_object *parent, cfs_umode_t child_mode)
1672 {
1673         LASSERT(ah);
1674
1675         memset(ah, 0, sizeof(*ah));
1676         ah->dah_parent = parent;
1677         ah->dah_mode = child_mode;
1678 }
1679
1680 /**
1681  * Helper function for osd_object_create()
1682  *
1683  * \retval 0, on success
1684  */
1685 static int __osd_object_create(struct osd_thread_info *info,
1686                                struct osd_object *obj, struct lu_attr *attr,
1687                                struct dt_allocation_hint *hint,
1688                                struct dt_object_format *dof,
1689                                struct thandle *th)
1690 {
1691
1692         int result;
1693
1694         result = osd_create_pre(info, obj, attr, th);
1695         if (result == 0) {
1696                 result = osd_create_type_f(dof->dof_type)(info, obj,
1697                                            attr, hint, dof, th);
1698                 if (result == 0)
1699                         result = osd_create_post(info, obj, attr, th);
1700         }
1701         return result;
1702 }
1703
1704 /**
1705  * Helper function for osd_object_create()
1706  *
1707  * \retval 0, on success
1708  */
1709 static int __osd_oi_insert(const struct lu_env *env, struct osd_object *obj,
1710                            const struct lu_fid *fid, struct thandle *th)
1711 {
1712         struct osd_thread_info *info = osd_oti_get(env);
1713         struct osd_inode_id    *id   = &info->oti_id;
1714         struct osd_device      *osd  = osd_obj2dev(obj);
1715         struct md_ucred        *uc   = md_ucred(env);
1716
1717         LASSERT(obj->oo_inode != NULL);
1718         LASSERT(uc != NULL);
1719
1720         id->oii_ino = obj->oo_inode->i_ino;
1721         id->oii_gen = obj->oo_inode->i_generation;
1722
1723         return osd_oi_insert(info, &osd->od_oi, fid, id, th,
1724                              uc->mu_cap & CFS_CAP_SYS_RESOURCE_MASK);
1725 }
1726
1727 static int osd_object_create(const struct lu_env *env, struct dt_object *dt,
1728                              struct lu_attr *attr,
1729                              struct dt_allocation_hint *hint,
1730                              struct dt_object_format *dof,
1731                              struct thandle *th)
1732 {
1733         const struct lu_fid    *fid    = lu_object_fid(&dt->do_lu);
1734         struct osd_object      *obj    = osd_dt_obj(dt);
1735         struct osd_thread_info *info   = osd_oti_get(env);
1736         int result;
1737
1738         ENTRY;
1739
1740         LINVRNT(osd_invariant(obj));
1741         LASSERT(!dt_object_exists(dt));
1742         LASSERT(osd_write_locked(env, obj));
1743         LASSERT(th != NULL);
1744
1745         result = __osd_object_create(info, obj, attr, hint, dof, th);
1746         if (result == 0)
1747                 result = __osd_oi_insert(env, obj, fid, th);
1748
1749         LASSERT(ergo(result == 0, dt_object_exists(dt)));
1750         LASSERT(osd_invariant(obj));
1751         RETURN(result);
1752 }
1753
1754 /**
1755  * Helper function for osd_xattr_set()
1756  */
1757 static int __osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
1758                            const struct lu_buf *buf, const char *name, int fl)
1759 {
1760         struct osd_object      *obj      = osd_dt_obj(dt);
1761         struct inode           *inode    = obj->oo_inode;
1762         struct osd_thread_info *info     = osd_oti_get(env);
1763         struct dentry          *dentry   = &info->oti_child_dentry;
1764         struct timespec        *t        = &info->oti_time;
1765         int                     fs_flags = 0;
1766         int  rc;
1767
1768         LASSERT(dt_object_exists(dt));
1769         LASSERT(inode->i_op != NULL && inode->i_op->setxattr != NULL);
1770         LASSERT(osd_write_locked(env, obj));
1771
1772         if (fl & LU_XATTR_REPLACE)
1773                 fs_flags |= XATTR_REPLACE;
1774
1775         if (fl & LU_XATTR_CREATE)
1776                 fs_flags |= XATTR_CREATE;
1777
1778         dentry->d_inode = inode;
1779         *t = inode->i_ctime;
1780         rc = inode->i_op->setxattr(dentry, name, buf->lb_buf,
1781                                    buf->lb_len, fs_flags);
1782         /* ctime should not be updated with server-side time. */
1783         cfs_spin_lock(&obj->oo_guard);
1784         inode->i_ctime = *t;
1785         cfs_spin_unlock(&obj->oo_guard);
1786         mark_inode_dirty(inode);
1787         return rc;
1788 }
1789
1790 /**
1791  * Put the fid into lustre_mdt_attrs, and then place the structure
1792  * inode's ea. This fid should not be altered during the life time
1793  * of the inode.
1794  *
1795  * \retval +ve, on success
1796  * \retval -ve, on error
1797  *
1798  * FIXME: It is good to have/use ldiskfs_xattr_set_handle() here
1799  */
1800 static int osd_ea_fid_set(const struct lu_env *env, struct dt_object *dt,
1801                           const struct lu_fid *fid)
1802 {
1803         struct osd_thread_info  *info      = osd_oti_get(env);
1804         struct lustre_mdt_attrs *mdt_attrs = &info->oti_mdt_attrs;
1805
1806         lustre_lma_init(mdt_attrs, fid);
1807         lustre_lma_swab(mdt_attrs);
1808         return __osd_xattr_set(env, dt,
1809                                osd_buf_get(env, mdt_attrs, sizeof *mdt_attrs),
1810                                XATTR_NAME_LMA, LU_XATTR_CREATE);
1811
1812 }
1813
1814 /**
1815  * Helper function to form igif
1816  */
1817 static inline void osd_igif_get(const struct lu_env *env, struct inode  *inode,
1818                                 struct lu_fid *fid)
1819 {
1820         LU_IGIF_BUILD(fid, inode->i_ino, inode->i_generation);
1821 }
1822
1823 /**
1824  * Helper function to pack the fid, ldiskfs stores fid in packed format.
1825  */
1826 void osd_fid_pack(struct osd_fid_pack *pack, const struct dt_rec *fid,
1827                   struct lu_fid *befider)
1828 {
1829         fid_cpu_to_be(befider, (struct lu_fid *)fid);
1830         memcpy(pack->fp_area, befider, sizeof(*befider));
1831         pack->fp_len =  sizeof(*befider) + 1;
1832 }
1833
1834 /**
1835  * ldiskfs supports fid in dirent, it is passed in dentry->d_fsdata.
1836  * lustre 1.8 also uses d_fsdata for passing other info to ldiskfs.
1837  * To have compatilibility with 1.8 ldiskfs driver we need to have
1838  * magic number at start of fid data.
1839  * \ldiskfs_dentry_param is used only to pass fid from osd to ldiskfs.
1840  * its inmemory API.
1841  */
1842 void osd_get_ldiskfs_dirent_param(struct ldiskfs_dentry_param *param,
1843                                   const struct dt_rec *fid)
1844 {
1845         param->edp_magic = LDISKFS_LUFID_MAGIC;
1846         param->edp_len =  sizeof(struct lu_fid) + 1;
1847
1848         fid_cpu_to_be((struct lu_fid *)param->edp_data,
1849                       (struct lu_fid *)fid);
1850 }
1851
1852 int osd_fid_unpack(struct lu_fid *fid, const struct osd_fid_pack *pack)
1853 {
1854         int result;
1855
1856         result = 0;
1857         switch (pack->fp_len) {
1858         case sizeof *fid + 1:
1859                 memcpy(fid, pack->fp_area, sizeof *fid);
1860                 fid_be_to_cpu(fid, fid);
1861                 break;
1862         default:
1863                 CERROR("Unexpected packed fid size: %d\n", pack->fp_len);
1864                 result = -EIO;
1865         }
1866         return result;
1867 }
1868
1869 /**
1870  * Try to read the fid from inode ea into dt_rec, if return value
1871  * i.e. rc is +ve, then we got fid, otherwise we will have to form igif
1872  *
1873  * \param fid object fid.
1874  *
1875  * \retval 0 on success
1876  */
1877 static int osd_ea_fid_get(const struct lu_env *env, struct osd_object *obj,
1878                           __u32 ino, struct lu_fid *fid)
1879 {
1880         struct osd_thread_info  *info      = osd_oti_get(env);
1881         struct lustre_mdt_attrs *mdt_attrs = &info->oti_mdt_attrs;
1882         struct lu_device        *ldev   = obj->oo_dt.do_lu.lo_dev;
1883         struct dentry           *dentry = &info->oti_child_dentry;
1884         struct osd_inode_id     *id     = &info->oti_id;
1885         struct osd_device       *dev;
1886         struct inode            *inode;
1887         int                      rc;
1888
1889         ENTRY;
1890         dev  = osd_dev(ldev);
1891
1892         id->oii_ino = ino;
1893         id->oii_gen = OSD_OII_NOGEN;
1894
1895         inode = osd_iget(info, dev, id);
1896         if (IS_ERR(inode)) {
1897                 rc = PTR_ERR(inode);
1898                 GOTO(out,rc);
1899         }
1900         dentry->d_inode = inode;
1901
1902         LASSERT(inode->i_op != NULL && inode->i_op->getxattr != NULL);
1903         rc = inode->i_op->getxattr(dentry, XATTR_NAME_LMA, (void *)mdt_attrs,
1904                                    sizeof *mdt_attrs);
1905
1906         /* Check LMA compatibility */
1907         if (rc > 0 &&
1908             (mdt_attrs->lma_incompat & ~cpu_to_le32(LMA_INCOMPAT_SUPP))) {
1909                 CWARN("Inode %lx: Unsupported incompat LMA feature(s) %#x\n",
1910                       inode->i_ino, le32_to_cpu(mdt_attrs->lma_incompat) &
1911                       ~LMA_INCOMPAT_SUPP);
1912                 return -ENOSYS;
1913         }
1914
1915         if (rc > 0) {
1916                 lustre_lma_swab(mdt_attrs);
1917                 memcpy(fid, &mdt_attrs->lma_self_fid, sizeof(*fid));
1918                 rc = 0;
1919         } else if (rc == -ENODATA) {
1920                 osd_igif_get(env, inode, fid);
1921                 rc = 0;
1922         }
1923         iput(inode);
1924 out:
1925         RETURN(rc);
1926 }
1927
1928 /**
1929  * OSD layer object create function for interoperability mode (b11826).
1930  * This is mostly similar to osd_object_create(). Only difference being, fid is
1931  * inserted into inode ea here.
1932  *
1933  * \retval   0, on success
1934  * \retval -ve, on error
1935  */
1936 static int osd_object_ea_create(const struct lu_env *env, struct dt_object *dt,
1937                              struct lu_attr *attr,
1938                              struct dt_allocation_hint *hint,
1939                              struct dt_object_format *dof,
1940                              struct thandle *th)
1941 {
1942         const struct lu_fid    *fid    = lu_object_fid(&dt->do_lu);
1943         struct osd_object      *obj    = osd_dt_obj(dt);
1944         struct osd_thread_info *info   = osd_oti_get(env);
1945         int result;
1946
1947         ENTRY;
1948
1949         LASSERT(osd_invariant(obj));
1950         LASSERT(!dt_object_exists(dt));
1951         LASSERT(osd_write_locked(env, obj));
1952         LASSERT(th != NULL);
1953
1954         result = __osd_object_create(info, obj, attr, hint, dof, th);
1955
1956         /* objects under osd root shld have igif fid, so dont add fid EA */
1957         if (result == 0 && fid_seq(fid) >= FID_SEQ_NORMAL)
1958                 result = osd_ea_fid_set(env, dt, fid);
1959
1960         if (result == 0)
1961                 result = __osd_oi_insert(env, obj, fid, th);
1962
1963         LASSERT(ergo(result == 0, dt_object_exists(dt)));
1964         LINVRNT(osd_invariant(obj));
1965         RETURN(result);
1966 }
1967
1968 /*
1969  * Concurrency: @dt is write locked.
1970  */
1971 static void osd_object_ref_add(const struct lu_env *env,
1972                                struct dt_object *dt,
1973                                struct thandle *th)
1974 {
1975         struct osd_object *obj = osd_dt_obj(dt);
1976         struct inode *inode = obj->oo_inode;
1977
1978         LINVRNT(osd_invariant(obj));
1979         LASSERT(dt_object_exists(dt));
1980         LASSERT(osd_write_locked(env, obj));
1981         LASSERT(th != NULL);
1982
1983         cfs_spin_lock(&obj->oo_guard);
1984         LASSERT(inode->i_nlink < LDISKFS_LINK_MAX);
1985         inode->i_nlink++;
1986         cfs_spin_unlock(&obj->oo_guard);
1987         mark_inode_dirty(inode);
1988         LINVRNT(osd_invariant(obj));
1989 }
1990
1991 /*
1992  * Concurrency: @dt is write locked.
1993  */
1994 static void osd_object_ref_del(const struct lu_env *env,
1995                                struct dt_object *dt,
1996                                struct thandle *th)
1997 {
1998         struct osd_object *obj = osd_dt_obj(dt);
1999         struct inode *inode = obj->oo_inode;
2000
2001         LINVRNT(osd_invariant(obj));
2002         LASSERT(dt_object_exists(dt));
2003         LASSERT(osd_write_locked(env, obj));
2004         LASSERT(th != NULL);
2005
2006         cfs_spin_lock(&obj->oo_guard);
2007         LASSERT(inode->i_nlink > 0);
2008         inode->i_nlink--;
2009         cfs_spin_unlock(&obj->oo_guard);
2010         mark_inode_dirty(inode);
2011         LINVRNT(osd_invariant(obj));
2012 }
2013
2014 /*
2015  * Concurrency: @dt is read locked.
2016  */
2017 static int osd_xattr_get(const struct lu_env *env,
2018                          struct dt_object *dt,
2019                          struct lu_buf *buf,
2020                          const char *name,
2021                          struct lustre_capa *capa)
2022 {
2023         struct osd_object      *obj    = osd_dt_obj(dt);
2024         struct inode           *inode  = obj->oo_inode;
2025         struct osd_thread_info *info   = osd_oti_get(env);
2026         struct dentry          *dentry = &info->oti_obj_dentry;
2027
2028         LASSERT(dt_object_exists(dt));
2029         LASSERT(inode->i_op != NULL && inode->i_op->getxattr != NULL);
2030         LASSERT(osd_read_locked(env, obj) || osd_write_locked(env, obj));
2031
2032         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_READ))
2033                 return -EACCES;
2034
2035         dentry->d_inode = inode;
2036         return inode->i_op->getxattr(dentry, name, buf->lb_buf, buf->lb_len);
2037 }
2038
2039 /*
2040  * Concurrency: @dt is write locked.
2041  */
2042 static int osd_xattr_set(const struct lu_env *env, struct dt_object *dt,
2043                          const struct lu_buf *buf, const char *name, int fl,
2044                          struct thandle *handle, struct lustre_capa *capa)
2045 {
2046         LASSERT(handle != NULL);
2047
2048         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_WRITE))
2049                 return -EACCES;
2050
2051         return __osd_xattr_set(env, dt, buf, name, fl);
2052 }
2053
2054 /*
2055  * Concurrency: @dt is read locked.
2056  */
2057 static int osd_xattr_list(const struct lu_env *env,
2058                           struct dt_object *dt,
2059                           struct lu_buf *buf,
2060                           struct lustre_capa *capa)
2061 {
2062         struct osd_object      *obj    = osd_dt_obj(dt);
2063         struct inode           *inode  = obj->oo_inode;
2064         struct osd_thread_info *info   = osd_oti_get(env);
2065         struct dentry          *dentry = &info->oti_obj_dentry;
2066
2067         LASSERT(dt_object_exists(dt));
2068         LASSERT(inode->i_op != NULL && inode->i_op->listxattr != NULL);
2069         LASSERT(osd_read_locked(env, obj) || osd_write_locked(env, obj));
2070
2071         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_READ))
2072                 return -EACCES;
2073
2074         dentry->d_inode = inode;
2075         return inode->i_op->listxattr(dentry, buf->lb_buf, buf->lb_len);
2076 }
2077
2078 /*
2079  * Concurrency: @dt is write locked.
2080  */
2081 static int osd_xattr_del(const struct lu_env *env,
2082                          struct dt_object *dt,
2083                          const char *name,
2084                          struct thandle *handle,
2085                          struct lustre_capa *capa)
2086 {
2087         struct osd_object      *obj    = osd_dt_obj(dt);
2088         struct inode           *inode  = obj->oo_inode;
2089         struct osd_thread_info *info   = osd_oti_get(env);
2090         struct dentry          *dentry = &info->oti_obj_dentry;
2091         struct timespec        *t      = &info->oti_time;
2092         int                     rc;
2093
2094         LASSERT(dt_object_exists(dt));
2095         LASSERT(inode->i_op != NULL && inode->i_op->removexattr != NULL);
2096         LASSERT(osd_write_locked(env, obj));
2097         LASSERT(handle != NULL);
2098
2099         if (osd_object_auth(env, dt, capa, CAPA_OPC_META_WRITE))
2100                 return -EACCES;
2101
2102         dentry->d_inode = inode;
2103         *t = inode->i_ctime;
2104         rc = inode->i_op->removexattr(dentry, name);
2105         /* ctime should not be updated with server-side time. */
2106         cfs_spin_lock(&obj->oo_guard);
2107         inode->i_ctime = *t;
2108         cfs_spin_unlock(&obj->oo_guard);
2109         mark_inode_dirty(inode);
2110         return rc;
2111 }
2112
2113 static struct obd_capa *osd_capa_get(const struct lu_env *env,
2114                                      struct dt_object *dt,
2115                                      struct lustre_capa *old,
2116                                      __u64 opc)
2117 {
2118         struct osd_thread_info *info = osd_oti_get(env);
2119         const struct lu_fid *fid = lu_object_fid(&dt->do_lu);
2120         struct osd_object *obj = osd_dt_obj(dt);
2121         struct osd_device *dev = osd_obj2dev(obj);
2122         struct lustre_capa_key *key = &info->oti_capa_key;
2123         struct lustre_capa *capa = &info->oti_capa;
2124         struct obd_capa *oc;
2125         struct md_capainfo *ci;
2126         int rc;
2127         ENTRY;
2128
2129         if (!dev->od_fl_capa)
2130                 RETURN(ERR_PTR(-ENOENT));
2131
2132         LASSERT(dt_object_exists(dt));
2133         LINVRNT(osd_invariant(obj));
2134
2135         /* renewal sanity check */
2136         if (old && osd_object_auth(env, dt, old, opc))
2137                 RETURN(ERR_PTR(-EACCES));
2138
2139         ci = md_capainfo(env);
2140         if (unlikely(!ci))
2141                 RETURN(ERR_PTR(-ENOENT));
2142
2143         switch (ci->mc_auth) {
2144         case LC_ID_NONE:
2145                 RETURN(NULL);
2146         case LC_ID_PLAIN:
2147                 capa->lc_uid = obj->oo_inode->i_uid;
2148                 capa->lc_gid = obj->oo_inode->i_gid;
2149                 capa->lc_flags = LC_ID_PLAIN;
2150                 break;
2151         case LC_ID_CONVERT: {
2152                 __u32 d[4], s[4];
2153
2154                 s[0] = obj->oo_inode->i_uid;
2155                 cfs_get_random_bytes(&(s[1]), sizeof(__u32));
2156                 s[2] = obj->oo_inode->i_gid;
2157                 cfs_get_random_bytes(&(s[3]), sizeof(__u32));
2158                 rc = capa_encrypt_id(d, s, key->lk_key, CAPA_HMAC_KEY_MAX_LEN);
2159                 if (unlikely(rc))
2160                         RETURN(ERR_PTR(rc));
2161
2162                 capa->lc_uid   = ((__u64)d[1] << 32) | d[0];
2163                 capa->lc_gid   = ((__u64)d[3] << 32) | d[2];
2164                 capa->lc_flags = LC_ID_CONVERT;
2165                 break;
2166         }
2167         default:
2168                 RETURN(ERR_PTR(-EINVAL));
2169         }
2170
2171         capa->lc_fid = *fid;
2172         capa->lc_opc = opc;
2173         capa->lc_flags |= dev->od_capa_alg << 24;
2174         capa->lc_timeout = dev->od_capa_timeout;
2175         capa->lc_expiry = 0;
2176
2177         oc = capa_lookup(dev->od_capa_hash, capa, 1);
2178         if (oc) {
2179                 LASSERT(!capa_is_expired(oc));
2180                 RETURN(oc);
2181         }
2182
2183         cfs_spin_lock(&capa_lock);
2184         *key = dev->od_capa_keys[1];
2185         cfs_spin_unlock(&capa_lock);
2186
2187         capa->lc_keyid = key->lk_keyid;
2188         capa->lc_expiry = cfs_time_current_sec() + dev->od_capa_timeout;
2189
2190         rc = capa_hmac(capa->lc_hmac, capa, key->lk_key);
2191         if (rc) {
2192                 DEBUG_CAPA(D_ERROR, capa, "HMAC failed: %d for", rc);
2193                 RETURN(ERR_PTR(rc));
2194         }
2195
2196         oc = capa_add(dev->od_capa_hash, capa);
2197         RETURN(oc);
2198 }
2199
2200 static int osd_object_sync(const struct lu_env *env, struct dt_object *dt)
2201 {
2202         int rc;
2203         struct osd_object      *obj    = osd_dt_obj(dt);
2204         struct inode           *inode  = obj->oo_inode;
2205         struct osd_thread_info *info   = osd_oti_get(env);
2206         struct dentry          *dentry = &info->oti_obj_dentry;
2207         struct file            *file   = &info->oti_file;
2208         ENTRY;
2209
2210         dentry->d_inode = inode;
2211         file->f_dentry = dentry;
2212         file->f_mapping = inode->i_mapping;
2213         file->f_op = inode->i_fop;
2214         LOCK_INODE_MUTEX(inode);
2215         rc = file->f_op->fsync(file, dentry, 0);
2216         UNLOCK_INODE_MUTEX(inode);
2217         RETURN(rc);
2218 }
2219
2220 /*
2221  * Get the 64-bit version for an inode.
2222  */
2223 static dt_obj_version_t osd_object_version_get(const struct lu_env *env,
2224                                                struct dt_object *dt)
2225 {
2226         struct inode *inode = osd_dt_obj(dt)->oo_inode;
2227
2228         CDEBUG(D_INFO, "Get version "LPX64" for inode %lu\n",
2229                LDISKFS_I(inode)->i_fs_version, inode->i_ino);
2230         return LDISKFS_I(inode)->i_fs_version;
2231 }
2232
2233 /*
2234  * Set the 64-bit version and return the old version.
2235  */
2236 static void osd_object_version_set(const struct lu_env *env, struct dt_object *dt,
2237                                    dt_obj_version_t new_version)
2238 {
2239         struct inode *inode = osd_dt_obj(dt)->oo_inode;
2240
2241         CDEBUG(D_INFO, "Set version "LPX64" (old "LPX64") for inode %lu\n",
2242                new_version, LDISKFS_I(inode)->i_fs_version, inode->i_ino);
2243         LDISKFS_I(inode)->i_fs_version = new_version;
2244         /** Version is set after all inode operations are finished,
2245          *  so we should mark it dirty here */
2246         inode->i_sb->s_op->dirty_inode(inode);
2247 }
2248
2249 static int osd_data_get(const struct lu_env *env, struct dt_object *dt,
2250                         void **data)
2251 {
2252         struct osd_object *obj = osd_dt_obj(dt);
2253         ENTRY;
2254
2255         *data = (void *)obj->oo_inode;
2256         RETURN(0);
2257 }
2258
2259 /*
2260  * Index operations.
2261  */
2262
2263 static int osd_iam_index_probe(const struct lu_env *env, struct osd_object *o,
2264                            const struct dt_index_features *feat)
2265 {
2266         struct iam_descr *descr;
2267
2268         if (osd_object_is_root(o))
2269                 return feat == &dt_directory_features;
2270
2271         LASSERT(o->oo_dir != NULL);
2272
2273         descr = o->oo_dir->od_container.ic_descr;
2274         if (feat == &dt_directory_features) {
2275                 if (descr->id_rec_size == sizeof(struct osd_fid_pack))
2276                         return 1;
2277                 else
2278                         return 0;
2279         } else {
2280                 return
2281                         feat->dif_keysize_min <= descr->id_key_size &&
2282                         descr->id_key_size <= feat->dif_keysize_max &&
2283                         feat->dif_recsize_min <= descr->id_rec_size &&
2284                         descr->id_rec_size <= feat->dif_recsize_max &&
2285                         !(feat->dif_flags & (DT_IND_VARKEY |
2286                                              DT_IND_VARREC | DT_IND_NONUNQ)) &&
2287                         ergo(feat->dif_flags & DT_IND_UPDATE,
2288                              1 /* XXX check that object (and file system) is
2289                                 * writable */);
2290         }
2291 }
2292
2293 static int osd_iam_container_init(const struct lu_env *env,
2294                                   struct osd_object *obj,
2295                                   struct osd_directory *dir)
2296 {
2297         int result;
2298         struct iam_container *bag;
2299
2300         bag    = &dir->od_container;
2301         result = iam_container_init(bag, &dir->od_descr, obj->oo_inode);
2302         if (result == 0) {
2303                 result = iam_container_setup(bag);
2304                 if (result == 0)
2305                         obj->oo_dt.do_index_ops = &osd_index_iam_ops;
2306                 else
2307                         iam_container_fini(bag);
2308         }
2309         return result;
2310 }
2311
2312
2313 /*
2314  * Concurrency: no external locking is necessary.
2315  */
2316 static int osd_index_try(const struct lu_env *env, struct dt_object *dt,
2317                          const struct dt_index_features *feat)
2318 {
2319         int result;
2320         int ea_dir = 0;
2321         struct osd_object *obj = osd_dt_obj(dt);
2322         struct osd_device *osd = osd_obj2dev(obj);
2323
2324         LINVRNT(osd_invariant(obj));
2325         LASSERT(dt_object_exists(dt));
2326
2327         if (osd_object_is_root(obj)) {
2328                 dt->do_index_ops = &osd_index_ea_ops;
2329                 result = 0;
2330         } else if (feat == &dt_directory_features && osd->od_iop_mode) {
2331                 dt->do_index_ops = &osd_index_ea_ops;
2332                 if (S_ISDIR(obj->oo_inode->i_mode))
2333                         result = 0;
2334                 else
2335                         result = -ENOTDIR;
2336                 ea_dir = 1;
2337         } else if (!osd_has_index(obj)) {
2338                 struct osd_directory *dir;
2339
2340                 OBD_ALLOC_PTR(dir);
2341                 if (dir != NULL) {
2342
2343                         cfs_spin_lock(&obj->oo_guard);
2344                         if (obj->oo_dir == NULL)
2345                                 obj->oo_dir = dir;
2346                         else
2347                                 /*
2348                                  * Concurrent thread allocated container data.
2349                                  */
2350                                 OBD_FREE_PTR(dir);
2351                         cfs_spin_unlock(&obj->oo_guard);
2352                         /*
2353                          * Now, that we have container data, serialize its
2354                          * initialization.
2355                          */
2356                         cfs_down_write(&obj->oo_ext_idx_sem);
2357                         /*
2358                          * recheck under lock.
2359                          */
2360                         if (!osd_has_index(obj))
2361                                 result = osd_iam_container_init(env, obj, dir);
2362                         else
2363                                 result = 0;
2364                         cfs_up_write(&obj->oo_ext_idx_sem);
2365                 } else
2366                         result = -ENOMEM;
2367         } else
2368                 result = 0;
2369
2370         if (result == 0 && ea_dir == 0) {
2371                 if (!osd_iam_index_probe(env, obj, feat))
2372                         result = -ENOTDIR;
2373         }
2374         LINVRNT(osd_invariant(obj));
2375
2376         return result;
2377 }
2378
2379 static const struct dt_object_operations osd_obj_ops = {
2380         .do_read_lock    = osd_object_read_lock,
2381         .do_write_lock   = osd_object_write_lock,
2382         .do_read_unlock  = osd_object_read_unlock,
2383         .do_write_unlock = osd_object_write_unlock,
2384         .do_write_locked = osd_object_write_locked,
2385         .do_attr_get     = osd_attr_get,
2386         .do_attr_set     = osd_attr_set,
2387         .do_ah_init      = osd_ah_init,
2388         .do_create       = osd_object_create,
2389         .do_index_try    = osd_index_try,
2390         .do_ref_add      = osd_object_ref_add,
2391         .do_ref_del      = osd_object_ref_del,
2392         .do_xattr_get    = osd_xattr_get,
2393         .do_xattr_set    = osd_xattr_set,
2394         .do_xattr_del    = osd_xattr_del,
2395         .do_xattr_list   = osd_xattr_list,
2396         .do_capa_get     = osd_capa_get,
2397         .do_object_sync  = osd_object_sync,
2398         .do_version_get  = osd_object_version_get,
2399         .do_version_set  = osd_object_version_set,
2400         .do_data_get     = osd_data_get,
2401 };
2402
2403 /**
2404  * dt_object_operations for interoperability mode
2405  * (i.e. to run 2.0 mds on 1.8 disk) (b11826)
2406  */
2407 static const struct dt_object_operations osd_obj_ea_ops = {
2408         .do_read_lock    = osd_object_read_lock,
2409         .do_write_lock   = osd_object_write_lock,
2410         .do_read_unlock  = osd_object_read_unlock,
2411         .do_write_unlock = osd_object_write_unlock,
2412         .do_write_locked = osd_object_write_locked,
2413         .do_attr_get     = osd_attr_get,
2414         .do_attr_set     = osd_attr_set,
2415         .do_ah_init      = osd_ah_init,
2416         .do_create       = osd_object_ea_create,
2417         .do_index_try    = osd_index_try,
2418         .do_ref_add      = osd_object_ref_add,
2419         .do_ref_del      = osd_object_ref_del,
2420         .do_xattr_get    = osd_xattr_get,
2421         .do_xattr_set    = osd_xattr_set,
2422         .do_xattr_del    = osd_xattr_del,
2423         .do_xattr_list   = osd_xattr_list,
2424         .do_capa_get     = osd_capa_get,
2425         .do_object_sync  = osd_object_sync,
2426         .do_version_get  = osd_object_version_get,
2427         .do_version_set  = osd_object_version_set,
2428         .do_data_get     = osd_data_get,
2429 };
2430
2431 /*
2432  * Body operations.
2433  */
2434
2435 /*
2436  * XXX: Another layering violation for now.
2437  *
2438  * We don't want to use ->f_op->read methods, because generic file write
2439  *
2440  *         - serializes on ->i_sem, and
2441  *
2442  *         - does a lot of extra work like balance_dirty_pages(),
2443  *
2444  * which doesn't work for globally shared files like /last-received.
2445  */
2446 static int osd_ldiskfs_readlink(struct inode *inode, char *buffer, int buflen)
2447 {
2448         struct ldiskfs_inode_info *ei = LDISKFS_I(inode);
2449
2450         memcpy(buffer, (char*)ei->i_data, buflen);
2451
2452         return  buflen;
2453 }
2454
2455 static int osd_ldiskfs_read(struct inode *inode, void *buf, int size,
2456                             loff_t *offs)
2457 {
2458         struct buffer_head *bh;
2459         unsigned long block;
2460         int osize = size;
2461         int blocksize;
2462         int csize;
2463         int boffs;
2464         int err;
2465
2466         /* prevent reading after eof */
2467         spin_lock(&inode->i_lock);
2468         if (i_size_read(inode) < *offs + size) {
2469                 size = i_size_read(inode) - *offs;
2470                 spin_unlock(&inode->i_lock);
2471                 if (size < 0) {
2472                         CDEBUG(D_EXT2, "size %llu is too short to read @%llu\n",
2473                                i_size_read(inode), *offs);
2474                         return -EBADR;
2475                 } else if (size == 0) {
2476                         return 0;
2477                 }
2478         } else {
2479                 spin_unlock(&inode->i_lock);
2480         }
2481
2482         blocksize = 1 << inode->i_blkbits;
2483
2484         while (size > 0) {
2485                 block = *offs >> inode->i_blkbits;
2486                 boffs = *offs & (blocksize - 1);
2487                 csize = min(blocksize - boffs, size);
2488                 bh = ldiskfs_bread(NULL, inode, block, 0, &err);
2489                 if (!bh) {
2490                         CERROR("can't read block: %d\n", err);
2491                         return err;
2492                 }
2493
2494                 memcpy(buf, bh->b_data + boffs, csize);
2495                 brelse(bh);
2496
2497                 *offs += csize;
2498                 buf += csize;
2499                 size -= csize;
2500         }
2501         return osize;
2502 }
2503
2504 static ssize_t osd_read(const struct lu_env *env, struct dt_object *dt,
2505                         struct lu_buf *buf, loff_t *pos,
2506                         struct lustre_capa *capa)
2507 {
2508         struct osd_object      *obj    = osd_dt_obj(dt);
2509         struct inode           *inode  = obj->oo_inode;
2510         int rc;
2511
2512         if (osd_object_auth(env, dt, capa, CAPA_OPC_BODY_READ))
2513                 RETURN(-EACCES);
2514
2515         /* Read small symlink from inode body as we need to maintain correct
2516          * on-disk symlinks for ldiskfs.
2517          */
2518         if (S_ISLNK(obj->oo_dt.do_lu.lo_header->loh_attr) &&
2519             (buf->lb_len <= sizeof (LDISKFS_I(inode)->i_data)))
2520                 rc = osd_ldiskfs_readlink(inode, buf->lb_buf, buf->lb_len);
2521         else
2522                 rc = osd_ldiskfs_read(inode, buf->lb_buf, buf->lb_len, pos);
2523
2524         return rc;
2525 }
2526
2527 static int osd_ldiskfs_writelink(struct inode *inode, char *buffer, int buflen)
2528 {
2529
2530         memcpy((char*)&LDISKFS_I(inode)->i_data, (char *)buffer,
2531                buflen);
2532         LDISKFS_I(inode)->i_disksize = buflen;
2533         i_size_write(inode, buflen);
2534         inode->i_sb->s_op->dirty_inode(inode);
2535
2536         return 0;
2537 }
2538
2539 static int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
2540                                     loff_t *offs, handle_t *handle)
2541 {
2542         struct buffer_head *bh = NULL;
2543         loff_t offset = *offs;
2544         loff_t new_size = i_size_read(inode);
2545         unsigned long block;
2546         int blocksize = 1 << inode->i_blkbits;
2547         int err = 0;
2548         int size;
2549         int boffs;
2550         int dirty_inode = 0;
2551
2552         while (bufsize > 0) {
2553                 if (bh != NULL)
2554                         brelse(bh);
2555
2556                 block = offset >> inode->i_blkbits;
2557                 boffs = offset & (blocksize - 1);
2558                 size = min(blocksize - boffs, bufsize);
2559                 bh = ldiskfs_bread(handle, inode, block, 1, &err);
2560                 if (!bh) {
2561                         CERROR("can't read/create block: %d\n", err);
2562                         break;
2563                 }
2564
2565                 err = ldiskfs_journal_get_write_access(handle, bh);
2566                 if (err) {
2567                         CERROR("journal_get_write_access() returned error %d\n",
2568                                err);
2569                         break;
2570                 }
2571                 LASSERTF(boffs + size <= bh->b_size,
2572                          "boffs %d size %d bh->b_size %lu",
2573                          boffs, size, (unsigned long)bh->b_size);
2574                 memcpy(bh->b_data + boffs, buf, size);
2575                 err = ldiskfs_journal_dirty_metadata(handle, bh);
2576                 if (err)
2577                         break;
2578
2579                 if (offset + size > new_size)
2580                         new_size = offset + size;
2581                 offset += size;
2582                 bufsize -= size;
2583                 buf += size;
2584         }
2585         if (bh)
2586                 brelse(bh);
2587
2588         /* correct in-core and on-disk sizes */
2589         if (new_size > i_size_read(inode)) {
2590                 spin_lock(&inode->i_lock);
2591                 if (new_size > i_size_read(inode))
2592                         i_size_write(inode, new_size);
2593                 if (i_size_read(inode) > LDISKFS_I(inode)->i_disksize) {
2594                         LDISKFS_I(inode)->i_disksize = i_size_read(inode);
2595                         dirty_inode = 1;
2596                 }
2597                 spin_unlock(&inode->i_lock);
2598                 if (dirty_inode)
2599                         inode->i_sb->s_op->dirty_inode(inode);
2600         }
2601
2602         if (err == 0)
2603                 *offs = offset;
2604         return err;
2605 }
2606
2607 static ssize_t osd_write(const struct lu_env *env, struct dt_object *dt,
2608                          const struct lu_buf *buf, loff_t *pos,
2609                          struct thandle *handle, struct lustre_capa *capa,
2610                          int ignore_quota)
2611 {
2612         struct osd_object  *obj   = osd_dt_obj(dt);
2613         struct inode       *inode = obj->oo_inode;
2614         struct osd_thandle *oh;
2615         ssize_t            result = 0;
2616 #ifdef HAVE_QUOTA_SUPPORT
2617         cfs_cap_t           save = cfs_curproc_cap_pack();
2618 #endif
2619
2620         LASSERT(handle != NULL);
2621
2622         if (osd_object_auth(env, dt, capa, CAPA_OPC_BODY_WRITE))
2623                 RETURN(-EACCES);
2624
2625         oh = container_of(handle, struct osd_thandle, ot_super);
2626         LASSERT(oh->ot_handle->h_transaction != NULL);
2627 #ifdef HAVE_QUOTA_SUPPORT
2628         if (ignore_quota)
2629                 cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
2630         else
2631                 cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
2632 #endif
2633         /* Write small symlink to inode body as we need to maintain correct
2634          * on-disk symlinks for ldiskfs.
2635          */
2636         if(S_ISLNK(obj->oo_dt.do_lu.lo_header->loh_attr) &&
2637            (buf->lb_len < sizeof (LDISKFS_I(inode)->i_data)))
2638                 result = osd_ldiskfs_writelink(inode, buf->lb_buf, buf->lb_len);
2639         else
2640                 result = osd_ldiskfs_write_record(inode, buf->lb_buf,
2641                                                   buf->lb_len, pos,
2642                                                   oh->ot_handle);
2643 #ifdef HAVE_QUOTA_SUPPORT
2644         cfs_curproc_cap_unpack(save);
2645 #endif
2646         if (result == 0)
2647                 result = buf->lb_len;
2648         return result;
2649 }
2650
2651 static const struct dt_body_operations osd_body_ops = {
2652         .dbo_read  = osd_read,
2653         .dbo_write = osd_write
2654 };
2655
2656
2657 /**
2658  *      delete a (key, value) pair from index \a dt specified by \a key
2659  *
2660  *      \param  dt      osd index object
2661  *      \param  key     key for index
2662  *      \param  rec     record reference
2663  *      \param  handle  transaction handler
2664  *
2665  *      \retval  0  success
2666  *      \retval -ve   failure
2667  */
2668
2669 static int osd_index_iam_delete(const struct lu_env *env, struct dt_object *dt,
2670                                 const struct dt_key *key, struct thandle *handle,
2671                                 struct lustre_capa *capa)
2672 {
2673         struct osd_object     *obj = osd_dt_obj(dt);
2674         struct osd_thandle    *oh;
2675         struct iam_path_descr *ipd;
2676         struct iam_container  *bag = &obj->oo_dir->od_container;
2677         int rc;
2678
2679         ENTRY;
2680
2681         LINVRNT(osd_invariant(obj));
2682         LASSERT(dt_object_exists(dt));
2683         LASSERT(bag->ic_object == obj->oo_inode);
2684         LASSERT(handle != NULL);
2685
2686         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_DELETE))
2687                 RETURN(-EACCES);
2688
2689         ipd = osd_idx_ipd_get(env, bag);
2690         if (unlikely(ipd == NULL))
2691                 RETURN(-ENOMEM);
2692
2693         oh = container_of0(handle, struct osd_thandle, ot_super);
2694         LASSERT(oh->ot_handle != NULL);
2695         LASSERT(oh->ot_handle->h_transaction != NULL);
2696
2697         rc = iam_delete(oh->ot_handle, bag, (const struct iam_key *)key, ipd);
2698         osd_ipd_put(env, bag, ipd);
2699         LINVRNT(osd_invariant(obj));
2700         RETURN(rc);
2701 }
2702
2703 static inline int osd_get_fid_from_dentry(struct ldiskfs_dir_entry_2 *de,
2704                                           struct dt_rec *fid)
2705 {
2706         struct osd_fid_pack *rec;
2707         int rc = -ENODATA;
2708
2709         if (de->file_type & LDISKFS_DIRENT_LUFID) {
2710                 rec = (struct osd_fid_pack *) (de->name + de->name_len + 1);
2711                 rc = osd_fid_unpack((struct lu_fid *)fid, rec);
2712         }
2713         RETURN(rc);
2714 }
2715
2716 /**
2717  * Index delete function for interoperability mode (b11826).
2718  * It will remove the directory entry added by osd_index_ea_insert().
2719  * This entry is needed to maintain name->fid mapping.
2720  *
2721  * \param key,  key i.e. file entry to be deleted
2722  *
2723  * \retval   0, on success
2724  * \retval -ve, on error
2725  */
2726 static int osd_index_ea_delete(const struct lu_env *env, struct dt_object *dt,
2727                                const struct dt_key *key, struct thandle *handle,
2728                                struct lustre_capa *capa)
2729 {
2730         struct osd_object          *obj    = osd_dt_obj(dt);
2731         struct inode               *dir    = obj->oo_inode;
2732         struct dentry              *dentry;
2733         struct osd_thandle         *oh;
2734         struct ldiskfs_dir_entry_2 *de;
2735         struct buffer_head         *bh;
2736
2737         int rc;
2738
2739         ENTRY;
2740
2741         LINVRNT(osd_invariant(obj));
2742         LASSERT(dt_object_exists(dt));
2743         LASSERT(handle != NULL);
2744
2745         oh = container_of(handle, struct osd_thandle, ot_super);
2746         LASSERT(oh->ot_handle != NULL);
2747         LASSERT(oh->ot_handle->h_transaction != NULL);
2748
2749         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_DELETE))
2750                 RETURN(-EACCES);
2751
2752         dentry = osd_child_dentry_get(env, obj,
2753                                       (char *)key, strlen((char *)key));
2754
2755         cfs_down_write(&obj->oo_ext_idx_sem);
2756         bh = ll_ldiskfs_find_entry(dir, dentry, &de);
2757         if (bh) {
2758                 struct osd_thread_info *oti = osd_oti_get(env);
2759                 struct timespec *ctime = &oti->oti_time;
2760                 struct timespec *mtime = &oti->oti_time2;
2761
2762                 *ctime = dir->i_ctime;
2763                 *mtime = dir->i_mtime;
2764                 rc = ldiskfs_delete_entry(oh->ot_handle,
2765                                 dir, de, bh);
2766                 /* xtime should not be updated with server-side time. */
2767                 cfs_spin_lock(&obj->oo_guard);
2768                 dir->i_ctime = *ctime;
2769                 dir->i_mtime = *mtime;
2770                 cfs_spin_unlock(&obj->oo_guard);
2771                 mark_inode_dirty(dir);
2772                 brelse(bh);
2773         } else
2774                 rc = -ENOENT;
2775
2776         cfs_up_write(&obj->oo_ext_idx_sem);
2777         LASSERT(osd_invariant(obj));
2778         RETURN(rc);
2779 }
2780
2781 /**
2782  *      Lookup index for \a key and copy record to \a rec.
2783  *
2784  *      \param  dt      osd index object
2785  *      \param  key     key for index
2786  *      \param  rec     record reference
2787  *
2788  *      \retval  +ve  success : exact mach
2789  *      \retval  0    return record with key not greater than \a key
2790  *      \retval -ve   failure
2791  */
2792 static int osd_index_iam_lookup(const struct lu_env *env, struct dt_object *dt,
2793                                 struct dt_rec *rec, const struct dt_key *key,
2794                                 struct lustre_capa *capa)
2795 {
2796         struct osd_object     *obj = osd_dt_obj(dt);
2797         struct iam_path_descr *ipd;
2798         struct iam_container  *bag = &obj->oo_dir->od_container;
2799         struct osd_thread_info *oti = osd_oti_get(env);
2800         struct iam_iterator    *it = &oti->oti_idx_it;
2801         struct iam_rec *iam_rec;
2802         int rc;
2803         ENTRY;
2804
2805         LASSERT(osd_invariant(obj));
2806         LASSERT(dt_object_exists(dt));
2807         LASSERT(bag->ic_object == obj->oo_inode);
2808
2809         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_LOOKUP))
2810                 RETURN(-EACCES);
2811
2812         ipd = osd_idx_ipd_get(env, bag);
2813         if (IS_ERR(ipd))
2814                 RETURN(-ENOMEM);
2815
2816         /* got ipd now we can start iterator. */
2817         iam_it_init(it, bag, 0, ipd);
2818
2819         rc = iam_it_get(it, (struct iam_key *)key);
2820         if (rc >= 0) {
2821                 if (S_ISDIR(obj->oo_inode->i_mode))
2822                         iam_rec = (struct iam_rec *)oti->oti_ldp;
2823                 else
2824                         iam_rec = (struct iam_rec *) rec;
2825
2826                 iam_reccpy(&it->ii_path.ip_leaf, (struct iam_rec *)iam_rec);
2827                 if (S_ISDIR(obj->oo_inode->i_mode))
2828                         osd_fid_unpack((struct lu_fid *) rec,
2829                                        (struct osd_fid_pack *)iam_rec);
2830         }
2831         iam_it_put(it);
2832         iam_it_fini(it);
2833         osd_ipd_put(env, bag, ipd);
2834
2835         LINVRNT(osd_invariant(obj));
2836
2837         RETURN(rc);
2838 }
2839
2840 /**
2841  *      Inserts (key, value) pair in \a dt index object.
2842  *
2843  *      \param  dt      osd index object
2844  *      \param  key     key for index
2845  *      \param  rec     record reference
2846  *      \param  th      transaction handler
2847  *
2848  *      \retval  0  success
2849  *      \retval -ve failure
2850  */
2851 static int osd_index_iam_insert(const struct lu_env *env, struct dt_object *dt,
2852                                 const struct dt_rec *rec, const struct dt_key *key,
2853                                 struct thandle *th, struct lustre_capa *capa,
2854                                 int ignore_quota)
2855 {
2856         struct osd_object     *obj = osd_dt_obj(dt);
2857         struct iam_path_descr *ipd;
2858         struct osd_thandle    *oh;
2859         struct iam_container  *bag = &obj->oo_dir->od_container;
2860 #ifdef HAVE_QUOTA_SUPPORT
2861         cfs_cap_t              save = cfs_curproc_cap_pack();
2862 #endif
2863         struct osd_thread_info *oti = osd_oti_get(env);
2864         struct iam_rec *iam_rec = (struct iam_rec *)oti->oti_ldp;
2865         int rc;
2866
2867         ENTRY;
2868
2869         LINVRNT(osd_invariant(obj));
2870         LASSERT(dt_object_exists(dt));
2871         LASSERT(bag->ic_object == obj->oo_inode);
2872         LASSERT(th != NULL);
2873
2874         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_INSERT))
2875                 return -EACCES;
2876
2877         ipd = osd_idx_ipd_get(env, bag);
2878         if (unlikely(ipd == NULL))
2879                 RETURN(-ENOMEM);
2880
2881         oh = container_of0(th, struct osd_thandle, ot_super);
2882         LASSERT(oh->ot_handle != NULL);
2883         LASSERT(oh->ot_handle->h_transaction != NULL);
2884 #ifdef HAVE_QUOTA_SUPPORT
2885         if (ignore_quota)
2886                 cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
2887         else
2888                 cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
2889 #endif
2890         if (S_ISDIR(obj->oo_inode->i_mode))
2891                 osd_fid_pack((struct osd_fid_pack *)iam_rec, rec, &oti->oti_fid);
2892         else
2893                 iam_rec = (struct iam_rec *) rec;
2894         rc = iam_insert(oh->ot_handle, bag, (const struct iam_key *)key,
2895                         iam_rec, ipd);
2896 #ifdef HAVE_QUOTA_SUPPORT
2897         cfs_curproc_cap_unpack(save);
2898 #endif
2899         osd_ipd_put(env, bag, ipd);
2900         LINVRNT(osd_invariant(obj));
2901         RETURN(rc);
2902 }
2903
2904 /**
2905  * Calls ldiskfs_add_entry() to add directory entry
2906  * into the directory. This is required for
2907  * interoperability mode (b11826)
2908  *
2909  * \retval   0, on success
2910  * \retval -ve, on error
2911  */
2912 static int __osd_ea_add_rec(struct osd_thread_info *info,
2913                             struct osd_object *pobj,
2914                             struct inode  *cinode,
2915                             const char *name,
2916                             const struct dt_rec *fid,
2917                             struct thandle *th)
2918 {
2919         struct ldiskfs_dentry_param *ldp;
2920         struct dentry      *child;
2921         struct osd_thandle *oth;
2922         int rc;
2923
2924         oth = container_of(th, struct osd_thandle, ot_super);
2925         LASSERT(oth->ot_handle != NULL);
2926         LASSERT(oth->ot_handle->h_transaction != NULL);
2927
2928         child = osd_child_dentry_get(info->oti_env, pobj, name, strlen(name));
2929
2930         if (fid_is_igif((struct lu_fid *)fid) ||
2931             fid_seq((struct lu_fid *)fid) >= FID_SEQ_NORMAL) {
2932                 ldp = (struct ldiskfs_dentry_param *)info->oti_ldp;
2933                 osd_get_ldiskfs_dirent_param(ldp, fid);
2934                 child->d_fsdata = (void*) ldp;
2935         } else
2936                 child->d_fsdata = NULL;
2937         rc = ldiskfs_add_entry(oth->ot_handle, child, cinode);
2938
2939         RETURN(rc);
2940 }
2941
2942 /**
2943  * Calls ldiskfs_add_dot_dotdot() to add dot and dotdot entries
2944  * into the directory.Also sets flags into osd object to
2945  * indicate dot and dotdot are created. This is required for
2946  * interoperability mode (b11826)
2947  *
2948  * \param dir   directory for dot and dotdot fixup.
2949  * \param obj   child object for linking
2950  *
2951  * \retval   0, on success
2952  * \retval -ve, on error
2953  */
2954 static int osd_add_dot_dotdot(struct osd_thread_info *info,
2955                               struct osd_object *dir,
2956                               struct inode  *parent_dir, const char *name,
2957                               const struct dt_rec *dot_fid,
2958                               const struct dt_rec *dot_dot_fid,
2959                               struct thandle *th)
2960 {
2961         struct inode            *inode  = dir->oo_inode;
2962         struct ldiskfs_dentry_param *dot_ldp;
2963         struct ldiskfs_dentry_param *dot_dot_ldp;
2964         struct osd_thandle      *oth;
2965         int result = 0;
2966
2967         oth = container_of(th, struct osd_thandle, ot_super);
2968         LASSERT(oth->ot_handle->h_transaction != NULL);
2969         LASSERT(S_ISDIR(dir->oo_inode->i_mode));
2970
2971         if (strcmp(name, dot) == 0) {
2972                 if (dir->oo_compat_dot_created) {
2973                         result = -EEXIST;
2974                 } else {
2975                         LASSERT(inode == parent_dir);
2976                         dir->oo_compat_dot_created = 1;
2977                         result = 0;
2978                 }
2979         } else if(strcmp(name, dotdot) == 0) {
2980                 dot_ldp = (struct ldiskfs_dentry_param *)info->oti_ldp;
2981                 dot_dot_ldp = (struct ldiskfs_dentry_param *)info->oti_ldp2;
2982
2983                 if (!dir->oo_compat_dot_created)
2984                         return -EINVAL;
2985                 if (fid_seq((struct lu_fid *)dot_fid) >= FID_SEQ_NORMAL) {
2986                         osd_get_ldiskfs_dirent_param(dot_ldp, dot_fid);
2987                         osd_get_ldiskfs_dirent_param(dot_dot_ldp, dot_dot_fid);
2988                 } else {
2989                         dot_ldp = NULL;
2990                         dot_dot_ldp = NULL;
2991                 }
2992                 /* in case of rename, dotdot is already created */
2993                 if (dir->oo_compat_dotdot_created) {
2994                         return __osd_ea_add_rec(info, dir, parent_dir, name,
2995                                                 dot_dot_fid, th);
2996                 }
2997
2998                 result = ldiskfs_add_dot_dotdot(oth->ot_handle, parent_dir, inode,
2999                                                 dot_ldp, dot_dot_ldp);
3000                 if (result == 0)
3001                        dir->oo_compat_dotdot_created = 1;
3002         }
3003
3004         return result;
3005 }
3006
3007
3008 /**
3009  * It will call the appropriate osd_add* function and return the
3010  * value, return by respective functions.
3011  */
3012 static int osd_ea_add_rec(const struct lu_env *env,
3013                           struct osd_object *pobj,
3014                           struct inode *cinode,
3015                           const char *name,
3016                           const struct dt_rec *fid,
3017                           struct thandle *th)
3018 {
3019         struct osd_thread_info    *info   = osd_oti_get(env);
3020         int rc;
3021
3022         if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' &&
3023                                                    name[2] =='\0')))
3024                 rc = osd_add_dot_dotdot(info, pobj, cinode, name,
3025                      (struct dt_rec *)lu_object_fid(&pobj->oo_dt.do_lu),
3026                                         fid, th);
3027         else
3028                 rc = __osd_ea_add_rec(info, pobj, cinode, name, fid, th);
3029
3030         return rc;
3031 }
3032
3033 /**
3034  * Calls ->lookup() to find dentry. From dentry get inode and
3035  * read inode's ea to get fid. This is required for  interoperability
3036  * mode (b11826)
3037  *
3038  * \retval   0, on success
3039  * \retval -ve, on error
3040  */
3041 static int osd_ea_lookup_rec(const struct lu_env *env, struct osd_object *obj,
3042                              struct dt_rec *rec, const struct dt_key *key)
3043 {
3044         struct inode               *dir    = obj->oo_inode;
3045         struct dentry              *dentry;
3046         struct ldiskfs_dir_entry_2 *de;
3047         struct buffer_head         *bh;
3048         struct lu_fid              *fid = (struct lu_fid *) rec;
3049         int ino;
3050         int rc;
3051
3052         LASSERT(dir->i_op != NULL && dir->i_op->lookup != NULL);
3053
3054         dentry = osd_child_dentry_get(env, obj,
3055                                       (char *)key, strlen((char *)key));
3056
3057         cfs_down_read(&obj->oo_ext_idx_sem);
3058         bh = ll_ldiskfs_find_entry(dir, dentry, &de);
3059         if (bh) {
3060                 ino = le32_to_cpu(de->inode);
3061                 rc = osd_get_fid_from_dentry(de, rec);
3062
3063                 /* done with de, release bh */
3064                 brelse(bh);
3065                 if (rc != 0)
3066                         rc = osd_ea_fid_get(env, obj, ino, fid);
3067         } else
3068                 rc = -ENOENT;
3069
3070         cfs_up_read(&obj->oo_ext_idx_sem);
3071         RETURN (rc);
3072 }
3073
3074 /**
3075  * Find the osd object for given fid.
3076  *
3077  * \param fid need to find the osd object having this fid
3078  *
3079  * \retval osd_object on success
3080  * \retval        -ve on error
3081  */
3082 struct osd_object *osd_object_find(const struct lu_env *env,
3083                                    struct dt_object *dt,
3084                                    const struct lu_fid *fid)
3085 {
3086         struct lu_device         *ludev = dt->do_lu.lo_dev;
3087         struct osd_object        *child = NULL;
3088         struct lu_object         *luch;
3089         struct lu_object         *lo;
3090
3091         luch = lu_object_find(env, ludev, fid, NULL);
3092         if (!IS_ERR(luch)) {
3093                 if (lu_object_exists(luch)) {
3094                         lo = lu_object_locate(luch->lo_header, ludev->ld_type);
3095                         if (lo != NULL)
3096                                 child = osd_obj(lo);
3097                         else
3098                                 LU_OBJECT_DEBUG(D_ERROR, env, luch,
3099                                                 "lu_object can't be located"
3100                                                 ""DFID"\n", PFID(fid));
3101
3102                         if (child == NULL) {
3103                                 lu_object_put(env, luch);
3104                                 CERROR("Unable to get osd_object\n");
3105                                 child = ERR_PTR(-ENOENT);
3106                         }
3107                 } else {
3108                         LU_OBJECT_DEBUG(D_ERROR, env, luch,
3109                                         "lu_object does not exists "DFID"\n",
3110                                         PFID(fid));
3111                         child = ERR_PTR(-ENOENT);
3112                 }
3113         } else
3114                 child = (void *)luch;
3115
3116         return child;
3117 }
3118
3119 /**
3120  * Put the osd object once done with it.
3121  *
3122  * \param obj osd object that needs to be put
3123  */
3124 static inline void osd_object_put(const struct lu_env *env,
3125                                   struct osd_object *obj)
3126 {
3127         lu_object_put(env, &obj->oo_dt.do_lu);
3128 }
3129
3130 /**
3131  * Index add function for interoperability mode (b11826).
3132  * It will add the directory entry.This entry is needed to
3133  * maintain name->fid mapping.
3134  *
3135  * \param key it is key i.e. file entry to be inserted
3136  * \param rec it is value of given key i.e. fid
3137  *
3138  * \retval   0, on success
3139  * \retval -ve, on error
3140  */
3141 static int osd_index_ea_insert(const struct lu_env *env, struct dt_object *dt,
3142                                const struct dt_rec *rec,
3143                                const struct dt_key *key, struct thandle *th,
3144                                struct lustre_capa *capa, int ignore_quota)
3145 {
3146         struct osd_object        *obj   = osd_dt_obj(dt);
3147         struct lu_fid            *fid   = (struct lu_fid *) rec;
3148         const char               *name  = (const char *)key;
3149         struct osd_object        *child;
3150 #ifdef HAVE_QUOTA_SUPPORT
3151         cfs_cap_t                 save  = cfs_curproc_cap_pack();
3152 #endif
3153         int rc;
3154
3155         ENTRY;
3156
3157         LASSERT(osd_invariant(obj));
3158         LASSERT(dt_object_exists(dt));
3159         LASSERT(th != NULL);
3160
3161         if (osd_object_auth(env, dt, capa, CAPA_OPC_INDEX_INSERT))
3162                 RETURN(-EACCES);
3163
3164         child = osd_object_find(env, dt, fid);
3165         if (!IS_ERR(child)) {
3166                 struct inode *inode = obj->oo_inode;
3167                 struct osd_thread_info *oti = osd_oti_get(env);
3168                 struct timespec *ctime = &oti->oti_time;
3169                 struct timespec *mtime = &oti->oti_time2;
3170
3171                 *ctime = inode->i_ctime;
3172                 *mtime = inode->i_mtime;
3173 #ifdef HAVE_QUOTA_SUPPORT
3174                 if (ignore_quota)
3175                         cfs_cap_raise(CFS_CAP_SYS_RESOURCE);
3176                 else
3177                         cfs_cap_lower(CFS_CAP_SYS_RESOURCE);
3178 #endif
3179                 cfs_down_write(&obj->oo_ext_idx_sem);
3180                 rc = osd_ea_add_rec(env, obj, child->oo_inode, name, rec, th);
3181                 cfs_up_write(&obj->oo_ext_idx_sem);
3182 #ifdef HAVE_QUOTA_SUPPORT
3183                 cfs_curproc_cap_unpack(save);
3184 #endif
3185                 osd_object_put(env, child);
3186                 /* xtime should not be updated with server-side time. */
3187                 cfs_spin_lock(&obj->oo_guard);
3188                 inode->i_ctime = *ctime;
3189                 inode->i_mtime = *mtime;
3190                 cfs_spin_unlock(&obj->oo_guard);
3191                 mark_inode_dirty(inode);
3192         } else {
3193                 rc = PTR_ERR(child);
3194         }
3195
3196         LASSERT(osd_invariant(obj));
3197         RETURN(rc);
3198 }
3199
3200 /**
3201  *  Initialize osd Iterator for given osd index object.
3202  *
3203  *  \param  dt      osd index object
3204  */
3205
3206 static struct dt_it *osd_it_iam_init(const struct lu_env *env,
3207                                  struct dt_object *dt,
3208                                  struct lustre_capa *capa)
3209 {
3210         struct osd_it_iam         *it;
3211         struct osd_thread_info *oti = osd_oti_get(env);
3212         struct osd_object     *obj = osd_dt_obj(dt);
3213         struct lu_object      *lo  = &dt->do_lu;
3214         struct iam_path_descr *ipd;
3215         struct iam_container  *bag = &obj->oo_dir->od_container;
3216
3217         LASSERT(lu_object_exists(lo));
3218
3219         if (osd_object_auth(env, dt, capa, CAPA_OPC_BODY_READ))
3220                 return ERR_PTR(-EACCES);
3221
3222         it = &oti->oti_it;
3223         ipd = osd_it_ipd_get(env, bag);
3224         if (likely(ipd != NULL)) {
3225                 it->oi_obj = obj;
3226                 it->oi_ipd = ipd;
3227                 lu_object_get(lo);
3228                 iam_it_init(&it->oi_it, bag, IAM_IT_MOVE, ipd);
3229                 return (struct dt_it *)it;
3230         }
3231         return ERR_PTR(-ENOMEM);
3232 }
3233
3234 /**
3235  * free given Iterator.
3236  */
3237
3238 static void osd_it_iam_fini(const struct lu_env *env, struct dt_it *di)
3239 {
3240         struct osd_it_iam     *it = (struct osd_it_iam *)di;
3241         struct osd_object *obj = it->oi_obj;
3242
3243         iam_it_fini(&it->oi_it);
3244         osd_ipd_put(env, &obj->oo_dir->od_container, it->oi_ipd);
3245         lu_object_put(env, &obj->oo_dt.do_lu);
3246 }
3247
3248 /**
3249  *  Move Iterator to record specified by \a key
3250  *
3251  *  \param  di      osd iterator
3252  *  \param  key     key for index
3253  *
3254  *  \retval +ve  di points to record with least key not larger than key
3255  *  \retval  0   di points to exact matched key
3256  *  \retval -ve  failure
3257  */
3258
3259 static int osd_it_iam_get(const struct lu_env *env,
3260                       struct dt_it *di, const struct dt_key *key)
3261 {
3262         struct osd_it_iam *it = (struct osd_it_iam *)di;
3263
3264         return iam_it_get(&it->oi_it, (const struct iam_key *)key);
3265 }
3266
3267 /**
3268  *  Release Iterator
3269  *
3270  *  \param  di      osd iterator
3271  */
3272
3273 static void osd_it_iam_put(const struct lu_env *env, struct dt_it *di)
3274 {
3275         struct osd_it_iam *it = (struct osd_it_iam *)di;
3276
3277         iam_it_put(&it->oi_it);
3278 }
3279
3280 /**
3281  *  Move iterator by one record
3282  *
3283  *  \param  di      osd iterator
3284  *
3285  *  \retval +1   end of container reached
3286  *  \retval  0   success
3287  *  \retval -ve  failure
3288  */
3289
3290 static int osd_it_iam_next(const struct lu_env *env, struct dt_it *di)
3291 {
3292         struct osd_it_iam *it = (struct osd_it_iam *)di;
3293
3294         return iam_it_next(&it->oi_it);
3295 }
3296