X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Finclude%2Flu_object.h;h=2ac4144054d3a284158f4110928cd8187eb848ee;hp=4e035cd2952a0970bdd584e497282f6c28f382c7;hb=ecd28d9b6cb691bda8184a7e07f1acc1ccded391;hpb=c70afdcb058adebfd517540e72185403a09a126b diff --git a/lustre/include/lu_object.h b/lustre/include/lu_object.h index 4e035cd..2ac4144 100644 --- a/lustre/include/lu_object.h +++ b/lustre/include/lu_object.h @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -28,9 +26,8 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. - */ -/* - * Copyright (c) 2011 Whamcloud, Inc. + * + * Copyright (c) 2011, 2014, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -41,14 +38,8 @@ #define __LUSTRE_LU_OBJECT_H #include - -/* - * struct lu_fid - */ #include - #include - #include struct seq_file; @@ -175,8 +166,13 @@ struct lu_device_operations { * For lu_object_conf flags */ typedef enum { - /* Currently, only used for client-side object initialization. */ - LOC_F_NEW = 0x1, + /* This is a new object to be allocated, or the file + * corresponding to the object does not exists. */ + LOC_F_NEW = 0x00000001, + + /* When find a dying object, just return -EAGAIN at once instead of + * blocking the thread. */ + LOC_F_NOWAIT = 0x00000002, } loc_flags_t; /** @@ -266,17 +262,17 @@ struct lu_device_type; * Device: a layer in the server side abstraction stacking. */ struct lu_device { - /** - * reference count. This is incremented, in particular, on each object - * created at this layer. - * - * \todo XXX which means that atomic_t is probably too small. - */ - cfs_atomic_t ld_ref; - /** - * Pointer to device type. Never modified once set. - */ - struct lu_device_type *ld_type; + /** + * reference count. This is incremented, in particular, on each object + * created at this layer. + * + * \todo XXX which means that atomic_t is probably too small. + */ + atomic_t ld_ref; + /** + * Pointer to device type. Never modified once set. + */ + struct lu_device_type *ld_type; /** * Operation vector for this device. */ @@ -293,6 +289,10 @@ struct lu_device { * A list of references to this object, for debugging. */ struct lu_ref ld_reference; + /** + * Link the device to the site. + **/ + struct list_head ld_linkage; }; struct lu_device_type_operations; @@ -337,13 +337,13 @@ struct lu_device_type { /** * Number of existing device type instances. */ - unsigned ldt_device_nr; - /** - * Linkage into a global list of all device types. - * - * \see lu_device_types. - */ - cfs_list_t ldt_linkage; + atomic_t ldt_device_nr; + /** + * Linkage into a global list of all device types. + * + * \see lu_device_types. + */ + struct list_head ldt_linkage; }; /** @@ -396,16 +396,10 @@ struct lu_device_type_operations { void (*ldto_stop)(struct lu_device_type *t); }; -/** - * Flags for the object layers. - */ -enum lu_object_flags { - /** - * this flags is set if lu_object_operations::loo_object_init() has - * been called for this layer. Used by lu_object_alloc(). - */ - LU_OBJECT_ALLOCATED = (1 << 0) -}; +static inline int lu_device_is_md(const struct lu_device *d) +{ + return ergo(d != NULL, d->ld_type->ldt_tags & LU_DEVICE_MD); +} /** * Common object attributes. @@ -413,12 +407,12 @@ enum lu_object_flags { struct lu_attr { /** size in bytes */ __u64 la_size; - /** modification time in seconds since Epoch */ - obd_time la_mtime; - /** access time in seconds since Epoch */ - obd_time la_atime; - /** change time in seconds since Epoch */ - obd_time la_ctime; + /** modification time in seconds since Epoch */ + s64 la_mtime; + /** access time in seconds since Epoch */ + s64 la_atime; + /** change time in seconds since Epoch */ + s64 la_ctime; /** 512-byte blocks allocated to object */ __u64 la_blocks; /** permission bits and file type */ @@ -483,28 +477,24 @@ struct lu_object { /** * Linkage into list of all layers. */ - cfs_list_t lo_linkage; - /** - * Depth. Top level layer depth is 0. - */ - int lo_depth; - /** - * Flags from enum lu_object_flags. - */ - unsigned long lo_flags; - /** - * Link to the device, for debugging. - */ - struct lu_ref_link *lo_dev_ref; + struct list_head lo_linkage; + /** + * Link to the device, for debugging. + */ + struct lu_ref_link lo_dev_ref; }; enum lu_object_header_flags { - /** - * Don't keep this object in cache. Object will be destroyed as soon - * as last reference to it is released. This flag cannot be cleared - * once set. - */ - LU_OBJECT_HEARD_BANSHEE = 0 + /** + * Don't keep this object in cache. Object will be destroyed as soon + * as last reference to it is released. This flag cannot be cleared + * once set. + */ + LU_OBJECT_HEARD_BANSHEE = 0, + /** + * Mark this object has already been taken out of cache. + */ + LU_OBJECT_UNHASHED = 1, }; enum lu_object_header_attr { @@ -529,68 +519,68 @@ enum lu_object_header_attr { * whether object is backed by persistent storage entity. */ struct lu_object_header { - /** - * Object flags from enum lu_object_header_flags. Set and checked - * atomically. - */ - unsigned long loh_flags; - /** - * Object reference count. Protected by lu_site::ls_guard. - */ - cfs_atomic_t loh_ref; - /** - * Fid, uniquely identifying this object. - */ - struct lu_fid loh_fid; - /** - * Common object attributes, cached for efficiency. From enum - * lu_object_header_attr. - */ - __u32 loh_attr; - /** - * Linkage into per-site hash table. Protected by lu_site::ls_guard. - */ - cfs_hlist_node_t loh_hash; - /** - * Linkage into per-site LRU list. Protected by lu_site::ls_guard. - */ - cfs_list_t loh_lru; - /** - * Linkage into list of layers. Never modified once set (except lately - * during object destruction). No locking is necessary. - */ - cfs_list_t loh_layers; - /** - * A list of references to this object, for debugging. - */ - struct lu_ref loh_reference; + /** + * Fid, uniquely identifying this object. + */ + struct lu_fid loh_fid; + /** + * Object flags from enum lu_object_header_flags. Set and checked + * atomically. + */ + unsigned long loh_flags; + /** + * Object reference count. Protected by lu_site::ls_guard. + */ + atomic_t loh_ref; + /** + * Common object attributes, cached for efficiency. From enum + * lu_object_header_attr. + */ + __u32 loh_attr; + /** + * Linkage into per-site hash table. Protected by lu_site::ls_guard. + */ + struct hlist_node loh_hash; + /** + * Linkage into per-site LRU list. Protected by lu_site::ls_guard. + */ + struct list_head loh_lru; + /** + * Linkage into list of layers. Never modified once set (except lately + * during object destruction). No locking is necessary. + */ + struct list_head loh_layers; + /** + * A list of references to this object, for debugging. + */ + struct lu_ref loh_reference; }; struct fld; struct lu_site_bkt_data { - /** - * number of busy object on this bucket - */ - long lsb_busy; - /** - * LRU list, updated on each access to object. Protected by - * bucket lock of lu_site::ls_obj_hash. - * - * "Cold" end of LRU is lu_site::ls_lru.next. Accessed object are - * moved to the lu_site::ls_lru.prev (this is due to the non-existence - * of list_for_each_entry_safe_reverse()). - */ - cfs_list_t lsb_lru; - /** - * Wait-queue signaled when an object in this site is ultimately - * destroyed (lu_object_free()). It is used by lu_object_find() to - * wait before re-trying when object in the process of destruction is - * found in the hash table. - * - * \see htable_lookup(). - */ - cfs_waitq_t lsb_marche_funebre; + /** + * number of busy object on this bucket + */ + long lsb_busy; + /** + * LRU list, updated on each access to object. Protected by + * bucket lock of lu_site::ls_obj_hash. + * + * "Cold" end of LRU is lu_site::ls_lru.next. Accessed object are + * moved to the lu_site::ls_lru.prev (this is due to the non-existence + * of list_for_each_entry_safe_reverse()). + */ + struct list_head lsb_lru; + /** + * Wait-queue signaled when an object in this site is ultimately + * destroyed (lu_object_free()). It is used by lu_object_find() to + * wait before re-trying when object in the process of destruction is + * found in the hash table. + * + * \see htable_lookup(). + */ + wait_queue_head_t lsb_marche_funebre; }; enum { @@ -617,24 +607,45 @@ struct lu_site { /** * objects hash table */ - cfs_hash_t *ls_obj_hash; + cfs_hash_t *ls_obj_hash; /** * index of bucket on hash table while purging */ - int ls_purge_start; - /** - * Top-level device for this stack. - */ - struct lu_device *ls_top_dev; - /** - * Linkage into global list of sites. - */ - cfs_list_t ls_linkage; - /** - * lu_site stats - */ - struct lprocfs_stats *ls_stats; - struct lprocfs_stats *ls_time_stats; + unsigned int ls_purge_start; + /** + * Top-level device for this stack. + */ + struct lu_device *ls_top_dev; + /** + * Bottom-level device for this stack + */ + struct lu_device *ls_bottom_dev; + /** + * Linkage into global list of sites. + */ + struct list_head ls_linkage; + /** + * List for lu device for this site, protected + * by ls_ld_lock. + **/ + struct list_head ls_ld_linkage; + spinlock_t ls_ld_lock; + /** + * Lock to serialize site purge. + */ + struct mutex ls_purge_mutex; + /** + * lu_site stats + */ + struct lprocfs_stats *ls_stats; + /** + * XXX: a hack! fld has to find md_site via site, remove when possible + */ + struct seq_server_site *ld_seq_site; + /** + * Pointer to the lu_target for this site. + */ + struct lu_target *ls_tgt; }; static inline struct lu_site_bkt_data * @@ -646,6 +657,11 @@ lu_site_bkt_from_fid(struct lu_site *site, struct lu_fid *fid) return cfs_hash_bd_extra_get(site->ls_obj_hash, &bd); } +static inline struct seq_server_site *lu_site2seq(const struct lu_site *s) +{ + return s->ld_seq_site; +} + /** \name ctors * Constructors/destructors. * @{ @@ -667,13 +683,15 @@ void lu_object_fini (struct lu_object *o); void lu_object_add_top (struct lu_object_header *h, struct lu_object *o); void lu_object_add (struct lu_object *before, struct lu_object *o); +void lu_dev_add_linkage(struct lu_site *s, struct lu_device *d); +void lu_dev_del_linkage(struct lu_site *s, struct lu_device *d); + /** * Helpers to initialize and finalize device types. */ int lu_device_type_init(struct lu_device_type *ldt); void lu_device_type_fini(struct lu_device_type *ldt); -void lu_types_stop(void); /** @} ctors */ @@ -689,8 +707,8 @@ void lu_types_stop(void); */ static inline void lu_object_get(struct lu_object *o) { - LASSERT(cfs_atomic_read(&o->lo_header->loh_ref) > 0); - cfs_atomic_inc(&o->lo_header->loh_ref); + LASSERT(atomic_read(&o->lo_header->loh_ref) > 0); + atomic_inc(&o->lo_header->loh_ref); } /** @@ -699,10 +717,12 @@ static inline void lu_object_get(struct lu_object *o) */ static inline int lu_object_is_dying(const struct lu_object_header *h) { - return cfs_test_bit(LU_OBJECT_HEARD_BANSHEE, &h->loh_flags); + return test_bit(LU_OBJECT_HEARD_BANSHEE, &h->loh_flags); } void lu_object_put(const struct lu_env *env, struct lu_object *o); +void lu_object_put_nocache(const struct lu_env *env, struct lu_object *o); +void lu_object_unhash(const struct lu_env *env, struct lu_object *o); int lu_site_purge(const struct lu_env *env, struct lu_site *s, int nr); @@ -731,8 +751,8 @@ struct lu_object *lu_object_find_slice(const struct lu_env *env, */ static inline struct lu_object *lu_object_top(struct lu_object_header *h) { - LASSERT(!cfs_list_empty(&h->loh_layers)); - return container_of0(h->loh_layers.next, struct lu_object, lo_linkage); + LASSERT(!list_empty(&h->loh_layers)); + return container_of0(h->loh_layers.next, struct lu_object, lo_linkage); } /** @@ -767,40 +787,22 @@ lu_object_ops(const struct lu_object *o) struct lu_object *lu_object_locate(struct lu_object_header *h, const struct lu_device_type *dtype); -struct lu_cdebug_print_info { - int lpi_subsys; - int lpi_mask; - const char *lpi_file; - const char *lpi_fn; - int lpi_line; -}; - /** * Printer function emitting messages through libcfs_debug_msg(). */ int lu_cdebug_printer(const struct lu_env *env, void *cookie, const char *format, ...); -#define DECLARE_LU_CDEBUG_PRINT_INFO(var, mask) \ - struct lu_cdebug_print_info var = { \ - .lpi_subsys = DEBUG_SUBSYSTEM, \ - .lpi_mask = (mask), \ - .lpi_file = __FILE__, \ - .lpi_fn = __FUNCTION__, \ - .lpi_line = __LINE__ \ - } - /** * Print object description followed by a user-supplied message. */ -#define LU_OBJECT_DEBUG(mask, env, object, format, ...) \ -do { \ - static DECLARE_LU_CDEBUG_PRINT_INFO(__info, mask); \ - \ - if (cfs_cdebug_show(mask, DEBUG_SUBSYSTEM)) { \ - lu_object_print(env, &__info, lu_cdebug_printer, object); \ - CDEBUG(mask, format , ## __VA_ARGS__); \ - } \ +#define LU_OBJECT_DEBUG(mask, env, object, format, ...) \ +do { \ + if (cfs_cdebug_show(mask, DEBUG_SUBSYSTEM)) { \ + LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, NULL); \ + lu_object_print(env, &msgdata, lu_cdebug_printer, object);\ + CDEBUG(mask, format , ## __VA_ARGS__); \ + } \ } while (0) /** @@ -808,12 +810,11 @@ do { \ */ #define LU_OBJECT_HEADER(mask, env, object, format, ...) \ do { \ - static DECLARE_LU_CDEBUG_PRINT_INFO(__info, mask); \ - \ if (cfs_cdebug_show(mask, DEBUG_SUBSYSTEM)) { \ - lu_object_header_print(env, &__info, lu_cdebug_printer, \ + LIBCFS_DEBUG_MSG_DATA_DECL(msgdata, mask, NULL); \ + lu_object_header_print(env, &msgdata, lu_cdebug_printer,\ (object)->lo_header); \ - lu_cdebug_printer(env, &__info, "\n"); \ + lu_cdebug_printer(env, &msgdata, "\n"); \ CDEBUG(mask, format , ## __VA_ARGS__); \ } \ } while (0) @@ -831,31 +832,25 @@ int lu_object_invariant(const struct lu_object *o); /** - * \retval 1 iff object \a o exists on stable storage, - * \retval 0 iff object \a o not exists on stable storage. - * \retval -1 iff object \a o is on remote server. + * Check whether object exists, no matter on local or remote storage. + * Note: LOHA_EXISTS will be set once some one created the object, + * and it does not needs to be committed to storage. */ -static inline int lu_object_exists(const struct lu_object *o) -{ - __u32 attr; - - attr = o->lo_header->loh_attr; - if (attr & LOHA_REMOTE) - return -1; - else if (attr & LOHA_EXISTS) - return +1; - else - return 0; -} +#define lu_object_exists(o) ((o)->lo_header->loh_attr & LOHA_EXISTS) + +/** + * Check whether object on the remote storage. + */ +#define lu_object_remote(o) unlikely((o)->lo_header->loh_attr & LOHA_REMOTE) static inline int lu_object_assert_exists(const struct lu_object *o) { - return lu_object_exists(o) != 0; + return lu_object_exists(o); } static inline int lu_object_assert_not_exists(const struct lu_object *o) { - return lu_object_exists(o) <= 0; + return !lu_object_exists(o); } /** @@ -863,15 +858,23 @@ static inline int lu_object_assert_not_exists(const struct lu_object *o) */ static inline __u32 lu_object_attr(const struct lu_object *o) { - LASSERT(lu_object_exists(o) > 0); + LASSERT(lu_object_exists(o) != 0); return o->lo_header->loh_attr; } -static inline struct lu_ref_link *lu_object_ref_add(struct lu_object *o, - const char *scope, - const void *source) +static inline void lu_object_ref_add(struct lu_object *o, + const char *scope, + const void *source) +{ + lu_ref_add(&o->lo_header->loh_reference, scope, source); +} + +static inline void lu_object_ref_add_at(struct lu_object *o, + struct lu_ref_link *link, + const char *scope, + const void *source) { - return lu_ref_add(&o->lo_header->loh_reference, scope, source); + lu_ref_add_at(&o->lo_header->loh_reference, link, scope, source); } static inline void lu_object_ref_del(struct lu_object *o, @@ -902,8 +905,8 @@ struct lu_rdpg { }; enum lu_xattr_flags { - LU_XATTR_REPLACE = (1 << 0), - LU_XATTR_CREATE = (1 << 1) + LU_XATTR_REPLACE = (1 << 0), + LU_XATTR_CREATE = (1 << 1) }; /** @} helpers */ @@ -952,6 +955,7 @@ struct lu_context { * from enum lu_context_tag. */ __u32 lc_tags; + enum lu_context_state lc_state; /** * Pointer to the home service thread. NULL for other execution * contexts. @@ -961,23 +965,22 @@ struct lu_context { * Pointer to an array with key values. Internal implementation * detail. */ - void **lc_value; - enum lu_context_state lc_state; - /** - * Linkage into a list of all remembered contexts. Only - * `non-transient' contexts, i.e., ones created for service threads - * are placed here. - */ - cfs_list_t lc_remember; - /** - * Version counter used to skip calls to lu_context_refill() when no - * keys were registered. - */ - unsigned lc_version; + void **lc_value; + /** + * Linkage into a list of all remembered contexts. Only + * `non-transient' contexts, i.e., ones created for service threads + * are placed here. + */ + struct list_head lc_remember; + /** + * Version counter used to skip calls to lu_context_refill() when no + * keys were registered. + */ + unsigned lc_version; /** * Debugging cookie. */ - unsigned lc_cookie; + unsigned lc_cookie; }; /** @@ -1006,7 +1009,22 @@ enum lu_context_tag { * a client. */ LCT_SESSION = 1 << 4, - + /** + * A per-request data on OSP device + */ + LCT_OSP_THREAD = 1 << 5, + /** + * MGS device thread + */ + LCT_MG_THREAD = 1 << 6, + /** + * Context for local operations + */ + LCT_LOCAL = 1 << 7, + /** + * session for server thread + **/ + LCT_SERVER_SESSION = 1 << 8, /** * Set when at least one of keys, having values in this context has * non-NULL lu_context_key::lct_exit() method. This is used to @@ -1093,24 +1111,24 @@ struct lu_context_key { */ void (*lct_exit)(const struct lu_context *ctx, struct lu_context_key *key, void *data); - /** - * Internal implementation detail: index within lu_context::lc_value[] - * reserved for this key. - */ - int lct_index; - /** - * Internal implementation detail: number of values created for this - * key. - */ - cfs_atomic_t lct_used; - /** - * Internal implementation detail: module for this key. - */ - cfs_module_t *lct_owner; - /** - * References to this key. For debugging. - */ - struct lu_ref lct_reference; + /** + * Internal implementation detail: index within lu_context::lc_value[] + * reserved for this key. + */ + int lct_index; + /** + * Internal implementation detail: number of values created for this + * key. + */ + atomic_t lct_used; + /** + * Internal implementation detail: module for this key. + */ + struct module *lct_owner; + /** + * References to this key. For debugging. + */ + struct lu_ref lct_reference; }; #define LU_KEY_INIT(mod, type) \ @@ -1119,7 +1137,7 @@ struct lu_context_key { { \ type *value; \ \ - CLASSERT(CFS_PAGE_SIZE >= sizeof (*value)); \ + CLASSERT(PAGE_CACHE_SIZE >= sizeof (*value)); \ \ OBD_ALLOC_PTR(value); \ if (value == NULL) \ @@ -1236,6 +1254,14 @@ void lu_context_key_degister_many(struct lu_context_key *k, ...); void lu_context_key_revive_many (struct lu_context_key *k, ...); void lu_context_key_quiesce_many (struct lu_context_key *k, ...); +/* + * update/clear ctx/ses tags. + */ +void lu_context_tags_update(__u32 tags); +void lu_context_tags_clear(__u32 tags); +void lu_session_tags_update(__u32 tags); +void lu_session_tags_clear(__u32 tags); + /** * Environment. */ @@ -1253,6 +1279,7 @@ struct lu_env { int lu_env_init (struct lu_env *env, __u32 tags); void lu_env_fini (struct lu_env *env); int lu_env_refill(struct lu_env *env); +int lu_env_refill_by_tags(struct lu_env *env, __u32 ctags, __u32 stags); /** @} lu_context */ @@ -1260,6 +1287,7 @@ int lu_env_refill(struct lu_env *env); * Output site statistical counters into a buffer. Suitable for * ll_rd_*()-style functions. */ +int lu_site_stats_seq_print(const struct lu_site *s, struct seq_file *m); int lu_site_stats_print(const struct lu_site *s, char *page, int count); /** @@ -1271,18 +1299,44 @@ struct lu_name { }; /** + * Validate names (path components) + * + * To be valid \a name must be non-empty, '\0' terminated of length \a + * name_len, and not contain '/'. The maximum length of a name (before + * say -ENAMETOOLONG will be returned) is really controlled by llite + * and the server. We only check for something insane coming from bad + * integer handling here. + */ +static inline bool lu_name_is_valid_2(const char *name, size_t name_len) +{ + return name != NULL && + name_len > 0 && + name_len < INT_MAX && + name[name_len] == '\0' && + strlen(name) == name_len && + memchr(name, '/', name_len) == NULL; +} + +static inline bool lu_name_is_valid(const struct lu_name *ln) +{ + return lu_name_is_valid_2(ln->ln_name, ln->ln_namelen); +} + +#define DNAME "%.*s" +#define PNAME(ln) \ + (lu_name_is_valid(ln) ? (ln)->ln_namelen : 0), \ + (lu_name_is_valid(ln) ? (ln)->ln_name : "") + +/** * Common buffer structure to be passed around for various xattr_{s,g}et() * methods. */ struct lu_buf { - void *lb_buf; - ssize_t lb_len; + void *lb_buf; + size_t lb_len; }; -/** null buffer */ -extern struct lu_buf LU_BUF_NULL; - -#define DLUBUF "(%p %z)" +#define DLUBUF "(%p %zu)" #define PLUBUF(buf) (buf)->lb_buf, (buf)->lb_len /** * One-time initializers, called at obdclass module initialization, not @@ -1299,17 +1353,8 @@ int lu_global_init(void); */ void lu_global_fini(void); -enum { - LU_TIME_FIND_LOOKUP, - LU_TIME_FIND_ALLOC, - LU_TIME_FIND_INSERT, - LU_TIME_NR -}; - -extern const char *lu_time_names[LU_TIME_NR]; - struct lu_kmem_descr { - cfs_mem_cache_t **ckd_cache; + struct kmem_cache **ckd_cache; const char *ckd_name; const size_t ckd_size; }; @@ -1317,5 +1362,34 @@ struct lu_kmem_descr { int lu_kmem_init(struct lu_kmem_descr *caches); void lu_kmem_fini(struct lu_kmem_descr *caches); +void lu_object_assign_fid(const struct lu_env *env, struct lu_object *o, + const struct lu_fid *fid); +struct lu_object *lu_object_anon(const struct lu_env *env, + struct lu_device *dev, + const struct lu_object_conf *conf); + +/** null buffer */ +extern struct lu_buf LU_BUF_NULL; + +void lu_buf_free(struct lu_buf *buf); +void lu_buf_alloc(struct lu_buf *buf, size_t size); +void lu_buf_realloc(struct lu_buf *buf, size_t size); + +int lu_buf_check_and_grow(struct lu_buf *buf, size_t len); +struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, size_t len); + +extern __u32 lu_context_tags_default; +extern __u32 lu_session_tags_default; + +static inline bool lu_device_is_cl(const struct lu_device *d) +{ + return d->ld_type->ldt_tags & LU_DEVICE_CL; +} + +static inline bool lu_object_is_cl(const struct lu_object *o) +{ + return lu_device_is_cl(o->lo_dev); +} + /** @} lu */ #endif /* __LUSTRE_LU_OBJECT_H */