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