diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_block.c')
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index fb5a556725b3..e2fa0a1d8e96 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -215,7 +215,7 @@ xfs_dir2_block_addname( | |||
215 | /* | 215 | /* |
216 | * If this isn't a real add, we're done with the buffer. | 216 | * If this isn't a real add, we're done with the buffer. |
217 | */ | 217 | */ |
218 | if (args->justcheck) | 218 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
219 | xfs_da_brelse(tp, bp); | 219 | xfs_da_brelse(tp, bp); |
220 | /* | 220 | /* |
221 | * If we don't have space for the new entry & leaf ... | 221 | * If we don't have space for the new entry & leaf ... |
@@ -225,7 +225,7 @@ xfs_dir2_block_addname( | |||
225 | * Not trying to actually do anything, or don't have | 225 | * Not trying to actually do anything, or don't have |
226 | * a space reservation: return no-space. | 226 | * a space reservation: return no-space. |
227 | */ | 227 | */ |
228 | if (args->justcheck || args->total == 0) | 228 | if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) |
229 | return XFS_ERROR(ENOSPC); | 229 | return XFS_ERROR(ENOSPC); |
230 | /* | 230 | /* |
231 | * Convert to the next larger format. | 231 | * Convert to the next larger format. |
@@ -240,7 +240,7 @@ xfs_dir2_block_addname( | |||
240 | /* | 240 | /* |
241 | * Just checking, and it would work, so say so. | 241 | * Just checking, and it would work, so say so. |
242 | */ | 242 | */ |
243 | if (args->justcheck) | 243 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
244 | return 0; | 244 | return 0; |
245 | needlog = needscan = 0; | 245 | needlog = needscan = 0; |
246 | /* | 246 | /* |
@@ -610,14 +610,15 @@ xfs_dir2_block_lookup( | |||
610 | /* | 610 | /* |
611 | * Get the offset from the leaf entry, to point to the data. | 611 | * Get the offset from the leaf entry, to point to the data. |
612 | */ | 612 | */ |
613 | dep = (xfs_dir2_data_entry_t *) | 613 | dep = (xfs_dir2_data_entry_t *)((char *)block + |
614 | ((char *)block + xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); | 614 | xfs_dir2_dataptr_to_off(mp, be32_to_cpu(blp[ent].address))); |
615 | /* | 615 | /* |
616 | * Fill in inode number, release the block. | 616 | * Fill in inode number, CI name if appropriate, release the block. |
617 | */ | 617 | */ |
618 | args->inumber = be64_to_cpu(dep->inumber); | 618 | args->inumber = be64_to_cpu(dep->inumber); |
619 | error = xfs_dir_cilookup_result(args, dep->name, dep->namelen); | ||
619 | xfs_da_brelse(args->trans, bp); | 620 | xfs_da_brelse(args->trans, bp); |
620 | return XFS_ERROR(EEXIST); | 621 | return XFS_ERROR(error); |
621 | } | 622 | } |
622 | 623 | ||
623 | /* | 624 | /* |
@@ -643,6 +644,7 @@ xfs_dir2_block_lookup_int( | |||
643 | int mid; /* binary search current idx */ | 644 | int mid; /* binary search current idx */ |
644 | xfs_mount_t *mp; /* filesystem mount point */ | 645 | xfs_mount_t *mp; /* filesystem mount point */ |
645 | xfs_trans_t *tp; /* transaction pointer */ | 646 | xfs_trans_t *tp; /* transaction pointer */ |
647 | enum xfs_dacmp cmp; /* comparison result */ | ||
646 | 648 | ||
647 | dp = args->dp; | 649 | dp = args->dp; |
648 | tp = args->trans; | 650 | tp = args->trans; |
@@ -673,7 +675,7 @@ xfs_dir2_block_lookup_int( | |||
673 | else | 675 | else |
674 | high = mid - 1; | 676 | high = mid - 1; |
675 | if (low > high) { | 677 | if (low > high) { |
676 | ASSERT(args->oknoent); | 678 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); |
677 | xfs_da_brelse(tp, bp); | 679 | xfs_da_brelse(tp, bp); |
678 | return XFS_ERROR(ENOENT); | 680 | return XFS_ERROR(ENOENT); |
679 | } | 681 | } |
@@ -697,20 +699,31 @@ xfs_dir2_block_lookup_int( | |||
697 | dep = (xfs_dir2_data_entry_t *) | 699 | dep = (xfs_dir2_data_entry_t *) |
698 | ((char *)block + xfs_dir2_dataptr_to_off(mp, addr)); | 700 | ((char *)block + xfs_dir2_dataptr_to_off(mp, addr)); |
699 | /* | 701 | /* |
700 | * Compare, if it's right give back buffer & entry number. | 702 | * Compare name and if it's an exact match, return the index |
703 | * and buffer. If it's the first case-insensitive match, store | ||
704 | * the index and buffer and continue looking for an exact match. | ||
701 | */ | 705 | */ |
702 | if (dep->namelen == args->namelen && | 706 | cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); |
703 | dep->name[0] == args->name[0] && | 707 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { |
704 | memcmp(dep->name, args->name, args->namelen) == 0) { | 708 | args->cmpresult = cmp; |
705 | *bpp = bp; | 709 | *bpp = bp; |
706 | *entno = mid; | 710 | *entno = mid; |
707 | return 0; | 711 | if (cmp == XFS_CMP_EXACT) |
712 | return 0; | ||
708 | } | 713 | } |
709 | } while (++mid < be32_to_cpu(btp->count) && be32_to_cpu(blp[mid].hashval) == hash); | 714 | } while (++mid < be32_to_cpu(btp->count) && |
715 | be32_to_cpu(blp[mid].hashval) == hash); | ||
716 | |||
717 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); | ||
718 | /* | ||
719 | * Here, we can only be doing a lookup (not a rename or replace). | ||
720 | * If a case-insensitive match was found earlier, return success. | ||
721 | */ | ||
722 | if (args->cmpresult == XFS_CMP_CASE) | ||
723 | return 0; | ||
710 | /* | 724 | /* |
711 | * No match, release the buffer and return ENOENT. | 725 | * No match, release the buffer and return ENOENT. |
712 | */ | 726 | */ |
713 | ASSERT(args->oknoent); | ||
714 | xfs_da_brelse(tp, bp); | 727 | xfs_da_brelse(tp, bp); |
715 | return XFS_ERROR(ENOENT); | 728 | return XFS_ERROR(ENOENT); |
716 | } | 729 | } |
@@ -1033,6 +1046,7 @@ xfs_dir2_sf_to_block( | |||
1033 | xfs_dir2_sf_t *sfp; /* shortform structure */ | 1046 | xfs_dir2_sf_t *sfp; /* shortform structure */ |
1034 | __be16 *tagp; /* end of data entry */ | 1047 | __be16 *tagp; /* end of data entry */ |
1035 | xfs_trans_t *tp; /* transaction pointer */ | 1048 | xfs_trans_t *tp; /* transaction pointer */ |
1049 | struct xfs_name name; | ||
1036 | 1050 | ||
1037 | xfs_dir2_trace_args("sf_to_block", args); | 1051 | xfs_dir2_trace_args("sf_to_block", args); |
1038 | dp = args->dp; | 1052 | dp = args->dp; |
@@ -1071,7 +1085,7 @@ xfs_dir2_sf_to_block( | |||
1071 | */ | 1085 | */ |
1072 | error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno); | 1086 | error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno); |
1073 | if (error) { | 1087 | if (error) { |
1074 | kmem_free(buf, buf_len); | 1088 | kmem_free(buf); |
1075 | return error; | 1089 | return error; |
1076 | } | 1090 | } |
1077 | /* | 1091 | /* |
@@ -1079,7 +1093,7 @@ xfs_dir2_sf_to_block( | |||
1079 | */ | 1093 | */ |
1080 | error = xfs_dir2_data_init(args, blkno, &bp); | 1094 | error = xfs_dir2_data_init(args, blkno, &bp); |
1081 | if (error) { | 1095 | if (error) { |
1082 | kmem_free(buf, buf_len); | 1096 | kmem_free(buf); |
1083 | return error; | 1097 | return error; |
1084 | } | 1098 | } |
1085 | block = bp->data; | 1099 | block = bp->data; |
@@ -1187,8 +1201,10 @@ xfs_dir2_sf_to_block( | |||
1187 | tagp = xfs_dir2_data_entry_tag_p(dep); | 1201 | tagp = xfs_dir2_data_entry_tag_p(dep); |
1188 | *tagp = cpu_to_be16((char *)dep - (char *)block); | 1202 | *tagp = cpu_to_be16((char *)dep - (char *)block); |
1189 | xfs_dir2_data_log_entry(tp, bp, dep); | 1203 | xfs_dir2_data_log_entry(tp, bp, dep); |
1190 | blp[2 + i].hashval = cpu_to_be32(xfs_da_hashname( | 1204 | name.name = sfep->name; |
1191 | (char *)sfep->name, sfep->namelen)); | 1205 | name.len = sfep->namelen; |
1206 | blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops-> | ||
1207 | hashname(&name)); | ||
1192 | blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, | 1208 | blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, |
1193 | (char *)dep - (char *)block)); | 1209 | (char *)dep - (char *)block)); |
1194 | offset = (int)((char *)(tagp + 1) - (char *)block); | 1210 | offset = (int)((char *)(tagp + 1) - (char *)block); |
@@ -1198,7 +1214,7 @@ xfs_dir2_sf_to_block( | |||
1198 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | 1214 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); |
1199 | } | 1215 | } |
1200 | /* Done with the temporary buffer */ | 1216 | /* Done with the temporary buffer */ |
1201 | kmem_free(buf, buf_len); | 1217 | kmem_free(buf); |
1202 | /* | 1218 | /* |
1203 | * Sort the leaf entries by hash value. | 1219 | * Sort the leaf entries by hash value. |
1204 | */ | 1220 | */ |