[Ocfs2-devel] [PATCH 2/2] Ocfs2: Handle deletion of refcounted oprhan_inode correctly.
tristan
tristan.ye at oracle.com
Sun Feb 28 18:21:03 PST 2010
Joel Becker wrote:
> On Sat, Feb 27, 2010 at 06:34:02PM +0800, tristan ye wrote:
>
>>> Why is this necessary? Don't we have the open lock on the
>>> reflink target? That should keep an orphan scan from wiping a life
>>> refount target. Tao, do we not have the open lock?
>>>
>>>
>> Yes, we have the open lock all time during reflink operation, but we
>> didn't hold the orphan_dir's lock during this period, which means
>> orphan_scan would have a chance to add our half-refcounted target into
>> its working queue, which will be deferred to invoke ocfs2_inode_delete
>> after reflink operation done(actually it always be invoked after reflink
>> done since we hold the open lock of target inode all the time), in this
>> case, we definitely failed at ocfs2_query_inode_wipe() as bug 1215
>> described, since the ORPHAN_FLAG here have been cleared by reflink
>> operation. that's not so good to me, we shouldn't have treated this as a
>> 'ML_ERROR'.
>>
>
> Aha! I think this is what we're all missing. The rule of the
> orphan dir is that all inodes in the orphan dir have ORPHANED_FL. But
> you're right, we queue the orphans. A reflink inode can be moved out of
> the orphan dir and have its ORPHANED_FL cleared before the queue is run.
> Thus, the queue finds an inode without ORPHANED_FL. This is correct,
> because the inode is no longer orphaned.
>
Yes, that's exactly what I meant:)
> The comment didn't help me. Let's try reversing the order and
> changing the comment.
>
Yes, comment here is expected to be more descriptive.
> -----------------------------------------------------------------
> if (!(di->i_flags & cpu_to_le32(OCFS2_ORPHANED_FL))) {
> + /*
> + * Inodes in the orphan dir must have ORPHANED_FL. The
> + * only inodes that come back out of the orphan dir are
> + * reflink targets. A reflink target may be moved out
> + * of the orphan dir between the time we scan the
> + * directory and the time we process it. This would
> + * lead to HAS_REFCOUNT_FL being set but ORPHANED_FL
> + * not.
> + */
> + if (di->i_dyn_features & cpu_to_le16(OCFS2_HAS_REFCOUNT_FL)) {
> + mlog(0, "Reflinked inode %llu is no longer orphaned. "
> + "it must not be deleted\n",
> + (unsigned long long)oi->ip_blkno);
> + goto bail;
> + }
> +
> /* for lack of a better error? */
>
Oh, Joel,
I loved your comments...it's more straightforward and makes much more sense.
> status = -EEXIST;
> mlog(ML_ERROR,
> "Inode %llu (on-disk %llu) not orphaned! "
> "Disk flags 0x%x, inode flags 0x%x\n",
> (unsigned long long)oi->ip_blkno,
> (unsigned long long)le64_to_cpu(di->i_blkno),
> le32_to_cpu(di->i_flags), oi->ip_flags);
> goto bail;
> }
> -----------------------------------------------------------------
>
> I find this more readable. We're just special casing the
> reflink behavior.
> Now let's look at our cases. First, orphan scans. If the
> orphan flag is not set, we know it was moved out. If ORPHANED_FL is
> set, we continue on to wiping. This checks the open lock. If the open
> lock is held, query_inode_wipe knows it is in use, and it is skipped.
>
Exactly, if it hasn't the open lock, we then know it's a failed reflink
target inode from a crash or something else, which is expected to be
wiped off!
> What about crash recovery? Well, if it is in the orphan dir, it
> will have ORPHANED_FL. We'll process it like normal. If it was already
> moved out, recovery won't see it.
> I think this covers everything.
>
Definitely.
> Joel
>
>
More information about the Ocfs2-devel
mailing list