diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-14 18:29:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-14 18:29:08 -0400 |
| commit | 4e337adae4e960f64043b9f433c4a825c902616c (patch) | |
| tree | 407ea9edaec1ec666e5a0a6368dc51be2bc913c9 | |
| parent | 0bdd0f385a44344f83409b9e00797bfe2596faf8 (diff) | |
| parent | b36c3f84988eebf38acaccc756e05f6b70e333ab (diff) | |
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/mfasheh/ocfs2
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/mfasheh/ocfs2:
ocfs2_dlm: Add missing locks in dlm_empty_lockres
ocfs2_dlm: Missing get/put lockres in dlm_run_purge_lockres
configfs: add missing mutex_unlock()
ocfs2: add some missing address space callbacks
ocfs2: Concurrent access of o2hb_region->hr_task was not locked
ocfs2: Proper cleanup in case of error in ocfs2_register_hb_callbacks()
| -rw-r--r-- | fs/configfs/dir.c | 27 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 26 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 50 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.h | 2 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/tcp.c | 13 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmthread.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/heartbeat.c | 15 |
8 files changed, 84 insertions, 54 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 34750d5e4ff2..5e6e37e58f36 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -1141,25 +1141,22 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
| 1141 | 1141 | ||
| 1142 | err = -ENOMEM; | 1142 | err = -ENOMEM; |
| 1143 | dentry = d_alloc(configfs_sb->s_root, &name); | 1143 | dentry = d_alloc(configfs_sb->s_root, &name); |
| 1144 | if (!dentry) | 1144 | if (dentry) { |
| 1145 | goto out_release; | 1145 | d_add(dentry, NULL); |
| 1146 | |||
| 1147 | d_add(dentry, NULL); | ||
| 1148 | 1146 | ||
| 1149 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1147 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
| 1150 | dentry); | 1148 | dentry); |
| 1151 | if (!err) | 1149 | if (err) { |
| 1152 | dentry = NULL; | 1150 | d_delete(dentry); |
| 1153 | else | 1151 | dput(dentry); |
| 1154 | d_delete(dentry); | 1152 | } |
| 1153 | } | ||
| 1155 | 1154 | ||
| 1156 | mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); | 1155 | mutex_unlock(&configfs_sb->s_root->d_inode->i_mutex); |
| 1157 | 1156 | ||
| 1158 | if (dentry) { | 1157 | if (err) { |
| 1159 | dput(dentry); | 1158 | unlink_group(group); |
| 1160 | out_release: | 1159 | configfs_release_fs(); |
| 1161 | unlink_group(group); | ||
| 1162 | configfs_release_fs(); | ||
| 1163 | } | 1160 | } |
| 1164 | 1161 | ||
| 1165 | return err; | 1162 | return err; |
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 | */ | ||
| 622 | static 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 | |||
| 629 | static 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 | |||
| 617 | static ssize_t ocfs2_direct_IO(int rw, | 638 | static 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(®->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1); | 1321 | atomic_set(®->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(®->hr_steady_iterations) == 0); | 1336 | atomic_read(®->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: | |||
| 1354 | static ssize_t o2hb_region_pid_read(struct o2hb_region *reg, | 1363 | static 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 | ||
| 1363 | struct o2hb_region_attribute { | 1379 | struct o2hb_region_attribute { |
| @@ -1495,13 +1511,17 @@ out: | |||
| 1495 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, | 1511 | static 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 | } |
| 1683 | EXPORT_SYMBOL_GPL(o2hb_register_callback); | 1703 | EXPORT_SYMBOL_GPL(o2hb_register_callback); |
| 1684 | 1704 | ||
| 1685 | int o2hb_unregister_callback(struct o2hb_callback_func *hc) | 1705 | void 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 | } |
| 1703 | EXPORT_SYMBOL_GPL(o2hb_unregister_callback); | 1721 | EXPORT_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); |
| 72 | int o2hb_register_callback(struct o2hb_callback_func *hc); | 72 | int o2hb_register_callback(struct o2hb_callback_func *hc); |
| 73 | int o2hb_unregister_callback(struct o2hb_callback_func *hc); | 73 | void o2hb_unregister_callback(struct o2hb_callback_func *hc); |
| 74 | void o2hb_fill_node_map(unsigned long *map, | 74 | void o2hb_fill_node_map(unsigned long *map, |
| 75 | unsigned bytes); | 75 | unsigned bytes); |
| 76 | void o2hb_init(void); | 76 | void 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 | ||
| 1639 | void o2net_unregister_hb_callbacks(void) | 1639 | void 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 | ||
| 1654 | int o2net_register_hb_callbacks(void) | 1645 | int o2net_register_hb_callbacks(void) |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 77e4e6169a0d..9229e04362f6 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
| @@ -2730,14 +2730,17 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) | |||
| 2730 | int ret; | 2730 | int ret; |
| 2731 | int lock_dropped = 0; | 2731 | int lock_dropped = 0; |
| 2732 | 2732 | ||
| 2733 | spin_lock(&res->spinlock); | ||
| 2733 | if (res->owner != dlm->node_num) { | 2734 | if (res->owner != dlm->node_num) { |
| 2734 | if (!__dlm_lockres_unused(res)) { | 2735 | if (!__dlm_lockres_unused(res)) { |
| 2735 | mlog(ML_ERROR, "%s:%.*s: this node is not master, " | 2736 | mlog(ML_ERROR, "%s:%.*s: this node is not master, " |
| 2736 | "trying to free this but locks remain\n", | 2737 | "trying to free this but locks remain\n", |
| 2737 | dlm->name, res->lockname.len, res->lockname.name); | 2738 | dlm->name, res->lockname.len, res->lockname.name); |
| 2738 | } | 2739 | } |
| 2740 | spin_unlock(&res->spinlock); | ||
| 2739 | goto leave; | 2741 | goto leave; |
| 2740 | } | 2742 | } |
| 2743 | spin_unlock(&res->spinlock); | ||
| 2741 | 2744 | ||
| 2742 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ | 2745 | /* Wheee! Migrate lockres here! Will sleep so drop spinlock. */ |
| 2743 | spin_unlock(&dlm->spinlock); | 2746 | spin_unlock(&dlm->spinlock); |
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c index 8ffa0916eb86..6421a8fae1de 100644 --- a/fs/ocfs2/dlm/dlmthread.c +++ b/fs/ocfs2/dlm/dlmthread.c | |||
| @@ -265,8 +265,10 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm, | |||
| 265 | /* This may drop and reacquire the dlm spinlock if it | 265 | /* This may drop and reacquire the dlm spinlock if it |
| 266 | * has to do migration. */ | 266 | * has to do migration. */ |
| 267 | mlog(0, "calling dlm_purge_lockres!\n"); | 267 | mlog(0, "calling dlm_purge_lockres!\n"); |
| 268 | dlm_lockres_get(lockres); | ||
| 268 | if (dlm_purge_lockres(dlm, lockres)) | 269 | if (dlm_purge_lockres(dlm, lockres)) |
| 269 | BUG(); | 270 | BUG(); |
| 271 | dlm_lockres_put(lockres); | ||
| 270 | mlog(0, "DONE calling dlm_purge_lockres!\n"); | 272 | mlog(0, "DONE calling dlm_purge_lockres!\n"); |
| 271 | 273 | ||
| 272 | /* Avoid adding any scheduling latencies */ | 274 | /* Avoid adding any scheduling latencies */ |
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 | ||
| 170 | bail: | 172 | bail: |
| 171 | return status; | 173 | return status; |
| @@ -173,18 +175,11 @@ bail: | |||
| 173 | 175 | ||
| 174 | void ocfs2_clear_hb_callbacks(struct ocfs2_super *osb) | 176 | void 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 | ||
| 190 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) | 185 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) |
