aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/dlm/dlmrecovery.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2/dlm/dlmrecovery.c')
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 91f747b8a538..bcb9260c3735 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -519,9 +519,9 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
519 return 0; 519 return 0;
520 520
521master_here: 521master_here:
522 mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n", 522 mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node "
523 task_pid_nr(dlm->dlm_reco_thread_task), 523 "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task),
524 dlm->name, dlm->reco.dead_node, dlm->node_num); 524 dlm->node_num, dlm->reco.dead_node, dlm->name);
525 525
526 status = dlm_remaster_locks(dlm, dlm->reco.dead_node); 526 status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
527 if (status < 0) { 527 if (status < 0) {
@@ -1191,7 +1191,7 @@ static int dlm_add_lock_to_array(struct dlm_lock *lock,
1191 (ml->type == LKM_EXMODE || 1191 (ml->type == LKM_EXMODE ||
1192 memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) { 1192 memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
1193 mlog(ML_ERROR, "mismatched lvbs!\n"); 1193 mlog(ML_ERROR, "mismatched lvbs!\n");
1194 __dlm_print_one_lock_resource(lock->lockres); 1194 dlm_print_one_lock_resource(lock->lockres);
1195 BUG(); 1195 BUG();
1196 } 1196 }
1197 memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN); 1197 memcpy(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN);
@@ -1327,6 +1327,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
1327 (struct dlm_migratable_lockres *)msg->buf; 1327 (struct dlm_migratable_lockres *)msg->buf;
1328 int ret = 0; 1328 int ret = 0;
1329 u8 real_master; 1329 u8 real_master;
1330 u8 extra_refs = 0;
1330 char *buf = NULL; 1331 char *buf = NULL;
1331 struct dlm_work_item *item = NULL; 1332 struct dlm_work_item *item = NULL;
1332 struct dlm_lock_resource *res = NULL; 1333 struct dlm_lock_resource *res = NULL;
@@ -1404,16 +1405,28 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
1404 __dlm_insert_lockres(dlm, res); 1405 __dlm_insert_lockres(dlm, res);
1405 spin_unlock(&dlm->spinlock); 1406 spin_unlock(&dlm->spinlock);
1406 1407
1408 /* Add an extra ref for this lock-less lockres lest the
1409 * dlm_thread purges it before we get the chance to add
1410 * locks to it */
1411 dlm_lockres_get(res);
1412
1413 /* There are three refs that need to be put.
1414 * 1. Taken above.
1415 * 2. kref_init in dlm_new_lockres()->dlm_init_lockres().
1416 * 3. dlm_lookup_lockres()
1417 * The first one is handled at the end of this function. The
1418 * other two are handled in the worker thread after locks have
1419 * been attached. Yes, we don't wait for purge time to match
1420 * kref_init. The lockres will still have atleast one ref
1421 * added because it is in the hash __dlm_insert_lockres() */
1422 extra_refs++;
1423
1407 /* now that the new lockres is inserted, 1424 /* now that the new lockres is inserted,
1408 * make it usable by other processes */ 1425 * make it usable by other processes */
1409 spin_lock(&res->spinlock); 1426 spin_lock(&res->spinlock);
1410 res->state &= ~DLM_LOCK_RES_IN_PROGRESS; 1427 res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
1411 spin_unlock(&res->spinlock); 1428 spin_unlock(&res->spinlock);
1412 wake_up(&res->wq); 1429 wake_up(&res->wq);
1413
1414 /* add an extra ref for just-allocated lockres
1415 * otherwise the lockres will be purged immediately */
1416 dlm_lockres_get(res);
1417 } 1430 }
1418 1431
1419 /* at this point we have allocated everything we need, 1432 /* at this point we have allocated everything we need,
@@ -1443,12 +1456,17 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
1443 dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf); 1456 dlm_init_work_item(dlm, item, dlm_mig_lockres_worker, buf);
1444 item->u.ml.lockres = res; /* already have a ref */ 1457 item->u.ml.lockres = res; /* already have a ref */
1445 item->u.ml.real_master = real_master; 1458 item->u.ml.real_master = real_master;
1459 item->u.ml.extra_ref = extra_refs;
1446 spin_lock(&dlm->work_lock); 1460 spin_lock(&dlm->work_lock);
1447 list_add_tail(&item->list, &dlm->work_list); 1461 list_add_tail(&item->list, &dlm->work_list);
1448 spin_unlock(&dlm->work_lock); 1462 spin_unlock(&dlm->work_lock);
1449 queue_work(dlm->dlm_worker, &dlm->dispatched_work); 1463 queue_work(dlm->dlm_worker, &dlm->dispatched_work);
1450 1464
1451leave: 1465leave:
1466 /* One extra ref taken needs to be put here */
1467 if (extra_refs)
1468 dlm_lockres_put(res);
1469
1452 dlm_put(dlm); 1470 dlm_put(dlm);
1453 if (ret < 0) { 1471 if (ret < 0) {
1454 if (buf) 1472 if (buf)
@@ -1464,17 +1482,19 @@ leave:
1464 1482
1465static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data) 1483static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data)
1466{ 1484{
1467 struct dlm_ctxt *dlm = data; 1485 struct dlm_ctxt *dlm;
1468 struct dlm_migratable_lockres *mres; 1486 struct dlm_migratable_lockres *mres;
1469 int ret = 0; 1487 int ret = 0;
1470 struct dlm_lock_resource *res; 1488 struct dlm_lock_resource *res;
1471 u8 real_master; 1489 u8 real_master;
1490 u8 extra_ref;
1472 1491
1473 dlm = item->dlm; 1492 dlm = item->dlm;
1474 mres = (struct dlm_migratable_lockres *)data; 1493 mres = (struct dlm_migratable_lockres *)data;
1475 1494
1476 res = item->u.ml.lockres; 1495 res = item->u.ml.lockres;
1477 real_master = item->u.ml.real_master; 1496 real_master = item->u.ml.real_master;
1497 extra_ref = item->u.ml.extra_ref;
1478 1498
1479 if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) { 1499 if (real_master == DLM_LOCK_RES_OWNER_UNKNOWN) {
1480 /* this case is super-rare. only occurs if 1500 /* this case is super-rare. only occurs if
@@ -1517,6 +1537,12 @@ again:
1517 } 1537 }
1518 1538
1519leave: 1539leave:
1540 /* See comment in dlm_mig_lockres_handler() */
1541 if (res) {
1542 if (extra_ref)
1543 dlm_lockres_put(res);
1544 dlm_lockres_put(res);
1545 }
1520 kfree(data); 1546 kfree(data);
1521 mlog_exit(ret); 1547 mlog_exit(ret);
1522} 1548}
@@ -1644,7 +1670,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
1644 /* retry!? */ 1670 /* retry!? */
1645 BUG(); 1671 BUG();
1646 } 1672 }
1647 } 1673 } else /* put.. incase we are not the master */
1674 dlm_lockres_put(res);
1648 spin_unlock(&res->spinlock); 1675 spin_unlock(&res->spinlock);
1649 } 1676 }
1650 spin_unlock(&dlm->spinlock); 1677 spin_unlock(&dlm->spinlock);
@@ -1921,6 +1948,7 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
1921 "Recovering res %s:%.*s, is already on recovery list!\n", 1948 "Recovering res %s:%.*s, is already on recovery list!\n",
1922 dlm->name, res->lockname.len, res->lockname.name); 1949 dlm->name, res->lockname.len, res->lockname.name);
1923 list_del_init(&res->recovering); 1950 list_del_init(&res->recovering);
1951 dlm_lockres_put(res);
1924 } 1952 }
1925 /* We need to hold a reference while on the recovery list */ 1953 /* We need to hold a reference while on the recovery list */
1926 dlm_lockres_get(res); 1954 dlm_lockres_get(res);
@@ -2130,11 +2158,16 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
2130 assert_spin_locked(&dlm->spinlock); 2158 assert_spin_locked(&dlm->spinlock);
2131 assert_spin_locked(&res->spinlock); 2159 assert_spin_locked(&res->spinlock);
2132 2160
2161 /* We do two dlm_lock_put(). One for removing from list and the other is
2162 * to force the DLM_UNLOCK_FREE_LOCK action so as to free the locks */
2163
2133 /* TODO: check pending_asts, pending_basts here */ 2164 /* TODO: check pending_asts, pending_basts here */
2134 list_for_each_entry_safe(lock, next, &res->granted, list) { 2165 list_for_each_entry_safe(lock, next, &res->granted, list) {
2135 if (lock->ml.node == dead_node) { 2166 if (lock->ml.node == dead_node) {
2136 list_del_init(&lock->list); 2167 list_del_init(&lock->list);
2137 dlm_lock_put(lock); 2168 dlm_lock_put(lock);
2169 /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
2170 dlm_lock_put(lock);
2138 freed++; 2171 freed++;
2139 } 2172 }
2140 } 2173 }
@@ -2142,6 +2175,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
2142 if (lock->ml.node == dead_node) { 2175 if (lock->ml.node == dead_node) {
2143 list_del_init(&lock->list); 2176 list_del_init(&lock->list);
2144 dlm_lock_put(lock); 2177 dlm_lock_put(lock);
2178 /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
2179 dlm_lock_put(lock);
2145 freed++; 2180 freed++;
2146 } 2181 }
2147 } 2182 }
@@ -2149,6 +2184,8 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
2149 if (lock->ml.node == dead_node) { 2184 if (lock->ml.node == dead_node) {
2150 list_del_init(&lock->list); 2185 list_del_init(&lock->list);
2151 dlm_lock_put(lock); 2186 dlm_lock_put(lock);
2187 /* Can't schedule DLM_UNLOCK_FREE_LOCK - do manually */
2188 dlm_lock_put(lock);
2152 freed++; 2189 freed++;
2153 } 2190 }
2154 } 2191 }