-/* -*- 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.
* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2012, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#error Do not #include this file directly. #include <obd.h> instead
#endif
+#include <obd_support.h>
+
#ifdef __KERNEL__
# include <linux/fs.h>
# include <linux/list.h>
# include <linux/sched.h> /* for struct task_struct, for current.h */
-# include <asm/current.h> /* for smp_lock.h */
-# include <linux/smp_lock.h>
# include <linux/proc_fs.h>
# include <linux/mount.h>
-# ifndef HAVE_VFS_INTENT_PATCHES
-# include <linux/lustre_intent.h>
-# endif
+# include <linux/lustre_intent.h>
#endif
-typedef spinlock_t client_obd_lock_t;
+struct ll_iattr {
+ struct iattr iattr;
+ unsigned int ia_attr_flags;
+};
-static inline void client_obd_list_lock_init(client_obd_lock_t *lock)
+#ifdef __KERNEL__
+#define CLIENT_OBD_LIST_LOCK_DEBUG 1
+#endif
+
+typedef struct {
+ spinlock_t lock;
+
+#ifdef CLIENT_OBD_LIST_LOCK_DEBUG
+ unsigned long time;
+ struct task_struct *task;
+ const char *func;
+ int line;
+#endif
+} client_obd_lock_t;
+
+#ifdef CLIENT_OBD_LIST_LOCK_DEBUG
+static inline void __client_obd_list_lock(client_obd_lock_t *lock,
+ const char *func, int line)
{
- spin_lock_init(lock);
+ unsigned long cur = jiffies;
+ while (1) {
+ if (spin_trylock(&lock->lock)) {
+ LASSERT(lock->task == NULL);
+ lock->task = current;
+ lock->func = func;
+ lock->line = line;
+ lock->time = jiffies;
+ break;
+ }
+
+ if ((jiffies - cur > 5 * CFS_HZ) &&
+ (jiffies - lock->time > 5 * CFS_HZ)) {
+ struct task_struct *task = lock->task;
+
+ if (task == NULL)
+ continue;
+
+ LCONSOLE_WARN("%s:%d: lock %p was acquired"
+ " by <%s:%d:%s:%d> for %lu seconds.\n",
+ current->comm, current->pid,
+ lock, task->comm, task->pid,
+ lock->func, lock->line,
+ (jiffies - lock->time) / CFS_HZ);
+ LCONSOLE_WARN("====== for process holding the "
+ "lock =====\n");
+ libcfs_debug_dumpstack(task);
+ LCONSOLE_WARN("====== for current process =====\n");
+ libcfs_debug_dumpstack(NULL);
+ LCONSOLE_WARN("====== end =======\n");
+ cfs_pause(1000 * CFS_HZ);
+ }
+ cpu_relax();
+ }
}
-static inline void client_obd_list_lock_done(client_obd_lock_t *lock)
-{}
+#define client_obd_list_lock(lock) \
+ __client_obd_list_lock(lock, __FUNCTION__, __LINE__)
+static inline void client_obd_list_unlock(client_obd_lock_t *lock)
+{
+ LASSERT(lock->task != NULL);
+ lock->task = NULL;
+ lock->time = jiffies;
+ spin_unlock(&lock->lock);
+}
+
+#else /* ifdef CLIENT_OBD_LIST_LOCK_DEBUG */
static inline void client_obd_list_lock(client_obd_lock_t *lock)
{
- spin_lock(lock);
+ spin_lock(&lock->lock);
}
static inline void client_obd_list_unlock(client_obd_lock_t *lock)
{
- spin_unlock(lock);
+ spin_unlock(&lock->lock);
+}
+
+#endif /* ifdef CLIENT_OBD_LIST_LOCK_DEBUG */
+
+static inline void client_obd_list_lock_init(client_obd_lock_t *lock)
+{
+ spin_lock_init(&lock->lock);
}
+static inline void client_obd_list_lock_done(client_obd_lock_t *lock)
+{}
+
#if defined(__KERNEL__) && !defined(HAVE_ADLER)
/* zlib_adler() is an inline function defined in zutil.h */
#define HAVE_ADLER