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