On 19.01.2018 12:39, Qu Wenruo wrote: > > > On 2018年01月19日 18:21, Nikolay Borisov wrote: >> >> >> On 19.01.2018 12:03, Qu Wenruo wrote: >>> >>> >>> On 2018年01月19日 17:40, Nikolay Borisov wrote: >>>> >>>> >>>> On 19.01.2018 09:25, Qu Wenruo wrote: >>>>> btrfs_match_dir_item_name() will check if its filetype is valid before >>>>> doing search, this makes btrfs-progs unable to locate and remove invalid >>>>> dir_index for btrfs_unlink().> >>>>> This function only affects btrfs_link() and btrfs_unlink() in upper >>>>> layer, and normal check can find invalid filetype by itself. >>>> >>>> There is no function btrfs_link in btrfs-progs, there is, however, >>>> btrfs_add_link did you mean that function? >>> >>> Yep, sorry for the wrong name. >>> >>>> However, it doesn't seem to >>>> use verify_dir_item hence the check you are removing. I think this part >>>> of the commit log should be more precise. Also it's not really clear >>>> what you mean by "normal check" in this sentence. >>> >>> I skipped several function calls. >>> >>> btrfs_add_link() >>> |- check_dir_conflict >>> |- btrfs_lookup_dir_index() / btrfs_lookup_dir_item() >>> |- btrfs_match_dir_item_name() >>> |- verify_dir_item() >>> >>> And for btrfs_add_link() without checking invalid filetype, we can avoid >>> case like inserting duplicated DIR_ITEM/DIR_INDEX to avoid further >>> screwing up things. >> >> Right, since if verify_dir_item fails we just return NULL as opposed to >> an error from btrfs_match_dir_item_name. >> >> <offtopic> >> Hm, so is it really possible to get a result for (key DIR_ITEM offset) >> and have btrfs_match_dir_item_name fail for that result? >> >> What I'm getting is that if btrfs_Search_slot returns 0 for such a query >> irrespective of whether the string name matches or not we should return >> some error code other than NULL ? > > This sounds reasonable, but it may end up as replacing NULL to > PTR_ERR(-ENOENT).
Well in the case of check_dir_conflict it makes a whole lot of difference. Currently if verify_dir_item fails then we propagate NULL up to check_dir_conflict where we have the following error handling: if (IS_ERR(dir_item)) { ret = PTR_ERR(dir_item); goto out; } if (dir_item) { ret = -EEXIST; goto out; } so NULL won't really trigger anything, OTOH if we return an error and IS_ERR triggers we won't add a duplicate item. Be that as it may, I still think your patch as-is with modified commit message is a good enough fix. > Not much different for callers though. > > Thanks, > Qu > >> </offtopic> >> >> >>> >>> For btrfs_unlink() it will be different story, as btrfs_unlink() can >>> locate the conflicting but invalid DIR_ITEM/DIR_INDEX and remove it, >>> allow us to fix the problem. >>> >>> And by "normal check" I mean btrfs check. >>> >>> I'll add the call trace to it. >>> >>>>> >>>>> So remove the filetype check is completely safe in this case, and will >>>>> enhance btrfs_unlink() to remove invalid dir_index/dir_item for repair. >>>> >>>> So the problem is that since btrfs_unlink calls verify_item and the >>>> latter has the filetype check in case of wrong filetype (corruption) >>>> verify_dir_item fails, hence we cannot perform the unlink? If my >>>> understanding is correct how about something like: >>>> >>>> >>>> If we have a corrupted dir item and enough information to repair it we >>>> need to first delete the old/corrupted version and then insert a new >>>> one. >>>> However, btrfs_unlink calls btrfs_match_dir_item_name to locate the >>>> offending dir item for deletion. The latter, in turn, uses >>>> verify_dir_item which checks if the value for DIR item's type is sane. >>>> In case of a corrupted type value then verify_dir_item will fail which >>>> in turn will prevent btrfs_unlink from deleting the offending item. >>> >>> Your understanding is completely right, and much shorter than my planned >>> explanation. >>> >>> I'll take it with extra call trace. >>> >>> Thanks, >>> Qu >>> >>>> >>>>> >>>>> Signed-off-by: Qu Wenruo <w...@suse.com> >>>>> --- >>>>> dir-item.c | 6 ------ >>>>> 1 file changed, 6 deletions(-) >>>>> >>>>> diff --git a/dir-item.c b/dir-item.c >>>>> index 462546c0eaf4..e0a0ab4d7a5d 100644 >>>>> --- a/dir-item.c >>>>> +++ b/dir-item.c >>>>> @@ -294,12 +294,6 @@ static int verify_dir_item(struct btrfs_root *root, >>>>> u16 namelen = BTRFS_NAME_LEN; >>>>> u8 type = btrfs_dir_type(leaf, dir_item); >>>>> >>>>> - if (type >= BTRFS_FT_MAX) { >>>>> - fprintf(stderr, "invalid dir item type: %d\n", >>>>> - (int)type); >>>>> - return 1; >>>>> - } >>>>> - >>>>> if (type == BTRFS_FT_XATTR) >>>>> namelen = XATTR_NAME_MAX; >>>>> >>>>> >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in >>>> the body of a message to majord...@vger.kernel.org >>>> More majordomo info at http://vger.kernel.org/majordomo-info.html >>>> >>> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html