aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/aops.c26
-rw-r--r--fs/ocfs2/cluster/heartbeat.c50
-rw-r--r--fs/ocfs2/cluster/heartbeat.h2
-rw-r--r--fs/ocfs2/cluster/tcp.c13
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c8
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c102
-rw-r--r--fs/ocfs2/dlm/dlmthread.c10
-rw-r--r--fs/ocfs2/heartbeat.c15
8 files changed, 144 insertions, 82 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 93628b02ef5d..875c11443817 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -614,6 +614,27 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
614 ocfs2_rw_unlock(inode, 0); 614 ocfs2_rw_unlock(inode, 0);
615} 615}
616 616
617/*
618 * ocfs2_invalidatepage() and ocfs2_releasepage() are shamelessly stolen
619 * from ext3. PageChecked() bits have been removed as OCFS2 does not
620 * do journalled data.
621 */
622static void ocfs2_invalidatepage(struct page *page, unsigned long offset)
623{
624 journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
625
626 journal_invalidatepage(journal, page, offset);
627}
628
629static int ocfs2_releasepage(struct page *page, gfp_t wait)
630{
631 journal_t *journal = OCFS2_SB(page->mapping->host->i_sb)->journal->j_journal;
632
633 if (!page_has_buffers(page))
634 return 0;
635 return journal_try_to_free_buffers(journal, page, wait);
636}
637
617static ssize_t ocfs2_direct_IO(int rw, 638static ssize_t ocfs2_direct_IO(int rw,
618 struct kiocb *iocb, 639 struct kiocb *iocb,
619 const struct iovec *iov, 640 const struct iovec *iov,
@@ -661,5 +682,8 @@ const struct address_space_operations ocfs2_aops = {
661 .commit_write = ocfs2_commit_write, 682 .commit_write = ocfs2_commit_write,
662 .bmap = ocfs2_bmap, 683 .bmap = ocfs2_bmap,
663 .sync_page = block_sync_page, 684 .sync_page = block_sync_page,
664 .direct_IO = ocfs2_direct_IO 685 .direct_IO = ocfs2_direct_IO,
686 .invalidatepage = ocfs2_invalidatepage,
687 .releasepage = ocfs2_releasepage,
688 .migratepage = buffer_migrate_page,
665}; 689};
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 5a9779bb9236..eba282da500e 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -1234,6 +1234,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
1234 const char *page, 1234 const char *page,
1235 size_t count) 1235 size_t count)
1236{ 1236{
1237 struct task_struct *hb_task;
1237 long fd; 1238 long fd;
1238 int sectsize; 1239 int sectsize;
1239 char *p = (char *)page; 1240 char *p = (char *)page;
@@ -1319,20 +1320,28 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
1319 */ 1320 */
1320 atomic_set(&reg->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); 1321 atomic_set(&reg->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1);
1321 1322
1322 reg->hr_task = kthread_run(o2hb_thread, reg, "o2hb-%s", 1323 hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
1323 reg->hr_item.ci_name); 1324 reg->hr_item.ci_name);
1324 if (IS_ERR(reg->hr_task)) { 1325 if (IS_ERR(hb_task)) {
1325 ret = PTR_ERR(reg->hr_task); 1326 ret = PTR_ERR(hb_task);
1326 mlog_errno(ret); 1327 mlog_errno(ret);
1327 reg->hr_task = NULL;
1328 goto out; 1328 goto out;
1329 } 1329 }
1330 1330
1331 spin_lock(&o2hb_live_lock);
1332 reg->hr_task = hb_task;
1333 spin_unlock(&o2hb_live_lock);
1334
1331 ret = wait_event_interruptible(o2hb_steady_queue, 1335 ret = wait_event_interruptible(o2hb_steady_queue,
1332 atomic_read(&reg->hr_steady_iterations) == 0); 1336 atomic_read(&reg->hr_steady_iterations) == 0);
1333 if (ret) { 1337 if (ret) {
1334 kthread_stop(reg->hr_task); 1338 spin_lock(&o2hb_live_lock);
1339 hb_task = reg->hr_task;
1335 reg->hr_task = NULL; 1340 reg->hr_task = NULL;
1341 spin_unlock(&o2hb_live_lock);
1342
1343 if (hb_task)
1344 kthread_stop(hb_task);
1336 goto out; 1345 goto out;
1337 } 1346 }
1338 1347
@@ -1354,10 +1363,17 @@ out:
1354static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, 1363static ssize_t o2hb_region_pid_read(struct o2hb_region *reg,
1355 char *page) 1364 char *page)
1356{ 1365{
1357 if (!reg->hr_task) 1366 pid_t pid = 0;
1367
1368 spin_lock(&o2hb_live_lock);
1369 if (reg->hr_task)
1370 pid = reg->hr_task->pid;
1371 spin_unlock(&o2hb_live_lock);
1372
1373 if (!pid)
1358 return 0; 1374 return 0;
1359 1375
1360 return sprintf(page, "%u\n", reg->hr_task->pid); 1376 return sprintf(page, "%u\n", pid);
1361} 1377}
1362 1378
1363struct o2hb_region_attribute { 1379struct o2hb_region_attribute {
@@ -1495,13 +1511,17 @@ out:
1495static void o2hb_heartbeat_group_drop_item(struct config_group *group, 1511static void o2hb_heartbeat_group_drop_item(struct config_group *group,
1496 struct config_item *item) 1512 struct config_item *item)
1497{ 1513{
1514 struct task_struct *hb_task;
1498 struct o2hb_region *reg = to_o2hb_region(item); 1515 struct o2hb_region *reg = to_o2hb_region(item);
1499 1516
1500 /* stop the thread when the user removes the region dir */ 1517 /* stop the thread when the user removes the region dir */
1501 if (reg->hr_task) { 1518 spin_lock(&o2hb_live_lock);
1502 kthread_stop(reg->hr_task); 1519 hb_task = reg->hr_task;
1503 reg->hr_task = NULL; 1520 reg->hr_task = NULL;
1504 } 1521 spin_unlock(&o2hb_live_lock);
1522
1523 if (hb_task)
1524 kthread_stop(hb_task);
1505 1525
1506 config_item_put(item); 1526 config_item_put(item);
1507} 1527}
@@ -1682,7 +1702,7 @@ out:
1682} 1702}
1683EXPORT_SYMBOL_GPL(o2hb_register_callback); 1703EXPORT_SYMBOL_GPL(o2hb_register_callback);
1684 1704
1685int o2hb_unregister_callback(struct o2hb_callback_func *hc) 1705void o2hb_unregister_callback(struct o2hb_callback_func *hc)
1686{ 1706{
1687 BUG_ON(hc->hc_magic != O2HB_CB_MAGIC); 1707 BUG_ON(hc->hc_magic != O2HB_CB_MAGIC);
1688 1708
@@ -1690,15 +1710,13 @@ int o2hb_unregister_callback(struct o2hb_callback_func *hc)
1690 __builtin_return_address(0), hc); 1710 __builtin_return_address(0), hc);
1691 1711
1692 if (list_empty(&hc->hc_item)) 1712 if (list_empty(&hc->hc_item))
1693 return 0; 1713 return;
1694 1714
1695 down_write(&o2hb_callback_sem); 1715 down_write(&o2hb_callback_sem);
1696 1716
1697 list_del_init(&hc->hc_item); 1717 list_del_init(&hc->hc_item);
1698 1718
1699 up_write(&o2hb_callback_sem); 1719 up_write(&o2hb_callback_sem);
1700
1701 return 0;
1702} 1720}
1703EXPORT_SYMBOL_GPL(o2hb_unregister_callback); 1721EXPORT_SYMBOL_GPL(o2hb_unregister_callback);
1704 1722
diff --git a/fs/ocfs2/cluster/heartbeat.h b/fs/ocfs2/cluster/heartbeat.h
index cac6223206a9..cc6d40b39771 100644
--- a/fs/ocfs2/cluster/heartbeat.h
+++ b/fs/ocfs2/cluster/heartbeat.h
@@ -70,7 +70,7 @@ void o2hb_setup_callback(struct o2hb_callback_func *hc,
70 void *data, 70 void *data,
71 int priority); 71 int priority);
72int o2hb_register_callback(struct o2hb_callback_func *hc); 72int o2hb_register_callback(struct o2hb_callback_func *hc);
73int o2hb_unregister_callback(struct o2hb_callback_func *hc); 73void o2hb_unregister_callback(struct o2hb_callback_func *hc);
74void o2hb_fill_node_map(unsigned long *map, 74void o2hb_fill_node_map(unsigned long *map,
75 unsigned bytes); 75 unsigned bytes);
76void o2hb_init(void); 76void o2hb_init(void);
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 1718215fc018..69caf3e12fea 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1638,17 +1638,8 @@ static void o2net_hb_node_up_cb(struct o2nm_node *node, int node_num,
1638 1638
1639void o2net_unregister_hb_callbacks(void) 1639void o2net_unregister_hb_callbacks(void)
1640{ 1640{
1641 int ret; 1641 o2hb_unregister_callback(&o2net_hb_up);
1642 1642 o2hb_unregister_callback(&o2net_hb_down);
1643 ret = o2hb_unregister_callback(&o2net_hb_up);
1644 if (ret < 0)
1645 mlog(ML_ERROR, "Status return %d unregistering heartbeat up "
1646 "callback!\n", ret);
1647
1648 ret = o2hb_unregister_callback(&o2net_hb_down);
1649 if (ret < 0)
1650 mlog(ML_ERROR, "Status return %d unregistering heartbeat down "
1651 "callback!\n", ret);
1652} 1643}
1653 1644
1654int o2net_register_hb_callbacks(void) 1645int o2net_register_hb_callbacks(void)
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 6087c4749fee..c558442a0b44 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -138,8 +138,10 @@ static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
138 138
139void __dlm_unhash_lockres(struct dlm_lock_resource *lockres) 139void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
140{ 140{
141 hlist_del_init(&lockres->hash_node); 141 if (!hlist_unhashed(&lockres->hash_node)) {
142 dlm_lockres_put(lockres); 142 hlist_del_init(&lockres->hash_node);
143 dlm_lockres_put(lockres);
144 }
143} 145}
144 146
145void __dlm_insert_lockres(struct dlm_ctxt *dlm, 147void __dlm_insert_lockres(struct dlm_ctxt *dlm,
@@ -655,6 +657,8 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
655 dlm_kick_thread(dlm, NULL); 657 dlm_kick_thread(dlm, NULL);
656 658
657 while (dlm_migrate_all_locks(dlm)) { 659 while (dlm_migrate_all_locks(dlm)) {
660 /* Give dlm_thread time to purge the lockres' */
661 msleep(500);
658 mlog(0, "%s: more migration to do\n", dlm->name); 662 mlog(0, "%s: more migration to do\n", dlm->name);
659 } 663 }
660 dlm_mark_domain_leaving(dlm); 664 dlm_mark_domain_leaving(dlm);
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 77e4e6169a0d..6edffca99d98 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2424,6 +2424,57 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
2424 dlm_lockres_put(res); 2424 dlm_lockres_put(res);
2425} 2425}
2426 2426
2427/* Checks whether the lockres can be migrated. Returns 0 if yes, < 0
2428 * if not. If 0, numlocks is set to the number of locks in the lockres.
2429 */
2430static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
2431 struct dlm_lock_resource *res,
2432 int *numlocks)
2433{
2434 int ret;
2435 int i;
2436 int count = 0;
2437 struct list_head *queue, *iter;
2438 struct dlm_lock *lock;
2439
2440 assert_spin_locked(&res->spinlock);
2441
2442 ret = -EINVAL;
2443 if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
2444 mlog(0, "cannot migrate lockres with unknown owner!\n");
2445 goto leave;
2446 }
2447
2448 if (res->owner != dlm->node_num) {
2449 mlog(0, "cannot migrate lockres this node doesn't own!\n");
2450 goto leave;
2451 }
2452
2453 ret = 0;
2454 queue = &res->granted;
2455 for (i = 0; i < 3; i++) {
2456 list_for_each(iter, queue) {
2457 lock = list_entry(iter, struct dlm_lock, list);
2458 ++count;
2459 if (lock->ml.node == dlm->node_num) {
2460 mlog(0, "found a lock owned by this node still "
2461 "on the %s queue! will not migrate this "
2462 "lockres\n", (i == 0 ? "granted" :
2463 (i == 1 ? "converting" :
2464 "blocked")));
2465 ret = -ENOTEMPTY;
2466 goto leave;
2467 }
2468 }
2469 queue++;
2470 }
2471
2472 *numlocks = count;
2473 mlog(0, "migrateable lockres having %d locks\n", *numlocks);
2474
2475leave:
2476 return ret;
2477}
2427 2478
2428/* 2479/*
2429 * DLM_MIGRATE_LOCKRES 2480 * DLM_MIGRATE_LOCKRES
@@ -2437,14 +2488,12 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
2437 struct dlm_master_list_entry *mle = NULL; 2488 struct dlm_master_list_entry *mle = NULL;
2438 struct dlm_master_list_entry *oldmle = NULL; 2489 struct dlm_master_list_entry *oldmle = NULL;
2439 struct dlm_migratable_lockres *mres = NULL; 2490 struct dlm_migratable_lockres *mres = NULL;
2440 int ret = -EINVAL; 2491 int ret = 0;
2441 const char *name; 2492 const char *name;
2442 unsigned int namelen; 2493 unsigned int namelen;
2443 int mle_added = 0; 2494 int mle_added = 0;
2444 struct list_head *queue, *iter; 2495 int numlocks;
2445 int i; 2496 int wake = 0;
2446 struct dlm_lock *lock;
2447 int empty = 1, wake = 0;
2448 2497
2449 if (!dlm_grab(dlm)) 2498 if (!dlm_grab(dlm))
2450 return -EINVAL; 2499 return -EINVAL;
@@ -2458,42 +2507,16 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
2458 * ensure this lockres is a proper candidate for migration 2507 * ensure this lockres is a proper candidate for migration
2459 */ 2508 */
2460 spin_lock(&res->spinlock); 2509 spin_lock(&res->spinlock);
2461 if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { 2510 ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
2462 mlog(0, "cannot migrate lockres with unknown owner!\n"); 2511 if (ret < 0) {
2463 spin_unlock(&res->spinlock);
2464 goto leave;
2465 }
2466 if (res->owner != dlm->node_num) {
2467 mlog(0, "cannot migrate lockres this node doesn't own!\n");
2468 spin_unlock(&res->spinlock); 2512 spin_unlock(&res->spinlock);
2469 goto leave; 2513 goto leave;
2470 } 2514 }
2471 mlog(0, "checking queues...\n");
2472 queue = &res->granted;
2473 for (i=0; i<3; i++) {
2474 list_for_each(iter, queue) {
2475 lock = list_entry (iter, struct dlm_lock, list);
2476 empty = 0;
2477 if (lock->ml.node == dlm->node_num) {
2478 mlog(0, "found a lock owned by this node "
2479 "still on the %s queue! will not "
2480 "migrate this lockres\n",
2481 i==0 ? "granted" :
2482 (i==1 ? "converting" : "blocked"));
2483 spin_unlock(&res->spinlock);
2484 ret = -ENOTEMPTY;
2485 goto leave;
2486 }
2487 }
2488 queue++;
2489 }
2490 mlog(0, "all locks on this lockres are nonlocal. continuing\n");
2491 spin_unlock(&res->spinlock); 2515 spin_unlock(&res->spinlock);
2492 2516
2493 /* no work to do */ 2517 /* no work to do */
2494 if (empty) { 2518 if (numlocks == 0) {
2495 mlog(0, "no locks were found on this lockres! done!\n"); 2519 mlog(0, "no locks were found on this lockres! done!\n");
2496 ret = 0;
2497 goto leave; 2520 goto leave;
2498 } 2521 }
2499 2522
@@ -2729,15 +2752,26 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
2729{ 2752{
2730 int ret; 2753 int ret;
2731 int lock_dropped = 0; 2754 int lock_dropped = 0;
2755 int numlocks;
2732 2756
2757 spin_lock(&res->spinlock);
2733 if (res->owner != dlm->node_num) { 2758 if (res->owner != dlm->node_num) {
2734 if (!__dlm_lockres_unused(res)) { 2759 if (!__dlm_lockres_unused(res)) {
2735 mlog(ML_ERROR, "%s:%.*s: this node is not master, " 2760 mlog(ML_ERROR, "%s:%.*s: this node is not master, "
2736 "trying to free this but locks remain\n", 2761 "trying to free this but locks remain\n",
2737 dlm->name, res->lockname.len, res->lockname.name); 2762 dlm->name, res->lockname.len, res->lockname.name);
2738 } 2763 }
2764 spin_unlock(&res->spinlock);
2765 goto leave;
2766 }
2767
2768 /* No need to migrate a lockres having no locks */
2769 ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
2770 if (ret >= 0 && numlocks == 0) {
2771 spin_unlock(&res->spinlock);
2739 goto leave; 2772 goto leave;
2740 } 2773 }
2774 spin_unlock(&res->spinlock);
2741 2775
2742 /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ 2776 /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */
2743 spin_unlock(&dlm->spinlock); 2777 spin_unlock(&dlm->spinlock);
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 8ffa0916eb86..2b264c6ba039 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -256,18 +256,14 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
256 break; 256 break;
257 } 257 }
258 258
259 mlog(0, "removing lockres %.*s:%p from purgelist\n", 259 dlm_lockres_get(lockres);
260 lockres->lockname.len, lockres->lockname.name, lockres);
261 list_del_init(&lockres->purge);
262 dlm_lockres_put(lockres);
263 dlm->purge_count--;
264 260
265 /* This may drop and reacquire the dlm spinlock if it 261 /* This may drop and reacquire the dlm spinlock if it
266 * has to do migration. */ 262 * has to do migration. */
267 mlog(0, "calling dlm_purge_lockres!\n");
268 if (dlm_purge_lockres(dlm, lockres)) 263 if (dlm_purge_lockres(dlm, lockres))
269 BUG(); 264 BUG();
270 mlog(0, "DONE calling dlm_purge_lockres!\n"); 265
266 dlm_lockres_put(lockres);
271 267
272 /* Avoid adding any scheduling latencies */ 268 /* Avoid adding any scheduling latencies */
273 cond_resched_lock(&dlm->spinlock); 269 cond_resched_lock(&dlm->spinlock);
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c
index 8fc52d6d0ce7..b25ef63781ba 100644
--- a/fs/ocfs2/heartbeat.c
+++ b/fs/ocfs2/heartbeat.c
@@ -164,8 +164,10 @@ int ocfs2_register_hb_callbacks(struct ocfs2_super *osb)
164 } 164 }
165 165
166 status = o2hb_register_callback(&osb->osb_hb_up); 166 status = o2hb_register_callback(&osb->osb_hb_up);
167 if (status < 0) 167 if (status < 0) {
168 mlog_errno(status); 168 mlog_errno(status);
169 o2hb_unregister_callback(&osb->osb_hb_down);
170 }
169 171
170bail: 172bail:
171 return status; 173 return status;
@@ -173,18 +175,11 @@ bail:
173 175
174void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb) 176void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb)
175{ 177{
176 int status;
177
178 if (ocfs2_mount_local(osb)) 178 if (ocfs2_mount_local(osb))
179 return; 179 return;
180 180
181 status = o2hb_unregister_callback(&osb->osb_hb_down); 181 o2hb_unregister_callback(&osb->osb_hb_down);
182 if (status < 0) 182 o2hb_unregister_callback(&osb->osb_hb_up);
183 mlog_errno(status);
184
185 status = o2hb_unregister_callback(&osb->osb_hb_up);
186 if (status < 0)
187 mlog_errno(status);
188} 183}
189 184
190void ocfs2_stop_heartbeat(struct ocfs2_super *osb) 185void ocfs2_stop_heartbeat(struct ocfs2_super *osb)