return 0;
}
+/**
+ * Dump Lustre log to ::debug_file_path by calling tracefile_dump_all_pages()
+ */
void libcfs_debug_dumplog_internal(void *arg)
{
CFS_DECL_JOURNAL_DATA;
printk(KERN_ALERT "LustreError: dumping log to %s\n",
debug_file_name);
tracefile_dump_all_pages(debug_file_name);
+ libcfs_run_debug_log_upcall(debug_file_name);
}
CFS_POP_JOURNAL;
}
#endif
char lnet_upcall[1024] = "/usr/lib/lustre/lnet_upcall";
+char lnet_debug_log_upcall[1024] = "/usr/lib/lustre/lnet_debug_log_upcall";
+
+/**
+ * Upcall function once a Lustre log has been dumped.
+ *
+ * \param file path of the dumped log
+ */
+void libcfs_run_debug_log_upcall(char *file)
+{
+ char *argv[3];
+ int rc;
+ char *envp[] = {
+ "HOME=/",
+ "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
+ NULL};
+ ENTRY;
+
+ argv[0] = lnet_debug_log_upcall;
+
+ LASSERTF(file != NULL, "called on a null filename\n");
+ argv[1] = file; //only need to pass the path of the file
+
+ argv[2] = NULL;
+
+ rc = USERMODEHELPER(argv[0], argv, envp);
+ if (rc < 0 && rc != -ENOENT) {
+ CERROR("Error %d invoking LNET debug log upcall %s %s; "
+ "check /proc/sys/lnet/debug_log_upcall\n",
+ rc, argv[0], argv[1]);
+ } else {
+ CDEBUG(D_HA, "Invoked LNET debug log upcall %s %s\n",
+ argv[0], argv[1]);
+ }
+
+ EXIT;
+}
void libcfs_run_upcall(char **argv)
{
static cfs_sysctl_table_header_t *lnet_table_header = NULL;
extern char lnet_upcall[1024];
+/**
+ * The path of debug log dump upcall script.
+ */
+extern char lnet_debug_log_upcall[1024];
#define PSDEV_LNET (0x100)
enum {
PSDEV_LNET_DUMP_KERNEL, /* snapshot kernel debug buffer to file */
PSDEV_LNET_DAEMON_FILE, /* spool kernel debug buffer to file */
PSDEV_LNET_DEBUG_MB, /* size of debug buffer */
+ PSDEV_LNET_DEBUG_LOG_UPCALL, /* debug log upcall script */
};
-static int
-proc_call_handler(void *data, int write,
- loff_t *ppos, void *buffer, size_t *lenp,
+static int
+proc_call_handler(void *data, int write,
+ loff_t *ppos, void *buffer, size_t *lenp,
int (*handler)(void *data, int write,
loff_t pos, void *buffer, int len))
{
__##name); \
}
-static int __proc_dobitmasks(void *data, int write,
+static int __proc_dobitmasks(void *data, int write,
loff_t pos, void *buffer, int nob)
{
const int tmpstrlen = 512;
{
if (!write)
return 0;
-
+
return trace_dump_debug_buffer_usrstr(buffer, nob);
}
{
if (!write) {
int len = strlen(tracefile);
-
+
if (pos >= len)
return 0;
-
- return trace_copyout_string(buffer, nob,
+
+ return trace_copyout_string(buffer, nob,
tracefile + pos, "\n");
}
-
+
return trace_daemon_command_usrstr(buffer, nob);
}
if (pos >= len)
return 0;
-
+
return trace_copyout_string(buffer, nob, tmpstr + pos, "\n");
}
-
+
return trace_set_debug_mb_usrstr(buffer, nob);
}
.proc_handler = &proc_dostring,
},
{
+ .ctl_name = PSDEV_LNET_DEBUG_LOG_UPCALL,
+ .procname = "debug_log_upcall",
+ .data = lnet_debug_log_upcall,
+ .maxlen = sizeof(lnet_debug_log_upcall),
+ .mode = 0644,
+ .proc_handler = &proc_dostring,
+ },
+ {
.ctl_name = PSDEV_LNET_MEMUSED,
.procname = "memused",
.data = (int *)&libcfs_kmemory.counter,
extern char tracefile[TRACEFILE_NAME_SIZE];
extern long long tracefile_size;
+extern void libcfs_run_debug_log_upcall(char *file);
+
int tracefile_init_arch(void);
void tracefile_fini_arch(void);
#define TRACEFILE_SIZE (500 << 20)
-/* Size of a buffer for sprinting console messages if we can't get a page
+/* Size of a buffer for sprinting console messages if we can't get a page
* from system */
#define TRACE_CONSOLE_BUFFER_SIZE 1024
/*
* Maximal number of pages allowed on ->tcd_pages and
- * ->tcd_daemon_pages each.
+ * ->tcd_daemon_pages each.
* Always TCD_MAX_PAGES * tcd_pages_factor / 100 in current
* implementation.
*/
*/
unsigned short cpu;
/*
- * type(context) of this page
+ * type(context) of this page
*/
unsigned short type;
};
* RHEL 4 and RHEL 5/SLES 10 clients behaves differently on 'cd' to a
removed cwd "./" (refer to Bugzilla 14399).
+Severity : enhancement
+Bugzilla : 16566
+Description: Upcall on Lustre log has been dumped
+Details : Allow for a user mode script to be called once a Lustre log has
+ been dumped. It passes the filename of the dumped log to the
+ script, the location of the script can be specified via
+ /proc/sys/lnet/debug_log_upcall.
+
Severity : minor
Bugzilla : 16583
Frequency : rare
-Description: avoid messages about idr_remove called for id which is not allocated.
-Details : Move assigment s_dev for clustered nfs to end of initialization, for avoid
- problem with error handling.
+Description: avoid messages about idr_remove called for id which is not allocated.
+Details : Move assigment s_dev for clustered nfs to end of initialization, for
+ avoid problem with error handling.
Severity : minor
Bugzilla : 16109
#define OBD_FAIL_PTLRPC_PAUSE_REQ 0x50a
#define OBD_FAIL_PTLRPC_PAUSE_REP 0x50c
+#define OBD_FAIL_PTLRPC_DUMP_LOG 0x50e
+
#define OBD_FAIL_OBD_PING_NET 0x600
#define OBD_FAIL_OBD_LOG_CANCEL_NET 0x601
#define OBD_FAIL_OBD_LOGD_NET 0x602
/* Set timer for closest deadline */
rq = list_entry(svc->srv_at_list.next, struct ptlrpc_request,
rq_timed_list);
- next = (__s32)(rq->rq_deadline - cfs_time_current_sec() -
+ next = (__s32)(rq->rq_deadline - cfs_time_current_sec() -
at_early_margin);
if (next <= 0)
ptlrpc_at_timer((unsigned long)svc);
spin_unlock(&svc->srv_lock);
+ if(OBD_FAIL_CHECK(OBD_FAIL_PTLRPC_DUMP_LOG))
+ libcfs_debug_dumplog();
+
do_gettimeofday(&work_start);
timediff = cfs_timeval_sub(&work_start, &request->rq_arrival_time,NULL);
if (likely(svc->srv_stats != NULL)) {
if (rc == -EMFILE)
break;
if (rc) {
- CERROR("cannot start %s thread #%d: rc %d\n",
+ CERROR("cannot start %s thread #%d: rc %d\n",
svc->srv_thread_name, i, rc);
ptlrpc_stop_all_threads(svc);
}
d.thread = thread;
CDEBUG(D_RPCTRACE, "starting thread '%s'\n", name);
-
+
/* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
* just drop the VM and FILES in ptlrpc_daemonize() right away.
*/