ENTRY;
LASSERT(fid_is_sane(fid));
-
+
ls = cm->cmm_md_dev.md_lu_dev.ld_site;
-
+
rc = fld_client_lookup(ls->ls_client_fld,
fid_seq(fid), mds);
if (rc) {
return lu_object_exists(ctx, lu_object_next(lo));
}
-static int cml_object_print(const struct lu_context *ctx,
- struct seq_file *f, const struct lu_object *lo)
+static int cml_object_print(const struct lu_context *ctx, void *cookie,
+ lu_printer_t p, const struct lu_object *lo)
{
- return seq_printf(f, LUSTRE_CMM0_NAME"-local@%p", lo);
+ return (*p)(ctx, cookie, LUSTRE_CMM0_NAME"-local@%p", lo);
}
static struct lu_object_operations cml_obj_ops = {
}
-static int cml_create(const struct lu_context *ctx, struct md_object *mo_p,
- const char *child_name, struct md_object *mo_c,
+static int cml_create(const struct lu_context *ctx, struct md_object *mo_p,
+ const char *child_name, struct md_object *mo_c,
const char *target_name, struct md_attr *ma)
{
int rc;
return -1;
}
-static int cmr_object_print(const struct lu_context *ctx,
- struct seq_file *f, const struct lu_object *lo)
+static int cmr_object_print(const struct lu_context *ctx, void *cookie,
+ lu_printer_t p, const struct lu_object *lo)
{
- return seq_printf(f, LUSTRE_CMM0_NAME"-remote@%p", lo);
+ return (*p)(ctx, cookie, LUSTRE_CMM0_NAME"-remote@%p", lo);
}
static struct lu_object_operations cmr_obj_ops = {
*
*/
static int cmr_create(const struct lu_context *ctx, struct md_object *mo_p,
- const char *child_name, struct md_object *mo_c,
+ const char *child_name, struct md_object *mo_c,
const char *target_name, struct md_attr *ma)
{
int rc;
RETURN(rc);
}
-/* part of cross-ref rename(). Used to insert new name in new parent
+/* part of cross-ref rename(). Used to insert new name in new parent
* and unlink target with same name if it exists */
static int cmr_rename_tgt(const struct lu_context *ctx,
struct md_object *mo_p, struct md_object *mo_t,
RETURN(0);
}
-static int mdc_object_print(const struct lu_context *ctx,
- struct seq_file *f, const struct lu_object *lo)
+static int mdc_object_print(const struct lu_context *ctx, void *cookie,
+ lu_printer_t p, const struct lu_object *lo)
{
- return seq_printf(f, LUSTRE_MDC0_NAME"-object@%p", lo);
+ return (*p)(ctx, cookie, LUSTRE_MDC0_NAME"-object@%p", lo);
}
static struct lu_object_operations mdc_obj_ops = {
mci = lu_context_key_get(ctx, &mdc_thread_key);
LASSERT(mci);
-
+
memset(&mci->mci_opdata, 0, sizeof(mci->mci_opdata));
mci->mci_opdata.fid1 = *lu_object_fid(&mo->mo_lu);
mci->mci_opdata.mod_time = attr->la_mtime;
};
/*
+ * Type of "printer" function used by ->loo_object_print() method.
+ *
+ * Printer function is needed to provide some flexibility in (semi-)debugging
+ * output: possible implementations: printk, CDEBUG, sysfs/seq_file
+ */
+typedef int (*lu_printer_t)(const struct lu_context *ctx,
+ void *cookie, const char *format, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+/*
* Operations specific for particular lu_object.
*/
struct lu_object_operations {
/*
* Debugging helper. Print given object.
*/
- int (*loo_object_print)(const struct lu_context *ctx,
- struct seq_file *f, const struct lu_object *o);
+ int (*loo_object_print)(const struct lu_context *ctx, void *cookie,
+ lu_printer_t p, const struct lu_object *o);
/*
* Optional debugging method. Returns true iff method is internally
* consistent.
};
struct fld;
+
/*
* lu_site is a "compartment" within which objects are unique, and LRU
* discipline is maintained.
struct lu_object *lu_object_locate(struct lu_object_header *h,
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_context *ctx,
+ void *cookie, const char *format, ...);
+
+/*
+ * Print object description followed by user-supplied message.
+ */
+#define LU_OBJECT_DEBUG(mask, ctx, object, format, ...) \
+({ \
+ static struct lu_cdebug_print_info __info = { \
+ .lpi_subsys = DEBUG_SUBSYSTEM, \
+ .lpi_mask = (mask), \
+ .lpi_file = __FILE__, \
+ .lpi_fn = __FUNCTION__, \
+ .lpi_line = __LINE__ \
+ }; \
+ lu_object_print(ctx, &__info, lu_cdebug_printer, object); \
+ CDEBUG(mask, format , ## __VA_ARGS__); \
+})
+
/*
* Print human readable representation of the @o to the @f.
*/
-int lu_object_print(const struct lu_context *ctxt,
- struct seq_file *f, const struct lu_object *o);
+void lu_object_print(const struct lu_context *ctxt, void *cookie,
+ lu_printer_t printer, const struct lu_object *o);
/*
* Check object consistency.
/*
* Returns 1 iff object @o exists on the stable storage,
- * returns -1 iif object @o is on remote server.
+ * returns -1 iff object @o is on remote server.
*/
static inline int lu_object_exists(const struct lu_context *ctx,
const struct lu_object *o)
}
static inline int lu_object_assert_exists(const struct lu_context *ctx,
- const struct lu_object *o)
+ const struct lu_object *o)
{
return lu_object_exists(ctx, o) != 0;
}
static inline int lu_object_assert_not_exists(const struct lu_context *ctx,
- const struct lu_object *o)
+ const struct lu_object *o)
{
return lu_object_exists(ctx, o) <= 0;
}
*/
void lu_context_exit(struct lu_context *ctx);
+/*
+ * Initialization of global lu_* data.
+ */
+int lu_global_init(void);
+
+/*
+ * Dual to lu_global_init().
+ */
+void lu_global_fini(void);
+
#endif /* __LUSTRE_LU_OBJECT_H */
Index: iam/fs/ext3/Makefile
===================================================================
---- iam.orig/fs/ext3/Makefile 2006-07-20 18:33:52.000000000 +0400
-+++ iam/fs/ext3/Makefile 2006-07-20 18:33:52.000000000 +0400
+--- iam.orig/fs/ext3/Makefile 2006-07-21 23:12:10.000000000 +0400
++++ iam/fs/ext3/Makefile 2006-07-21 23:12:10.000000000 +0400
@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT3_FS) += ext3.o
ext3-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o iopen.o \
ext3-$(CONFIG_EXT3_FS_POSIX_ACL) += acl.o
Index: iam/fs/ext3/dir.c
===================================================================
---- iam.orig/fs/ext3/dir.c 2006-07-20 18:33:52.000000000 +0400
-+++ iam/fs/ext3/dir.c 2006-07-20 18:33:52.000000000 +0400
+--- iam.orig/fs/ext3/dir.c 2006-07-21 23:12:10.000000000 +0400
++++ iam/fs/ext3/dir.c 2006-07-21 23:12:10.000000000 +0400
@@ -28,6 +28,7 @@
#include <linux/smp_lock.h>
#include <linux/slab.h>
(filp->f_version != inode->i_version)) {
Index: iam/fs/ext3/file.c
===================================================================
---- iam.orig/fs/ext3/file.c 2006-07-20 18:33:52.000000000 +0400
-+++ iam/fs/ext3/file.c 2006-07-20 18:33:52.000000000 +0400
+--- iam.orig/fs/ext3/file.c 2006-07-21 23:12:10.000000000 +0400
++++ iam/fs/ext3/file.c 2006-07-21 23:12:10.000000000 +0400
@@ -23,6 +23,7 @@
#include <linux/jbd.h>
#include <linux/ext3_fs.h>
Index: iam/fs/ext3/iam-uapi.c
===================================================================
--- iam.orig/fs/ext3/iam-uapi.c 2004-04-06 17:27:52.000000000 +0400
-+++ iam/fs/ext3/iam-uapi.c 2006-07-20 18:33:52.000000000 +0400
++++ iam/fs/ext3/iam-uapi.c 2006-07-21 23:12:10.000000000 +0400
@@ -0,0 +1,361 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+}
Index: iam/fs/ext3/ioctl.c
===================================================================
---- iam.orig/fs/ext3/ioctl.c 2006-07-20 18:33:52.000000000 +0400
-+++ iam/fs/ext3/ioctl.c 2006-07-20 18:33:52.000000000 +0400
+--- iam.orig/fs/ext3/ioctl.c 2006-07-21 23:12:10.000000000 +0400
++++ iam/fs/ext3/ioctl.c 2006-07-21 23:12:10.000000000 +0400
@@ -250,6 +250,6 @@ flags_err:
}
Index: iam/include/linux/lustre_iam.h
===================================================================
---- iam.orig/include/linux/lustre_iam.h 2006-07-20 18:33:52.000000000 +0400
-+++ iam/include/linux/lustre_iam.h 2006-07-20 18:33:52.000000000 +0400
+--- iam.orig/include/linux/lustre_iam.h 2006-07-21 23:12:10.000000000 +0400
++++ iam/include/linux/lustre_iam.h 2006-07-21 23:12:10.000000000 +0400
@@ -30,9 +30,6 @@
#ifndef __LINUX_LUSTRE_IAM_H__
#define __LINUX_LUSTRE_IAM_H__
mdd_ctx_info(ctx)->mti_param.tp_credits = opd->mod_credits;
}
-static int mdd_object_print(const struct lu_context *ctxt,
- struct seq_file *f, const struct lu_object *o)
+static int mdd_object_print(const struct lu_context *ctxt, void *cookie,
+ lu_printer_t p, const struct lu_object *o)
{
- return seq_printf(f, LUSTRE_MDD0_NAME"-object@%p", o);
+ return (*p)(ctxt, cookie, LUSTRE_MDD0_NAME"-object@%p", o);
}
static int mdd_object_exists(const struct lu_context *ctx,
return rc == ELDLM_OK ? 0 : -EIO;
}
-/* just call ldlm_lock_decref() if decref,
+/* just call ldlm_lock_decref() if decref,
* else we only call ptlrpc_save_lock() to save this lock in req.
* when transaction committed, req will be released and lock will be released */
void fid_unlock(struct ptlrpc_request *req, const struct lu_fid *f,
}
if (decref)
ldlm_lock_decref(lh, mode);
- else
+ else
ptlrpc_save_lock(req, lh, mode);
}
ENTRY;
if (lustre_handle_is_used(&lh->mlh_lh)) {
- fid_unlock(req, mdt_object_fid(o),
+ fid_unlock(req, mdt_object_fid(o),
&lh->mlh_lh, lh->mlh_mode, decref);
lh->mlh_lh.cookie = 0;
}
EXIT;
}
-static int mdt_object_print(const struct lu_context *ctxt,
- struct seq_file *f, const struct lu_object *o)
+static int mdt_object_print(const struct lu_context *ctxt, void *cookie,
+ lu_printer_t p, const struct lu_object *o)
{
- return seq_printf(f, LUSTRE_MDT0_NAME"-object@%p", o);
+ return (*p)(ctxt, cookie, LUSTRE_MDT0_NAME"-object@%p", o);
}
int mdt_object_exists(const struct lu_context *ctx,
static int __init mdt_mod_init(void)
{
+ int result;
struct lprocfs_static_vars lvars;
mdt_num_threads = MDT_NUM_THREADS;
lprocfs_init_vars(mdt, &lvars);
- return class_register_type(&mdt_obd_device_ops, NULL,
- lvars.module_vars, LUSTRE_MDT0_NAME,
- &mdt_device_type);
+ result = lu_global_init();
+ if (result == 0)
+ result = class_register_type(&mdt_obd_device_ops, NULL,
+ lvars.module_vars,
+ LUSTRE_MDT0_NAME,
+ &mdt_device_type);
+ return result;
}
static void __exit mdt_mod_exit(void)
{
class_unregister_type(LUSTRE_MDT0_NAME);
+ lu_global_fini();
}
EXPORT_SYMBOL(lu_site_purge);
/*
- * Print human readable representation of the @o to the @f.
+ * Object printing.
+ *
+ * Code below has to jump through certain loops to output object description
+ * into libcfs_debug_msg-based log. The problem is that lu_object_print()
+ * composes object description from strings that are parts of _lines_ of
+ * output (i.e., strings that are not terminated by newline). This doesn't fit
+ * very well into libcfs_debug_msg() interface that assumes that each message
+ * supplied to it is a self-contained output line.
+ *
+ * To work around this, strings are collected in a temporary buffer
+ * (implemented as a value of lu_cdebug_key key), until terminating newline
+ * character is detected.
+ *
+ */
+
+enum {
+ /*
+ * Maximal line size.
+ *
+ * XXX overflow is not handled correctly.
+ */
+ LU_CDEBUG_LINE = 256
+};
+
+struct lu_cdebug_data {
+ /*
+ * Temporary buffer.
+ */
+ char lck_area[LU_CDEBUG_LINE];
+};
+
+static void *lu_cdebug_key_init(const struct lu_context *ctx,
+ struct lu_context_key *key)
+{
+ struct lu_cdebug_key *value;
+
+ OBD_ALLOC_PTR(value);
+ if (value == NULL)
+ value = ERR_PTR(-ENOMEM);
+ return value;
+}
+
+static void lu_cdebug_key_fini(const struct lu_context *ctx,
+ struct lu_context_key *key, void *data)
+{
+ struct lu_cdebug_key *value = data;
+ OBD_FREE_PTR(value);
+}
+
+/*
+ * Key, holding temporary buffer. This key is registered very early by
+ * lu_global_init().
+ */
+static struct lu_context_key lu_cdebug_key = {
+ .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD,
+ .lct_init = lu_cdebug_key_init,
+ .lct_fini = lu_cdebug_key_fini
+};
+
+/*
+ * Printer function emitting messages through libcfs_debug_msg().
+ */
+int lu_cdebug_printer(const struct lu_context *ctx,
+ void *cookie, const char *format, ...)
+{
+ struct lu_cdebug_print_info *info = cookie;
+ struct lu_cdebug_data *key;
+ int used;
+ int complete;
+ va_list args;
+
+ va_start(args, format);
+
+ key = lu_context_key_get(ctx, &lu_cdebug_key);
+ LASSERT(key != NULL);
+
+ used = strlen(key->lck_area);
+ complete = format[strlen(format) - 1] == '\n';
+ /*
+ * Append new chunk to the buffer.
+ */
+ vsnprintf(key->lck_area + used,
+ ARRAY_SIZE(key->lck_area) - used, format, args);
+ if (complete) {
+ libcfs_debug_msg(info->lpi_subsys, info->lpi_mask,
+ info->lpi_file, info->lpi_fn,
+ info->lpi_line, "%s", key->lck_area);
+ key->lck_area[0] = 0;
+ }
+ va_end(args);
+ return 0;
+}
+EXPORT_SYMBOL(lu_cdebug_printer);
+
+/*
+ * Print object header.
*/
-int lu_object_print(const struct lu_context *ctx,
- struct seq_file *f, const struct lu_object *o)
+static void lu_object_header_print(const struct lu_context *ctx,
+ void *cookie, lu_printer_t printer,
+ const struct lu_object_header *hdr)
{
- static char ruler[] = "........................................";
+ (*printer)(ctx, cookie, "header@%p[%#lx, %d, "DFID3"%s%s]",
+ hdr, hdr->loh_flags, hdr->loh_ref, PFID3(&hdr->loh_fid),
+ hlist_unhashed(&hdr->loh_hash) ? "" : " hash",
+ list_empty(&hdr->loh_lru) ? "" : " lru");
+}
+
+/*
+ * Print human readable representation of the @o to the @printer.
+ */
+void lu_object_print(const struct lu_context *ctx, void *cookie,
+ lu_printer_t printer, const struct lu_object *o)
+{
+ static const char ruler[] = "........................................";
struct lu_object_header *top;
- int nob;
int depth;
- nob = 0;
top = o->lo_header;
+ lu_object_header_print(ctx, cookie, printer, top);
+ (*printer)(ctx, cookie, "\n");
list_for_each_entry(o, &top->loh_layers, lo_linkage) {
- depth = o->lo_depth;
+ depth = o->lo_depth + 4;
LASSERT(o->lo_ops->loo_object_print != NULL);
/*
* print `.' @depth times.
*/
- nob += seq_printf(f, "%*.*s", depth, depth, ruler);
- nob += o->lo_ops->loo_object_print(ctx, f, o);
- nob += seq_printf(f, "\n");
+ (*printer)(ctx, cookie, "%*.*s", depth, depth, ruler);
+ o->lo_ops->loo_object_print(ctx, cookie, printer, o);
+ (*printer)(ctx, cookie, "\n");
}
- return nob;
}
EXPORT_SYMBOL(lu_object_print);
{
}
EXPORT_SYMBOL(lu_context_exit);
+
+/*
+ * Initialization of global lu_* data.
+ */
+int lu_global_init(void)
+{
+ static int initialized = 0;
+ int result;
+
+ if (!initialized) {
+ result = lu_context_key_register(&lu_cdebug_key);
+ initialized = 1;
+ } else {
+ CERROR("Double initialization\n");
+ result = 0;
+ }
+ return result;
+}
+EXPORT_SYMBOL(lu_global_init);
+
+/*
+ * Dual to lu_global_init().
+ */
+void lu_global_fini(void)
+{
+ lu_context_key_degister(&lu_cdebug_key);
+}
+EXPORT_SYMBOL(lu_global_fini);