#include <lustre_disk.h>
#include <lustre_fid.h>
#include <lu_object.h>
+#include <lu_ref.h>
#include <libcfs/list.h>
static void lu_object_free(const struct lu_env *env, struct lu_object *o);
* and LRU lock, no race with concurrent object lookup is possible
* and we can safely destroy object below.
*/
- cfs_hash_bd_del_locked(site->ls_obj_hash, &bd, &top->loh_hash);
+ if (!test_and_set_bit(LU_OBJECT_UNHASHED, &top->loh_flags))
+ cfs_hash_bd_del_locked(site->ls_obj_hash, &bd, &top->loh_hash);
cfs_hash_bd_unlock(site->ls_obj_hash, &bd, 1);
/*
* Object was already removed from hash and lru above, can
*/
void lu_object_put_nocache(const struct lu_env *env, struct lu_object *o)
{
- set_bit(LU_OBJECT_HEARD_BANSHEE,
- &o->lo_header->loh_flags);
+ set_bit(LU_OBJECT_HEARD_BANSHEE, &o->lo_header->loh_flags);
return lu_object_put(env, o);
}
EXPORT_SYMBOL(lu_object_put_nocache);
/**
+ * Kill the object and take it out of LRU cache.
+ * Currently used by client code for layout change.
+ */
+void lu_object_unhash(const struct lu_env *env, struct lu_object *o)
+{
+ struct lu_object_header *top;
+
+ top = o->lo_header;
+ set_bit(LU_OBJECT_HEARD_BANSHEE, &top->loh_flags);
+ if (!test_and_set_bit(LU_OBJECT_UNHASHED, &top->loh_flags)) {
+ cfs_hash_t *obj_hash = o->lo_dev->ld_site->ls_obj_hash;
+ cfs_hash_bd_t bd;
+
+ cfs_hash_bd_get_and_lock(obj_hash, &top->loh_fid, &bd, 1);
+ cfs_list_del_init(&top->loh_lru);
+ cfs_hash_bd_del_locked(obj_hash, &bd, &top->loh_hash);
+ cfs_hash_bd_unlock(obj_hash, &bd, 1);
+ }
+}
+EXPORT_SYMBOL(lu_object_unhash);
+
+/**
* Allocate new object.
*
* This follows object creation protocol, described in the comment within
int result;
ENTRY;
- /*
- * Create top-level object slice. This will also create
- * lu_object_header.
- */
- top = dev->ld_ops->ldo_object_alloc(env, NULL, dev);
- if (top == NULL)
- RETURN(ERR_PTR(-ENOMEM));
+ /*
+ * Create top-level object slice. This will also create
+ * lu_object_header.
+ */
+ top = dev->ld_ops->ldo_object_alloc(env, NULL, dev);
+ if (top == NULL)
+ RETURN(ERR_PTR(-ENOMEM));
+ if (IS_ERR(top))
+ RETURN(top);
/*
* This is the only place where object fid is assigned. It's constant
* after this point.
*/
- LASSERT(fid_is_igif(f) || fid_ver(f) == 0);
top->lo_header->loh_fid = *f;
layers = &top->lo_header->loh_layers;
do {
int bnr;
int i;
+ if (OBD_FAIL_CHECK(OBD_FAIL_OBD_NO_LRU))
+ RETURN(0);
+
CFS_INIT_LIST_HEAD(&dispose);
/*
* Under LRU list lock, scan LRU list and move unreferenced objects to
void lu_context_key_quiesce(struct lu_context_key *key)
{
struct lu_context *ctx;
- extern unsigned cl_env_cache_purge(unsigned nr);
if (!(key->lct_tags & LCT_QUIESCENT)) {
/*
* XXX layering violation.
*/
- cl_env_cache_purge(~0);
key->lct_tags |= LCT_QUIESCENT;
/*
* XXX memory barrier has to go here.
return 0;
}
-void lu_debugging_setup(void)
+int lu_debugging_setup(void)
{
- lu_env_init(&lu_debugging_env, ~0);
+ return lu_env_init(&lu_debugging_env, ~0);
}
void lu_context_keys_dump(void)
}
#endif /* __KERNEL__ */
-int cl_global_init(void);
-void cl_global_fini(void);
-int lu_ref_global_init(void);
-void lu_ref_global_fini(void);
-
-int dt_global_init(void);
-void dt_global_fini(void);
-
-int llo_global_init(void);
-void llo_global_fini(void);
-
-/* context key constructor/destructor: lu_ucred_key_init, lu_ucred_key_fini */
-LU_KEY_INIT_FINI(lu_ucred, struct lu_ucred);
-
-static struct lu_context_key lu_ucred_key = {
- .lct_tags = LCT_SESSION,
- .lct_init = lu_ucred_key_init,
- .lct_fini = lu_ucred_key_fini
-};
-
-/**
- * Get ucred key if session exists and ucred key is allocated on it.
- * Return NULL otherwise.
- */
-struct lu_ucred *lu_ucred(const struct lu_env *env)
-{
- if (!env->le_ses)
- return NULL;
- return lu_context_key_get(env->le_ses, &lu_ucred_key);
-}
-EXPORT_SYMBOL(lu_ucred);
-
-/**
- * Get ucred key and check if it is properly initialized.
- * Return NULL otherwise.
- */
-struct lu_ucred *lu_ucred_check(const struct lu_env *env)
-{
- struct lu_ucred *uc = lu_ucred(env);
- if (uc && uc->uc_valid != UCRED_OLD && uc->uc_valid != UCRED_NEW)
- return NULL;
- return uc;
-}
-EXPORT_SYMBOL(lu_ucred_check);
-
-/**
- * Get ucred key, which must exist and must be properly initialized.
- * Assert otherwise.
- */
-struct lu_ucred *lu_ucred_assert(const struct lu_env *env)
-{
- struct lu_ucred *uc = lu_ucred_check(env);
- LASSERT(uc != NULL);
- return uc;
-}
-EXPORT_SYMBOL(lu_ucred_assert);
-
/**
* Initialization of global lu_* data.
*/
if (result != 0)
return result;
- LU_CONTEXT_KEY_INIT(&lu_ucred_key);
- result = lu_context_key_register(&lu_ucred_key);
- if (result != 0)
- return result;
-
/*
* At this level, we don't know what tags are needed, so allocate them
* conservatively. This should not be too bad, because this
if (lu_site_shrinker == NULL)
return -ENOMEM;
-#ifdef __KERNEL__
- result = dt_global_init();
- if (result != 0)
- return result;
-
- result = llo_global_init();
- if (result != 0)
- return result;
-#endif
- result = cl_global_init();
-
return result;
}
*/
void lu_global_fini(void)
{
- cl_global_fini();
-#ifdef __KERNEL__
- llo_global_fini();
- dt_global_fini();
-#endif
if (lu_site_shrinker != NULL) {
cfs_remove_shrinker(lu_site_shrinker);
lu_site_shrinker = NULL;
}
- lu_context_key_degister(&lu_global_key);
- lu_context_key_degister(&lu_ucred_key);
+ lu_context_key_degister(&lu_global_key);
/*
* Tear shrinker environment down _after_ de-registering
lu_ref_global_fini();
}
-struct lu_buf LU_BUF_NULL = {
- .lb_buf = NULL,
- .lb_len = 0
-};
-EXPORT_SYMBOL(LU_BUF_NULL);
-
static __u32 ls_stats_read(struct lprocfs_stats *stats, int idx)
{
#ifdef LPROCFS
return o;
}
EXPORT_SYMBOL(lu_object_anon);
+
+struct lu_buf LU_BUF_NULL = {
+ .lb_buf = NULL,
+ .lb_len = 0
+};
+EXPORT_SYMBOL(LU_BUF_NULL);
+
+void lu_buf_free(struct lu_buf *buf)
+{
+ LASSERT(buf);
+ if (buf->lb_buf) {
+ LASSERT(buf->lb_len > 0);
+ OBD_FREE_LARGE(buf->lb_buf, buf->lb_len);
+ buf->lb_buf = NULL;
+ buf->lb_len = 0;
+ }
+}
+EXPORT_SYMBOL(lu_buf_free);
+
+void lu_buf_alloc(struct lu_buf *buf, int size)
+{
+ LASSERT(buf);
+ LASSERT(buf->lb_buf == NULL);
+ LASSERT(buf->lb_len == 0);
+ OBD_ALLOC_LARGE(buf->lb_buf, size);
+ if (likely(buf->lb_buf))
+ buf->lb_len = size;
+}
+EXPORT_SYMBOL(lu_buf_alloc);
+
+void lu_buf_realloc(struct lu_buf *buf, int size)
+{
+ lu_buf_free(buf);
+ lu_buf_alloc(buf, size);
+}
+EXPORT_SYMBOL(lu_buf_realloc);
+
+struct lu_buf *lu_buf_check_and_alloc(struct lu_buf *buf, int len)
+{
+ if (buf->lb_buf == NULL && buf->lb_len == 0)
+ lu_buf_alloc(buf, len);
+
+ if ((len > buf->lb_len) && (buf->lb_buf != NULL))
+ lu_buf_realloc(buf, len);
+
+ return buf;
+}
+EXPORT_SYMBOL(lu_buf_check_and_alloc);
+
+/**
+ * Increase the size of the \a buf.
+ * preserves old data in buffer
+ * old buffer remains unchanged on error
+ * \retval 0 or -ENOMEM
+ */
+int lu_buf_check_and_grow(struct lu_buf *buf, int len)
+{
+ char *ptr;
+
+ if (len <= buf->lb_len)
+ return 0;
+
+ OBD_ALLOC_LARGE(ptr, len);
+ if (ptr == NULL)
+ return -ENOMEM;
+
+ /* Free the old buf */
+ if (buf->lb_buf != NULL) {
+ memcpy(ptr, buf->lb_buf, buf->lb_len);
+ OBD_FREE_LARGE(buf->lb_buf, buf->lb_len);
+ }
+
+ buf->lb_buf = ptr;
+ buf->lb_len = len;
+ return 0;
+}
+EXPORT_SYMBOL(lu_buf_check_and_grow);
+