diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-18 19:50:28 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-18 19:50:28 -0400 |
| commit | 3f80fbff5f1ef8a842bbe5343bbc9ddad883f25c (patch) | |
| tree | 259f5be0f203b5c7e97837a1957f461abcfef5d0 | |
| parent | fce519588acfac249e8fdc1f5016c73d617de315 (diff) | |
| parent | 24307aa1e707b31613be92deaba7990e16bc1aec (diff) | |
Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2:
configfs: Fix race between configfs_readdir() and configfs_d_iput()
configfs: Don't try to d_delete() negative dentries.
ocfs2/dlm: Target node death during resource migration leads to thread spin
ocfs2: Skip mount recovery for hard-ro mounts
ocfs2/cluster: Heartbeat mismatch message improved
ocfs2/cluster: Increase the live threshold for global heartbeat
ocfs2/dlm: Use negotiated o2dlm protocol version
ocfs2: skip existing hole when removing the last extent_rec in punching-hole codes.
ocfs2: Initialize data_ac (might be used uninitialized)
| -rw-r--r-- | fs/configfs/dir.c | 39 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 61 | ||||
| -rw-r--r-- | fs/ocfs2/dir.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmmaster.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 12 | ||||
| -rw-r--r-- | fs/ocfs2/journal.c | 3 |
7 files changed, 96 insertions, 27 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 3313dd19f543..9a37a9b6de3a 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock); | |||
| 53 | static void configfs_d_iput(struct dentry * dentry, | 53 | static void configfs_d_iput(struct dentry * dentry, |
| 54 | struct inode * inode) | 54 | struct inode * inode) |
| 55 | { | 55 | { |
| 56 | struct configfs_dirent * sd = dentry->d_fsdata; | 56 | struct configfs_dirent *sd = dentry->d_fsdata; |
| 57 | 57 | ||
| 58 | if (sd) { | 58 | if (sd) { |
| 59 | BUG_ON(sd->s_dentry != dentry); | 59 | BUG_ON(sd->s_dentry != dentry); |
| 60 | /* Coordinate with configfs_readdir */ | ||
| 61 | spin_lock(&configfs_dirent_lock); | ||
| 60 | sd->s_dentry = NULL; | 62 | sd->s_dentry = NULL; |
| 63 | spin_unlock(&configfs_dirent_lock); | ||
| 61 | configfs_put(sd); | 64 | configfs_put(sd); |
| 62 | } | 65 | } |
| 63 | iput(inode); | 66 | iput(inode); |
| @@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group, | |||
| 689 | sd = child->d_fsdata; | 692 | sd = child->d_fsdata; |
| 690 | sd->s_type |= CONFIGFS_USET_DEFAULT; | 693 | sd->s_type |= CONFIGFS_USET_DEFAULT; |
| 691 | } else { | 694 | } else { |
| 692 | d_delete(child); | 695 | BUG_ON(child->d_inode); |
| 696 | d_drop(child); | ||
| 693 | dput(child); | 697 | dput(child); |
| 694 | } | 698 | } |
| 695 | } | 699 | } |
| @@ -1545,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
| 1545 | struct configfs_dirent * parent_sd = dentry->d_fsdata; | 1549 | struct configfs_dirent * parent_sd = dentry->d_fsdata; |
| 1546 | struct configfs_dirent *cursor = filp->private_data; | 1550 | struct configfs_dirent *cursor = filp->private_data; |
| 1547 | struct list_head *p, *q = &cursor->s_sibling; | 1551 | struct list_head *p, *q = &cursor->s_sibling; |
| 1548 | ino_t ino; | 1552 | ino_t ino = 0; |
| 1549 | int i = filp->f_pos; | 1553 | int i = filp->f_pos; |
| 1550 | 1554 | ||
| 1551 | switch (i) { | 1555 | switch (i) { |
| @@ -1573,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
| 1573 | struct configfs_dirent *next; | 1577 | struct configfs_dirent *next; |
| 1574 | const char * name; | 1578 | const char * name; |
| 1575 | int len; | 1579 | int len; |
| 1580 | struct inode *inode = NULL; | ||
| 1576 | 1581 | ||
| 1577 | next = list_entry(p, struct configfs_dirent, | 1582 | next = list_entry(p, struct configfs_dirent, |
| 1578 | s_sibling); | 1583 | s_sibling); |
| @@ -1581,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir | |||
| 1581 | 1586 | ||
| 1582 | name = configfs_get_name(next); | 1587 | name = configfs_get_name(next); |
| 1583 | len = strlen(name); | 1588 | len = strlen(name); |
| 1584 | if (next->s_dentry) | 1589 | |
| 1585 | ino = next->s_dentry->d_inode->i_ino; | 1590 | /* |
| 1586 | else | 1591 | * We'll have a dentry and an inode for |
| 1592 | * PINNED items and for open attribute | ||
| 1593 | * files. We lock here to prevent a race | ||
| 1594 | * with configfs_d_iput() clearing | ||
| 1595 | * s_dentry before calling iput(). | ||
| 1596 | * | ||
| 1597 | * Why do we go to the trouble? If | ||
| 1598 | * someone has an attribute file open, | ||
| 1599 | * the inode number should match until | ||
| 1600 | * they close it. Beyond that, we don't | ||
| 1601 | * care. | ||
| 1602 | */ | ||
| 1603 | spin_lock(&configfs_dirent_lock); | ||
| 1604 | dentry = next->s_dentry; | ||
| 1605 | if (dentry) | ||
| 1606 | inode = dentry->d_inode; | ||
| 1607 | if (inode) | ||
| 1608 | ino = inode->i_ino; | ||
| 1609 | spin_unlock(&configfs_dirent_lock); | ||
| 1610 | if (!inode) | ||
| 1587 | ino = iunique(configfs_sb, 2); | 1611 | ino = iunique(configfs_sb, 2); |
| 1588 | 1612 | ||
| 1589 | if (filldir(dirent, name, len, filp->f_pos, ino, | 1613 | if (filldir(dirent, name, len, filp->f_pos, ino, |
| @@ -1683,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys) | |||
| 1683 | err = configfs_attach_group(sd->s_element, &group->cg_item, | 1707 | err = configfs_attach_group(sd->s_element, &group->cg_item, |
| 1684 | dentry); | 1708 | dentry); |
| 1685 | if (err) { | 1709 | if (err) { |
| 1686 | d_delete(dentry); | 1710 | BUG_ON(dentry->d_inode); |
| 1711 | d_drop(dentry); | ||
| 1687 | dput(dentry); | 1712 | dput(dentry); |
| 1688 | } else { | 1713 | } else { |
| 1689 | spin_lock(&configfs_dirent_lock); | 1714 | spin_lock(&configfs_dirent_lock); |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 643720209a98..9a3e6bbff27b 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
| @@ -539,25 +539,41 @@ static int o2hb_verify_crc(struct o2hb_region *reg, | |||
| 539 | 539 | ||
| 540 | /* We want to make sure that nobody is heartbeating on top of us -- | 540 | /* We want to make sure that nobody is heartbeating on top of us -- |
| 541 | * this will help detect an invalid configuration. */ | 541 | * this will help detect an invalid configuration. */ |
| 542 | static int o2hb_check_last_timestamp(struct o2hb_region *reg) | 542 | static void o2hb_check_last_timestamp(struct o2hb_region *reg) |
| 543 | { | 543 | { |
| 544 | int node_num, ret; | ||
| 545 | struct o2hb_disk_slot *slot; | 544 | struct o2hb_disk_slot *slot; |
| 546 | struct o2hb_disk_heartbeat_block *hb_block; | 545 | struct o2hb_disk_heartbeat_block *hb_block; |
| 546 | char *errstr; | ||
| 547 | 547 | ||
| 548 | node_num = o2nm_this_node(); | 548 | slot = ®->hr_slots[o2nm_this_node()]; |
| 549 | |||
| 550 | ret = 1; | ||
| 551 | slot = ®->hr_slots[node_num]; | ||
| 552 | /* Don't check on our 1st timestamp */ | 549 | /* Don't check on our 1st timestamp */ |
| 553 | if (slot->ds_last_time) { | 550 | if (!slot->ds_last_time) |
| 554 | hb_block = slot->ds_raw_block; | 551 | return; |
| 555 | 552 | ||
| 556 | if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time) | 553 | hb_block = slot->ds_raw_block; |
| 557 | ret = 0; | 554 | if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time && |
| 558 | } | 555 | le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation && |
| 556 | hb_block->hb_node == slot->ds_node_num) | ||
| 557 | return; | ||
| 559 | 558 | ||
| 560 | return ret; | 559 | #define ERRSTR1 "Another node is heartbeating on device" |
| 560 | #define ERRSTR2 "Heartbeat generation mismatch on device" | ||
| 561 | #define ERRSTR3 "Heartbeat sequence mismatch on device" | ||
| 562 | |||
| 563 | if (hb_block->hb_node != slot->ds_node_num) | ||
| 564 | errstr = ERRSTR1; | ||
| 565 | else if (le64_to_cpu(hb_block->hb_generation) != | ||
| 566 | slot->ds_last_generation) | ||
| 567 | errstr = ERRSTR2; | ||
| 568 | else | ||
| 569 | errstr = ERRSTR3; | ||
| 570 | |||
| 571 | mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), " | ||
| 572 | "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name, | ||
| 573 | slot->ds_node_num, (unsigned long long)slot->ds_last_generation, | ||
| 574 | (unsigned long long)slot->ds_last_time, hb_block->hb_node, | ||
| 575 | (unsigned long long)le64_to_cpu(hb_block->hb_generation), | ||
| 576 | (unsigned long long)le64_to_cpu(hb_block->hb_seq)); | ||
| 561 | } | 577 | } |
| 562 | 578 | ||
| 563 | static inline void o2hb_prepare_block(struct o2hb_region *reg, | 579 | static inline void o2hb_prepare_block(struct o2hb_region *reg, |
| @@ -983,9 +999,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
| 983 | /* With an up to date view of the slots, we can check that no | 999 | /* With an up to date view of the slots, we can check that no |
| 984 | * other node has been improperly configured to heartbeat in | 1000 | * other node has been improperly configured to heartbeat in |
| 985 | * our slot. */ | 1001 | * our slot. */ |
| 986 | if (!o2hb_check_last_timestamp(reg)) | 1002 | o2hb_check_last_timestamp(reg); |
| 987 | mlog(ML_ERROR, "Device \"%s\": another node is heartbeating " | ||
| 988 | "in our slot!\n", reg->hr_dev_name); | ||
| 989 | 1003 | ||
| 990 | /* fill in the proper info for our next heartbeat */ | 1004 | /* fill in the proper info for our next heartbeat */ |
| 991 | o2hb_prepare_block(reg, reg->hr_generation); | 1005 | o2hb_prepare_block(reg, reg->hr_generation); |
| @@ -999,8 +1013,8 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg) | |||
| 999 | } | 1013 | } |
| 1000 | |||
