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

Commit a30bfd6c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2:
  O2net: Disallow o2net accept connection request from itself.
  ocfs2/dlm: remove potential deadlock -V3
  ocfs2/dlm: avoid incorrect bit set in refmap on recovery master
  Fix the nested PR lock calling issue in ACL
  ocfs2: Count more refcount records in file system fragmentation.
  ocfs2 fix o2dlm dlm run purgelist (rev 3)
  ocfs2/dlm: fix a dead lock
  ocfs2: do not overwrite error codes in ocfs2_init_acl
parents 4b17cafa 415cf32c
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -290,12 +290,30 @@ static int ocfs2_set_acl(handle_t *handle,

int ocfs2_check_acl(struct inode *inode, int mask)
{
	struct posix_acl *acl = ocfs2_get_acl(inode, ACL_TYPE_ACCESS);
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct buffer_head *di_bh = NULL;
	struct posix_acl *acl;
	int ret = -EAGAIN;

	if (IS_ERR(acl))
	if (!(osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL))
		return ret;

	ret = ocfs2_read_inode_block(inode, &di_bh);
	if (ret < 0) {
		mlog_errno(ret);
		return ret;
	}

	acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, di_bh);

	brelse(di_bh);

	if (IS_ERR(acl)) {
		mlog_errno(PTR_ERR(acl));
		return PTR_ERR(acl);
	}
	if (acl) {
		int ret = posix_acl_permission(inode, acl, mask);
		ret = posix_acl_permission(inode, acl, mask);
		posix_acl_release(acl);
		return ret;
	}
@@ -344,7 +362,7 @@ int ocfs2_init_acl(handle_t *handle,
{
	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
	struct posix_acl *acl = NULL;
	int ret = 0;
	int ret = 0, ret2;
	mode_t mode;

	if (!S_ISLNK(inode->i_mode)) {
@@ -381,7 +399,12 @@ int ocfs2_init_acl(handle_t *handle,
		mode = inode->i_mode;
		ret = posix_acl_create_masq(clone, &mode);
		if (ret >= 0) {
			ret = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
			ret2 = ocfs2_acl_set_mode(inode, di_bh, handle, mode);
			if (ret2) {
				mlog_errno(ret2);
				ret = ret2;
				goto cleanup;
			}
			if (ret > 0) {
				ret = ocfs2_set_acl(handle, inode,
						    di_bh, ACL_TYPE_ACCESS,
+12 −5
Original line number Diff line number Diff line
@@ -1759,6 +1759,7 @@ static int o2net_accept_one(struct socket *sock)
	struct sockaddr_in sin;
	struct socket *new_sock = NULL;
	struct o2nm_node *node = NULL;
	struct o2nm_node *local_node = NULL;
	struct o2net_sock_container *sc = NULL;
	struct o2net_node *nn;

@@ -1796,11 +1797,15 @@ static int o2net_accept_one(struct socket *sock)
		goto out;
	}

	if (o2nm_this_node() > node->nd_num) {
		mlog(ML_NOTICE, "unexpected connect attempted from a lower "
		     "numbered node '%s' at " "%pI4:%d with num %u\n",
		     node->nd_name, &sin.sin_addr.s_addr,
		     ntohs(sin.sin_port), node->nd_num);
	if (o2nm_this_node() >= node->nd_num) {
		local_node = o2nm_get_node_by_num(o2nm_this_node());
		mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' ("
		     "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n",
		     local_node->nd_name, local_node->nd_num,
		     &(local_node->nd_ipv4_address),
		     ntohs(local_node->nd_ipv4_port),
		     node->nd_name, node->nd_num, &sin.sin_addr.s_addr,
		     ntohs(sin.sin_port));
		ret = -EINVAL;
		goto out;
	}
@@ -1857,6 +1862,8 @@ out:
		sock_release(new_sock);
	if (node)
		o2nm_node_put(node);
	if (local_node)
		o2nm_node_put(local_node);
	if (sc)
		sc_put(sc);
	return ret;
+2 −7
Original line number Diff line number Diff line
@@ -511,8 +511,6 @@ static void dlm_lockres_release(struct kref *kref)

	atomic_dec(&dlm->res_cur_count);

	dlm_put(dlm);

	if (!hlist_unhashed(&res->hash_node) ||
	    !list_empty(&res->granted) ||
	    !list_empty(&res->converting) ||
@@ -585,8 +583,6 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm,
	res->migration_pending = 0;
	res->inflight_locks = 0;

	/* put in dlm_lockres_release */
	dlm_grab(dlm);
	res->dlm = dlm;

	kref_init(&res->refs);
@@ -3050,8 +3046,6 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
	/* check for pre-existing lock */
	spin_lock(&dlm->spinlock);
	res = __dlm_lookup_lockres(dlm, name, namelen, hash);
	spin_lock(&dlm->master_lock);

	if (res) {
		spin_lock(&res->spinlock);
		if (res->state & DLM_LOCK_RES_RECOVERING) {
@@ -3069,14 +3063,15 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data,
		spin_unlock(&res->spinlock);
	}

	spin_lock(&dlm->master_lock);
	/* ignore status.  only nonzero status would BUG. */
	ret = dlm_add_migration_mle(dlm, res, mle, &oldmle,
				    name, namelen,
				    migrate->new_master,
				    migrate->master);

unlock:
	spin_unlock(&dlm->master_lock);
unlock:
	spin_unlock(&dlm->spinlock);

	if (oldmle) {
+10 −12
Original line number Diff line number Diff line
@@ -1997,6 +1997,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm,
	struct list_head *queue;
	struct dlm_lock *lock, *next;

	assert_spin_locked(&dlm->spinlock);
	assert_spin_locked(&res->spinlock);
	res->state |= DLM_LOCK_RES_RECOVERING;
	if (!list_empty(&res->recovering)) {
		mlog(0,
@@ -2326,19 +2328,15 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
			/* zero the lvb if necessary */
			dlm_revalidate_lvb(dlm, res, dead_node);
			if (res->owner == dead_node) {
				if (res->state & DLM_LOCK_RES_DROPPING_REF)
					mlog(0, "%s:%.*s: owned by "
					     "dead node %u, this node was "
					     "dropping its ref when it died. "
					     "continue, dropping the flag.\n",
					     dlm->name, res->lockname.len,
					     res->lockname.name, dead_node);

				/* the wake_up for this will happen when the
				 * RECOVERING flag is dropped later */
				res->state &= ~DLM_LOCK_RES_DROPPING_REF;
				if (res->state & DLM_LOCK_RES_DROPPING_REF) {
					mlog(ML_NOTICE, "Ignore %.*s for "
					     "recovery as it is being freed\n",
					     res->lockname.len,
					     res->lockname.name);
				} else
					dlm_move_lockres_to_recovery_list(dlm,
									  res);

				dlm_move_lockres_to_recovery_list(dlm, res);
			} else if (res->owner == dlm->node_num) {
				dlm_free_dead_locks(dlm, res, dead_node);
				__dlm_lockres_calc_usage(dlm, res);
+55 −59
Original line number Diff line number Diff line
@@ -92,20 +92,28 @@ int __dlm_lockres_has_locks(struct dlm_lock_resource *res)
 * truly ready to be freed. */
int __dlm_lockres_unused(struct dlm_lock_resource *res)
{
	if (!__dlm_lockres_has_locks(res) &&
	    (list_empty(&res->dirty) && !(res->state & DLM_LOCK_RES_DIRTY))) {
		/* try not to scan the bitmap unless the first two
		 * conditions are already true */
		int bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
		if (bit >= O2NM_MAX_NODES) {
			/* since the bit for dlm->node_num is not
			 * set, inflight_locks better be zero */
	int bit;

	if (__dlm_lockres_has_locks(res))
		return 0;

	if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
		return 0;

	if (res->state & DLM_LOCK_RES_RECOVERING)
		return 0;

	bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
	if (bit < O2NM_MAX_NODES)
		return 0;

	/*
	 * since the bit for dlm->node_num is not set, inflight_locks better
	 * be zero
	 */
	BUG_ON(res->inflight_locks != 0);
	return 1;
}
	}
	return 0;
}


/* Call whenever you may have added or deleted something from one of
@@ -152,45 +160,25 @@ void dlm_lockres_calc_usage(struct dlm_ctxt *dlm,
	spin_unlock(&dlm->spinlock);
}

static int dlm_purge_lockres(struct dlm_ctxt *dlm,
static void dlm_purge_lockres(struct dlm_ctxt *dlm,
			     struct dlm_lock_resource *res)
{
	int master;
	int ret = 0;

	spin_lock(&res->spinlock);
	if (!__dlm_lockres_unused(res)) {
		mlog(0, "%s:%.*s: tried to purge but not unused\n",
		     dlm->name, res->lockname.len, res->lockname.name);
		__dlm_print_one_lock_resource(res);
		spin_unlock(&res->spinlock);
		BUG();
	}

	if (res->state & DLM_LOCK_RES_MIGRATING) {
		mlog(0, "%s:%.*s: Delay dropref as this lockres is "
		     "being remastered\n", dlm->name, res->lockname.len,
		     res->lockname.name);
		/* Re-add the lockres to the end of the purge list */
		if (!list_empty(&res->purge)) {
			list_del_init(&res->purge);
			list_add_tail(&res->purge, &dlm->purge_list);
		}
		spin_unlock(&res->spinlock);
		return 0;
	}
	assert_spin_locked(&dlm->spinlock);
	assert_spin_locked(&res->spinlock);

	master = (res->owner == dlm->node_num);

	if (!master)
		res->state |= DLM_LOCK_RES_DROPPING_REF;
	spin_unlock(&res->spinlock);

	mlog(0, "purging lockres %.*s, master = %d\n", res->lockname.len,
	     res->lockname.name, master);

	if (!master) {
		res->state |= DLM_LOCK_RES_DROPPING_REF;
		/* drop spinlock...  retake below */
		spin_unlock(&res->spinlock);
		spin_unlock(&dlm->spinlock);

		spin_lock(&res->spinlock);
@@ -208,31 +196,35 @@ static int dlm_purge_lockres(struct dlm_ctxt *dlm,
		mlog(0, "%s:%.*s: dlm_deref_lockres returned %d\n",
		     dlm->name, res->lockname.len, res->lockname.name, ret);
		spin_lock(&dlm->spinlock);
		spin_lock(&res->spinlock);
	}

	spin_lock(&res->spinlock);
	if (!list_empty(&res->purge)) {
		mlog(0, "removing lockres %.*s:%p from purgelist, "
		     "master = %d\n", res->lockname.len, res->lockname.name,
		     res, master);
		list_del_init(&res->purge);
		spin_unlock(&res->spinlock);
		dlm_lockres_put(res);
		dlm->purge_count--;
	} else
		spin_unlock(&res->spinlock);
	}

	if (!__dlm_lockres_unused(res)) {
		mlog(ML_ERROR, "found lockres %s:%.*s: in use after deref\n",
		     dlm->name, res->lockname.len, res->lockname.name);
		__dlm_print_one_lock_resource(res);
		BUG();
	}

	__dlm_unhash_lockres(res);

	/* lockres is not in the hash now.  drop the flag and wake up
	 * any processes waiting in dlm_get_lock_resource. */
	if (!master) {
		spin_lock(&res->spinlock);
		res->state &= ~DLM_LOCK_RES_DROPPING_REF;
		spin_unlock(&res->spinlock);
		wake_up(&res->wq);
	}
	return 0;
	} else
		spin_unlock(&res->spinlock);
}

static void dlm_run_purge_list(struct dlm_ctxt *dlm,
@@ -251,17 +243,7 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
		lockres = list_entry(dlm->purge_list.next,
				     struct dlm_lock_resource, purge);

		/* Status of the lockres *might* change so double
		 * check. If the lockres is unused, holding the dlm
		 * spinlock will prevent people from getting and more
		 * refs on it -- there's no need to keep the lockres
		 * spinlock. */
		spin_lock(&lockres->spinlock);
		unused = __dlm_lockres_unused(lockres);
		spin_unlock(&lockres->spinlock);

		if (!unused)
			continue;

		purge_jiffies = lockres->last_used +
			msecs_to_jiffies(DLM_PURGE_INTERVAL_MS);
@@ -273,15 +255,29 @@ static void dlm_run_purge_list(struct dlm_ctxt *dlm,
			 * in tail order, we can stop at the first
			 * unpurgable resource -- anyone added after
			 * him will have a greater last_used value */
			spin_unlock(&lockres->spinlock);
			break;
		}

		/* Status of the lockres *might* change so double
		 * check. If the lockres is unused, holding the dlm
		 * spinlock will prevent people from getting and more
		 * refs on it. */
		unused = __dlm_lockres_unused(lockres);
		if (!unused ||
		    (lockres->state & DLM_LOCK_RES_MIGRATING)) {
			mlog(0, "lockres %s:%.*s: is in use or "
			     "being remastered, used %d, state %d\n",
			     dlm->name, lockres->lockname.len,
			     lockres->lockname.name, !unused, lockres->state);
			list_move_tail(&dlm->purge_list, &lockres->purge);
			spin_unlock(&lockres->spinlock);
			continue;
		}

		dlm_lockres_get(lockres);

		/* This may drop and reacquire the dlm spinlock if it
		 * has to do migration. */
		if (dlm_purge_lockres(dlm, lockres))
			BUG();
		dlm_purge_lockres(dlm, lockres);

		dlm_lockres_put(lockres);

Loading