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