Re: [PATCH] sysv: convert pointers_lock from rw_lock to rw_sem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 2023/03/27 9:04, Al Viro wrote:
> However, I don't think this is the right fix.  Note that the problem is
> with get_branch() done under the rwlock; all other places are safe.  But
> in get_branch() we only need the lock (and only shared, at that) around
> the verify+add pair.  See how it's done in fs/minix/itree_common.c...
> Something like this:

I can see fs/minix/itree_common.c is doing similar things. But since I'm not
familiar with filesystems, I can't be convinced that minix's assumption is safe.

>  static Indirect *find_shared(struct inode *inode,
>                                 int depth,
>                                 int offsets[],
>                                 Indirect chain[],
>                                 sysv_zone_t *top)
>  {
>         Indirect *partial, *p;
>         int k, err;
> 
>         *top = 0;
>         for (k = depth; k > 1 && !offsets[k-1]; k--)
>                 ;
> 
> -       write_lock(&pointers_lock);
>         partial = get_branch(inode, k, offsets, chain, &err);

Does the result of verify_chain() from get_branch() remain valid even after
sleep by preemption at this line made get_branch() to execute "*err = -EAGAIN;"
line rather than "return NULL;" line?

>         if (!partial)
>                 partial = chain + k-1;

Can sleep by preemption at this line or

> +
> +       write_lock(&pointers_lock);
>         /*
>          * If the branch acquired continuation since we've looked at it -
>          * fine, it should all survive and (new) top doesn't belong to us.
>          */
>         if (!partial->key && *partial->p) {
>                 write_unlock(&pointers_lock);

at this line change the result of "!partial->key && *partial->p" test above?

>                 goto no_top;
>         }
>         for (p=partial; p>chain && all_zeroes((sysv_zone_t*)p->bh->b_data,p->p); p--)
>                 ;
>         /*
>          * OK, we've found the last block that must survive. The rest of our
>          * branch should be detached before unlocking. However, if that rest
>          * of branch is all ours and does not grow immediately from the inode
>          * it's easier to cheat and just decrement partial->p.
>          */
>         if (p == chain + k - 1 && p > chain) {
>                 p->p--;
>         } else {
>                 *top = *p->p;
>                 *p->p = 0;
>         }
>         write_unlock(&pointers_lock);
>  
>         while (partial > p) {
>                 brelse(partial->bh);
>                 partial--;
>         }
>  no_top:
>         return partial;
>  }

I feel worried about

	/*
	 * Indirect block might be removed by truncate while we were
	 * reading it. Handling of that case (forget what we've got and
	 * reread) is taken out of the main path.
	 */
	if (err == -EAGAIN)
		goto changed;

in get_block()...




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux