linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Manfred Spraul <manfred@colorfullife.com>
To: Matthew Wilcox <willy@infradead.org>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH] ipc: Convert ipcs_idr to XArray
Date: Mon, 20 Apr 2020 17:35:20 +0200	[thread overview]
Message-ID: <80ab3182-5a17-7434-9007-33eb1da46d85@colorfullife.com> (raw)
In-Reply-To: <20200326151418.27545-1-willy@infradead.org>

Hi Matthew,

On 3/26/20 4:14 PM, Matthew Wilcox wrote:
> From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
>
> The XArray has better loops than the IDR has, removing the need to
> open-code them.  We also don't need to call idr_destroy() any more.
> Allocating the ID is a little tricky due to needing to get 'seq'
> correct.  Open-code a variant of __xa_alloc() which lets us set the
> ID and the seq before depositing the pointer in the array.
>
> Signed-off-by: Matthew Wilcox <willy@infradead.org>
> ---

> -		max_idx = max(ids->in_use*3/2, ipc_min_cycle);
> -		max_idx = min(max_idx, ipc_mni);
> -
> -		/* allocate the idx, with a NULL struct kern_ipc_perm */
> -		idx = idr_alloc_cyclic(&ids->ipcs_idr, NULL, 0, max_idx,
> -					GFP_NOWAIT);
> -
> -		if (idx >= 0) {
> -			/*
> -			 * idx got allocated successfully.
> -			 * Now calculate the sequence number and set the
> -			 * pointer for real.
> -			 */
> -			if (idx <= ids->last_idx) {
> +		min_idx = ids->next_idx;
> +		new->seq = ids->seq;
> +
> +		/* Modified version of __xa_alloc */
> +		do {
> +			xas.xa_index = min_idx;
> +			xas_find_marked(&xas, max_idx, XA_FREE_MARK);
> +			if (xas.xa_node == XAS_RESTART && min_idx > 0) {
>   				ids->seq++;
>   				if (ids->seq >= ipcid_seq_max())
>   					ids->seq = 0;
> +				new->seq = ids->seq;
> +				xas.xa_index = 0;
> +				min_idx = 0;
> +				xas_find_marked(&xas, max_idx, XA_FREE_MARK);
>   			}

Is is nessary to have that many details of xarray in ipc/util?

This function is not performance critical.

The core requirement is that ipc_obtain_object_check() must scale.

Would it be possible to use something like

     xa_alloc(,entry=NULL,)

     new->seq = ...

     xa_store(,entry=new,);

> -			ids->last_idx = idx;
> -
> -			new->seq = ids->seq;
> -			/* no need for smp_wmb(), this is done
> -			 * inside idr_replace, as part of
> -			 * rcu_assign_pointer
> -			 */

Could you leave the memory barrier comments in the code?

The rcu_assign_pointer() is the first hands-off from semget() or msgget().

Before the rcu_assign_pointer, e.g. semop() calls would return -EINVAL;

After the rcu_assign_pointer, semwhatever() must work - and e.g. the 
permission checks are lockless.

> -			idr_replace(&ids->ipcs_idr, new, idx);
> -		}
> +			if (xas.xa_node == XAS_RESTART)
> +				xas_set_err(&xas, -ENOSPC);
> +			else
> +				new->id = (new->seq << ipcmni_seq_shift()) +
> +					xas.xa_index;

Setting new->id should remain at the end, outside any locking:

The variable has no special protection, access is only allowed after 
proper locking, thus no need to have the initialization in the middle.

What is crucial is that the final value of new->seq is visible to all 
cpus before a storing the pointer.
> +			xas_store(&xas, new);
> +			xas_clear_mark(&xas, XA_FREE_MARK);
> +		} while (__xas_nomem(&xas, GFP_KERNEL));
> +

Just for my curiosity:

If the xas is in an invalid state, then xas_store() will not store anything.
Thus the loop will not store "new" multiple times, it will be stored 
only once.

@@ -472,7 +487,7 @@ void ipc_rmid(struct ipc_ids *ids, struct 
kern_ipc_perm *ipcp)
>   			idx--;
>   			if (idx == -1)
>   				break;
> -		} while (!idr_find(&ids->ipcs_idr, idx));
> +		} while (!xa_load(&ids->ipcs, idx));
>   		ids->max_idx = idx;
>   	}
>   }

Is there an xa_find_last() function?

It is outside of any hot path, I have a patch that does a binary search 
with idr_get_next().

If there is no xa_find_last(), then I would rebase that patch.


--

     Manfred


  parent reply	other threads:[~2020-04-20 15:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-26 15:14 [PATCH] ipc: Convert ipcs_idr to XArray Matthew Wilcox
2020-04-18 20:15 ` Andrew Morton
2020-04-18 21:34   ` Matthew Wilcox
2020-04-18 22:08     ` Andrew Morton
2020-04-20 15:35 ` Manfred Spraul [this message]
2020-04-20 17:06   ` Matthew Wilcox
2020-04-21 18:33     ` Matthew Wilcox

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=80ab3182-5a17-7434-9007-33eb1da46d85@colorfullife.com \
    --to=manfred@colorfullife.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).