.. | .. |
---|
33 | 33 | { |
---|
34 | 34 | int i; |
---|
35 | 35 | struct exfat_entry_set_cache *es; |
---|
| 36 | + unsigned int uni_len = 0, len; |
---|
36 | 37 | |
---|
37 | 38 | es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES); |
---|
38 | 39 | if (!es) |
---|
.. | .. |
---|
51 | 52 | if (exfat_get_entry_type(ep) != TYPE_EXTEND) |
---|
52 | 53 | break; |
---|
53 | 54 | |
---|
54 | | - exfat_extract_uni_name(ep, uniname); |
---|
| 55 | + len = exfat_extract_uni_name(ep, uniname); |
---|
| 56 | + uni_len += len; |
---|
| 57 | + if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH) |
---|
| 58 | + break; |
---|
55 | 59 | uniname += EXFAT_FILE_NAME_LEN; |
---|
56 | 60 | } |
---|
57 | 61 | |
---|
.. | .. |
---|
102 | 106 | clu.dir = ei->hint_bmap.clu; |
---|
103 | 107 | } |
---|
104 | 108 | |
---|
105 | | - while (clu_offset > 0) { |
---|
| 109 | + while (clu_offset > 0 && clu.dir != EXFAT_EOF_CLUSTER) { |
---|
106 | 110 | if (exfat_get_next_cluster(sb, &(clu.dir))) |
---|
107 | 111 | return -EIO; |
---|
108 | 112 | |
---|
.. | .. |
---|
148 | 152 | 0); |
---|
149 | 153 | |
---|
150 | 154 | *uni_name.name = 0x0; |
---|
151 | | - exfat_get_uniname_from_ext_entry(sb, &dir, dentry, |
---|
| 155 | + exfat_get_uniname_from_ext_entry(sb, &clu, i, |
---|
152 | 156 | uni_name.name); |
---|
153 | 157 | exfat_utf16_to_nls(sb, &uni_name, |
---|
154 | 158 | dir_entry->namebuf.lfn, |
---|
.. | .. |
---|
210 | 214 | exfat_init_namebuf(nb); |
---|
211 | 215 | } |
---|
212 | 216 | |
---|
213 | | -/* skip iterating emit_dots when dir is empty */ |
---|
| 217 | +/* |
---|
| 218 | + * Before calling dir_emit*(), sbi->s_lock should be released |
---|
| 219 | + * because page fault can occur in dir_emit*(). |
---|
| 220 | + */ |
---|
214 | 221 | #define ITER_POS_FILLED_DOTS (2) |
---|
215 | 222 | static int exfat_iterate(struct file *filp, struct dir_context *ctx) |
---|
216 | 223 | { |
---|
.. | .. |
---|
225 | 232 | int err = 0, fake_offset = 0; |
---|
226 | 233 | |
---|
227 | 234 | exfat_init_namebuf(nb); |
---|
228 | | - mutex_lock(&EXFAT_SB(sb)->s_lock); |
---|
229 | 235 | |
---|
230 | 236 | cpos = ctx->pos; |
---|
231 | 237 | if (!dir_emit_dots(filp, ctx)) |
---|
232 | | - goto unlock; |
---|
| 238 | + goto out; |
---|
233 | 239 | |
---|
234 | 240 | if (ctx->pos == ITER_POS_FILLED_DOTS) { |
---|
235 | 241 | cpos = 0; |
---|
236 | 242 | fake_offset = 1; |
---|
237 | 243 | } |
---|
238 | 244 | |
---|
239 | | - if (cpos & (DENTRY_SIZE - 1)) { |
---|
240 | | - err = -ENOENT; |
---|
241 | | - goto unlock; |
---|
242 | | - } |
---|
| 245 | + cpos = round_up(cpos, DENTRY_SIZE); |
---|
243 | 246 | |
---|
244 | 247 | /* name buffer should be allocated before use */ |
---|
245 | 248 | err = exfat_alloc_namebuf(nb); |
---|
246 | 249 | if (err) |
---|
247 | | - goto unlock; |
---|
| 250 | + goto out; |
---|
248 | 251 | get_new: |
---|
| 252 | + mutex_lock(&EXFAT_SB(sb)->s_lock); |
---|
| 253 | + |
---|
249 | 254 | if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode)) |
---|
250 | 255 | goto end_of_dir; |
---|
251 | 256 | |
---|
252 | 257 | err = exfat_readdir(inode, &cpos, &de); |
---|
253 | 258 | if (err) { |
---|
254 | 259 | /* |
---|
255 | | - * At least we tried to read a sector. Move cpos to next sector |
---|
256 | | - * position (should be aligned). |
---|
| 260 | + * At least we tried to read a sector. |
---|
| 261 | + * Move cpos to next sector position (should be aligned). |
---|
257 | 262 | */ |
---|
258 | 263 | if (err == -EIO) { |
---|
259 | 264 | cpos += 1 << (sb->s_blocksize_bits); |
---|
.. | .. |
---|
276 | 281 | inum = iunique(sb, EXFAT_ROOT_INO); |
---|
277 | 282 | } |
---|
278 | 283 | |
---|
279 | | - /* |
---|
280 | | - * Before calling dir_emit(), sb_lock should be released. |
---|
281 | | - * Because page fault can occur in dir_emit() when the size |
---|
282 | | - * of buffer given from user is larger than one page size. |
---|
283 | | - */ |
---|
284 | 284 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
---|
285 | 285 | if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum, |
---|
286 | 286 | (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) |
---|
287 | | - goto out_unlocked; |
---|
288 | | - mutex_lock(&EXFAT_SB(sb)->s_lock); |
---|
| 287 | + goto out; |
---|
289 | 288 | ctx->pos = cpos; |
---|
290 | 289 | goto get_new; |
---|
291 | 290 | |
---|
.. | .. |
---|
293 | 292 | if (!cpos && fake_offset) |
---|
294 | 293 | cpos = ITER_POS_FILLED_DOTS; |
---|
295 | 294 | ctx->pos = cpos; |
---|
296 | | -unlock: |
---|
297 | 295 | mutex_unlock(&EXFAT_SB(sb)->s_lock); |
---|
298 | | -out_unlocked: |
---|
| 296 | +out: |
---|
299 | 297 | /* |
---|
300 | 298 | * To improve performance, free namebuf after unlock sb_lock. |
---|
301 | 299 | * If namebuf is not allocated, this function do nothing |
---|
.. | .. |
---|
615 | 613 | bforget(es->bh[i]); |
---|
616 | 614 | else |
---|
617 | 615 | brelse(es->bh[i]); |
---|
| 616 | + |
---|
| 617 | + if (IS_DYNAMIC_ES(es)) |
---|
| 618 | + kfree(es->bh); |
---|
| 619 | + |
---|
618 | 620 | kfree(es); |
---|
619 | 621 | return err; |
---|
620 | 622 | } |
---|
.. | .. |
---|
850 | 852 | /* byte offset in sector */ |
---|
851 | 853 | off = EXFAT_BLK_OFFSET(byte_offset, sb); |
---|
852 | 854 | es->start_off = off; |
---|
| 855 | + es->bh = es->__bh; |
---|
853 | 856 | |
---|
854 | 857 | /* sector offset in cluster */ |
---|
855 | 858 | sec = EXFAT_B_TO_BLK(byte_offset, sb); |
---|
.. | .. |
---|
869 | 872 | es->num_entries = num_entries; |
---|
870 | 873 | |
---|
871 | 874 | num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb); |
---|
| 875 | + if (num_bh > ARRAY_SIZE(es->__bh)) { |
---|
| 876 | + es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_KERNEL); |
---|
| 877 | + if (!es->bh) { |
---|
| 878 | + brelse(bh); |
---|
| 879 | + kfree(es); |
---|
| 880 | + return NULL; |
---|
| 881 | + } |
---|
| 882 | + es->bh[0] = bh; |
---|
| 883 | + } |
---|
| 884 | + |
---|
872 | 885 | for (i = 1; i < num_bh; i++) { |
---|
873 | 886 | /* get the next sector */ |
---|
874 | 887 | if (exfat_is_last_sector_in_cluster(sbi, sec)) { |
---|
.. | .. |
---|
908 | 921 | }; |
---|
909 | 922 | |
---|
910 | 923 | /* |
---|
911 | | - * return values: |
---|
912 | | - * >= 0 : return dir entiry position with the name in dir |
---|
913 | | - * -ENOENT : entry with the name does not exist |
---|
914 | | - * -EIO : I/O error |
---|
| 924 | + * @ei: inode info of parent directory |
---|
| 925 | + * @p_dir: directory structure of parent directory |
---|
| 926 | + * @num_entries:entry size of p_uniname |
---|
| 927 | + * @hint_opt: If p_uniname is found, filled with optimized dir/entry |
---|
| 928 | + * for traversing cluster chain. |
---|
| 929 | + * @return: |
---|
| 930 | + * >= 0: file directory entry position where the name exists |
---|
| 931 | + * -ENOENT: entry with the name does not exist |
---|
| 932 | + * -EIO: I/O error |
---|
915 | 933 | */ |
---|
916 | 934 | int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, |
---|
917 | 935 | struct exfat_chain *p_dir, struct exfat_uni_name *p_uniname, |
---|
918 | | - int num_entries, unsigned int type) |
---|
| 936 | + int num_entries, unsigned int type, struct exfat_hint *hint_opt) |
---|
919 | 937 | { |
---|
920 | 938 | int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len; |
---|
921 | 939 | int order, step, name_len = 0; |
---|
.. | .. |
---|
992 | 1010 | |
---|
993 | 1011 | if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) { |
---|
994 | 1012 | step = DIRENT_STEP_FILE; |
---|
| 1013 | + hint_opt->clu = clu.dir; |
---|
| 1014 | + hint_opt->eidx = i; |
---|
995 | 1015 | if (type == TYPE_ALL || type == entry_type) { |
---|
996 | 1016 | num_ext = ep->dentry.file.num_ext; |
---|
997 | 1017 | step = DIRENT_STEP_STRM; |
---|
.. | .. |
---|
1026 | 1046 | if (entry_type == TYPE_EXTEND) { |
---|
1027 | 1047 | unsigned short entry_uniname[16], unichar; |
---|
1028 | 1048 | |
---|
1029 | | - if (step != DIRENT_STEP_NAME) { |
---|
| 1049 | + if (step != DIRENT_STEP_NAME || |
---|
| 1050 | + name_len >= MAX_NAME_LENGTH) { |
---|
1030 | 1051 | step = DIRENT_STEP_FILE; |
---|
1031 | 1052 | continue; |
---|
1032 | 1053 | } |
---|