Whamcloud - gitweb
LU-15 slow IO with read-intense application
[fs/lustre-release.git] / lustre / include / dt_object.h
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
37 #ifndef __LUSTRE_DT_OBJECT_H
38 #define __LUSTRE_DT_OBJECT_H
39
40 /** \defgroup dt dt
41  * Sub-class of lu_object with methods common for "data" objects in OST stack.
42  *
43  * Data objects behave like regular files: you can read/write them, get and
44  * set their attributes. Implementation of dt interface is supposed to
45  * implement some form of garbage collection, normally reference counting
46  * (nlink) based one.
47  *
48  * Examples: osd (lustre/osd) is an implementation of dt interface.
49  * @{
50  */
51
52
53 /*
54  * super-class definitions.
55  */
56 #include <lu_object.h>
57
58 #include <libcfs/libcfs.h>
59
60 struct seq_file;
61 struct proc_dir_entry;
62 struct lustre_cfg;
63
64 struct thandle;
65 struct txn_param;
66 struct dt_device;
67 struct dt_object;
68 struct dt_index_features;
69 struct dt_quota_ctxt;
70
71 struct dt_device_param {
72         unsigned           ddp_max_name_len;
73         unsigned           ddp_max_nlink;
74         unsigned           ddp_block_shift;
75 };
76
77 /**
78  * Basic transaction credit op
79  */
80 enum dt_txn_op {
81         DTO_INDEX_INSERT,
82         DTO_INDEX_DELETE,
83         DTO_IDNEX_UPDATE,
84         DTO_OBJECT_CREATE,
85         DTO_OBJECT_DELETE,
86         DTO_ATTR_SET_BASE,
87         DTO_XATTR_SET,
88         DTO_LOG_REC, /**< XXX temporary: dt layer knows nothing about llog. */
89         DTO_WRITE_BASE,
90         DTO_WRITE_BLOCK,
91         DTO_ATTR_SET_CHOWN,
92
93         DTO_NR
94 };
95
96 /**
97  * Operations on dt device.
98  */
99 struct dt_device_operations {
100         /**
101          * Return device-wide statistics.
102          */
103         int   (*dt_statfs)(const struct lu_env *env,
104                            struct dt_device *dev, cfs_kstatfs_t *sfs);
105         /**
106          * Start transaction, described by \a param.
107          */
108         struct thandle *(*dt_trans_start)(const struct lu_env *env,
109                                           struct dt_device *dev,
110                                           struct txn_param *param);
111         /**
112          * Finish previously started transaction.
113          */
114         void  (*dt_trans_stop)(const struct lu_env *env,
115                                struct thandle *th);
116         /**
117          * Return fid of root index object.
118          */
119         int   (*dt_root_get)(const struct lu_env *env,
120                              struct dt_device *dev, struct lu_fid *f);
121         /**
122          * Return device configuration data.
123          */
124         void  (*dt_conf_get)(const struct lu_env *env,
125                              const struct dt_device *dev,
126                              struct dt_device_param *param);
127         /**
128          *  handling device state, mostly for tests
129          */
130         int   (*dt_sync)(const struct lu_env *env, struct dt_device *dev);
131         void  (*dt_ro)(const struct lu_env *env, struct dt_device *dev);
132         /**
133           * Start a transaction commit asynchronously
134           *
135           * \param env environment
136           * \param dev dt_device to start commit on
137           *
138           * \return 0 success, negative value if error
139           */
140          int   (*dt_commit_async)(const struct lu_env *env,
141                                   struct dt_device *dev);
142         /**
143          * Initialize capability context.
144          */
145         int   (*dt_init_capa_ctxt)(const struct lu_env *env,
146                                    struct dt_device *dev,
147                                    int mode, unsigned long timeout,
148                                    __u32 alg, struct lustre_capa_key *keys);
149         /**
150          * Initialize quota context.
151          */
152         void (*dt_init_quota_ctxt)(const struct lu_env *env,
153                                    struct dt_device *dev,
154                                    struct dt_quota_ctxt *ctxt, void *data);
155
156         /**
157          *  get transaction credits for given \a op.
158          */
159         int (*dt_credit_get)(const struct lu_env *env, struct dt_device *dev,
160                              enum dt_txn_op);
161 };
162
163 struct dt_index_features {
164         /** required feature flags from enum dt_index_flags */
165         __u32 dif_flags;
166         /** minimal required key size */
167         size_t dif_keysize_min;
168         /** maximal required key size, 0 if no limit */
169         size_t dif_keysize_max;
170         /** minimal required record size */
171         size_t dif_recsize_min;
172         /** maximal required record size, 0 if no limit */
173         size_t dif_recsize_max;
174         /** pointer size for record */
175         size_t dif_ptrsize;
176 };
177
178 enum dt_index_flags {
179         /** index supports variable sized keys */
180         DT_IND_VARKEY = 1 << 0,
181         /** index supports variable sized records */
182         DT_IND_VARREC = 1 << 1,
183         /** index can be modified */
184         DT_IND_UPDATE = 1 << 2,
185         /** index supports records with non-unique (duplicate) keys */
186         DT_IND_NONUNQ = 1 << 3
187 };
188
189 /**
190  * Features, required from index to support file system directories (mapping
191  * names to fids).
192  */
193 extern const struct dt_index_features dt_directory_features;
194
195 /**
196  * This is a general purpose dt allocation hint.
197  * It now contains the parent object.
198  * It can contain any allocation hint in the future.
199  */
200 struct dt_allocation_hint {
201         struct dt_object           *dah_parent;
202         __u32                       dah_mode;
203 };
204
205 /**
206  * object type specifier.
207  */
208
209 enum dt_format_type {
210         DFT_REGULAR,
211         DFT_DIR,
212         /** for mknod */
213         DFT_NODE,
214         /** for special index */
215         DFT_INDEX,
216         /** for symbolic link */
217         DFT_SYM,
218 };
219
220 /**
221  * object format specifier.
222  */
223 struct dt_object_format {
224         /** type for dt object */
225         enum dt_format_type dof_type;
226         union {
227                 struct dof_regular {
228                 } dof_reg;
229                 struct dof_dir {
230                 } dof_dir;
231                 struct dof_node {
232                 } dof_node;
233                 /**
234                  * special index need feature as parameter to create
235                  * special idx
236                  */
237                 struct dof_index {
238                         const struct dt_index_features *di_feat;
239                 } dof_idx;
240         } u;
241 };
242
243 enum dt_format_type dt_mode_to_dft(__u32 mode);
244
245 /** Version type. May differ in DMU and ldiskfs */
246 typedef __u64 dt_obj_version_t;
247
248 /**
249  * Per-dt-object operations.
250  */
251 struct dt_object_operations {
252         void  (*do_read_lock)(const struct lu_env *env,
253                               struct dt_object *dt, unsigned role);
254         void  (*do_write_lock)(const struct lu_env *env,
255                                struct dt_object *dt, unsigned role);
256         void  (*do_read_unlock)(const struct lu_env *env,
257                                 struct dt_object *dt);
258         void  (*do_write_unlock)(const struct lu_env *env,
259                                  struct dt_object *dt);
260         int  (*do_write_locked)(const struct lu_env *env,
261                                 struct dt_object *dt);
262         /**
263          * Note: following ->do_{x,}attr_{set,get}() operations are very
264          * similar to ->moo_{x,}attr_{set,get}() operations in struct
265          * md_object_operations (see md_object.h). These operations are not in
266          * lu_object_operations, because ->do_{x,}attr_set() versions take
267          * transaction handle as an argument (this transaction is started by
268          * caller). We might factor ->do_{x,}attr_get() into
269          * lu_object_operations, but that would break existing symmetry.
270          */
271
272         /**
273          * Return standard attributes.
274          *
275          * precondition: lu_object_exists(&dt->do_lu);
276          */
277         int   (*do_attr_get)(const struct lu_env *env,
278                              struct dt_object *dt, struct lu_attr *attr,
279                              struct lustre_capa *capa);
280         /**
281          * Set standard attributes.
282          *
283          * precondition: dt_object_exists(dt);
284          */
285         int   (*do_attr_set)(const struct lu_env *env,
286                              struct dt_object *dt,
287                              const struct lu_attr *attr,
288                              struct thandle *handle,
289                              struct lustre_capa *capa);
290         /**
291          * Return a value of an extended attribute.
292          *
293          * precondition: dt_object_exists(dt);
294          */
295         int   (*do_xattr_get)(const struct lu_env *env, struct dt_object *dt,
296                               struct lu_buf *buf, const char *name,
297                               struct lustre_capa *capa);
298         /**
299          * Set value of an extended attribute.
300          *
301          * \a fl - flags from enum lu_xattr_flags
302          *
303          * precondition: dt_object_exists(dt);
304          */
305         int   (*do_xattr_set)(const struct lu_env *env,
306                               struct dt_object *dt, const struct lu_buf *buf,
307                               const char *name, int fl, struct thandle *handle,
308                               struct lustre_capa *capa);
309         /**
310          * Delete existing extended attribute.
311          *
312          * precondition: dt_object_exists(dt);
313          */
314         int   (*do_xattr_del)(const struct lu_env *env,
315                               struct dt_object *dt,
316                               const char *name, struct thandle *handle,
317                               struct lustre_capa *capa);
318         /**
319          * Place list of existing extended attributes into \a buf (which has
320          * length len).
321          *
322          * precondition: dt_object_exists(dt);
323          */
324         int   (*do_xattr_list)(const struct lu_env *env,
325                                struct dt_object *dt, struct lu_buf *buf,
326                                struct lustre_capa *capa);
327         /**
328          * Init allocation hint using parent object and child mode.
329          * (1) The \a parent might be NULL if this is a partial creation for
330          *     remote object.
331          * (2) The type of child is in \a child_mode.
332          * (3) The result hint is stored in \a ah;
333          */
334         void  (*do_ah_init)(const struct lu_env *env,
335                             struct dt_allocation_hint *ah,
336                             struct dt_object *parent,
337                             cfs_umode_t child_mode);
338         /**
339          * Create new object on this device.
340          *
341          * precondition: !dt_object_exists(dt);
342          * postcondition: ergo(result == 0, dt_object_exists(dt));
343          */
344         int   (*do_create)(const struct lu_env *env, struct dt_object *dt,
345                            struct lu_attr *attr,
346                            struct dt_allocation_hint *hint,
347                            struct dt_object_format *dof,
348                            struct thandle *th);
349
350         /**
351          * Announce that this object is going to be used as an index. This
352          * operation check that object supports indexing operations and
353          * installs appropriate dt_index_operations vector on success.
354          *
355          * Also probes for features. Operation is successful if all required
356          * features are supported.
357          */
358         int   (*do_index_try)(const struct lu_env *env,
359                               struct dt_object *dt,
360                               const struct dt_index_features *feat);
361         /**
362          * Add nlink of the object
363          * precondition: dt_object_exists(dt);
364          */
365         void  (*do_ref_add)(const struct lu_env *env,
366                             struct dt_object *dt, struct thandle *th);
367         /**
368          * Del nlink of the object
369          * precondition: dt_object_exists(dt);
370          */
371         void  (*do_ref_del)(const struct lu_env *env,
372                             struct dt_object *dt, struct thandle *th);
373
374         struct obd_capa *(*do_capa_get)(const struct lu_env *env,
375                                         struct dt_object *dt,
376                                         struct lustre_capa *old,
377                                         __u64 opc);
378         int (*do_object_sync)(const struct lu_env *, struct dt_object *);
379         dt_obj_version_t (*do_version_get)(const struct lu_env *env,
380                                            struct dt_object *dt);
381         void (*do_version_set)(const struct lu_env *env, struct dt_object *dt,
382                                dt_obj_version_t new_version);
383         /**
384          * Get object info of next level. Currently, only get inode from osd.
385          * This is only used by quota b=16542
386          * precondition: dt_object_exists(dt);
387          */
388         int (*do_data_get)(const struct lu_env *env, struct dt_object *dt,
389                            void **data);
390 };
391
392 /**
393  * Per-dt-object operations on "file body".
394  */
395 struct dt_body_operations {
396         /**
397          * precondition: dt_object_exists(dt);
398          */
399         ssize_t (*dbo_read)(const struct lu_env *env, struct dt_object *dt,
400                             struct lu_buf *buf, loff_t *pos,
401                             struct lustre_capa *capa);
402         /**
403          * precondition: dt_object_exists(dt);
404          */
405         ssize_t (*dbo_write)(const struct lu_env *env, struct dt_object *dt,
406                              const struct lu_buf *buf, loff_t *pos,
407                              struct thandle *handle, struct lustre_capa *capa,
408                              int ignore_quota);
409 };
410
411 /**
412  * Incomplete type of index record.
413  */
414 struct dt_rec;
415
416 /**
417  * Incomplete type of index key.
418  */
419 struct dt_key;
420
421 /**
422  * Incomplete type of dt iterator.
423  */
424 struct dt_it;
425
426 /**
427  * Per-dt-object operations on object as index.
428  */
429 struct dt_index_operations {
430         /**
431          * precondition: dt_object_exists(dt);
432          */
433         int (*dio_lookup)(const struct lu_env *env, struct dt_object *dt,
434                           struct dt_rec *rec, const struct dt_key *key,
435                           struct lustre_capa *capa);
436         /**
437          * precondition: dt_object_exists(dt);
438          */
439         int (*dio_insert)(const struct lu_env *env, struct dt_object *dt,
440                           const struct dt_rec *rec, const struct dt_key *key,
441                           struct thandle *handle, struct lustre_capa *capa,
442                           int ignore_quota);
443         /**
444          * precondition: dt_object_exists(dt);
445          */
446         int (*dio_delete)(const struct lu_env *env, struct dt_object *dt,
447                           const struct dt_key *key, struct thandle *handle,
448                           struct lustre_capa *capa);
449         /**
450          * Iterator interface
451          */
452         struct dt_it_ops {
453                 /**
454                  * Allocate and initialize new iterator.
455                  *
456                  * precondition: dt_object_exists(dt);
457                  */
458                 struct dt_it *(*init)(const struct lu_env *env,
459                                       struct dt_object *dt,
460                                       __u32 attr,
461                                       struct lustre_capa *capa);
462                 void          (*fini)(const struct lu_env *env,
463                                       struct dt_it *di);
464                 int            (*get)(const struct lu_env *env,
465                                       struct dt_it *di,
466                                       const struct dt_key *key);
467                 void           (*put)(const struct lu_env *env,
468                                       struct dt_it *di);
469                 int           (*next)(const struct lu_env *env,
470                                       struct dt_it *di);
471                 struct dt_key *(*key)(const struct lu_env *env,
472                                       const struct dt_it *di);
473                 int       (*key_size)(const struct lu_env *env,
474                                       const struct dt_it *di);
475                 int            (*rec)(const struct lu_env *env,
476                                       const struct dt_it *di,
477                                       struct lu_dirent *lde,
478                                       __u32 attr);
479                 __u64        (*store)(const struct lu_env *env,
480                                       const struct dt_it *di);
481                 int           (*load)(const struct lu_env *env,
482                                       const struct dt_it *di, __u64 hash);
483         } dio_it;
484 };
485
486 struct dt_device {
487         struct lu_device                   dd_lu_dev;
488         const struct dt_device_operations *dd_ops;
489
490         /**
491          * List of dt_txn_callback (see below). This is not protected in any
492          * way, because callbacks are supposed to be added/deleted only during
493          * single-threaded start-up shut-down procedures.
494          */
495         cfs_list_t                         dd_txn_callbacks;
496 };
497
498 int  dt_device_init(struct dt_device *dev, struct lu_device_type *t);
499 void dt_device_fini(struct dt_device *dev);
500
501 static inline int lu_device_is_dt(const struct lu_device *d)
502 {
503         return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_DT);
504 }
505
506 static inline struct dt_device * lu2dt_dev(struct lu_device *l)
507 {
508         LASSERT(lu_device_is_dt(l));
509         return container_of0(l, struct dt_device, dd_lu_dev);
510 }
511
512 struct dt_object {
513         struct lu_object                   do_lu;
514         const struct dt_object_operations *do_ops;
515         const struct dt_body_operations   *do_body_ops;
516         const struct dt_index_operations  *do_index_ops;
517 };
518
519 int  dt_object_init(struct dt_object *obj,
520                     struct lu_object_header *h, struct lu_device *d);
521
522 void dt_object_fini(struct dt_object *obj);
523
524 static inline int dt_object_exists(const struct dt_object *dt)
525 {
526         return lu_object_exists(&dt->do_lu);
527 }
528
529 struct txn_param {
530         /** number of blocks this transaction will modify */
531         unsigned int tp_credits;
532         /** sync transaction is needed */
533         __u32        tp_sync:1;
534 };
535
536 static inline void txn_param_init(struct txn_param *p, unsigned int credits)
537 {
538         memset(p, 0, sizeof(*p));
539         p->tp_credits = credits;
540 }
541
542 static inline void txn_param_credit_add(struct txn_param *p,
543                                         unsigned int credits)
544 {
545         p->tp_credits += credits;
546 }
547
548 static inline void txn_param_sync(struct txn_param *p)
549 {
550         p->tp_sync = 1;
551 }
552
553 /**
554  * This is the general purpose transaction handle.
555  * 1. Transaction Life Cycle
556  *      This transaction handle is allocated upon starting a new transaction,
557  *      and deallocated after this transaction is committed.
558  * 2. Transaction Nesting
559  *      We do _NOT_ support nested transaction. So, every thread should only
560  *      have one active transaction, and a transaction only belongs to one
561  *      thread. Due to this, transaction handle need no reference count.
562  * 3. Transaction & dt_object locking
563  *      dt_object locks should be taken inside transaction.
564  * 4. Transaction & RPC
565  *      No RPC request should be issued inside transaction.
566  */
567 struct thandle {
568         /** the dt device on which the transactions are executed */
569         struct dt_device *th_dev;
570
571         /** context for this transaction, tag is LCT_TX_HANDLE */
572         struct lu_context th_ctx;
573
574         /** the last operation result in this transaction.
575          * this value is used in recovery */
576         __s32             th_result;
577 };
578
579 /**
580  * Transaction call-backs.
581  *
582  * These are invoked by osd (or underlying transaction engine) when
583  * transaction changes state.
584  *
585  * Call-backs are used by upper layers to modify transaction parameters and to
586  * perform some actions on for each transaction state transition. Typical
587  * example is mdt registering call-back to write into last-received file
588  * before each transaction commit.
589  */
590 struct dt_txn_callback {
591         int (*dtc_txn_start)(const struct lu_env *env,
592                              struct txn_param *param, void *cookie);
593         int (*dtc_txn_stop)(const struct lu_env *env,
594                             struct thandle *txn, void *cookie);
595         int (*dtc_txn_commit)(const struct lu_env *env,
596                               struct thandle *txn, void *cookie);
597         void                *dtc_cookie;
598         __u32                dtc_tag;
599         cfs_list_t           dtc_linkage;
600 };
601
602 void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb);
603 void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb);
604
605 int dt_txn_hook_start(const struct lu_env *env,
606                       struct dt_device *dev, struct txn_param *param);
607 int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn);
608 int dt_txn_hook_commit(const struct lu_env *env, struct thandle *txn);
609
610 int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj);
611
612 /**
613  * Callback function used for parsing path.
614  * \see llo_store_resolve
615  */
616 typedef int (*dt_entry_func_t)(const struct lu_env *env,
617                             const char *name,
618                             void *pvt);
619
620 #define DT_MAX_PATH 1024
621
622 int dt_path_parser(const struct lu_env *env,
623                    char *local, dt_entry_func_t entry_func,
624                    void *data);
625
626 struct dt_object *dt_store_open(const struct lu_env *env,
627                                 struct dt_device *dt,
628                                 const char *dirname,
629                                 const char *filename,
630                                 struct lu_fid *fid);
631
632 struct dt_object *dt_locate(const struct lu_env *env,
633                             struct dt_device *dev,
634                             const struct lu_fid *fid);
635
636 static inline dt_obj_version_t do_version_get(const struct lu_env *env,
637                                               struct dt_object *o)
638 {
639         LASSERT(o->do_ops->do_version_get);
640         return o->do_ops->do_version_get(env, o);
641 }
642
643 static inline void do_version_set(const struct lu_env *env,
644                                   struct dt_object *o, dt_obj_version_t v)
645 {
646         LASSERT(o->do_ops->do_version_set);
647         return o->do_ops->do_version_set(env, o, v);
648 }
649
650 int dt_record_read(const struct lu_env *env, struct dt_object *dt,
651                    struct lu_buf *buf, loff_t *pos);
652 int dt_record_write(const struct lu_env *env, struct dt_object *dt,
653                     const struct lu_buf *buf, loff_t *pos, struct thandle *th);
654
655
656 static inline struct thandle *dt_trans_start(const struct lu_env *env,
657                                              struct dt_device *d,
658                                              struct txn_param *p)
659 {
660         LASSERT(d->dd_ops->dt_trans_start);
661         return d->dd_ops->dt_trans_start(env, d, p);
662 }
663
664 static inline void dt_trans_stop(const struct lu_env *env,
665                                  struct dt_device *d,
666                                  struct thandle *th)
667 {
668         LASSERT(d->dd_ops->dt_trans_stop);
669         return d->dd_ops->dt_trans_stop(env, th);
670 }
671 /** @} dt */
672 #endif /* __LUSTRE_DT_OBJECT_H */