Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f80fbff authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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)
parents fce51958 24307aa1
Loading
Loading
Loading
Loading
+32 −7
Original line number Diff line number Diff line
@@ -57,7 +57,10 @@ static void configfs_d_iput(struct dentry * dentry,

	if (sd) {
		BUG_ON(sd->s_dentry != dentry);
		/* Coordinate with configfs_readdir */
		spin_lock(&configfs_dirent_lock);
		sd->s_dentry = NULL;
		spin_unlock(&configfs_dirent_lock);
		configfs_put(sd);
	}
	iput(inode);
@@ -689,7 +692,8 @@ static int create_default_group(struct config_group *parent_group,
			sd = child->d_fsdata;
			sd->s_type |= CONFIGFS_USET_DEFAULT;
		} else {
			d_delete(child);
			BUG_ON(child->d_inode);
			d_drop(child);
			dput(child);
		}
	}
@@ -1545,7 +1549,7 @@ static int configfs_readdir(struct file * filp, void * dirent, filldir_t filldir
	struct configfs_dirent * parent_sd = dentry->d_fsdata;
	struct configfs_dirent *cursor = filp->private_data;
	struct list_head *p, *q = &cursor->s_sibling;
	ino_t ino;
	ino_t ino = 0;
	int i = filp->f_pos;

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

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

				name = configfs_get_name(next);
				len = strlen(name);
				if (next->s_dentry)
					ino = next->s_dentry->d_inode->i_ino;
				else

				/*
				 * We'll have a dentry and an inode for
				 * PINNED items and for open attribute
				 * files.  We lock here to prevent a race
				 * with configfs_d_iput() clearing
				 * s_dentry before calling iput().
				 *
				 * Why do we go to the trouble?  If
				 * someone has an attribute file open,
				 * the inode number should match until
				 * they close it.  Beyond that, we don't
				 * care.
				 */
				spin_lock(&configfs_dirent_lock);
				dentry = next->s_dentry;
				if (dentry)
					inode = dentry->d_inode;
				if (inode)
					ino = inode->i_ino;
				spin_unlock(&configfs_dirent_lock);
				if (!inode)
					ino = iunique(configfs_sb, 2);

				if (filldir(dirent, name, len, filp->f_pos, ino,
@@ -1683,7 +1707,8 @@ int configfs_register_subsystem(struct configfs_subsystem *subsys)
		err = configfs_attach_group(sd->s_element, &group->cg_item,
					    dentry);
		if (err) {
			d_delete(dentry);
			BUG_ON(dentry->d_inode);
			d_drop(dentry);
			dput(dentry);
		} else {
			spin_lock(&configfs_dirent_lock);
+43 −18
Original line number Diff line number Diff line
@@ -539,25 +539,41 @@ static int o2hb_verify_crc(struct o2hb_region *reg,

/* We want to make sure that nobody is heartbeating on top of us --
 * this will help detect an invalid configuration. */
static int o2hb_check_last_timestamp(struct o2hb_region *reg)
static void o2hb_check_last_timestamp(struct o2hb_region *reg)
{
	int node_num, ret;
	struct o2hb_disk_slot *slot;
	struct o2hb_disk_heartbeat_block *hb_block;
	char *errstr;

	node_num = o2nm_this_node();

	ret = 1;
	slot = &reg->hr_slots[node_num];
	slot = &reg->hr_slots[o2nm_this_node()];
	/* Don't check on our 1st timestamp */
	if (slot->ds_last_time) {
	if (!slot->ds_last_time)
		return;

	hb_block = slot->ds_raw_block;
	if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time &&
	    le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation &&
	    hb_block->hb_node == slot->ds_node_num)
		return;

		if (le64_to_cpu(hb_block->hb_seq) != slot->ds_last_time)
			ret = 0;
	}
#define ERRSTR1		"Another node is heartbeating on device"
#define ERRSTR2		"Heartbeat generation mismatch on device"
#define ERRSTR3		"Heartbeat sequence mismatch on device"

	return ret;
	if (hb_block->hb_node != slot->ds_node_num)
		errstr = ERRSTR1;
	else if (le64_to_cpu(hb_block->hb_generation) !=
		 slot->ds_last_generation)
		errstr = ERRSTR2;
	else
		errstr = ERRSTR3;

	mlog(ML_ERROR, "%s (%s): expected(%u:0x%llx, 0x%llx), "
	     "ondisk(%u:0x%llx, 0x%llx)\n", errstr, reg->hr_dev_name,
	     slot->ds_node_num, (unsigned long long)slot->ds_last_generation,
	     (unsigned long long)slot->ds_last_time, hb_block->hb_node,
	     (unsigned long long)le64_to_cpu(hb_block->hb_generation),
	     (unsigned long long)le64_to_cpu(hb_block->hb_seq));
}

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

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

	i = -1;
	while((i = find_next_bit(configured_nodes, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {

	while((i = find_next_bit(configured_nodes,
				 O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
		change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
	}

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

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

	hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
			      reg->hr_item.ci_name);
+1 −1
Original line number Diff line number Diff line
@@ -2868,7 +2868,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
		bytes = blocks_wanted << sb->s_blocksize_bits;
	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
	struct ocfs2_inode_info *oi = OCFS2_I(dir);
	struct ocfs2_alloc_context *data_ac;
	struct ocfs2_alloc_context *data_ac = NULL;
	struct ocfs2_alloc_context *meta_ac = NULL;
	struct buffer_head *dirdata_bh = NULL;
	struct buffer_head *dx_root_bh = NULL;
+2 −1
Original line number Diff line number Diff line
@@ -1614,7 +1614,8 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
	spin_unlock(&dlm->spinlock);

	/* Support for global heartbeat and node info was added in 1.1 */
	if (dlm_protocol.pv_major > 1 || dlm_protocol.pv_minor > 0) {
	if (dlm->dlm_locking_proto.pv_major > 1 ||
	    dlm->dlm_locking_proto.pv_minor > 0) {
		status = dlm_send_nodeinfo(dlm, ctxt->yes_resp_map);
		if (status) {
			mlog_errno(status);
+3 −0
Original line number Diff line number Diff line
@@ -2574,6 +2574,9 @@ fail:
		res->state &= ~DLM_LOCK_RES_MIGRATING;
		wake = 1;
		spin_unlock(&res->spinlock);
		if (dlm_is_host_down(ret))
			dlm_wait_for_node_death(dlm, target,
						DLM_NODE_DEATH_WAIT_MAX);
		goto leave;
	}

Loading