Skip to content

Commit 3f80fbf

Browse files
committed
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)
2 parents fce5195 + 24307aa commit 3f80fbf

File tree

7 files changed

+96
-27
lines changed

7 files changed

+96
-27
lines changed

fs/configfs/dir.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,14 @@ DEFINE_SPINLOCK(configfs_dirent_lock);
5353
static void configfs_d_iput(struct dentry * dentry,
5454
struct inode * inode)
5555
{
56-
struct configfs_dirent * sd = dentry->d_fsdata;
56+
struct configfs_dirent *sd = dentry->d_fsdata;
5757

5858
if (sd) {
5959
BUG_ON(sd->s_dentry != dentry);
60+
/* Coordinate with configfs_readdir */
61+
spin_lock(&configfs_dirent_lock);
6062
sd->s_dentry = NULL;
63+
spin_unlock(&configfs_dirent_lock);
6164
configfs_put(sd);
6265
}
6366
iput(inode);
@@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group,
689692
sd = child->d_fsdata;
690693
sd->s_type |= CONFIGFS_USET_DEFAULT;
691694
} else {
692-
d_delete(child);
695+
BUG_ON(child->d_inode);
696+
d_drop(child);
693697
dput(child);
694698
}
695699
}
@@ -1545,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
15451549
struct configfs_dirent * parent_sd = dentry->d_fsdata;
15461550
struct configfs_dirent *cursor = filp->private_data;
15471551
struct list_head *p, *q = &cursor->s_sibling;
1548-
ino_t ino;
1552+
ino_t ino = 0;
15491553
int i = filp->f_pos;
15501554

15511555
switch (i) {
@@ -1573,6 +1577,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
15731577
struct configfs_dirent *next;
15741578
const char * name;
15751579
int len;
1580+
struct inode *inode = NULL;
15761581

15771582
next = list_entry(p, struct configfs_dirent,
15781583
s_sibling);
@@ -1581,9 +1586,28 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
15811586

15821587
name = configfs_get_name(next);
15831588
len = strlen(name);
1584-
if (next->s_dentry)
1585-
ino = next->s_dentry->d_inode->i_ino;
1586-
else
1589+
1590+
/*
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)
15871611
ino = iunique(configfs_sb, 2);
15881612

15891613
if (filldir(dirent, name, len, filp->f_pos, ino,
@@ -1683,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
16831707
err = configfs_attach_group(sd->s_element, &group->cg_item,
16841708
dentry);
16851709
if (err) {
1686-
d_delete(dentry);
1710+
BUG_ON(dentry->d_inode);
1711+
d_drop(dentry);
16871712
dput(dentry);
16881713
} else {
16891714
spin_lock(&configfs_dirent_lock);

fs/ocfs2/cluster/heartbeat.c

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -539,25 +539,41 @@ static int o2hb_verify_crc(struct o2hb_region *reg,
539539

540540
/* We want to make sure that nobody is heartbeating on top of us --
541541
* 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)
543543
{
544-
int node_num, ret;
545544
struct o2hb_disk_slot *slot;
546545
struct o2hb_disk_heartbeat_block *hb_block;
546+
char *errstr;
547547

548-
node_num = o2nm_this_node();
549-
550-
ret = 1;
551-
slot = &reg->hr_slots[node_num];
548+
slot = &reg->hr_slots[o2nm_this_node()];
552549
/* Don't check on our 1st timestamp */
553-
if (slot->ds_last_time) {
554-
hb_block = slot->ds_raw_block;
550+
if (!slot->ds_last_time)
551+
return;
555552

556-
if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time)
557-
ret = 0;
558-
}
553+
hb_block = slot->ds_raw_block;
554+
if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time &&
555+
le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation &&
556+
hb_block->hb_node == slot->ds_node_num)
557+
return;
559558

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));
561577
}
562578

563579
static inline void o2hb_prepare_block(struct o2hb_region *reg,
@@ -983,9 +999,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
983999
/* With an up to date view of the slots, we can check that no
9841000
* other node has been improperly configured to heartbeat in
9851001
* our slot. */
986-
if (!o2hb_check_last_timestamp(reg))
987-
mlog(ML_ERROR, "Device \"%s\": another node is heartbeating "
988-
"in our slot!\n", reg->hr_dev_name);
1002+
o2hb_check_last_timestamp(reg);
9891003

9901004
/* fill in the proper info for our next heartbeat */
9911005
o2hb_prepare_block(reg, reg->hr_generation);
@@ -999,8 +1013,8 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
9991013
}
10001014

