hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/exfat/dir.c
....@@ -33,6 +33,7 @@
3333 {
3434 int i;
3535 struct exfat_entry_set_cache *es;
36
+ unsigned int uni_len = 0, len;
3637
3738 es = exfat_get_dentry_set(sb, p_dir, entry, ES_ALL_ENTRIES);
3839 if (!es)
....@@ -51,7 +52,10 @@
5152 if (exfat_get_entry_type(ep) != TYPE_EXTEND)
5253 break;
5354
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;
5559 uniname += EXFAT_FILE_NAME_LEN;
5660 }
5761
....@@ -102,7 +106,7 @@
102106 clu.dir = ei->hint_bmap.clu;
103107 }
104108
105
- while (clu_offset > 0) {
109
+ while (clu_offset > 0 && clu.dir != EXFAT_EOF_CLUSTER) {
106110 if (exfat_get_next_cluster(sb, &(clu.dir)))
107111 return -EIO;
108112
....@@ -148,7 +152,7 @@
148152 0);
149153
150154 *uni_name.name = 0x0;
151
- exfat_get_uniname_from_ext_entry(sb, &dir, dentry,
155
+ exfat_get_uniname_from_ext_entry(sb, &clu, i,
152156 uni_name.name);
153157 exfat_utf16_to_nls(sb, &uni_name,
154158 dir_entry->namebuf.lfn,
....@@ -210,7 +214,10 @@
210214 exfat_init_namebuf(nb);
211215 }
212216
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
+ */
214221 #define ITER_POS_FILLED_DOTS (2)
215222 static int exfat_iterate(struct file *filp, struct dir_context *ctx)
216223 {
....@@ -225,35 +232,33 @@
225232 int err = 0, fake_offset = 0;
226233
227234 exfat_init_namebuf(nb);
228
- mutex_lock(&EXFAT_SB(sb)->s_lock);
229235
230236 cpos = ctx->pos;
231237 if (!dir_emit_dots(filp, ctx))
232
- goto unlock;
238
+ goto out;
233239
234240 if (ctx->pos == ITER_POS_FILLED_DOTS) {
235241 cpos = 0;
236242 fake_offset = 1;
237243 }
238244
239
- if (cpos & (DENTRY_SIZE - 1)) {
240
- err = -ENOENT;
241
- goto unlock;
242
- }
245
+ cpos = round_up(cpos, DENTRY_SIZE);
243246
244247 /* name buffer should be allocated before use */
245248 err = exfat_alloc_namebuf(nb);
246249 if (err)
247
- goto unlock;
250
+ goto out;
248251 get_new:
252
+ mutex_lock(&EXFAT_SB(sb)->s_lock);
253
+
249254 if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
250255 goto end_of_dir;
251256
252257 err = exfat_readdir(inode, &cpos, &de);
253258 if (err) {
254259 /*
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).
257262 */
258263 if (err == -EIO) {
259264 cpos += 1 << (sb->s_blocksize_bits);
....@@ -276,16 +281,10 @@
276281 inum = iunique(sb, EXFAT_ROOT_INO);
277282 }
278283
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
- */
284284 mutex_unlock(&EXFAT_SB(sb)->s_lock);
285285 if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum,
286286 (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG))
287
- goto out_unlocked;
288
- mutex_lock(&EXFAT_SB(sb)->s_lock);
287
+ goto out;
289288 ctx->pos = cpos;
290289 goto get_new;
291290
....@@ -293,9 +292,8 @@
293292 if (!cpos && fake_offset)
294293 cpos = ITER_POS_FILLED_DOTS;
295294 ctx->pos = cpos;
296
-unlock:
297295 mutex_unlock(&EXFAT_SB(sb)->s_lock);
298
-out_unlocked:
296
+out:
299297 /*
300298 * To improve performance, free namebuf after unlock sb_lock.
301299 * If namebuf is not allocated, this function do nothing
....@@ -615,6 +613,10 @@
615613 bforget(es->bh[i]);
616614 else
617615 brelse(es->bh[i]);
616
+
617
+ if (IS_DYNAMIC_ES(es))
618
+ kfree(es->bh);
619
+
618620 kfree(es);
619621 return err;
620622 }
....@@ -850,6 +852,7 @@
850852 /* byte offset in sector */
851853 off = EXFAT_BLK_OFFSET(byte_offset, sb);
852854 es->start_off = off;
855
+ es->bh = es->__bh;
853856
854857 /* sector offset in cluster */
855858 sec = EXFAT_B_TO_BLK(byte_offset, sb);
....@@ -869,6 +872,16 @@
869872 es->num_entries = num_entries;
870873
871874 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
+
872885 for (i = 1; i < num_bh; i++) {
873886 /* get the next sector */
874887 if (exfat_is_last_sector_in_cluster(sbi, sec)) {
....@@ -908,14 +921,19 @@
908921 };
909922
910923 /*
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
915933 */
916934 int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,
917935 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)
919937 {
920938 int i, rewind = 0, dentry = 0, end_eidx = 0, num_ext = 0, len;
921939 int order, step, name_len = 0;
....@@ -992,6 +1010,8 @@
9921010
9931011 if (entry_type == TYPE_FILE || entry_type == TYPE_DIR) {
9941012 step = DIRENT_STEP_FILE;
1013
+ hint_opt->clu = clu.dir;
1014
+ hint_opt->eidx = i;
9951015 if (type == TYPE_ALL || type == entry_type) {
9961016 num_ext = ep->dentry.file.num_ext;
9971017 step = DIRENT_STEP_STRM;
....@@ -1026,7 +1046,8 @@
10261046 if (entry_type == TYPE_EXTEND) {
10271047 unsigned short entry_uniname[16], unichar;
10281048
1029
- if (step != DIRENT_STEP_NAME) {
1049
+ if (step != DIRENT_STEP_NAME ||
1050
+ name_len >= MAX_NAME_LENGTH) {
10301051 step = DIRENT_STEP_FILE;
10311052 continue;
10321053 }