Whamcloud - gitweb
b=16098
[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 };
312
313 /*
314  * Per-dt-object operations on "file body".
315  */
316 struct dt_body_operations {
317         /*
318          * precondition: dt_object_exists(dt);
319          */
320         ssize_t (*dbo_read)(const struct lu_env *env, struct dt_object *dt,
321                             struct lu_buf *buf, loff_t *pos,
322                             struct lustre_capa *capa);
323         /*
324          * precondition: dt_object_exists(dt);
325          */
326         ssize_t (*dbo_write)(const struct lu_env *env, struct dt_object *dt,
327                              const struct lu_buf *buf, loff_t *pos,
328                              struct thandle *handle, struct lustre_capa *capa);
329 };
330
331 /*
332  * Incomplete type of index record.
333  */
334 struct dt_rec;
335
336 /*
337  * Incomplete type of index key.
338  */
339 struct dt_key;
340
341 /*
342  * Incomplete type of dt iterator.
343  */
344 struct dt_it;
345
346 /*
347  * Per-dt-object operations on object as index.
348  */
349 struct dt_index_operations {
350         /*
351          * precondition: dt_object_exists(dt);
352          */
353         int (*dio_lookup)(const struct lu_env *env, struct dt_object *dt,
354                           struct dt_rec *rec, const struct dt_key *key,
355                           struct lustre_capa *capa);
356         /*
357          * precondition: dt_object_exists(dt);
358          */
359         int (*dio_insert)(const struct lu_env *env, struct dt_object *dt,
360                           const struct dt_rec *rec, const struct dt_key *key,
361                           struct thandle *handle, struct lustre_capa *capa);
362         /*
363          * precondition: dt_object_exists(dt);
364          */
365         int (*dio_delete)(const struct lu_env *env, struct dt_object *dt,
366                           const struct dt_key *key, struct thandle *handle,
367                           struct lustre_capa *capa);
368         /*
369          * Iterator interface
370          */
371         struct dt_it_ops {
372                 /*
373                  * Allocate and initialize new iterator.
374                  *
375                  * precondition: dt_object_exists(dt);
376                  */
377                 struct dt_it *(*init)(const struct lu_env *env,
378                                       struct dt_object *dt, int writable,
379                                       struct lustre_capa *capa);
380                 void          (*fini)(const struct lu_env *env,
381                                       struct dt_it *di);
382                 int            (*get)(const struct lu_env *env,
383                                       struct dt_it *di,
384                                       const struct dt_key *key);
385                 void           (*put)(const struct lu_env *env,
386                                       struct dt_it *di);
387                 int            (*del)(const struct lu_env *env,
388                                       struct dt_it *di, struct thandle *th);
389                 int           (*next)(const struct lu_env *env,
390                                       struct dt_it *di);
391                 struct dt_key *(*key)(const struct lu_env *env,
392                                       const struct dt_it *di);
393                 int       (*key_size)(const struct lu_env *env,
394                                       const struct dt_it *di);
395                 struct dt_rec *(*rec)(const struct lu_env *env,
396                                       const struct dt_it *di);
397                 __u64        (*store)(const struct lu_env *env,
398                                       const struct dt_it *di);
399                 int           (*load)(const struct lu_env *env,
400                                       const struct dt_it *di, __u64 hash);
401         } dio_it;
402 };
403
404 struct dt_device {
405         struct lu_device             dd_lu_dev;
406         struct dt_device_operations *dd_ops;
407
408         /*
409          * List of dt_txn_callback (see below). This is not protected in any
410          * way, because callbacks are supposed to be added/deleted only during
411          * single-threaded start-up shut-down procedures.
412          */
413         struct list_head             dd_txn_callbacks;
414 };
415
416 int  dt_device_init(struct dt_device *dev, struct lu_device_type *t);
417 void dt_device_fini(struct dt_device *dev);
418
419 static inline int lu_device_is_dt(const struct lu_device *d)
420 {
421         return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_DT);
422 }
423
424 static inline struct dt_device * lu2dt_dev(struct lu_device *l)
425 {
426         LASSERT(lu_device_is_dt(l));
427         return container_of0(l, struct dt_device, dd_lu_dev);
428 }
429
430 struct dt_object {
431         struct lu_object             do_lu;
432         struct dt_object_operations *do_ops;
433         struct dt_body_operations   *do_body_ops;
434         struct dt_index_operations  *do_index_ops;
435 };
436
437 int  dt_object_init(struct dt_object *obj,
438                     struct lu_object_header *h, struct lu_device *d);
439
440 void dt_object_fini(struct dt_object *obj);
441
442 static inline int dt_object_exists(const struct dt_object *dt)
443 {
444         return lu_object_exists(&dt->do_lu);
445 }
446
447 struct txn_param {
448         /* number of blocks this transaction will modify */
449         unsigned int tp_credits;
450         /* sync transaction is needed */
451         __u32        tp_sync:1;
452 };
453
454 static inline void txn_param_init(struct txn_param *p, unsigned int credits)
455 {
456         memset(p, 0, sizeof(*p));
457         p->tp_credits = credits;
458 }
459
460 /*
461  * This is the general purpose transaction handle.
462  * 1. Transaction Life Cycle
463  *      This transaction handle is allocated upon starting a new transaction,
464  *      and deallocated after this transaction is committed.
465  * 2. Transaction Nesting
466  *      We do _NOT_ support nested transaction. So, every thread should only
467  *      have one active transaction, and a transaction only belongs to one
468  *      thread. Due to this, transaction handle need no reference count.
469  * 3. Transaction & dt_object locking
470  *      dt_object locks should be taken inside transaction.
471  * 4. Transaction & RPC
472  *      No RPC request should be issued inside transaction.
473  */
474 struct thandle {
475         /* the dt device on which the transactions are executed */
476         struct dt_device *th_dev;
477
478         /* context for this transaction, tag is LCT_TX_HANDLE */
479         struct lu_context th_ctx;
480
481         /* the last operation result in this transaction.
482          * this value is used in recovery */
483         __s32             th_result;
484 };
485
486 /*
487  * Transaction call-backs.
488  *
489  * These are invoked by osd (or underlying transaction engine) when
490  * transaction changes state.
491  *
492  * Call-backs are used by upper layers to modify transaction parameters and to
493  * perform some actions on for each transaction state transition. Typical
494  * example is mdt registering call-back to write into last-received file
495  * before each transaction commit.
496  */
497 struct dt_txn_callback {
498         int (*dtc_txn_start)(const struct lu_env *env,
499                              struct txn_param *param, void *cookie);
500         int (*dtc_txn_stop)(const struct lu_env *env,
501                             struct thandle *txn, void *cookie);
502         int (*dtc_txn_commit)(const struct lu_env *env,
503                               struct thandle *txn, void *cookie);
504         void            *dtc_cookie;
505         struct list_head dtc_linkage;
506 };
507
508 void dt_txn_callback_add(struct dt_device *dev, struct dt_txn_callback *cb);
509 void dt_txn_callback_del(struct dt_device *dev, struct dt_txn_callback *cb);
510
511 int dt_txn_hook_start(const struct lu_env *env,
512                       struct dt_device *dev, struct txn_param *param);
513 int dt_txn_hook_stop(const struct lu_env *env, struct thandle *txn);
514 int dt_txn_hook_commit(const struct lu_env *env, struct thandle *txn);
515
516 int dt_try_as_dir(const struct lu_env *env, struct dt_object *obj);
517 struct dt_object *dt_store_open(const struct lu_env *env,
518                                 struct dt_device *dt, const char *name,
519                                 struct lu_fid *fid);
520
521 #endif /* __LUSTRE_DT_OBJECT_H */