Re: [PATCH] z3fold: add inter-page compaction

From: Vitaly Wool
Date: Mon May 27 2019 - 06:57:51 EST


On Sun, May 26, 2019 at 12:09 AM Andrew Morton
<akpm@xxxxxxxxxxxxxxxxxxxx> wrote:

<snip>
> Forward-declaring inline functions is peculiar, but it does appear to work.
>
> z3fold is quite inline-happy. Fortunately the compiler will ignore the
> inline hint if it seems a bad idea. Even then, the below shrinks
> z3fold.o text from 30k to 27k. Which might even make it faster....

It is faster with inlines, I'll try to find a better balance between
size and performance in the next version of the patch though.

<snip>
> >
> > ...
> >
> > +static inline struct z3fold_header *__get_z3fold_header(unsigned long handle,
> > + bool lock)
> > +{
> > + struct z3fold_buddy_slots *slots;
> > + struct z3fold_header *zhdr;
> > + unsigned int seq;
> > + bool is_valid;
> > +
> > + if (!(handle & (1 << PAGE_HEADLESS))) {
> > + slots = handle_to_slots(handle);
> > + do {
> > + unsigned long addr;
> > +
> > + seq = read_seqbegin(&slots->seqlock);
> > + addr = *(unsigned long *)handle;
> > + zhdr = (struct z3fold_header *)(addr & PAGE_MASK);
> > + preempt_disable();
>
> Why is this done?
>
> > + is_valid = !read_seqretry(&slots->seqlock, seq);
> > + if (!is_valid) {
> > + preempt_enable();
> > + continue;
> > + }
> > + /*
> > + * if we are here, zhdr is a pointer to a valid z3fold
> > + * header. Lock it! And then re-check if someone has
> > + * changed which z3fold page this handle points to
> > + */
> > + if (lock)
> > + z3fold_page_lock(zhdr);
> > + preempt_enable();
> > + /*
> > + * we use is_valid as a "cached" value: if it's false,
> > + * no other checks needed, have to go one more round
> > + */
> > + } while (!is_valid || (read_seqretry(&slots->seqlock, seq) &&
> > + (lock ? ({ z3fold_page_unlock(zhdr); 1; }) : 1)));
> > + } else {
> > + zhdr = (struct z3fold_header *)(handle & PAGE_MASK);
> > + }
> > +
> > + return zhdr;
> > +}
> >
> > ...
> >
> > static unsigned short handle_to_chunks(unsigned long handle)
> > {
> > - unsigned long addr = *(unsigned long *)handle;
> > + unsigned long addr;
> > + struct z3fold_buddy_slots *slots = handle_to_slots(handle);
> > + unsigned int seq;
> > +
> > + do {
> > + seq = read_seqbegin(&slots->seqlock);
> > + addr = *(unsigned long *)handle;
> > + } while (read_seqretry(&slots->seqlock, seq));
>
> It isn't done here (I think).

handle_to_chunks() is always called with z3fold header locked which
makes it a lot easier in this case. I'll add some comments in V2.

Thanks,
Vitaly