-/* -*- 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.
/*
* 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, 2013, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#define __LUSTRE_LU_OBJECT_H
#include <stdarg.h>
-
-/*
- * struct lu_fid
- */
#include <libcfs/libcfs.h>
-
#include <lustre/lustre_idl.h>
-
#include <lu_ref.h>
struct seq_file;
* 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;
/**
* 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.
*/
* 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;
/**
* 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;
};
/**
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.
/**
* 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 {
* 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 {
/**
* 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;
+ 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;
};
static inline struct lu_site_bkt_data *
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.
* @{
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 */
*/
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);
}
/**
*/
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);
struct lu_device *dev,
const struct lu_fid *f,
const struct lu_object_conf *conf);
+void lu_object_purge(const struct lu_env *env, struct lu_device *dev,
+ const struct lu_fid *f);
struct lu_object *lu_object_find_slice(const struct lu_env *env,
struct lu_device *dev,
const struct lu_fid *f,
*/
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);
}
/**
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)
/**
*/
#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)
/**
- * \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);
}
/**
*/
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,
};
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 */
* 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.
* 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;
};
/**
* 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
*/
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) \
{ \
type *value; \
\
- CLASSERT(CFS_PAGE_SIZE >= sizeof (*value)); \
+ CLASSERT(PAGE_CACHE_SIZE >= sizeof (*value)); \
\
OBD_ALLOC_PTR(value); \
if (value == NULL) \
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.
*/
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 */
* 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);
/**
};
/**
+ * 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
*/
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;
};
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);
+
/** @} lu */
#endif /* __LUSTRE_LU_OBJECT_H */