10011015
i = -1;
1002-
while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
1003-
1016+
while((i = find_next_bit(configured_nodes,
1017+
O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
10041018
change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
10051019
}
10061020

@@ -1690,6 +1704,7 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
16901704
struct file *filp = NULL;
16911705
struct inode *inode = NULL;
16921706
ssize_t ret = -EINVAL;
1707+
int live_threshold;
16931708

16941709
if (reg->hr_bdev)
16951710
goto out;
@@ -1766,8 +1781,18 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
17661781
* A node is considered live after it has beat LIVE_THRESHOLD
17671782
* times. We're not steady until we've given them a chance
17681783
* _after_ our first read.
1784+
* The default threshold is bare minimum so as to limit the delay
1785+
* during mounts. For global heartbeat, the threshold doubled for the
1786+
* first region.
17691787
*/
1770-
atomic_set(&reg->hr_steady_iterations, O2HB_LIVE_THRESHOLD + 1);
1788+
live_threshold = O2HB_LIVE_THRESHOLD;
1789+
if (o2hb_global_heartbeat_active()) {
1790+
spin_lock(&o2hb_live_lock);
1791+
if (o2hb_pop_count(&o2hb_region_bitmap, O2NM_MAX_REGIONS) == 1)
1792+
live_threshold <<= 1;
1793+
spin_unlock(&o2hb_live_lock);
1794+
}
1795+
atomic_set(&reg->hr_steady_iterations, live_threshold + 1);
17711796

17721797
hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
17731798
reg->hr_item.ci_name);

fs/ocfs2/dir.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2868,7 +2868,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
28682868
bytes = blocks_wanted << sb->s_blocksize_bits;
28692869
struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
28702870
struct ocfs2_inode_info *oi = OCFS2_I(dir);
2871-
struct ocfs2_alloc_context *data_ac;
2871+
struct ocfs2_alloc_context *data_ac = NULL;
28722872
struct ocfs2_alloc_context *meta_ac = NULL;
28732873
struct buffer_head *dirdata_bh = NULL;
28742874
struct buffer_head *dx_root_bh = NULL;

fs/ocfs2/dlm/dlmdomain.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,8 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
16141614
spin_unlock(&dlm->spinlock);
16151615

16161616
/* Support for global heartbeat and node info was added in 1.1 */
1617-
if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) {
1617+
if (dlm->dlm_locking_proto.pv_major > 1 ||
1618+
dlm->dlm_locking_proto.pv_minor > 0) {
16181619
status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map);
16191620
if (status) {
16201621
mlog_errno(status);

fs/ocfs2/dlm/dlmmaster.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,9 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
25742574
res->state &= ~DLM_LOCK_RES_MIGRATING;
25752575
wake = 1;
25762576
spin_unlock(&res->spinlock);
2577+
if (dlm_is_host_down(ret))
2578+
dlm_wait_for_node_death(dlm, target,
2579+
DLM_NODE_DEATH_WAIT_MAX);
25772580
goto leave;
25782581
}
25792582

fs/ocfs2/file.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
16071607
range = le32_to_cpu(rec->e_cpos) + ocfs2_rec_clusters(el, rec);
16081608

16091609
if (le32_to_cpu(rec->e_cpos) >= trunc_start) {
1610+
/*
1611+
* remove an entire extent record.
1612+
*/
16101613
*trunc_cpos = le32_to_cpu(rec->e_cpos);
16111614
/*
16121615
* Skip holes if any.
@@ -1617,7 +1620,16 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
16171620
*blkno = le64_to_cpu(rec->e_blkno);
16181621
*trunc_end = le32_to_cpu(rec->e_cpos);
16191622
} else if (range > trunc_start) {
1623+
/*
1624+
* remove a partial extent record, which means we're
1625+
* removing the last extent record.
1626+
*/
16201627
*trunc_cpos = trunc_start;
1628+
/*
1629+
* skip hole if any.
1630+
*/
1631+
if (range < *trunc_end)
1632+
*trunc_end = range;
16211633
*trunc_len = *trunc_end - trunc_start;
16221634
coff = trunc_start - le32_to_cpu(rec->e_cpos);
16231635
*blkno = le64_to_cpu(rec->e_blkno) +

fs/ocfs2/journal.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,9 @@ void ocfs2_complete_mount_recovery(struct ocfs2_super *osb)
12601260
{
12611261
struct ocfs2_journal *journal = osb->journal;
12621262

1263+
if (ocfs2_is_hard_readonly(osb))
1264+
return;
1265+
12631266
/* No need to queue up our truncate_log as regular cleanup will catch
12641267
* that */
12651268
ocfs2_queue_recovery_completion(journal, osb->slot_num,

0 commit comments

Comments
 (0)