diff options
Diffstat (limited to 'fs/xfs/xfs_dir2_sf.c')
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 919d275a1cef..b46af0013ec9 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -255,7 +255,7 @@ xfs_dir2_block_to_sf( | |||
255 | xfs_dir2_sf_check(args); | 255 | xfs_dir2_sf_check(args); |
256 | out: | 256 | out: |
257 | xfs_trans_log_inode(args->trans, dp, logflags); | 257 | xfs_trans_log_inode(args->trans, dp, logflags); |
258 | kmem_free(block, mp->m_dirblksize); | 258 | kmem_free(block); |
259 | return error; | 259 | return error; |
260 | } | 260 | } |
261 | 261 | ||
@@ -332,7 +332,7 @@ xfs_dir2_sf_addname( | |||
332 | /* | 332 | /* |
333 | * Just checking or no space reservation, it doesn't fit. | 333 | * Just checking or no space reservation, it doesn't fit. |
334 | */ | 334 | */ |
335 | if (args->justcheck || args->total == 0) | 335 | if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) |
336 | return XFS_ERROR(ENOSPC); | 336 | return XFS_ERROR(ENOSPC); |
337 | /* | 337 | /* |
338 | * Convert to block form then add the name. | 338 | * Convert to block form then add the name. |
@@ -345,7 +345,7 @@ xfs_dir2_sf_addname( | |||
345 | /* | 345 | /* |
346 | * Just checking, it fits. | 346 | * Just checking, it fits. |
347 | */ | 347 | */ |
348 | if (args->justcheck) | 348 | if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
349 | return 0; | 349 | return 0; |
350 | /* | 350 | /* |
351 | * Do it the easy way - just add it at the end. | 351 | * Do it the easy way - just add it at the end. |
@@ -512,7 +512,7 @@ xfs_dir2_sf_addname_hard( | |||
512 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); | 512 | sfep = xfs_dir2_sf_nextentry(sfp, sfep); |
513 | memcpy(sfep, oldsfep, old_isize - nbytes); | 513 | memcpy(sfep, oldsfep, old_isize - nbytes); |
514 | } | 514 | } |
515 | kmem_free(buf, old_isize); | 515 | kmem_free(buf); |
516 | dp->i_d.di_size = new_isize; | 516 | dp->i_d.di_size = new_isize; |
517 | xfs_dir2_sf_check(args); | 517 | xfs_dir2_sf_check(args); |
518 | } | 518 | } |
@@ -812,8 +812,11 @@ xfs_dir2_sf_lookup( | |||
812 | { | 812 | { |
813 | xfs_inode_t *dp; /* incore directory inode */ | 813 | xfs_inode_t *dp; /* incore directory inode */ |
814 | int i; /* entry index */ | 814 | int i; /* entry index */ |
815 | int error; | ||
815 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ | 816 | xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */ |
816 | xfs_dir2_sf_t *sfp; /* shortform structure */ | 817 | xfs_dir2_sf_t *sfp; /* shortform structure */ |
818 | enum xfs_dacmp cmp; /* comparison result */ | ||
819 | xfs_dir2_sf_entry_t *ci_sfep; /* case-insens. entry */ | ||
817 | 820 | ||
818 | xfs_dir2_trace_args("sf_lookup", args); | 821 | xfs_dir2_trace_args("sf_lookup", args); |
819 | xfs_dir2_sf_check(args); | 822 | xfs_dir2_sf_check(args); |
@@ -836,6 +839,7 @@ xfs_dir2_sf_lookup( | |||
836 | */ | 839 | */ |
837 | if (args->namelen == 1 && args->name[0] == '.') { | 840 | if (args->namelen == 1 && args->name[0] == '.') { |
838 | args->inumber = dp->i_ino; | 841 | args->inumber = dp->i_ino; |
842 | args->cmpresult = XFS_CMP_EXACT; | ||
839 | return XFS_ERROR(EEXIST); | 843 | return XFS_ERROR(EEXIST); |
840 | } | 844 | } |
841 | /* | 845 | /* |
@@ -844,28 +848,41 @@ xfs_dir2_sf_lookup( | |||
844 | if (args->namelen == 2 && | 848 | if (args->namelen == 2 && |
845 | args->name[0] == '.' && args->name[1] == '.') { | 849 | args->name[0] == '.' && args->name[1] == '.') { |
846 | args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); | 850 | args->inumber = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); |
851 | args->cmpresult = XFS_CMP_EXACT; | ||
847 | return XFS_ERROR(EEXIST); | 852 | return XFS_ERROR(EEXIST); |
848 | } | 853 | } |
849 | /* | 854 | /* |
850 | * Loop over all the entries trying to match ours. | 855 | * Loop over all the entries trying to match ours. |
851 | */ | 856 | */ |
852 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); | 857 | ci_sfep = NULL; |
853 | i < sfp->hdr.count; | 858 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count; |
854 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { | 859 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { |
855 | if (sfep->namelen == args->namelen && | 860 | /* |
856 | sfep->name[0] == args->name[0] && | 861 | * Compare name and if it's an exact match, return the inode |
857 | memcmp(args->name, sfep->name, args->namelen) == 0) { | 862 | * number. If it's the first case-insensitive match, store the |
858 | args->inumber = | 863 | * inode number and continue looking for an exact match. |
859 | xfs_dir2_sf_get_inumber(sfp, | 864 | */ |
860 | xfs_dir2_sf_inumberp(sfep)); | 865 | cmp = dp->i_mount->m_dirnameops->compname(args, sfep->name, |
861 | return XFS_ERROR(EEXIST); | 866 | sfep->namelen); |
867 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { | ||
868 | args->cmpresult = cmp; | ||
869 | args->inumber = xfs_dir2_sf_get_inumber(sfp, | ||
870 | xfs_dir2_sf_inumberp(sfep)); | ||
871 | if (cmp == XFS_CMP_EXACT) | ||
872 | return XFS_ERROR(EEXIST); | ||
873 | ci_sfep = sfep; | ||
862 | } | 874 | } |
863 | } | 875 | } |
876 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); | ||
864 | /* | 877 | /* |
865 | * Didn't find it. | 878 | * Here, we can only be doing a lookup (not a rename or replace). |
879 | * If a case-insensitive match was not found, return ENOENT. | ||
866 | */ | 880 | */ |
867 | ASSERT(args->oknoent); | 881 | if (!ci_sfep) |
868 | return XFS_ERROR(ENOENT); | 882 | return XFS_ERROR(ENOENT); |
883 | /* otherwise process the CI match as required by the caller */ | ||
884 | error = xfs_dir_cilookup_result(args, ci_sfep->name, ci_sfep->namelen); | ||
885 | return XFS_ERROR(error); | ||
869 | } | 886 | } |
870 | 887 | ||
871 | /* | 888 | /* |
@@ -904,24 +921,21 @@ xfs_dir2_sf_removename( | |||
904 | * Loop over the old directory entries. | 921 | * Loop over the old directory entries. |
905 | * Find the one we're deleting. | 922 | * Find the one we're deleting. |
906 | */ | 923 | */ |
907 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); | 924 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->hdr.count; |
908 | i < sfp->hdr.count; | 925 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { |
909 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { | 926 | if (xfs_da_compname(args, sfep->name, sfep->namelen) == |
910 | if (sfep->namelen == args->namelen && | 927 | XFS_CMP_EXACT) { |
911 | sfep->name[0] == args->name[0] && | ||
912 | memcmp(sfep->name, args->name, args->namelen) == 0) { | ||
913 | ASSERT(xfs_dir2_sf_get_inumber(sfp, | 928 | ASSERT(xfs_dir2_sf_get_inumber(sfp, |
914 | xfs_dir2_sf_inumberp(sfep)) == | 929 | xfs_dir2_sf_inumberp(sfep)) == |
915 | args->inumber); | 930 | args->inumber); |
916 | break; | 931 | break; |
917 | } | 932 | } |
918 | } | 933 | } |
919 | /* | 934 | /* |
920 | * Didn't find it. | 935 | * Didn't find it. |
921 | */ | 936 | */ |
922 | if (i == sfp->hdr.count) { | 937 | if (i == sfp->hdr.count) |
923 | return XFS_ERROR(ENOENT); | 938 | return XFS_ERROR(ENOENT); |
924 | } | ||
925 | /* | 939 | /* |
926 | * Calculate sizes. | 940 | * Calculate sizes. |
927 | */ | 941 | */ |
@@ -1042,11 +1056,10 @@ xfs_dir2_sf_replace( | |||
1042 | */ | 1056 | */ |
1043 | else { | 1057 | else { |
1044 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); | 1058 | for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); |
1045 | i < sfp->hdr.count; | 1059 | i < sfp->hdr.count; |
1046 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { | 1060 | i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { |
1047 | if (sfep->namelen == args->namelen && | 1061 | if (xfs_da_compname(args, sfep->name, sfep->namelen) == |
1048 | sfep->name[0] == args->name[0] && | 1062 | XFS_CMP_EXACT) { |
1049 | memcmp(args->name, sfep->name, args->namelen) == 0) { | ||
1050 | #if XFS_BIG_INUMS || defined(DEBUG) | 1063 | #if XFS_BIG_INUMS || defined(DEBUG) |
1051 | ino = xfs_dir2_sf_get_inumber(sfp, | 1064 | ino = xfs_dir2_sf_get_inumber(sfp, |
1052 | xfs_dir2_sf_inumberp(sfep)); | 1065 | xfs_dir2_sf_inumberp(sfep)); |
@@ -1061,7 +1074,7 @@ xfs_dir2_sf_replace( | |||
1061 | * Didn't find it. | 1074 | * Didn't find it. |
1062 | */ | 1075 | */ |
1063 | if (i == sfp->hdr.count) { | 1076 | if (i == sfp->hdr.count) { |
1064 | ASSERT(args->oknoent); | 1077 | ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); |
1065 | #if XFS_BIG_INUMS | 1078 | #if XFS_BIG_INUMS |
1066 | if (i8elevated) | 1079 | if (i8elevated) |
1067 | xfs_dir2_sf_toino4(args); | 1080 | xfs_dir2_sf_toino4(args); |
@@ -1174,7 +1187,7 @@ xfs_dir2_sf_toino4( | |||
1174 | /* | 1187 | /* |
1175 | * Clean up the inode. | 1188 | * Clean up the inode. |
1176 | */ | 1189 | */ |
1177 | kmem_free(buf, oldsize); | 1190 | kmem_free(buf); |
1178 | dp->i_d.di_size = newsize; | 1191 | dp->i_d.di_size = newsize; |
1179 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); | 1192 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); |
1180 | } | 1193 | } |
@@ -1251,7 +1264,7 @@ xfs_dir2_sf_toino8( | |||
1251 | /* | 1264 | /* |
1252 | * Clean up the inode. | 1265 | * Clean up the inode. |
1253 | */ | 1266 | */ |
1254 | kmem_free(buf, oldsize); | 1267 | kmem_free(buf); |
1255 | dp->i_d.di_size = newsize; | 1268 | dp->i_d.di_size = newsize; |
1256 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); | 1269 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); |
1257 | } | 1270 | } |