[Ocfs2-commits] mfasheh commits r2142 - trunk/fs/ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Apr 13 18:32:50 CDT 2005
Author: mfasheh
Signed-off-by: khackel
Date: 2005-04-13 18:32:49 -0500 (Wed, 13 Apr 2005)
New Revision: 2142
Modified:
trunk/fs/ocfs2/dlmglue.c
trunk/fs/ocfs2/inode.c
trunk/fs/ocfs2/ocfs.h
Log:
* We had missed using the lockres flag set functions in a couple places.
* ocfs2_recover_from_dlm_error was forgetting to wake_up after clearing the
busy flag.
* Don't clear the OCFS2_LOCK_LOCAL flag in ocfs2_create_new_inode_locks,
have the ast do it instead.
* Genericize more of the drop_lock path, have ocfs2_drop_lock actually wait
on busy locks instead of stampeding forward regardless.
* Don't let drop_lock exit on a signal... it needs to wait until the lock
has been destroyed, otherwise we'll be referencing memory that doesn't
belong to us in the ast handler.
* Clear the inode initialized flag later in ocfs_clear_inode. This allows us
to assert on it in a few more paths, including the inode ast function.
Signed-off-by: khackel
Modified: trunk/fs/ocfs2/dlmglue.c
===================================================================
--- trunk/fs/ocfs2/dlmglue.c 2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/dlmglue.c 2005-04-13 23:32:49 UTC (rev 2142)
@@ -84,9 +84,11 @@
char **ret);
static void ocfs2_inode_ast_func(void *opaque);
-static void ocfs2_inode_bast_func(void *opaque, int level);
+static void ocfs2_inode_bast_func(void *opaque,
+ int level);
static void ocfs2_super_ast_func(void *opaque);
-static void ocfs2_super_bast_func(void *opaque, int level);
+static void ocfs2_super_bast_func(void *opaque,
+ int level);
/* so far, all locks have gotten along with the same unlock ast */
static void ocfs2_unlock_ast_func(void *opaque,
dlm_status status);
@@ -204,8 +206,6 @@
int new_level);
static int ocfs2_meta_lock_update(struct inode *inode,
struct buffer_head **bh);
-static int __ocfs2_drop_lock(ocfs_super *osb,
- ocfs2_lock_res *lockres);
static void ocfs2_drop_super_lock(ocfs_super *osb);
static inline int ocfs2_highest_compat_lock_level(int level);
static int __ocfs2_downconvert_lock(ocfs_super *osb,
@@ -316,7 +316,6 @@
enum ocfs2_lock_type type,
void *priv)
{
- LOG_ENTRY();
memset(res, 0, sizeof(ocfs2_lock_res));
spin_lock_init(&res->l_lock);
init_waitqueue_head(&res->l_event);
@@ -325,7 +324,6 @@
INIT_LIST_HEAD(&res->l_blocked_list);
INIT_LIST_HEAD(&res->l_flag_cb_list);
res->l_priv = priv;
- LOG_EXIT();
}
int ocfs2_inode_lock_res_init(ocfs2_lock_res *res,
@@ -601,6 +599,8 @@
OCFS_ASSERT(ocfs2_is_inode_lock(lockres));
+ OCFS_ASSERT(OCFS_I(inode)->ip_flags & OCFS_INODE_INITIALIZED);
+
spin_lock(&lockres->l_lock);
lksb = &(lockres->l_lksb);
@@ -621,6 +621,7 @@
ocfs2_inc_inode_seq(osb, inode);
ocfs2_generic_handle_attach_action(lockres);
+ lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
break;
case OCFS2_AST_CONVERT:
if (lockres->l_type == OCFS_TYPE_META)
@@ -655,7 +656,7 @@
assert_spin_locked(&lockres->l_lock);
- lockres->l_flags |= OCFS2_LOCK_BLOCKED;
+ lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);
if (level > lockres->l_blocking) {
/* only schedule a downconvert if we haven't already scheduled
@@ -682,6 +683,8 @@
LOG_ENTRY();
+ OCFS_ASSERT(ocfs2_is_inode_lock(lockres));
+
inode = ocfs2_lock_res_inode(lockres);
osb = OCFS2_SB(inode->i_sb);
@@ -782,12 +785,15 @@
else
lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
spin_unlock(&lockres->l_lock);
+
+ wake_up(&lockres->l_event);
LOG_EXIT();
}
/* Note: If we detect another process working on the lock (i.e.,
* OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller
- * to do the right thing in that case. */
+ * to do the right thing in that case.
+ */
static int ocfs2_lock_create(ocfs_super *osb,
ocfs2_lock_res *lockres,
int level,
@@ -838,39 +844,33 @@
int flag)
{
int ret;
- LOG_ENTRY();
+
spin_lock(&lockres->l_lock);
ret = lockres->l_flags & flag;
spin_unlock(&lockres->l_lock);
- LOG_EXIT_STATUS(ret);
+
return ret;
}
static inline void ocfs2_wait_on_busy_lock(ocfs2_lock_res *lockres)
{
- LOG_ENTRY();
wait_event(lockres->l_event,
!ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY));
- LOG_EXIT();
}
static inline void ocfs2_wait_on_blocked_lock(ocfs2_lock_res *lockres)
{
- LOG_ENTRY();
wait_event(lockres->l_event,
!ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BLOCKED));
- LOG_EXIT();
}
static inline void ocfs2_wait_on_refreshing_lock(ocfs2_lock_res *lockres)
{
- LOG_ENTRY();
wait_event(lockres->l_event,
!ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING));
- LOG_EXIT();
}
static void lockres_add_flag_callback(ocfs2_lock_res *lockres,
@@ -967,6 +967,7 @@
if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) {
/* lock has not been created yet. */
spin_unlock(&lockres->l_lock);
+
ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0);
if (ret < 0) {
LOG_ERROR_STATUS(ret);
@@ -987,7 +988,7 @@
if (level > lockres->l_level) {
lockres->l_action = OCFS2_AST_CONVERT;
lockres->l_requested = level;
- lockres->l_flags |= OCFS2_LOCK_BUSY;
+ lockres_or_flags(lockres, OCFS2_LOCK_BUSY);
spin_unlock(&lockres->l_lock);
OCFS_ASSERT(level != LKM_IVMODE);
@@ -1091,7 +1092,6 @@
lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
status = ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL);
- lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -1102,7 +1102,6 @@
lockres_or_flags(lockres, OCFS2_LOCK_LOCAL);
status = ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL);
- lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto bail;
@@ -1687,7 +1686,8 @@
LOG_EXIT();
}
-/* BEWARE: called with lockres lock, and always drops it. */
+/* BEWARE: called with lockres lock, and always drops it. Caller
+ * should not be calling us with a busy lock... */
static int __ocfs2_drop_lock(ocfs_super *osb,
ocfs2_lock_res *lockres)
{
@@ -1729,63 +1729,99 @@
ret = -ENOENT;
goto bail;
}
-
dprintk("lock %s, successfull return from dlmunlock\n",
lockres->l_name);
ocfs2_wait_on_busy_lock(lockres);
- if (signal_pending(current)) {
- LOG_TRACE_STR("Signal caught!\n");
- ret = -EINTR;
- }
bail:
LOG_EXIT_STATUS(ret);
return ret;
}
+typedef void (ocfs2_pre_drop_cb_t)(ocfs2_lock_res *, void *);
+
+struct drop_lock_cb {
+ ocfs2_pre_drop_cb_t *drop_func;
+ void *drop_data;
+};
+
+static int ocfs2_drop_lock(ocfs_super *osb,
+ ocfs2_lock_res *lockres,
+ struct drop_lock_cb *dcb)
+{
+ spin_lock(&lockres->l_lock);
+
+ while (lockres->l_flags & OCFS2_LOCK_BUSY) {
+ dprintk("waiting on busy lock \"%s\": flags = %lx, action = "
+ "%u, unlock_action = %u\n",
+ lockres->l_name, lockres->l_flags, lockres->l_action,
+ lockres->l_unlock_action);
+
+ spin_unlock(&lockres->l_lock);
+
+ /* XXX: Today we just wait on any busy
+ * locks... Perhaps we need to cancel converts in the
+ * future? */
+ ocfs2_wait_on_busy_lock(lockres);
+
+ spin_lock(&lockres->l_lock);
+ }
+
+ if (dcb)
+ dcb->drop_func(lockres, dcb->drop_data);
+
+ /* This will drop the spinlock for us. Dur de dur, at least we
+ * keep the ugliness in one place :) */
+ return __ocfs2_drop_lock(osb, lockres);
+}
+
static void ocfs2_drop_super_lock(ocfs_super *osb)
{
int status;
- ocfs2_lock_res *lockres;
LOG_ENTRY();
- lockres = &osb->super_lockres;
- spin_lock(&lockres->l_lock);
- status = __ocfs2_drop_lock(osb, lockres);
+ status = ocfs2_drop_lock(osb, &osb->super_lockres, NULL);
if (status < 0)
LOG_ERROR_STATUS(status);
+
LOG_EXIT_STATUS(status);
}
-int ocfs2_drop_inode_locks(struct inode *inode)
+static void ocfs2_meta_pre_drop(ocfs2_lock_res *lockres, void *data)
{
- int status, err;
- ocfs2_lock_res *lockres;
+ struct inode *inode = data;
- LOG_ENTRY();
- lockres = &OCFS_I(inode)->ip_data_lockres;
- spin_lock(&lockres->l_lock);
- err = __ocfs2_drop_lock(OCFS2_SB(inode->i_sb), lockres);
- if (err < 0)
- LOG_ERROR_STATUS(err);
-
- status = err;
-
/* the metadata lock requires a bit more work as we have an
* LVB to worry about. */
- lockres = &OCFS_I(inode)->ip_meta_lockres;
-
- spin_lock(&lockres->l_lock);
if (lockres->l_flags & OCFS2_LOCK_ATTACHED) {
if (lockres->l_level == LKM_EXMODE)
__ocfs2_stuff_meta_lvb(inode);
/* fake an NLMODE downconvert for the lvb code. */
__ocfs2_lvb_on_downconvert(lockres, LKM_NLMODE);
}
- err = __ocfs2_drop_lock(OCFS2_SB(inode->i_sb), lockres);
+}
+
+int ocfs2_drop_inode_locks(struct inode *inode)
+{
+ int status, err;
+ struct drop_lock_cb meta_dcb = { ocfs2_meta_pre_drop, inode, };
+
+ LOG_ENTRY();
+
+ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+ &OCFS_I(inode)->ip_data_lockres,
+ NULL);
if (err < 0)
LOG_ERROR_STATUS(err);
+
+ status = err;
+
+ err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb),
+ &OCFS_I(inode)->ip_meta_lockres,
+ &meta_dcb);
+ if (err < 0)
+ LOG_ERROR_STATUS(err);
if (err < 0 && !status)
status = err;
@@ -1836,6 +1872,7 @@
ocfs2_recover_from_dlm_error(lockres, 1);
goto bail;
}
+
status = 0;
bail:
LOG_EXIT_STATUS(status);
Modified: trunk/fs/ocfs2/inode.c
===================================================================
--- trunk/fs/ocfs2/inode.c 2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/inode.c 2005-04-13 23:32:49 UTC (rev 2142)
@@ -834,8 +834,6 @@
if (!INODE_DELETED(inode))
ocfs2_checkpoint_inode(inode);
- OCFS_I(inode)->ip_flags &= ~OCFS_INODE_INITIALIZED;
-
if (OCFS_I(inode)->ip_blkno == -1)
BUG();
@@ -856,6 +854,9 @@
ocfs2_lock_res_free(&OCFS_I(inode)->ip_meta_lockres);
ocfs2_lock_res_free(&OCFS_I(inode)->ip_data_lockres);
+
+ OCFS_I(inode)->ip_flags &= ~OCFS_INODE_INITIALIZED;
+
/* clean out the inode private ... why?! */
memset(inode->u.generic_ip, 0, sizeof(ocfs_inode_private));
@@ -868,7 +869,6 @@
LOG_EXIT ();
LOG_CLEAR_CONTEXT();
- return;
} /* ocfs_clear_inode */
/*
Modified: trunk/fs/ocfs2/ocfs.h
===================================================================
--- trunk/fs/ocfs2/ocfs.h 2005-04-13 21:04:19 UTC (rev 2141)
+++ trunk/fs/ocfs2/ocfs.h 2005-04-13 23:32:49 UTC (rev 2142)
@@ -174,8 +174,7 @@
int l_requested;
int l_blocking;
- wait_queue_head_t l_event;
-
+ wait_queue_head_t l_event;
} ocfs2_lock_res;
/* OCFS2 Inode Private Data */
More information about the Ocfs2-commits
mailing list