[Ocfs2-commits] mfasheh commits r1618 - branches/dlm-glue/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Nov 2 19:47:39 CST 2004
Author: mfasheh
Date: 2004-11-02 19:47:37 -0600 (Tue, 02 Nov 2004)
New Revision: 1618
Modified:
branches/dlm-glue/src/dlmglue.c
branches/dlm-glue/src/ocfs.h
Log:
* teach the dlmglue layer how to cancel an upconvert request
Modified: branches/dlm-glue/src/dlmglue.c
===================================================================
--- branches/dlm-glue/src/dlmglue.c 2004-11-02 20:22:12 UTC (rev 1617)
+++ branches/dlm-glue/src/dlmglue.c 2004-11-03 01:47:37 UTC (rev 1618)
@@ -132,7 +132,8 @@
struct inode *inode);
static void ocfs2_schedule_blocked_inode(struct inode *inode);
static inline void ocfs2_recover_from_dlm_error(ocfs2_lock_res *lockres,
- ocfs2_lock *lock);
+ ocfs2_lock *lock,
+ int convert);
static void ocfs2_vote_on_unlock(ocfs_super *osb,
ocfs2_lock *lock);
/* Called after we refresh our inode, only has any effect if we have
@@ -153,10 +154,14 @@
ocfs2_lock_res *lockres,
ocfs2_lock *lock);
static inline int ocfs2_highest_compat_lock_level(int level);
-static int __ocfs2_downconvert_lock(ocfs2_lock_res *lockres,
+static int __ocfs2_downconvert_lock(ocfs_super *osb,
+ ocfs2_lock_res *lockres,
ocfs2_lock *lock,
int new_level,
int lvb);
+static int __ocfs2_cancel_convert(ocfs_super *osb,
+ ocfs2_lock_res *lockres,
+ ocfs2_lock *lock);
static void ocfs2_process_blocked_inode(struct inode *inode);
static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
ocfs2_lock *lock,
@@ -493,11 +498,15 @@
}
static inline void ocfs2_recover_from_dlm_error(ocfs2_lock_res *lockres,
- ocfs2_lock *lock)
+ ocfs2_lock *lock,
+ int convert)
{
spin_lock(&lockres->lr_lock);
lock->l_flags &= ~OCFS2_LOCK_BUSY;
- lock->l_action = OCFS2_AST_INVALID;
+ if (convert)
+ lock->l_action = OCFS2_AST_INVALID;
+ else
+ lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
spin_unlock(&lockres->lr_lock);
}
@@ -536,7 +545,7 @@
if (status != DLM_NORMAL) {
LOG_ERROR_ARGS("Dlm returns %d\n", status);
ret = -ENOENT;
- ocfs2_recover_from_dlm_error(lockres, lock);
+ ocfs2_recover_from_dlm_error(lockres, lock, 1);
}
bail:
@@ -660,7 +669,7 @@
if (status != DLM_NORMAL) {
LOG_ERROR_ARGS("Dlm returns %d\n", status);
ret = -ENOENT;
- ocfs2_recover_from_dlm_error(lockres, lock);
+ ocfs2_recover_from_dlm_error(lockres, lock, 1);
goto bail;
}
@@ -1131,7 +1140,17 @@
LOG_ERROR_ARGS("Dlm returns status %d\n", status);
spin_lock(&lockres->lr_lock);
- lock->l_level = LKM_IVMODE;
+ switch(lock->l_unlock_action) {
+ case OCFS2_UNLOCK_CANCEL_CONVERT:
+ lock->l_action = OCFS2_AST_INVALID;
+ break;
+ case OCFS2_UNLOCK_DROP_LOCK:
+ lock->l_level = LKM_IVMODE;
+ break;
+ default:
+ BUG();
+ }
+ lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
lock->l_flags &= ~OCFS2_LOCK_BUSY;
spin_unlock(&lockres->lr_lock);
@@ -1158,8 +1177,13 @@
lock->l_flags &= ~OCFS2_LOCK_ATTACHED;
+ /* make sure we never get here while waiting for an ast to
+ * fire. */
+ OCFS_ASSERT(lock->l_action == OCFS2_AST_INVALID);
+
/* is this necessary? */
lock->l_flags |= OCFS2_LOCK_BUSY;
+ lock->l_unlock_action = OCFS2_UNLOCK_DROP_LOCK;
spin_unlock(&lockres->lr_lock);
status = dlmunlock(osb->dlm,
@@ -1232,13 +1256,13 @@
}
/* called with the spinlock held, and WILL drop it. */
-static int __ocfs2_downconvert_lock(ocfs2_lock_res *lockres,
+static int __ocfs2_downconvert_lock(ocfs_super *osb,
+ ocfs2_lock_res *lockres,
ocfs2_lock *lock,
int new_level,
int lvb)
{
int status, flags = LKM_CONVERT;
- struct inode *inode = lockres->lr_inode;
enum ocfs2_lock_type type = lock->l_type;
OCFS_ASSERT(lock->l_blocking > LKM_NLMODE);
OCFS_ASSERT(lock->l_level > new_level);
@@ -1251,7 +1275,7 @@
if (lvb)
flags |= LKM_VALBLK;
- status = dlmlock(OCFS2_SB(inode->i_sb)->dlm,
+ status = dlmlock(osb->dlm,
new_level,
&lock->l_lksb,
flags,
@@ -1262,7 +1286,7 @@
if (status != DLM_NORMAL) {
LOG_ERROR_ARGS("Dlm returns %d\n", status);
status = -ENOENT;
- ocfs2_recover_from_dlm_error(lockres, lock);
+ ocfs2_recover_from_dlm_error(lockres, lock, 1);
goto bail;
}
status = 0;
@@ -1270,6 +1294,45 @@
return status;
}
+/* called with the spinlock held, and WILL drop it. */
+static int __ocfs2_cancel_convert(ocfs_super *osb,
+ ocfs2_lock_res *lockres,
+ ocfs2_lock *lock)
+{
+ int status;
+
+ /* were we in a convert when we got the bast fire? */
+ OCFS_ASSERT(lock->l_action == OCFS2_AST_CONVERT ||
+ lock->l_action == OCFS2_AST_DOWNCONVERT);
+ /* set things up for the unlockast to know to just
+ * clear out the ast_action and unset busy, etc. */
+ lock->l_unlock_action = OCFS2_UNLOCK_CANCEL_CONVERT;
+ spin_unlock(&lockres->lr_lock);
+
+ status = dlmunlock(osb->dlm,
+ &lock->l_lksb,
+ LKM_CANCEL,
+ ocfs2_unlock_ast_func,
+ lock);
+ if (status == DLM_NORMAL)
+ status = 0;
+
+ if (status == DLM_CANCELGRANT) {
+ /* If we got this, then the ast was fired
+ * before we could cancel. We cleanup our
+ * state, and restart the function. */
+ spin_lock(&lockres->lr_lock);
+ lock->l_unlock_action = OCFS2_UNLOCK_INVALID;
+ spin_unlock(&lockres->lr_lock);
+ } else {
+ LOG_ERROR_ARGS("Dlm returns %d\n", status);
+ status = -ENOENT;
+ ocfs2_recover_from_dlm_error(lockres, lock, 0);
+ }
+
+ return status;
+}
+
static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode,
ocfs2_lock *lock,
int new_level)
@@ -1290,10 +1353,10 @@
static int ocfs2_process_blocked_meta(struct inode *inode,
int *requeue)
{
+ int new_level;
+ int set_lvb = 0;
ocfs2_lock_res *lockres = &OCFS_I(inode)->ip_lockres;
ocfs2_lock *lock = &lockres->lr_meta;
- int new_level;
- int set_lvb = 0;
spin_lock(&lockres->lr_lock);
if (!(lock->l_flags & OCFS2_LOCK_BLOCKED)) {
@@ -1301,10 +1364,23 @@
return 0;
}
- OCFS_ASSERT(!(lock->l_flags & OCFS2_LOCK_BUSY));
OCFS_ASSERT(lock->l_level == LKM_EXMODE ||
lock->l_level == LKM_PRMODE);
+ if (lock->l_flags & OCFS2_LOCK_BUSY) {
+ *requeue++;
+ if (lock->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+ /* If we're already trying to cancel a lock conversion
+ * then just drop the spinlock and requeue ourselves
+ * to check again later. */
+ spin_unlock(&lockres->lr_lock);
+ return 0;
+ }
+
+ return __ocfs2_cancel_convert(OCFS2_SB(inode->i_sb),
+ lockres, lock);
+ }
+
new_level = ocfs2_highest_compat_lock_level(lock->l_blocking);
if (ocfs2_can_downconvert_meta_lock(inode, lock, new_level)) {
if (lock->l_level == LKM_EXMODE) {
@@ -1312,7 +1388,8 @@
set_lvb = 1;
}
__ocfs2_lvb_on_downconvert(lock, new_level);
- return __ocfs2_downconvert_lock(lockres, lock, new_level,
+ return __ocfs2_downconvert_lock(OCFS2_SB(inode->i_sb),
+ lockres, lock, new_level,
set_lvb);
}
if (!ocfs_inode_fully_checkpointed(inode))
@@ -1341,6 +1418,20 @@
OCFS_ASSERT(!(lock->l_flags & OCFS2_LOCK_BUSY));
recheck:
+ if (lock->l_flags & OCFS2_LOCK_BUSY) {
+ *requeue++;
+ if (lock->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {
+ /* If we're already trying to cancel a lock conversion
+ * then just drop the spinlock and requeue ourselves
+ * to check again later. */
+ spin_unlock(&lockres->lr_lock);
+ return 0;
+ }
+
+ return __ocfs2_cancel_convert(OCFS2_SB(inode->i_sb),
+ lockres, lock);
+ }
+
/* if we're blocking an exclusive and we have *anyone* in I/O,
* then requeue. */
if ((lock->l_blocking == LKM_EXMODE)
@@ -1349,6 +1440,7 @@
*requeue++;
return 0;
}
+
/* If it's a PR we're blocking, then only
* requeue if we've got anyone doing write (ex) I/O */
if (lock->l_blocking == LKM_PRMODE &&
@@ -1380,7 +1472,8 @@
}
new_level = ocfs2_highest_compat_lock_level(lock->l_blocking);
- return __ocfs2_downconvert_lock(lockres, lock, new_level, 0);
+ return __ocfs2_downconvert_lock(OCFS2_SB(inode->i_sb), lockres, lock,
+ new_level, 0);
}
static void ocfs2_process_blocked_inode(struct inode *inode)
Modified: branches/dlm-glue/src/ocfs.h
===================================================================
--- branches/dlm-glue/src/ocfs.h 2004-11-02 20:22:12 UTC (rev 1617)
+++ branches/dlm-glue/src/ocfs.h 2004-11-03 01:47:37 UTC (rev 1618)
@@ -194,6 +194,13 @@
OCFS2_AST_DOWNCONVERT,
};
+/* actions for an unlockast function to take. */
+enum ocfs2_unlock_action {
+ OCFS2_UNLOCK_INVALID = 0,
+ OCFS2_UNLOCK_CANCEL_CONVERT,
+ OCFS2_UNLOCK_DROP_LOCK,
+};
+
struct _ocfs2_lock_res;
enum ocfs2_lock_type {
@@ -216,6 +223,7 @@
/* used from AST/BAST funcs. */
enum ocfs2_ast_action l_action;
+ enum ocfs2_unlock_action l_unlock_action;
int l_requested;
int l_blocking;
} ocfs2_lock;
More information about the Ocfs2-commits
mailing list