1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2006 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
23 #ifndef __LUSTRE_DT_OBJECT_H
24 #define __LUSTRE_DT_OBJECT_H
27 * Sub-class of lu_object with methods common for "data" objects in OST stack.
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
34 * Examples: osd (lustre/osd) is an implementation of dt interface.
39 * super-class definitions.
41 #include <lu_object.h>
43 #include <libcfs/list.h>
44 #include <libcfs/kp30.h>
47 struct proc_dir_entry;
54 struct dt_index_features;
56 struct dt_device_param {
57 unsigned ddp_max_name_len;
58 unsigned ddp_max_nlink;
59 unsigned ddp_block_shift;
63 * Basic transaction credit op
73 DTO_LOG_REC, /* XXX temporary: dt layer knows nothing about llog. */
81 * Operations on dt device.
83 struct dt_device_operations {
85 * Return device-wide statistics.
87 int (*dt_statfs)(const struct lu_env *env,
88 struct dt_device *dev, struct kstatfs *sfs);
90 * Start transaction, described by @param.
92 struct thandle *(*dt_trans_start)(const struct lu_env *env,
93 struct dt_device *dev,
94 struct txn_param *param);
96 * Finish previously started transaction.
98 void (*dt_trans_stop)(const struct lu_env *env,
101 * Return fid of root index object.
103 int (*dt_root_get)(const struct lu_env *env,
104 struct dt_device *dev, struct lu_fid *f);
106 * Return device configuration data.
108 void (*dt_conf_get)(const struct lu_env *env,
109 const struct dt_device *dev,
110 struct dt_device_param *param);
112 * handling device state, mostly for tests
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);
117 * Initialize capability context.
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);
125 * get transaction credits for given @op.
127 int (*dt_credit_get)(const struct lu_env *env, struct dt_device *dev,
131 struct dt_index_features {
132 /* required feature flags from enum dt_index_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;
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
156 * Features, required from index to support file system directories (mapping
159 extern const struct dt_index_features dt_directory_features;
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.
166 struct dt_allocation_hint {
167 struct dt_object *dah_parent;
172 * Per-dt-object operations.
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);
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.
194 * Return standard attributes.
196 * precondition: lu_object_exists(&dt->do_lu);
198 int (*do_attr_get)(const struct lu_env *env,
199 struct dt_object *dt, struct lu_attr *attr,
200 struct lustre_capa *capa);
202 * Set standard attributes.
204 * precondition: dt_object_exists(dt);
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);
212 * Return a value of an extended attribute.
214 * precondition: dt_object_exists(dt);
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);
220 * Set value of an extended attribute.
222 * @fl - flags from enum lu_xattr_flags
224 * precondition: dt_object_exists(dt);
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);
231 * Delete existing extended attribute.
233 * precondition: dt_object_exists(dt);
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);
240 * Place list of existing extended attributes into @buf (which has
243 * precondition: dt_object_exists(dt);
245 int (*do_xattr_list)(const struct lu_env *env,
246 struct dt_object *dt, struct lu_buf *buf,
247 struct lustre_capa *capa);
249 * Init allocation hint using parent object and child mode.
250 * (1) The @parent might be NULL if this is a partial creation for
252 * (2) The type of child is in @child_mode.
253 * (3) The result hint is stored in @ah;
255 void (*do_ah_init)(const struct lu_env *env,
256 struct dt_allocation_hint *ah,
257 struct dt_object *parent,
260 * Create new object on this device.
262 * precondition: !dt_object_exists(dt);
263 * postcondition: ergo(result == 0, dt_object_exists(dt));
265 int (*do_create)(const struct lu_env *env, struct dt_object *dt,
266 struct lu_attr *attr,
267 struct dt_allocation_hint *hint,
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.
275 * Also probes for features. Operation is successful if all required
276 * features are supported.
278 int (*do_index_try)(const struct lu_env *env,
279 struct dt_object *dt,
280 const struct dt_index_features *feat);
282 * Add nlink of the object
283 * precondition: dt_object_exists(dt);
285 void (*do_ref_add)(const struct lu_env *env,
286 struct dt_object *dt, struct thandle *th);
288 * Del nlink of the object
289 * precondition: dt_object_exists(dt);
291 void (*do_ref_del)(const struct lu_env *env,
292 struct dt_object *dt, struct thandle *th);
294 struct obd_capa *(*do_capa_get)(const struct lu_env *env,
295 struct dt_object *dt,
296 struct lustre_capa *old,
301 * Per-dt-object operations on "file body".
303 struct dt_body_operations {
305 * precondition: dt_object_exists(dt);
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);
311 * precondition: dt_object_exists(dt);
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);
319 * Incomplete type of index record.
324 * Incomplete type of index key.
329 * Incomplete type of dt iterator.
334 * Per-dt-object operations on object as index.
336 struct dt_index_operations {
338 * precondition: dt_object_exists(dt);
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);
344 * precondition: dt_object_exists(dt);
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);
350 * precondition: dt_object_exists(dt);
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);
360 * Allocate and initialize new iterator.
362 * precondition: dt_object_exists(dt);
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,
369 int (*get)(const struct lu_env *env,
371 const struct dt_key *key);
372 void (*put)(const struct lu_env *env,
374 int (*del)(const struct lu_env *env,
375 struct dt_it *di, struct thandle *th);
376 int (*next)(const struct lu_env *env,
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 __u64 (*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, __u64 hash);
392 struct lu_device dd_lu_dev;
393 struct dt_device_operations *dd_ops;
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.
400 struct list_head dd_txn_callbacks;
403 int dt_device_init(struct dt_device *dev, struct lu_device_type *t);
404 void dt_device_fini(struct dt_device *dev);
406 static inline int lu_device_is_dt(const struct lu_device *d)
408 return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_DT);
411 static inline struct dt_device * lu2dt_dev(struct lu_device *l)
413 LASSERT(lu_device_is_dt(l));
414 return container_of0(l, struct dt_device, dd_lu_dev);
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;
424 int dt_object_init(struct dt_object *obj,
425 struct lu_object_header *h, struct lu_device *d);
427 void dt_object_fini(struct dt_object *obj);
429 static inline int dt_object_exists(const struct dt_object *dt)
431 return lu_object_exists(&dt->do_lu);
435 /* number of blocks this transaction will modify */
436 unsigned int tp_credits;
437 /* sync transaction is needed */
441 static inline void txn_param_init(struct txn_param *p, unsigned int credits)
443 memset(p, 0, sizeof(*p));
444 p->tp_credits = credits;
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.
462 /* the dt device on which the transactions are executed */
463 struct dt_device *th_dev;
465 /* context for this transaction, tag is LCT_TX_HANDLE */
466 struct lu_context th_ctx;
468 /* the last operation result in this transaction.
469 * this value is used in recovery */
474 * Transaction call-backs.
476 * These are invoked by osd (or underlying transaction engine) when
477 * transaction changes state.
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.
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);
492 struct list_head dtc_linkage;
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);
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);
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,
508 #endif /* __LUSTRE_DT_OBJECT_H */