Whamcloud - gitweb
Branch HEAD
[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  2008 Sun Microsystems, Inc. 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 /*
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  * super-class definitions.
54  */
55 #include <lu_object.h>
56
57 #include <libcfs/libcfs.h>
58
59 struct seq_file;
60 struct proc_dir_entry;
61 struct lustre_cfg;
62
63 struct thandle;
64 struct txn_param;
65 struct dt_device;
66 struct dt_object;
67 struct dt_index_features;
68
69 struct dt_device_param {
70         unsigned           ddp_max_name_len;
71         unsigned           ddp_max_nlink;
72         unsigned           ddp_block_shift;
73 };
74
75 /*
76  * Basic transaction credit op
77  */
78 enum dt_txn_op {
79         DTO_INDEX_INSERT,
80         DTO_INDEX_DELETE,
81         DTO_IDNEX_UPDATE,
82         DTO_OBJECT_CREATE,
83         DTO_OBJECT_DELETE,
84         DTO_ATTR_SET,
85         DTO_XATTR_SET,
86         DTO_LOG_REC, /* XXX temporary: dt layer knows nothing about llog. */
87         DTO_WRITE_BASE,
88         DTO_WRITE_BLOCK,
89
90         DTO_NR
91 };
92
93 /*
94  * Operations on dt device.
95  */
96 struct dt_device_operations {
97         /*
98          * Return device-wide statistics.
99          */
100         int   (*dt_statfs)(const struct lu_env *env,
101                            struct dt_device *dev, struct kstatfs *sfs);
102         /*
103          * Start transaction, described by @param.
104          */
105         struct thandle *(*dt_trans_start)(const struct lu_env *env,
106                                           struct dt_device *dev,
107                                           struct txn_param *param);
108         /*
109          * Finish previously started transaction.
110          */
111         void  (*dt_trans_stop)(const struct lu_env *env,
112                                struct thandle *th);
113         /*
114          * Return fid of root index object.
115          */
116         int   (*dt_root_get)(const struct lu_env *env,
117                              struct dt_device *dev, struct lu_fid *f);
118         /*
119          * Return device configuration data.
120          */
121         void  (*dt_conf_get)(const struct lu_env *env,
122                              const struct dt_device *dev,
123                              struct dt_device_param *param);
124         /*
125          *  handling device state, mostly for tests
126          */
127         int   (*dt_sync)(const struct lu_env *env, struct dt_device *dev);
128         void  (*dt_ro)(const struct lu_env *env, struct dt_device *dev);
129         /*
130          * Initialize capability context.
131          */
132         int   (*dt_init_capa_ctxt)(const struct lu_env *env,
133                                    struct dt_device *dev,
134                                    int mode, unsigned long timeout,
135                                    __u32 alg, struct lustre_capa_key *keys);
136
137         /*
138          *  get transaction credits for given @op.
139          */
140         int (*dt_credit_get)(const struct lu_env *env, struct dt_device *dev,
141                              enum dt_txn_op);
142 };
143
144 struct dt_index_features {
145         /* required feature flags from enum dt_index_flags */
146         __u32 dif_flags;
147         /* minimal required key size */
148         size_t dif_keysize_min;
149         /* maximal required key size, 0 if no limit */
150         size_t dif_keysize_max;
151         /* minimal required record size */
152         size_t dif_recsize_min;
153         /* maximal required record size, 0 if no limit */
154         size_t dif_recsize_max;
155 };
156
157 enum dt_index_flags {
158         /* index supports variable sized keys */
159         DT_IND_VARKEY = 1 << 0,
160         /* index supports variable sized records */
161         DT_IND_VARREC = 1 << 1,
162         /* index can be modified */
163         DT_IND_UPDATE = 1 << 2,
164         /* index supports records with non-unique (duplicate) keys */
165         DT_IND_NONUNQ = 1 << 3
166 };
167
168 /*
169  * Features, required from index to support file system directories (mapping
170  * names to fids).
171  */
172 extern const struct dt_index_features dt_directory_features;
173
174 /*
175  * This is a general purpose dt allocation hint.
176  * It now contains the parent object. 
177  * It can contain any allocation hint in the future.
178  */
179 struct dt_allocation_hint {
180         struct dt_object *dah_parent;
181         __u32             dah_mode;
182 };
183
184 /*
185  * Per-dt-object operations.
186  */
187 struct dt_object_operations {
188         void  (*do_read_lock)(const struct lu_env *env,
189                               struct dt_object *dt);
190         void  (*do_write_lock)(const struct lu_env *env,
191                                struct dt_object *dt);
192         void  (*do_read_unlock)(const struct lu_env *env,
193                                 struct dt_object *dt);
194         void  (*do_write_unlock)(const struct lu_env *env,
195                                  struct dt_object *dt);
196         /*
197          * Note: following ->do_{x,}attr_{set,get}() operations are very
198          * similar to ->moo_{x,}attr_{set,get}() operations in struct
199          * md_object_operations (see md_object.h). These operations are not in
200          * lu_object_operations, because ->do_{x,}attr_set() versions take
201          * transaction handle as an argument (this transaction is started by
202          * caller). We might factor ->do_{x,}attr_get() into
203          * lu_object_operations, but that would break existing symmetry.
204          */
205
206         /*
207          * Return standard attributes.
208          *
209          * precondition: lu_object_exists(&dt->do_lu);
210          */
211         int   (*do_attr_get)(const struct lu_env *env,
212                              struct dt_object *dt, struct lu_attr *attr,
213                              struct lustre_capa *capa);
214         /*
215          * Set standard attributes.
216          *
217          * precondition: dt_object_exists(dt);
218          */
219         int   (*do_attr_set)(const struct lu_env *env,
220                              struct dt_object *dt,
221                              const struct lu_attr *attr,
222                              struct thandle *handle,
223                              struct lustre_capa *capa);
224         /*
225          * Return a value of an extended attribute.
226          *
227          * precondition: dt_object_exists(dt);
228          */
229         int   (*do_xattr_get)(const struct lu_env *env, struct dt_object *dt,
230                               struct lu_buf *buf, const char *name,
231                               struct lustre_capa *capa);
232         /*
233          * Set value of an extended attribute.
234          *
235          * @fl - flags from enum lu_xattr_flags
236          *
237          * precondition: dt_object_exists(dt);
238          */
239         int   (*do_xattr_set)(const struct lu_env *env,
240                               struct dt_object *dt, const struct lu_buf *buf,
241                               const char *name, int fl, struct thandle *handle,
242                               struct lustre_capa *capa);
243         /*
244          * Delete existing extended attribute.
245          *
246          * precondition: dt_object_exists(dt);
247          */
248         int   (*do_xattr_del)(const struct lu_env *env,
249                               struct dt_object *dt,
250                               const char *name, struct thandle *handle,
251                               struct lustre_capa *capa);
252         /*
253          * Place list of existing extended attributes into @buf (which has
254          * length len).
255          *
256          * precondition: dt_object_exists(dt);
257          */
258         int   (*do_xattr_list)(const struct lu_env *env,
259                                struct dt_object *dt, struct lu_buf *buf,
260                                struct lustre_capa *capa);
261         /*
262          * Init allocation hint using parent object and child mode.
263          * (1) The @parent might be NULL if this is a partial creation for
264          *     remote object.
265          * (2) The type of child is in @child_mode.
266          * (3) The result hint is stored in @ah;
267          */
268         void  (*do_ah_init)(const struct lu_env *env,
269                             struct dt_allocation_hint *ah,
270                             struct dt_object *parent,
271                             umode_t child_mode);
272         /*
273          * Create new object on this device.
274          *
275          * precondition: !dt_object_exists(dt);
276          * postcondition: ergo(result == 0, dt_object_exists(dt));
277          */
278         int   (*do_create)(const struct lu_env *env, struct dt_object *dt,
279                            struct lu_attr *attr, 
280                            struct dt_allocation_hint *hint,
281                            struct thandle *th);
282
283         /*
284          * Announce that this object is going to be used as an index. This
285          * operation check that object supports indexing operations and
286          * installs appropriate dt_index_operations vector on success.
287          *
288          * Also probes for features. Operation is successful if all required
289          * features are supported.
290          */
291         int   (*do_index_try)(const struct lu_env *env,
292                               struct dt_object *dt,
293                               const struct dt_index_features *feat);
294         /*
295          * Add nlink of the object
296          * precondition: dt_object_exists(dt);
297          */
298         void  (*do_ref_add)(const struct lu_env *env,
299                             struct dt_object *dt, struct thandle *th);
300         /*
301          * Del nlink of the object
302          * precondition: dt_object_exists(dt);
303          */
304         void  (*do_ref_del)(const struct lu_env *env,
305                             struct dt_object *dt, struct thandle *th);
306
307         struct obd_capa *(*do_capa_get)(const struct lu_env *env,
308                                         struct dt_object *dt,
309                                         struct lustre_capa *old,
310                                         __u64 opc);
311         int (*do_object_sync)(const struct lu_env *, struct dt_object *);
312 };
313
314 /*
315  * Per-dt-object operations on "file body".
316  */
317 struct dt_body_operations {
318         /*
319          * precondition: dt_object_exists(dt);
320          */
321         ssize_t (*dbo_read)(const struct lu_env *env, struct dt_object *dt,
322                             struct lu_buf *buf, loff_t *pos,
323                             struct lustre_capa *capa);
324         /*
325          * precondition: dt_object_exists(dt);
326          */
327         ssize_t (*dbo_write)(const struct lu_env *env, struct dt_object *dt,
328                              const struct lu_buf *buf, loff_t *pos,
329                              struct thandle *handle, struct lustre_capa *capa);
330 };
331
332 /*
333  * Incomplete type of index record.
334  */
335 struct dt_rec;
336
337 /*
338  * Incomplete type of index key.
339  */
340 struct dt_key;
341
342 /*
343  * Incomplete type of dt iterator.
344  */
345 struct dt_it;
346
347 /*
348  * Per-dt-object operations on object as index.
349  */
350 struct dt_index_operations {
351         /*
352          * precondition: dt_object_exists(dt);
353          */
354         int (*dio_lookup)(const struct lu_env *env, struct dt_object *dt,
355                           struct dt_rec *rec, const struct dt_key *key,
356                           struct lustre_capa *capa);
357         /*
358          * precondition: dt_object_exists(dt);
359          */
360         int (*dio_insert)(const struct lu_env *env, struct dt_object *dt,
361                           const struct dt_rec *rec, const struct dt_key *key,
362                           struct thandle *handle, struct lustre_capa *capa);
363         /*
364          * precondition: dt_object_exists(dt);
365          */
366         int (*dio_delete)(const struct lu_env *env, struct dt_object *dt,
367                           const struct dt_key *key, struct thandle *handle,
368                           struct lustre_capa *capa);
369         /*
370          * Iterator interface
371          */
372         struct dt_it_ops {
373                 /*
374                  * Allocate and initialize new iterator.
375                  *
376                  * precondition: dt_object_exists(dt);
377                  */
378                 struct dt_it *(*init)(const struct lu_env *env,
379                                       struct dt_object *dt, int writable,
380                                       struct lustre_capa *capa);
381                 void          (*fini)(const struct lu_env *env,
382                                       struct dt_it *di);
383                 int            (*get)(const struct lu_env *env,
384                                       struct dt_it *di,
385                                       const struct dt_key *key);
386                 void           (*put)(const struct lu_env *env,
387                                       struct dt_it *di);
388                 int            (*del)(const struct lu_env *env,
389                                       struct dt_it *di, struct thandle *th);
390                 int           (*next)(const struct lu_env *env,
391                                       struct dt_it *di);
392                 struct dt_key *(*key)(const struct lu_env *env,
393                                       const struct dt_it *di);
394                 int       (*key_size)(const struct lu_env *env,
395                                       const struct dt_it *di);
396                 struct dt_rec *(*rec)(const struct lu_env *env,
397                                       const struct dt_it *di);
398                 __u64        (*store)(const struct lu_env *env,
399                                       const struct dt_it *di);
400                 int           (*load)(const struct lu_env *env,
401                                       const struct dt_it *di, __u64 hash);
402         } dio_it;
403 };
404
405 struct dt_device {
406         struct lu_device             dd_lu_dev;
407         struct dt_device_operations *dd_ops;
408
409         /*
410          * List of dt_txn_callback (see below). This is not protected in any
411          * way, because callbacks are supposed to be added/deleted only during
412          * single-threaded start-up shut-down procedures.
413          */
414         struct list_head             dd_txn_callbacks;
415 };
416
417 int  dt_device_init(struct dt_device *dev, struct lu_device_type *t);
418 void dt_device_fini(struct dt_device *dev);
419
420 static inline int lu_device_is_dt(const struct lu_device *d)
421 {
422         return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_DT);
423 }
424
425 static inline struct dt_device * lu2dt_dev(struct lu_device *l)
426 {
427         LASSERT(lu_device_is_dt(l));
428         return container_of0(l, struct dt_device, dd_lu_dev);
429 }
430
431 struct dt_object {
432         struct lu_object             do_lu;
433         struct dt_object_operations *do_ops;
434         struct dt_body_operations   *do_body_ops;
435         struct dt_index_operations  *do_index_ops;
436 };
437
438 int  dt_object_init(struct dt_object *obj,
439                     struct lu_object_header *h, struct lu_device *d);
440
441 void dt_object_fini(struct dt_object *obj);
442
443 static inline int dt_object_exists(const struct dt_object *dt)
444 {
445         return lu_object_exists(&dt->do_lu);
446 }
447
448 struct txn_param {
449         /* number of blocks this transaction will modify */
450         unsigned int tp_credits;
451         /* sync transaction is needed */
452         __u32        tp_sync:1;
453 };
454
455 static inline void txn_param_init(struct txn_param *p, unsigned int credits)
456 {
457         memset(p, 0, sizeof(*p));
458         p->tp_credits = credits;
459 }
460
461 /*
462  * This is the general purpose transaction handle.
463  * 1. Transaction Life Cycle
464  *      This transaction handle is allocated upon starting a new transaction,
465  *      and deallocated after this transaction is committed.
466  * 2. Transaction Nesting
467  *      We do _NOT_ support nested transaction. So, every thread should only
468  *      have one active transaction, and a transaction only belongs to one
469  *      thread. Due to this, transaction handle need no reference count.
470  * 3. Transaction & dt_object locking
471  *      dt_object locks should be taken inside transaction.
472  * 4. Transaction & RPC
473  *      No RPC request should be issued inside transaction.
474  */
475 struct thandle {
476         /* the dt device on which the transactions are executed */
477         struct dt_device *th_dev;
478
479         /* context for this transaction, tag is LCT_TX_HANDLE */
480         struct lu_context th_ctx;
481
482         /* the last operation result in this transaction.
483          * this value is used in recovery */
484         __s32             th_result;
485 };
486
487 /*
488  * Transaction call-backs.
489  *
490  * These are invoked by osd (or underlying transaction engine) when
491  * transaction changes state.
492  *
493  * Call-backs are used by upper layers to modify transaction parameters and to
494  * perform some actions on for each transaction state transition. Typical
495  * example is mdt registering call-back to write into last-received file
496  * before each transaction commit.
497  */
498 struct dt_txn_callback {
499         int (*dtc_txn_start)(const struct lu_env *env,
500                              struct txn_param *param, void *cookie);
501         int (*dtc_txn_stop)(const struct lu_env *env,
502                             struct thandle *txn, void *cookie);
503         int (*dtc_txn_commit)(const struct lu_env *env,
504                               struct thandle *txn, void *cookie);
505         void            *dtc_cookie;
506         struct list_head dtc_linkage;
507 };
508
509 void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb);
510 void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb);
511
512 int dt_txn_hook_start(const struct lu_env *env,
513                       struct dt_device *dev, struct txn_param *param);
514 int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn);
515 int dt_txn_hook_commit(const struct lu_env *env, struct thandle *txn);
516
517 int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj);
518 struct dt_object *dt_store_open(const struct lu_env *env,
519                                 struct dt_device *dt, const char *name,
520                                 struct lu_fid *fid);
521
522 #endif /* __LUSTRE_DT_OBJECT_H */