fs: Add sdfat
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdfat / core.c
1 /*
2 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /************************************************************************/
19 /* */
20 /* PROJECT : exFAT & FAT12/16/32 File System */
21 /* FILE : core.c */
22 /* PURPOSE : FAT & exFAT common core code for sdFAT */
23 /* */
24 /*----------------------------------------------------------------------*/
25 /* NOTES */
26 /* */
27 /* */
28 /************************************************************************/
29
30 #include <linux/version.h>
31 #include <linux/blkdev.h>
32 #include <linux/workqueue.h>
33 #include <linux/writeback.h>
34 #include <linux/kernel.h>
35 #include <linux/log2.h>
36
37 #include "sdfat.h"
38 #include "core.h"
39 #include <asm/byteorder.h>
40 #include <asm/unaligned.h>
41
42 /*----------------------------------------------------------------------*/
43 /* Constant & Macro Definitions */
44 /*----------------------------------------------------------------------*/
45 static inline void __set_sb_dirty(struct super_block *sb)
46 {
47 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 7, 0)
48 sb->s_dirt = 1;
49 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) */
50 struct sdfat_sb_info *sbi = SDFAT_SB(sb);
51
52 sbi->s_dirt = 1;
53 /* Insert work */
54 spin_lock(&sbi->work_lock);
55 if (!sbi->write_super_queued) {
56 unsigned long delay;
57
58 delay = msecs_to_jiffies(CONFIG_SDFAT_WRITE_SB_INTERVAL_CSECS * 10);
59 queue_delayed_work(system_long_wq, &sbi->write_super_work, delay);
60 sbi->write_super_queued = 1;
61 }
62 spin_unlock(&sbi->work_lock);
63 #endif
64 }
65
66 void set_sb_dirty(struct super_block *sb)
67 {
68 __set_sb_dirty(sb);
69 // XXX: to be removed later, prints too much output
70 //TMSG("%s finished.\n", __func__);
71 }
72
73 /*----------------------------------------------------------------------*/
74 /* Global Variable Definitions */
75 /*----------------------------------------------------------------------*/
76
77 /*----------------------------------------------------------------------*/
78 /* Local Variable Definitions */
79 /*----------------------------------------------------------------------*/
80
81 static s8 *reserved_names[] = {
82 "AUX ", "CON ", "NUL ", "PRN ",
83 "COM1 ", "COM2 ", "COM3 ", "COM4 ",
84 "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ",
85 "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
86 "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ",
87 NULL
88 };
89
90 /*======================================================================*/
91 /* Local Function Definitions */
92 /*======================================================================*/
93
94 /*
95 * File System Management Functions
96 */
97
98 static s32 check_type_size(void)
99 {
100 /* critical check for system requirement on size of DENTRY_T structure */
101 if (sizeof(DENTRY_T) != DENTRY_SIZE)
102 return -EINVAL;
103
104 if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE)
105 return -EINVAL;
106
107 if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE)
108 return -EINVAL;
109
110 if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE)
111 return -EINVAL;
112
113 if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE)
114 return -EINVAL;
115
116 if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE)
117 return -EINVAL;
118
119 if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE)
120 return -EINVAL;
121
122 if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE)
123 return -EINVAL;
124
125 if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE)
126 return -EINVAL;
127
128 return 0;
129 }
130
131 static s32 __fs_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync)
132 {
133 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
134 s32 err;
135 s32 sync = 0;
136
137 /* flags are not changed */
138 if (fsi->vol_flag == new_flag)
139 return 0;
140
141 fsi->vol_flag = new_flag;
142
143 /* skip updating volume dirty flag,
144 * if this volume has been mounted with read-only
145 */
146 if (sb->s_flags & MS_RDONLY)
147 return 0;
148
149 if (!fsi->pbr_bh) {
150 err = read_sect(sb, 0, &(fsi->pbr_bh), 1);
151 if (err) {
152 EMSG("%s : failed to read boot sector\n", __func__);
153 return err;
154 }
155 }
156
157 if (fsi->vol_type == EXFAT) {
158 pbr64_t *bpb = (pbr64_t *)fsi->pbr_bh->b_data;
159 bpb->bsx.vol_flags = cpu_to_le16(new_flag);
160 } else if (fsi->vol_type == FAT32) {
161 pbr32_t *bpb = (pbr32_t *)fsi->pbr_bh->b_data;
162 bpb->bsx.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00;
163 } else { /* FAT16/12 */
164 pbr16_t *bpb = (pbr16_t *) fsi->pbr_bh->b_data;
165 bpb->bpb.state = new_flag & VOL_DIRTY ? FAT_VOL_DIRTY : 0x00;
166 }
167
168 if (always_sync)
169 sync = 1;
170 else if ((new_flag == VOL_DIRTY) && (!buffer_dirty(fsi->pbr_bh)))
171 sync = 1;
172 else
173 sync = 0;
174
175 err = write_sect(sb, 0, fsi->pbr_bh, sync);
176 if (err)
177 EMSG("%s : failed to modify volume flag\n", __func__);
178
179 return err;
180 }
181
182 static s32 fs_set_vol_flags(struct super_block *sb, u16 new_flag)
183 {
184 return __fs_set_vol_flags(sb, new_flag, 0);
185 }
186
187 s32 fscore_set_vol_flags(struct super_block *sb, u16 new_flag, s32 always_sync)
188 {
189 return __fs_set_vol_flags(sb, new_flag, always_sync);
190 }
191
192 static inline s32 __fs_meta_sync(struct super_block *sb, s32 do_sync)
193 {
194 #ifdef CONFIG_SDFAT_DELAYED_META_DIRTY
195 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
196
197 if (fsi->vol_type != EXFAT) {
198 MMSG("meta flush in fs_sync(sync=%d)\n", do_sync);
199 fcache_flush(sb, 0);
200 dcache_flush(sb, 0);
201 }
202 #else
203 /* DO NOTHING */
204 #endif
205 return 0;
206 }
207
208 static s32 fs_sync(struct super_block *sb, s32 do_sync)
209 {
210 s32 err;
211
212 if (!do_sync)
213 return 0;
214
215 err = __fs_meta_sync(sb, do_sync);
216
217 if (!err)
218 err = bdev_sync_all(sb);
219
220 if (err)
221 EMSG("%s : failed to sync. (err:%d)\n", __func__, err);
222
223 return err;
224 }
225
226 /*
227 * Cluster Management Functions
228 */
229
230 static s32 __clear_cluster(struct inode *inode, u32 clu)
231 {
232 u32 s, n;
233 struct super_block *sb = inode->i_sb;
234 u32 sect_size = (u32)sb->s_blocksize;
235 s32 ret = 0;
236 struct buffer_head *tmp_bh = NULL;
237 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
238
239 if (IS_CLUS_FREE(clu)) { /* FAT16 root_dir */
240 s = fsi->root_start_sector;
241 n = fsi->data_start_sector;
242 } else {
243 s = CLUS_TO_SECT(fsi, clu);
244 n = s + fsi->sect_per_clus;
245 }
246
247 if (IS_DIRSYNC(inode)) {
248 ret = write_msect_zero(sb, s, (s32)fsi->sect_per_clus);
249 if (ret != -EAGAIN)
250 return ret;
251 }
252
253 /* Trying buffered zero writes
254 * if it doesn't have DIRSYNC or write_msect_zero() returned -EAGAIN
255 */
256 for ( ; s < n; s++) {
257 #if 0
258 dcache_release(sb, s);
259 #endif
260 ret = read_sect(sb, s, &tmp_bh, 0);
261 if (ret)
262 goto out;
263
264 memset((u8 *)tmp_bh->b_data, 0x0, sect_size);
265 ret = write_sect(sb, s, tmp_bh, 0);
266 if (ret)
267 goto out;
268 }
269 out:
270 brelse(tmp_bh);
271 return ret;
272 } /* end of __clear_cluster */
273
274 static s32 __find_last_cluster(struct super_block *sb, CHAIN_T *p_chain, u32 *ret_clu)
275 {
276 u32 clu, next;
277 s32 count = 0;
278
279 next = p_chain->dir;
280 if (p_chain->flags == 0x03) {
281 *ret_clu = next + p_chain->size - 1;
282 return 0;
283 }
284
285 do {
286 count++;
287 clu = next;
288 if (fat_ent_get_safe(sb, clu, &next))
289 return -EIO;
290 } while (!IS_CLUS_EOF(next));
291
292 if (p_chain->size != count) {
293 sdfat_fs_error(sb, "bogus directory size "
294 "(clus : ondisk(%d) != counted(%d))",
295 p_chain->size, count);
296 sdfat_debug_bug_on(1);
297 return -EIO;
298 }
299
300 *ret_clu = clu;
301 return 0;
302 }
303
304
305 static s32 __count_num_clusters(struct super_block *sb, CHAIN_T *p_chain, s32 *ret_count)
306 {
307 s32 i, count;
308 u32 clu;
309 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
310
311 if (!p_chain->dir || IS_CLUS_EOF(p_chain->dir)) {
312 *ret_count = 0;
313 return 0;
314 }
315
316 if (p_chain->flags == 0x03) {
317 *ret_count = p_chain->size;
318 return 0;
319 }
320
321 clu = p_chain->dir;
322 count = 0;
323 for (i = CLUS_BASE; i < fsi->num_clusters; i++) {
324 count++;
325 if (fat_ent_get_safe(sb, clu, &clu))
326 return -EIO;
327 if (IS_CLUS_EOF(clu))
328 break;
329 }
330
331 *ret_count = count;
332 return 0;
333 }
334
335 /*
336 * Upcase table Management Functions
337 */
338 static void free_upcase_table(struct super_block *sb)
339 {
340 u32 i;
341 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
342 u16 **upcase_table;
343
344 upcase_table = fsi->vol_utbl;
345 for (i = 0 ; i < UTBL_COL_COUNT ; i++) {
346 /* kfree(NULL) is safe */
347 kfree(upcase_table[i]);
348 upcase_table[i] = NULL;
349 }
350
351 /* kfree(NULL) is safe */
352 kfree(fsi->vol_utbl);
353 fsi->vol_utbl = NULL;
354 }
355
356 static s32 __load_upcase_table(struct super_block *sb, u32 sector, u32 num_sectors, u32 utbl_checksum)
357 {
358 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
359 struct buffer_head *tmp_bh = NULL;
360 u32 sect_size = (u32)sb->s_blocksize;
361 s32 ret = -EIO;
362 u32 i, j;
363
364 u8 skip = false;
365 u32 index = 0;
366 u32 checksum = 0;
367 u16 **upcase_table = kzalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
368
369 if (!upcase_table)
370 return -ENOMEM;
371 /* thanks for kzalloc
372 * memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
373 */
374
375 fsi->vol_utbl = upcase_table;
376 num_sectors += sector;
377
378 while (sector < num_sectors) {
379 ret = read_sect(sb, sector, &tmp_bh, 1);
380 if (ret) {
381 EMSG("%s: failed to read sector(0x%x)\n",
382 __func__, sector);
383 goto error;
384 }
385 sector++;
386
387 for (i = 0; i < sect_size && index <= 0xFFFF; i += 2) {
388 /* FIXME : is __le16 ok? */
389 //u16 uni = le16_to_cpu(((__le16*)(tmp_bh->b_data))[i]);
390 u16 uni = get_unaligned_le16((u8 *)tmp_bh->b_data+i);
391
392 checksum = ((checksum & 1) ? 0x80000000 : 0) +
393 (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+i);
394 checksum = ((checksum & 1) ? 0x80000000 : 0) +
395 (checksum >> 1) + *(((u8 *)tmp_bh->b_data)+(i+1));
396
397 if (skip) {
398 MMSG("skip from 0x%X to 0x%X(amount of 0x%X)\n",
399 index, index+uni, uni);
400 index += uni;
401 skip = false;
402 } else if (uni == index) {
403 index++;
404 } else if (uni == 0xFFFF) {
405 skip = true;
406 } else { /* uni != index , uni != 0xFFFF */
407 u16 col_index = get_col_index(index);
408
409 if (!upcase_table[col_index]) {
410 upcase_table[col_index] =
411 kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
412 if (!upcase_table[col_index]) {
413 EMSG("failed to allocate memory"
414 " for column 0x%X\n",
415 col_index);
416 ret = -ENOMEM;
417 goto error;
418 }
419
420 for (j = 0; j < UTBL_ROW_COUNT; j++)
421 upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
422 }
423
424 upcase_table[col_index][get_row_index(index)] = uni;
425 index++;
426 }
427 }
428 }
429 if (index >= 0xFFFF && utbl_checksum == checksum) {
430 DMSG("%s: load upcase table successfully"
431 "(idx:0x%08x, utbl_chksum:0x%08x)\n",
432 __func__, index, utbl_checksum);
433 if (tmp_bh)
434 brelse(tmp_bh);
435 return 0;
436 }
437
438 EMSG("%s: failed to load upcase table"
439 "(idx:0x%08x, chksum:0x%08x, utbl_chksum:0x%08x)\n",
440 __func__, index, checksum, utbl_checksum);
441
442 ret = -EINVAL;
443 error:
444 if (tmp_bh)
445 brelse(tmp_bh);
446 free_upcase_table(sb);
447 return ret;
448 }
449
450 static s32 __load_default_upcase_table(struct super_block *sb)
451 {
452 s32 i, ret = -EIO;
453 u32 j;
454 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
455
456 u8 skip = false;
457 u32 index = 0;
458 u16 uni = 0;
459 u16 **upcase_table;
460
461 upcase_table = kmalloc((UTBL_COL_COUNT * sizeof(u16 *)), GFP_KERNEL);
462 if (!upcase_table)
463 return -ENOMEM;
464
465 fsi->vol_utbl = upcase_table;
466 memset(upcase_table, 0, UTBL_COL_COUNT * sizeof(u16 *));
467
468 for (i = 0; index <= 0xFFFF && i < SDFAT_NUM_UPCASE*2; i += 2) {
469 /* FIXME : is __le16 ok? */
470 //uni = le16_to_cpu(((__le16*)uni_def_upcase)[i>>1]);
471 uni = get_unaligned_le16((u8 *)uni_def_upcase+i);
472 if (skip) {
473 MMSG("skip from 0x%x ", index);
474 index += uni;
475 MMSG("to 0x%x (amount of 0x%x)\n", index, uni);
476 skip = false;
477 } else if (uni == index) {
478 index++;
479 } else if (uni == 0xFFFF) {
480 skip = true;
481 } else { /* uni != index , uni != 0xFFFF */
482 u16 col_index = get_col_index(index);
483
484 if (!upcase_table[col_index]) {
485 upcase_table[col_index] = kmalloc((UTBL_ROW_COUNT * sizeof(u16)), GFP_KERNEL);
486 if (!upcase_table[col_index]) {
487 EMSG("failed to allocate memory for "
488 "new column 0x%x\n", col_index);
489 ret = -ENOMEM;
490 goto error;
491 }
492
493 for (j = 0; j < UTBL_ROW_COUNT; j++)
494 upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
495 }
496
497 upcase_table[col_index][get_row_index(index)] = uni;
498 index++;
499 }
500 }
501
502 if (index >= 0xFFFF)
503 return 0;
504
505 error:
506 /* FATAL error: default upcase table has error */
507 free_upcase_table(sb);
508 return ret;
509 }
510
511 static s32 load_upcase_table(struct super_block *sb)
512 {
513 s32 i, ret;
514 u32 tbl_clu, tbl_size;
515 u32 type, sector, num_sectors;
516 u8 blksize_bits = sb->s_blocksize_bits;
517 CHAIN_T clu;
518 CASE_DENTRY_T *ep;
519 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
520
521 clu.dir = fsi->root_dir;
522 clu.flags = 0x01;
523
524 if (fsi->vol_type != EXFAT)
525 goto load_default;
526
527 while (!IS_CLUS_EOF(clu.dir)) {
528 for (i = 0; i < fsi->dentries_per_clu; i++) {
529 ep = (CASE_DENTRY_T *) get_dentry_in_dir(sb, &clu, i, NULL);
530 if (!ep)
531 return -EIO;
532
533 type = fsi->fs_func->get_entry_type((DENTRY_T *) ep);
534
535 if (type == TYPE_UNUSED)
536 break;
537 if (type != TYPE_UPCASE)
538 continue;
539
540 tbl_clu = le32_to_cpu(ep->start_clu);
541 tbl_size = (u32) le64_to_cpu(ep->size);
542
543 sector = CLUS_TO_SECT(fsi, tbl_clu);
544 num_sectors = ((tbl_size-1) >> blksize_bits) + 1;
545 ret = __load_upcase_table(sb, sector, num_sectors,
546 le32_to_cpu(ep->checksum));
547
548 if (ret && (ret != -EIO))
549 goto load_default;
550
551 /* load successfully */
552 return ret;
553 }
554
555 if (get_next_clus_safe(sb, &(clu.dir)))
556 return -EIO;
557 }
558
559 load_default:
560 sdfat_log_msg(sb, KERN_INFO, "trying to load default upcase table");
561 /* load default upcase table */
562 return __load_default_upcase_table(sb);
563 } /* end of load_upcase_table */
564
565
566 /*
567 * Directory Entry Management Functions
568 */
569 s32 walk_fat_chain(struct super_block *sb, CHAIN_T *p_dir, s32 byte_offset, u32 *clu)
570 {
571 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
572 s32 clu_offset;
573 u32 cur_clu;
574
575 clu_offset = byte_offset >> fsi->cluster_size_bits;
576 cur_clu = p_dir->dir;
577
578 if (p_dir->flags == 0x03) {
579 cur_clu += clu_offset;
580 } else {
581 while (clu_offset > 0) {
582 if (get_next_clus_safe(sb, &cur_clu))
583 return -EIO;
584 if (IS_CLUS_EOF(cur_clu)) {
585 sdfat_fs_error(sb, "invalid dentry access "
586 "beyond EOF (clu : %u, eidx : %d)",
587 p_dir->dir,
588 byte_offset >> DENTRY_SIZE_BITS);
589 return -EIO;
590 }
591 clu_offset--;
592 }
593 }
594
595 if (clu)
596 *clu = cur_clu;
597 return 0;
598 }
599
600 static s32 find_location(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector, s32 *offset)
601 {
602 s32 ret;
603 u32 off, clu = 0;
604 u32 blksize_mask = (u32)(sb->s_blocksize-1);
605 u8 blksize_bits = sb->s_blocksize_bits;
606 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
607
608 off = entry << DENTRY_SIZE_BITS;
609
610 /* FAT16 root_dir */
611 if (IS_CLUS_FREE(p_dir->dir)) {
612 *offset = off & blksize_mask;
613 *sector = off >> blksize_bits;
614 *sector += fsi->root_start_sector;
615 return 0;
616 }
617
618 ret = walk_fat_chain(sb, p_dir, off, &clu);
619 if (ret)
620 return ret;
621
622 /* byte offset in cluster */
623 off &= (fsi->cluster_size - 1);
624
625 /* byte offset in sector */
626 *offset = off & blksize_mask;
627
628 /* sector offset in cluster */
629 *sector = off >> blksize_bits;
630 *sector += CLUS_TO_SECT(fsi, clu);
631 return 0;
632 } /* end of find_location */
633
634 DENTRY_T *get_dentry_in_dir(struct super_block *sb, CHAIN_T *p_dir, s32 entry, u32 *sector)
635 {
636 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
637 u32 dentries_per_page = PAGE_SIZE >> DENTRY_SIZE_BITS;
638 s32 off;
639 u32 sec;
640 u8 *buf;
641
642 if (p_dir->dir == DIR_DELETED) {
643 EMSG("%s : abnormal access to deleted dentry\n", __func__);
644 BUG_ON(!fsi->prev_eio);
645 return NULL;
646 }
647
648 if (find_location(sb, p_dir, entry, &sec, &off))
649 return NULL;
650
651 /* DIRECTORY READAHEAD :
652 * Try to read ahead per a page except root directory of fat12/16
653 */
654 if ((!IS_CLUS_FREE(p_dir->dir)) &&
655 !(entry & (dentries_per_page - 1)))
656 dcache_readahead(sb, sec);
657
658 buf = dcache_getblk(sb, sec);
659 if (!buf)
660 return NULL;
661
662 if (sector)
663 *sector = sec;
664 return (DENTRY_T *)(buf + off);
665 } /* end of get_dentry_in_dir */
666
667 /* used only in search empty_slot() */
668 #define CNT_UNUSED_NOHIT (-1)
669 #define CNT_UNUSED_HIT (-2)
670 /* search EMPTY CONTINUOUS "num_entries" entries */
671 static s32 search_empty_slot(struct super_block *sb, HINT_FEMP_T *hint_femp, CHAIN_T *p_dir, s32 num_entries)
672 {
673 s32 i, dentry, num_empty = 0;
674 s32 dentries_per_clu;
675 u32 type;
676 CHAIN_T clu;
677 DENTRY_T *ep;
678 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
679
680 if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */
681 dentries_per_clu = fsi->dentries_in_root;
682 else
683 dentries_per_clu = fsi->dentries_per_clu;
684
685 ASSERT(-1 <= hint_femp->eidx);
686
687 if (hint_femp->eidx != -1) {
688 clu.dir = hint_femp->cur.dir;
689 clu.size = hint_femp->cur.size;
690 clu.flags = hint_femp->cur.flags;
691
692 dentry = hint_femp->eidx;
693
694 if (num_entries <= hint_femp->count) {
695 MMSG("%s: empty slot(HIT) - found "
696 "(clu : 0x%08x eidx : %d)\n",
697 __func__, hint_femp->cur.dir, hint_femp->eidx);
698 hint_femp->eidx = -1;
699
700 if (fsi->vol_type == EXFAT)
701 return dentry;
702
703 return dentry + (num_entries - 1);
704 }
705 MMSG("%s: empty slot(HIT) - search from "
706 "(clu : 0x%08x eidx : %d)\n",
707 __func__, hint_femp->cur.dir, hint_femp->eidx);
708 } else {
709 MMSG("%s: empty slot(MISS) - search from "
710 "(clu:0x%08x eidx : 0)\n",
711 __func__, p_dir->dir);
712
713 clu.dir = p_dir->dir;
714 clu.size = p_dir->size;
715 clu.flags = p_dir->flags;
716
717 dentry = 0;
718 }
719
720 while (!IS_CLUS_EOF(clu.dir)) {
721 /* FAT16 root_dir */
722 if (IS_CLUS_FREE(p_dir->dir))
723 i = dentry % dentries_per_clu;
724 else
725 i = dentry & (dentries_per_clu-1);
726
727 for ( ; i < dentries_per_clu; i++, dentry++) {
728 ep = get_dentry_in_dir(sb, &clu, i, NULL);
729 if (!ep)
730 return -EIO;
731
732 type = fsi->fs_func->get_entry_type(ep);
733
734 if ((type == TYPE_UNUSED) || (type == TYPE_DELETED)) {
735 num_empty++;
736 if (hint_femp->eidx == -1) {
737 hint_femp->eidx = dentry;
738 hint_femp->count = CNT_UNUSED_NOHIT;
739
740 hint_femp->cur.dir = clu.dir;
741 hint_femp->cur.size = clu.size;
742 hint_femp->cur.flags = clu.flags;
743 }
744
745 if ((type == TYPE_UNUSED) &&
746 (hint_femp->count != CNT_UNUSED_HIT)) {
747 hint_femp->count = CNT_UNUSED_HIT;
748 }
749 } else {
750 if ((hint_femp->eidx != -1) &&
751 (hint_femp->count == CNT_UNUSED_HIT)) {
752 /* unused empty group means
753 * an empty group which includes
754 * unused dentry
755 */
756 sdfat_fs_error(sb,
757 "found bogus dentry(%d) "
758 "beyond unused empty group(%d) "
759 "(start_clu : %u, cur_clu : %u)\n",
760 dentry, hint_femp->eidx, p_dir->dir,
761 clu.dir);
762 return -EIO;
763 }
764
765 num_empty = 0;
766 hint_femp->eidx = -1;
767 }
768
769 if (num_empty >= num_entries) {
770 /* found and invalidate hint_femp */
771 hint_femp->eidx = -1;
772
773 if (fsi->vol_type == EXFAT)
774 return (dentry - (num_entries-1));
775
776 return dentry;
777 }
778 }
779
780 if (IS_CLUS_FREE(p_dir->dir))
781 break; /* FAT16 root_dir */
782
783 if (clu.flags == 0x03) {
784 if ((--clu.size) > 0)
785 clu.dir++;
786 else
787 clu.dir = CLUS_EOF;
788 } else {
789 if (get_next_clus_safe(sb, &(clu.dir)))
790 return -EIO;
791 }
792 }
793
794 return -ENOSPC;
795 } /* end of search_empty_slot */
796
797 /* find empty directory entry.
798 * if there isn't any empty slot, expand cluster chain.
799 */
800 static s32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, s32 num_entries)
801 {
802 s32 ret, dentry;
803 u32 last_clu, sector;
804 u64 size = 0;
805 CHAIN_T clu;
806 DENTRY_T *ep = NULL;
807 struct super_block *sb = inode->i_sb;
808 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
809 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
810 HINT_FEMP_T hint_femp;
811
812 hint_femp.eidx = -1;
813
814 ASSERT(-1 <= fid->hint_femp.eidx);
815
816 if (fid->hint_femp.eidx != -1) {
817 memcpy(&hint_femp, &fid->hint_femp, sizeof(HINT_FEMP_T));
818 fid->hint_femp.eidx = -1;
819 }
820
821 /* FAT16 root_dir */
822 if (IS_CLUS_FREE(p_dir->dir))
823 return search_empty_slot(sb, &hint_femp, p_dir, num_entries);
824
825 while ((dentry = search_empty_slot(sb, &hint_femp, p_dir, num_entries)) < 0) {
826 if (dentry == -EIO)
827 break;
828
829 if (fsi->fs_func->check_max_dentries(fid))
830 return -ENOSPC;
831
832 /* we trust p_dir->size regardless of FAT type */
833 if (__find_last_cluster(sb, p_dir, &last_clu))
834 return -EIO;
835
836 /*
837 * Allocate new cluster to this directory
838 */
839 clu.dir = last_clu + 1;
840 clu.size = 0; /* UNUSED */
841 clu.flags = p_dir->flags;
842
843 /* (0) check if there are reserved clusters
844 * (create_dir 의 주석 참고)
845 */
846 if (!IS_CLUS_EOF(fsi->used_clusters) &&
847 ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)))
848 return -ENOSPC;
849
850 /* (1) allocate a cluster */
851 ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT);
852 if (!ret)
853 return -ENOSPC;
854 if (ret < 0)
855 return -EIO;
856
857 if (__clear_cluster(inode, clu.dir))
858 return -EIO;
859
860 /* (2) append to the FAT chain */
861 if (clu.flags != p_dir->flags) {
862 /* no-fat-chain bit is disabled,
863 * so fat-chain should be synced with alloc-bmp
864 */
865 chain_cont_cluster(sb, p_dir->dir, p_dir->size);
866 p_dir->flags = 0x01;
867 hint_femp.cur.flags = 0x01;
868 }
869
870 if (clu.flags == 0x01)
871 if (fat_ent_set(sb, last_clu, clu.dir))
872 return -EIO;
873
874 if (hint_femp.eidx == -1) {
875 /* the special case that new dentry
876 * should be allocated from the start of new cluster
877 */
878 hint_femp.eidx = p_dir->size <<
879 (fsi->cluster_size_bits - DENTRY_SIZE_BITS);
880 hint_femp.count = fsi->dentries_per_clu;
881
882 hint_femp.cur.dir = clu.dir;
883 hint_femp.cur.size = 0;
884 hint_femp.cur.flags = clu.flags;
885 }
886 hint_femp.cur.size++;
887 p_dir->size++;
888 size = (p_dir->size << fsi->cluster_size_bits);
889
890 /* (3) update the directory entry */
891 if ((fsi->vol_type == EXFAT) && (p_dir->dir != fsi->root_dir)) {
892 ep = get_dentry_in_dir(sb,
893 &(fid->dir), fid->entry+1, &sector);
894 if (!ep)
895 return -EIO;
896 fsi->fs_func->set_entry_size(ep, size);
897 fsi->fs_func->set_entry_flag(ep, p_dir->flags);
898 if (dcache_modify(sb, sector))
899 return -EIO;
900
901 if (update_dir_chksum(sb, &(fid->dir), fid->entry))
902 return -EIO;
903 }
904
905 /* directory inode should be updated in here */
906 i_size_write(inode, (loff_t)size);
907 SDFAT_I(inode)->i_size_ondisk += fsi->cluster_size;
908 SDFAT_I(inode)->i_size_aligned += fsi->cluster_size;
909 SDFAT_I(inode)->fid.size = size;
910 SDFAT_I(inode)->fid.flags = p_dir->flags;
911 inode->i_blocks += 1 << (fsi->cluster_size_bits - sb->s_blocksize_bits);
912 }
913
914 return dentry;
915 } /* end of find_empty_entry */
916
917 #define SDFAT_MIN_SUBDIR (2)
918 static const char *dot_name[SDFAT_MIN_SUBDIR] = { DOS_CUR_DIR_NAME, DOS_PAR_DIR_NAME };
919
920 static s32 __count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, u32 type, u32 *dotcnt)
921 {
922 s32 i, count = 0, check_dot = 0;
923 s32 dentries_per_clu;
924 u32 entry_type;
925 CHAIN_T clu;
926 DENTRY_T *ep;
927 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
928
929 if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */
930 dentries_per_clu = fsi->dentries_in_root;
931 else
932 dentries_per_clu = fsi->dentries_per_clu;
933
934 clu.dir = p_dir->dir;
935 clu.size = p_dir->size;
936 clu.flags = p_dir->flags;
937
938 if (dotcnt) {
939 *dotcnt = 0;
940 if (fsi->vol_type != EXFAT)
941 check_dot = 1;
942 }
943
944 while (!IS_CLUS_EOF(clu.dir)) {
945 for (i = 0; i < dentries_per_clu; i++) {
946 ep = get_dentry_in_dir(sb, &clu, i, NULL);
947 if (!ep)
948 return -EIO;
949
950 entry_type = fsi->fs_func->get_entry_type(ep);
951
952 if (entry_type == TYPE_UNUSED)
953 return count;
954 if (!(type & TYPE_CRITICAL_PRI) && !(type & TYPE_BENIGN_PRI))
955 continue;
956
957 if ((type != TYPE_ALL) && (type != entry_type))
958 continue;
959
960 count++;
961 if (check_dot && (i < SDFAT_MIN_SUBDIR)) {
962 BUG_ON(fsi->vol_type == EXFAT);
963 /* 11 is DOS_NAME_LENGTH */
964 if (!strncmp(ep->dummy, dot_name[i], 11))
965 (*dotcnt)++;
966 }
967 }
968
969 /* FAT16 root_dir */
970 if (IS_CLUS_FREE(p_dir->dir))
971 break;
972
973 if (clu.flags == 0x03) {
974 if ((--clu.size) > 0)
975 clu.dir++;
976 else
977 clu.dir = CLUS_EOF;
978 } else {
979 if (get_next_clus_safe(sb, &(clu.dir)))
980 return -EIO;
981 }
982
983 check_dot = 0;
984 }
985
986 return count;
987 }
988
989 s32 check_dir_empty(struct super_block *sb, CHAIN_T *p_dir)
990 {
991 s32 i, count = 0;
992 s32 dentries_per_clu;
993 u32 type;
994 CHAIN_T clu;
995 DENTRY_T *ep;
996 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
997
998 if (IS_CLUS_FREE(p_dir->dir)) /* FAT16 root_dir */
999 dentries_per_clu = fsi->dentries_in_root;
1000 else
1001 dentries_per_clu = fsi->dentries_per_clu;
1002
1003 clu.dir = p_dir->dir;
1004 clu.size = p_dir->size;
1005 clu.flags = p_dir->flags;
1006
1007 while (!IS_CLUS_EOF(clu.dir)) {
1008 for (i = 0; i < dentries_per_clu; i++) {
1009 ep = get_dentry_in_dir(sb, &clu, i, NULL);
1010 if (!ep)
1011 return -EIO;
1012
1013 type = fsi->fs_func->get_entry_type(ep);
1014
1015 if (type == TYPE_UNUSED)
1016 return 0;
1017
1018 if ((type != TYPE_FILE) && (type != TYPE_DIR))
1019 continue;
1020
1021 /* FAT16 root_dir */
1022 if (IS_CLUS_FREE(p_dir->dir))
1023 return -ENOTEMPTY;
1024
1025 if (fsi->vol_type == EXFAT)
1026 return -ENOTEMPTY;
1027
1028 if ((p_dir->dir == fsi->root_dir) || (++count > 2))
1029 return -ENOTEMPTY;
1030 }
1031
1032 /* FAT16 root_dir */
1033 if (IS_CLUS_FREE(p_dir->dir))
1034 return -ENOTEMPTY;
1035
1036 if (clu.flags == 0x03) {
1037 if ((--clu.size) > 0)
1038 clu.dir++;
1039 else
1040 clu.dir = CLUS_EOF;
1041 } else {
1042 if (get_next_clus_safe(sb, &(clu.dir)))
1043 return -EIO;
1044 }
1045 }
1046
1047 return 0;
1048 }
1049
1050 /*
1051 * Name Conversion Functions
1052 */
1053 #ifdef CONFIG_SDFAT_ALLOW_LOOKUP_LOSSY_SFN
1054 /* over name length only */
1055 #define NEED_INVALIDATE_SFN(x) ((x) & NLS_NAME_OVERLEN)
1056 #else
1057 /* all lossy case */
1058 #define NEED_INVALIDATE_SFN(x) (x)
1059 #endif
1060
1061 /* NOTE :
1062 * We should keep shortname code compatible with v1.0.15 or lower
1063 * So, we try to check ext-only-name at create-mode only.
1064 *
1065 * i.e. '.mtp' ->
1066 * v1.0.15 : ' MTP' with name_case, 0x10
1067 * v1.1.0 : 'MT????~?' with name_case, 0x00 and longname.
1068 */
1069 static inline void preprocess_ext_only_sfn(s32 lookup, u16 first_char, DOS_NAME_T *p_dosname, s32 *lossy)
1070 {
1071 #ifdef CONFIG_SDFAT_RESTRICT_EXT_ONLY_SFN
1072 int i;
1073 /* check ext-only-name at create-mode */
1074 if (*lossy || lookup || (first_char != (u16)'.'))
1075 return;
1076
1077 p_dosname->name_case = 0xFF;
1078
1079 /* move ext-name to base-name */
1080 for (i = 0; i < 3; i++) {
1081 p_dosname->name[i] = p_dosname->name[8+i];
1082 if (p_dosname->name[i] == ' ')
1083 p_dosname->name[i] = '_';
1084 }
1085
1086 /* fill remained space with '_' */
1087 for (i = 3; i < 8; i++)
1088 p_dosname->name[i] = '_';
1089
1090 /* eliminate ext-name */
1091 for (i = 8; i < 11; i++)
1092 p_dosname->name[i] = ' ';
1093
1094 *lossy = NLS_NAME_LOSSY;
1095 #endif /* CONFIG_SDFAT_CAN_CREATE_EXT_ONLY_SFN */
1096 }
1097
1098 /* input : dir, uni_name
1099 * output : num_of_entry, dos_name(format : aaaaaa~1.bbb)
1100 */
1101 static s32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir,
1102 UNI_NAME_T *p_uniname, s32 *entries,
1103 DOS_NAME_T *p_dosname, s32 lookup)
1104 {
1105 s32 ret, num_entries, lossy = NLS_NAME_NO_LOSSY;
1106 s8 **r;
1107 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1108
1109 /* Init null char. */
1110 p_dosname->name[0] = '\0';
1111
1112 num_entries = fsi->fs_func->calc_num_entries(p_uniname);
1113 if (num_entries == 0)
1114 return -EINVAL;
1115
1116 if (fsi->vol_type == EXFAT)
1117 goto out;
1118
1119 nls_uni16s_to_sfn(sb, p_uniname, p_dosname, &lossy);
1120
1121 preprocess_ext_only_sfn(lookup, p_uniname->name[0], p_dosname, &lossy);
1122
1123 if (!lossy) {
1124 for (r = reserved_names; *r; r++) {
1125 if (!strncmp((void *) p_dosname->name, *r, 8))
1126 return -EINVAL;
1127 }
1128
1129 if (p_dosname->name_case != 0xFF)
1130 num_entries = 1;
1131 } else if (!lookup) {
1132 /* create new dos name */
1133 ret = fat_generate_dos_name_new(sb, p_dir, p_dosname,
1134 num_entries);
1135 if (ret)
1136 return ret;
1137
1138 } else if (NEED_INVALIDATE_SFN(lossy)) {
1139 /* FIXME : We should check num_entries */
1140 p_dosname->name[0] = '\0';
1141 }
1142
1143 if (num_entries > 1)
1144 p_dosname->name_case = 0x0;
1145 out:
1146 *entries = num_entries;
1147 return 0;
1148 } /* end of get_num_entries_and_dos_name */
1149
1150 void get_uniname_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, u8 mode)
1151 {
1152 DOS_NAME_T dos_name;
1153
1154 if (mode == 0x0)
1155 dos_name.name_case = 0x0;
1156 else
1157 dos_name.name_case = ep->lcase;
1158
1159 memcpy(dos_name.name, ep->name, DOS_NAME_LENGTH);
1160 nls_sfn_to_uni16s(sb, &dos_name, p_uniname);
1161 } /* end of get_uniname_from_dos_entry */
1162
1163 /* returns the length of a struct qstr, ignoring trailing dots */
1164 static inline unsigned int __striptail_len(unsigned int len, const char *name)
1165 {
1166 while (len && name[len - 1] == '.')
1167 len--;
1168 return len;
1169 }
1170
1171 /*
1172 * Name Resolution Functions :
1173 * Zero if it was successful; otherwise nonzero.
1174 */
1175 static s32 __resolve_path(struct inode *inode, const u8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, int lookup)
1176 {
1177 s32 namelen;
1178 s32 lossy = NLS_NAME_NO_LOSSY;
1179 struct super_block *sb = inode->i_sb;
1180 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1181 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
1182
1183 /* DOT and DOTDOT are handled by VFS layer */
1184
1185 /* strip all trailing spaces */
1186 /* DO NOTHING : Is needed? */
1187
1188 /* strip all trailing periods */
1189 namelen = __striptail_len(strlen(path), path);
1190 if (!namelen)
1191 return -ENOENT;
1192
1193 /* the limitation of linux? */
1194 if (strlen(path) > (MAX_NAME_LENGTH * MAX_CHARSET_SIZE))
1195 return -ENAMETOOLONG;
1196
1197 /*
1198 * strip all leading spaces :
1199 * "MS windows 7" supports leading spaces.
1200 * So we should skip this preprocessing for compatibility.
1201 */
1202
1203 /* file name conversion :
1204 * If lookup case, we allow bad-name for compatibility.
1205 */
1206 namelen = nls_vfsname_to_uni16s(sb, path, namelen, p_uniname, &lossy);
1207 if (namelen < 0)
1208 return namelen; /* return error value */
1209
1210 if ((lossy && !lookup) || !namelen)
1211 return -EINVAL;
1212
1213 sdfat_debug_bug_on(fid->size != i_size_read(inode));
1214 // fid->size = i_size_read(inode);
1215
1216 p_dir->dir = fid->start_clu;
1217 p_dir->size = (s32)(fid->size >> fsi->cluster_size_bits);
1218 p_dir->flags = fid->flags;
1219
1220 return 0;
1221 }
1222
1223 static inline s32 resolve_path(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni)
1224 {
1225 return __resolve_path(inode, path, dir, uni, 0);
1226 }
1227
1228 static inline s32 resolve_path_for_lookup(struct inode *inode, const u8 *path, CHAIN_T *dir, UNI_NAME_T *uni)
1229 {
1230 return __resolve_path(inode, path, dir, uni, 1);
1231 }
1232
1233 static s32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
1234 {
1235 s32 ret, dentry, num_entries;
1236 u64 size;
1237 CHAIN_T clu;
1238 DOS_NAME_T dos_name, dot_name;
1239 struct super_block *sb = inode->i_sb;
1240 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1241
1242 ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name, 0);
1243 if (ret)
1244 return ret;
1245
1246 /* find_empty_entry must be called before alloc_cluster */
1247 dentry = find_empty_entry(inode, p_dir, num_entries);
1248 if (dentry < 0)
1249 return dentry; /* -EIO or -ENOSPC */
1250
1251 clu.dir = CLUS_EOF;
1252 clu.size = 0;
1253 clu.flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
1254
1255 /* (0) Check if there are reserved clusters up to max. */
1256 if ((fsi->used_clusters != (u32) ~0) &&
1257 ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2)))
1258 return -ENOSPC;
1259
1260 /* (1) allocate a cluster */
1261 ret = fsi->fs_func->alloc_cluster(sb, 1, &clu, ALLOC_HOT);
1262
1263 if (!ret)
1264 return -ENOSPC;
1265
1266 if (ret < 0)
1267 return -EIO;
1268
1269 ret = __clear_cluster(inode, clu.dir);
1270 if (ret)
1271 return ret;
1272
1273 size = fsi->cluster_size;
1274 if (fsi->vol_type != EXFAT) {
1275 /* initialize the . and .. entry
1276 * Information for . points to itself
1277 * Information for .. points to parent dir
1278 */
1279
1280 dot_name.name_case = 0x0;
1281 memcpy(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH);
1282
1283 ret = fsi->fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, 0);
1284 if (ret)
1285 return ret;
1286
1287 ret = fsi->fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name);
1288 if (ret)
1289 return ret;
1290
1291 memcpy(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH);
1292
1293 if (p_dir->dir == fsi->root_dir)
1294 ret = fsi->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, CLUS_FREE, 0);
1295 else
1296 ret = fsi->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, p_dir->dir, 0);
1297
1298 if (ret)
1299 return ret;
1300
1301 ret = fsi->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, &dot_name);
1302 if (ret)
1303 return ret;
1304 }
1305
1306 /* (2) update the directory entry */
1307 /* make sub-dir entry in parent directory */
1308 ret = fsi->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, size);
1309 if (ret)
1310 return ret;
1311
1312 ret = fsi->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name);
1313 if (ret)
1314 return ret;
1315
1316 fid->dir.dir = p_dir->dir;
1317 fid->dir.size = p_dir->size;
1318 fid->dir.flags = p_dir->flags;
1319 fid->entry = dentry;
1320
1321 fid->attr = ATTR_SUBDIR;
1322 fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
1323 fid->size = size;
1324 fid->start_clu = clu.dir;
1325
1326 fid->type = TYPE_DIR;
1327 fid->rwoffset = 0;
1328 fid->hint_bmap.off = -1;
1329
1330 /* hint_stat will be used if this is directory. */
1331 fid->version = 0;
1332 fid->hint_stat.eidx = 0;
1333 fid->hint_stat.clu = fid->start_clu;
1334 fid->hint_femp.eidx = -1;
1335
1336 return 0;
1337 } /* end of create_dir */
1338
1339 static s32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, u8 mode, FILE_ID_T *fid)
1340 {
1341 s32 ret, dentry, num_entries;
1342 DOS_NAME_T dos_name;
1343 struct super_block *sb = inode->i_sb;
1344 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1345
1346 ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name, 0);
1347 if (ret)
1348 return ret;
1349
1350 /* find_empty_entry must be called before alloc_cluster() */
1351 dentry = find_empty_entry(inode, p_dir, num_entries);
1352 if (dentry < 0)
1353 return dentry; /* -EIO or -ENOSPC */
1354
1355 /* (1) update the directory entry */
1356 /* fill the dos name directory entry information of the created file.
1357 * the first cluster is not determined yet. (0)
1358 */
1359 ret = fsi->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, CLUS_FREE, 0);
1360 if (ret)
1361 return ret;
1362
1363 ret = fsi->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name);
1364 if (ret)
1365 return ret;
1366
1367 fid->dir.dir = p_dir->dir;
1368 fid->dir.size = p_dir->size;
1369 fid->dir.flags = p_dir->flags;
1370 fid->entry = dentry;
1371
1372 fid->attr = ATTR_ARCHIVE | mode;
1373 fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
1374 fid->size = 0;
1375 fid->start_clu = CLUS_EOF;
1376
1377 fid->type = TYPE_FILE;
1378 fid->rwoffset = 0;
1379 fid->hint_bmap.off = -1;
1380
1381 /* hint_stat will be used if this is directory. */
1382 fid->version = 0;
1383 fid->hint_stat.eidx = 0;
1384 fid->hint_stat.clu = fid->start_clu;
1385 fid->hint_femp.eidx = -1;
1386
1387 return 0;
1388 } /* end of create_file */
1389
1390 static s32 remove_file(struct inode *inode, CHAIN_T *p_dir, s32 entry)
1391 {
1392 s32 num_entries;
1393 u32 sector;
1394 DENTRY_T *ep;
1395 struct super_block *sb = inode->i_sb;
1396 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1397
1398 ep = get_dentry_in_dir(sb, p_dir, entry, &sector);
1399 if (!ep)
1400 return -EIO;
1401
1402 dcache_lock(sb, sector);
1403
1404 /* dcache_lock() before call count_ext_entries() */
1405 num_entries = fsi->fs_func->count_ext_entries(sb, p_dir, entry, ep);
1406 if (num_entries < 0) {
1407 dcache_unlock(sb, sector);
1408 return -EIO;
1409 }
1410 num_entries++;
1411
1412 dcache_unlock(sb, sector);
1413
1414 /* (1) update the directory entry */
1415 return fsi->fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
1416 } /* end of remove_file */
1417
1418 static s32 rename_file(struct inode *inode, CHAIN_T *p_dir, s32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
1419 {
1420 s32 ret, newentry = -1, num_old_entries, num_new_entries;
1421 u32 sector_old, sector_new;
1422 DOS_NAME_T dos_name;
1423 DENTRY_T *epold, *epnew;
1424 struct super_block *sb = inode->i_sb;
1425 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1426
1427 epold = get_dentry_in_dir(sb, p_dir, oldentry, &sector_old);
1428 if (!epold)
1429 return -EIO;
1430
1431 dcache_lock(sb, sector_old);
1432
1433 /* dcache_lock() before call count_ext_entries() */
1434 num_old_entries = fsi->fs_func->count_ext_entries(sb, p_dir, oldentry, epold);
1435 if (num_old_entries < 0) {
1436 dcache_unlock(sb, sector_old);
1437 return -EIO;
1438 }
1439 num_old_entries++;
1440
1441 ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_new_entries, &dos_name, 0);
1442 if (ret) {
1443 dcache_unlock(sb, sector_old);
1444 return ret;
1445 }
1446
1447 if (num_old_entries < num_new_entries) {
1448 newentry = find_empty_entry(inode, p_dir, num_new_entries);
1449 if (newentry < 0) {
1450 dcache_unlock(sb, sector_old);
1451 return newentry; /* -EIO or -ENOSPC */
1452 }
1453
1454 epnew = get_dentry_in_dir(sb, p_dir, newentry, &sector_new);
1455 if (!epnew) {
1456 dcache_unlock(sb, sector_old);
1457 return -EIO;
1458 }
1459
1460 memcpy((void *) epnew, (void *) epold, DENTRY_SIZE);
1461 if (fsi->fs_func->get_entry_type(epnew) == TYPE_FILE) {
1462 fsi->fs_func->set_entry_attr(epnew, fsi->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE);
1463 fid->attr |= ATTR_ARCHIVE;
1464 }
1465 dcache_modify(sb, sector_new);
1466 dcache_unlock(sb, sector_old);
1467
1468 if (fsi->vol_type == EXFAT) {
1469 epold = get_dentry_in_dir(sb, p_dir, oldentry+1, &sector_old);
1470 dcache_lock(sb, sector_old);
1471 epnew = get_dentry_in_dir(sb, p_dir, newentry+1, &sector_new);
1472
1473 if (!epold || !epnew) {
1474 dcache_unlock(sb, sector_old);
1475 return -EIO;
1476 }
1477
1478 memcpy((void *) epnew, (void *) epold, DENTRY_SIZE);
1479 dcache_modify(sb, sector_new);
1480 dcache_unlock(sb, sector_old);
1481 }
1482
1483 ret = fsi->fs_func->init_ext_entry(sb, p_dir, newentry, num_new_entries, p_uniname, &dos_name);
1484 if (ret)
1485 return ret;
1486
1487 fsi->fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, num_old_entries);
1488 fid->entry = newentry;
1489 } else {
1490 if (fsi->fs_func->get_entry_type(epold) == TYPE_FILE) {
1491 fsi->fs_func->set_entry_attr(epold, fsi->fs_func->get_entry_attr(epold) | ATTR_ARCHIVE);
1492 fid->attr |= ATTR_ARCHIVE;
1493 }
1494 dcache_modify(sb, sector_old);
1495 dcache_unlock(sb, sector_old);
1496
1497 ret = fsi->fs_func->init_ext_entry(sb, p_dir, oldentry, num_new_entries, p_uniname, &dos_name);
1498 if (ret)
1499 return ret;
1500
1501 fsi->fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, num_old_entries);
1502 }
1503
1504 return 0;
1505 } /* end of rename_file */
1506
1507 static s32 move_file(struct inode *inode, CHAIN_T *p_olddir, s32 oldentry,
1508 CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid)
1509 {
1510 s32 ret, newentry, num_new_entries, num_old_entries;
1511 u32 sector_mov, sector_new;
1512 CHAIN_T clu;
1513 DOS_NAME_T dos_name;
1514 DENTRY_T *epmov, *epnew;
1515 struct super_block *sb = inode->i_sb;
1516 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1517
1518 epmov = get_dentry_in_dir(sb, p_olddir, oldentry, &sector_mov);
1519 if (!epmov)
1520 return -EIO;
1521
1522 /* check if the source and target directory is the same */
1523 if (fsi->fs_func->get_entry_type(epmov) == TYPE_DIR &&
1524 fsi->fs_func->get_entry_clu0(epmov) == p_newdir->dir)
1525 return -EINVAL;
1526
1527 dcache_lock(sb, sector_mov);
1528
1529 /* dcache_lock() before call count_ext_entries() */
1530 num_old_entries = fsi->fs_func->count_ext_entries(sb, p_olddir, oldentry, epmov);
1531 if (num_old_entries < 0) {
1532 dcache_unlock(sb, sector_mov);
1533 return -EIO;
1534 }
1535 num_old_entries++;
1536
1537 ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, &num_new_entries, &dos_name, 0);
1538 if (ret) {
1539 dcache_unlock(sb, sector_mov);
1540 return ret;
1541 }
1542
1543 newentry = find_empty_entry(inode, p_newdir, num_new_entries);
1544 if (newentry < 0) {
1545 dcache_unlock(sb, sector_mov);
1546 return newentry; /* -EIO or -ENOSPC */
1547 }
1548
1549 epnew = get_dentry_in_dir(sb, p_newdir, newentry, &sector_new);
1550 if (!epnew) {
1551 dcache_unlock(sb, sector_mov);
1552 return -EIO;
1553 }
1554
1555 memcpy((void *) epnew, (void *) epmov, DENTRY_SIZE);
1556 if (fsi->fs_func->get_entry_type(epnew) == TYPE_FILE) {
1557 fsi->fs_func->set_entry_attr(epnew, fsi->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE);
1558 fid->attr |= ATTR_ARCHIVE;
1559 }
1560 dcache_modify(sb, sector_new);
1561 dcache_unlock(sb, sector_mov);
1562
1563 if (fsi->vol_type == EXFAT) {
1564 epmov = get_dentry_in_dir(sb, p_olddir, oldentry+1, &sector_mov);
1565 dcache_lock(sb, sector_mov);
1566 epnew = get_dentry_in_dir(sb, p_newdir, newentry+1, &sector_new);
1567 if (!epmov || !epnew) {
1568 dcache_unlock(sb, sector_mov);
1569 return -EIO;
1570 }
1571
1572 memcpy((void *) epnew, (void *) epmov, DENTRY_SIZE);
1573 dcache_modify(sb, sector_new);
1574 dcache_unlock(sb, sector_mov);
1575 } else if (fsi->fs_func->get_entry_type(epnew) == TYPE_DIR) {
1576 /* change ".." pointer to new parent dir */
1577 clu.dir = fsi->fs_func->get_entry_clu0(epnew);
1578 clu.flags = 0x01;
1579
1580 epnew = get_dentry_in_dir(sb, &clu, 1, &sector_new);
1581 if (!epnew)
1582 return -EIO;
1583
1584 if (p_newdir->dir == fsi->root_dir)
1585 fsi->fs_func->set_entry_clu0(epnew, CLUS_FREE);
1586 else
1587 fsi->fs_func->set_entry_clu0(epnew, p_newdir->dir);
1588 dcache_modify(sb, sector_new);
1589 }
1590
1591 ret = fsi->fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, p_uniname, &dos_name);
1592 if (ret)
1593 return ret;
1594
1595 fsi->fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries);
1596
1597 fid->dir.dir = p_newdir->dir;
1598 fid->dir.size = p_newdir->size;
1599 fid->dir.flags = p_newdir->flags;
1600
1601 fid->entry = newentry;
1602
1603 return 0;
1604 } /* end of move_file */
1605
1606
1607 /*======================================================================*/
1608 /* Global Function Definitions */
1609 /*======================================================================*/
1610 /* roll back to the initial state of the file system */
1611 s32 fscore_init(void)
1612 {
1613 s32 ret;
1614
1615 ret = check_type_size();
1616 if (ret)
1617 return ret;
1618
1619 return extent_cache_init();
1620 }
1621
1622 /* make free all memory-alloced global buffers */
1623 s32 fscore_shutdown(void)
1624 {
1625 extent_cache_shutdown();
1626 return 0;
1627 }
1628
1629 static bool is_exfat(pbr_t *pbr)
1630 {
1631 int i = 53;
1632
1633 do {
1634 if (pbr->bpb.f64.res_zero[i-1])
1635 break;
1636 } while (--i);
1637 return i ? false : true;
1638 }
1639
1640 static bool is_fat32(pbr_t *pbr)
1641 {
1642 if (le16_to_cpu(pbr->bpb.f16.num_fat_sectors))
1643 return false;
1644 return true;
1645 }
1646
1647 inline pbr_t *read_pbr_with_logical_sector(struct super_block *sb, struct buffer_head **prev_bh)
1648 {
1649 pbr_t *p_pbr = (pbr_t *) (*prev_bh)->b_data;
1650 u16 logical_sect = 0;
1651
1652 if (is_exfat(p_pbr))
1653 logical_sect = 1 << p_pbr->bsx.f64.sect_size_bits;
1654 else
1655 logical_sect = get_unaligned_le16(&p_pbr->bpb.f16.sect_size);
1656
1657 /* is x a power of 2?
1658 * (x) != 0 && (((x) & ((x) - 1)) == 0)
1659 */
1660 if (!is_power_of_2(logical_sect)
1661 || (logical_sect < 512)
1662 || (logical_sect > 4096)) {
1663 sdfat_log_msg(sb, KERN_ERR, "bogus logical sector size %u",
1664 logical_sect);
1665 return NULL;
1666 }
1667
1668 if (logical_sect < sb->s_blocksize) {
1669 sdfat_log_msg(sb, KERN_ERR,
1670 "logical sector size too small for device"
1671 " (logical sector size = %u)", logical_sect);
1672 return NULL;
1673 }
1674
1675 if (logical_sect > sb->s_blocksize) {
1676 struct buffer_head *bh = NULL;
1677
1678 __brelse(*prev_bh);
1679 *prev_bh = NULL;
1680
1681 if (!sb_set_blocksize(sb, logical_sect)) {
1682 sdfat_log_msg(sb, KERN_ERR,
1683 "unable to set blocksize %u", logical_sect);
1684 return NULL;
1685 }
1686 bh = sb_bread(sb, 0);
1687 if (!bh) {
1688 sdfat_log_msg(sb, KERN_ERR,
1689 "unable to read boot sector "
1690 "(logical sector size = %lu)", sb->s_blocksize);
1691 return NULL;
1692 }
1693
1694 *prev_bh = bh;
1695 p_pbr = (pbr_t *) bh->b_data;
1696 }
1697
1698 sdfat_log_msg(sb, KERN_INFO,
1699 "set logical sector size : %lu", sb->s_blocksize);
1700
1701 return p_pbr;
1702 }
1703
1704 /* mount the file system volume */
1705 s32 fscore_mount(struct super_block *sb)
1706 {
1707 s32 ret;
1708 pbr_t *p_pbr;
1709 struct buffer_head *tmp_bh = NULL;
1710 struct gendisk *disk = sb->s_bdev->bd_disk;
1711 struct sdfat_mount_options *opts = &(SDFAT_SB(sb)->options);
1712 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1713
1714 /* initialize previous I/O error */
1715 fsi->prev_eio = 0;
1716
1717 /* open the block device */
1718 if (bdev_open_dev(sb))
1719 return -EIO;
1720
1721 /* set block size to read super block */
1722 sb_min_blocksize(sb, 512);
1723
1724 /* read boot sector */
1725 ret = read_sect(sb, 0, &tmp_bh, 1);
1726 if (ret) {
1727 sdfat_log_msg(sb, KERN_ERR, "unable to read boot sector");
1728 ret = -EIO;
1729 goto bd_close;
1730 }
1731
1732 /* PRB is read */
1733 p_pbr = (pbr_t *) tmp_bh->b_data;
1734
1735 /* check the validity of PBR */
1736 if (le16_to_cpu((p_pbr->signature)) != PBR_SIGNATURE) {
1737 sdfat_log_msg(sb, KERN_ERR, "invalid boot record signature");
1738 brelse(tmp_bh);
1739 ret = -EINVAL;
1740 goto bd_close;
1741 }
1742
1743 /* check logical sector size */
1744 p_pbr = read_pbr_with_logical_sector(sb, &tmp_bh);
1745 if (!p_pbr) {
1746 brelse(tmp_bh);
1747 ret = -EIO;
1748 goto bd_close;
1749 }
1750
1751 /* fill fs_struct */
1752 if (is_exfat(p_pbr)) {
1753 if (opts->fs_type && opts->fs_type != FS_TYPE_EXFAT) {
1754 sdfat_log_msg(sb, KERN_ERR,
1755 "not specified filesystem type "
1756 "(media:exfat, opts:%s)",
1757 FS_TYPE_STR[opts->fs_type]);
1758 ret = -EINVAL;
1759 goto free_bh;
1760 }
1761 /* set maximum file size for exFAT */
1762 sb->s_maxbytes = 0x7fffffffffffffffLL;
1763 opts->improved_allocation = 0;
1764 opts->defrag = 0;
1765 ret = mount_exfat(sb, p_pbr);
1766 } else if (is_fat32(p_pbr)) {
1767 if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
1768 sdfat_log_msg(sb, KERN_ERR,
1769 "not specified filesystem type "
1770 "(media:vfat, opts:%s)",
1771 FS_TYPE_STR[opts->fs_type]);
1772 ret = -EINVAL;
1773 goto free_bh;
1774 }
1775 /* set maximum file size for FAT */
1776 sb->s_maxbytes = 0xffffffff;
1777 ret = mount_fat32(sb, p_pbr);
1778 } else {
1779 if (opts->fs_type && opts->fs_type != FS_TYPE_VFAT) {
1780 sdfat_log_msg(sb, KERN_ERR,
1781 "not specified filesystem type "
1782 "(media:vfat, opts:%s)",
1783 FS_TYPE_STR[opts->fs_type]);
1784 ret = -EINVAL;
1785 goto free_bh;
1786 }
1787 /* set maximum file size for FAT */
1788 sb->s_maxbytes = 0xffffffff;
1789 opts->improved_allocation = 0;
1790 opts->defrag = 0;
1791 ret = mount_fat16(sb, p_pbr);
1792 }
1793 free_bh:
1794 brelse(tmp_bh);
1795 if (ret) {
1796 sdfat_log_msg(sb, KERN_ERR, "failed to mount fs-core");
1797 goto bd_close;
1798 }
1799
1800 /* warn misaligned data data start sector must be a multiple of clu_size */
1801 sdfat_log_msg(sb, KERN_INFO,
1802 "detected volume info : %s "
1803 "(bps : %lu, spc : %u, data start : %u, %s)",
1804 sdfat_get_vol_type_str(fsi->vol_type),
1805 sb->s_blocksize, fsi->sect_per_clus, fsi->data_start_sector,
1806 (fsi->data_start_sector & (fsi->sect_per_clus - 1)) ?
1807 "misaligned" : "aligned");
1808
1809 sdfat_log_msg(sb, KERN_INFO,
1810 "detected volume size : %u MB (disk_size : %llu MB)",
1811 fsi->num_sectors >> 11,
1812 disk ? (u64)((disk->part0.nr_sects) >> 11) : 0);
1813
1814 ret = load_upcase_table(sb);
1815 if (ret) {
1816 sdfat_log_msg(sb, KERN_ERR, "failed to load upcase table");
1817 goto bd_close;
1818 }
1819
1820 if (fsi->vol_type != EXFAT)
1821 goto success;
1822
1823 /* allocate-bitmap is only for exFAT */
1824 ret = load_alloc_bmp(sb);
1825 if (ret) {
1826 sdfat_log_msg(sb, KERN_ERR, "failed to load alloc-bitmap");
1827 goto free_upcase;
1828 }
1829 success:
1830 return 0;
1831 free_upcase:
1832 free_upcase_table(sb);
1833 bd_close:
1834 bdev_close_dev(sb);
1835 return ret;
1836 } /* end of fscore_mount */
1837
1838 /* umount the file system volume */
1839 s32 fscore_umount(struct super_block *sb)
1840 {
1841 s32 ret = 0;
1842 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1843
1844 if (fs_sync(sb, 0))
1845 ret = -EIO;
1846
1847 if (fs_set_vol_flags(sb, VOL_CLEAN))
1848 ret = -EIO;
1849
1850 free_upcase_table(sb);
1851
1852 if (fsi->vol_type == EXFAT)
1853 free_alloc_bmp(sb);
1854
1855 if (fcache_release_all(sb))
1856 ret = -EIO;
1857
1858 if (dcache_release_all(sb))
1859 ret = -EIO;
1860
1861 amap_destroy(sb);
1862
1863 if (fsi->prev_eio)
1864 ret = -EIO;
1865 /* close the block device */
1866 bdev_close_dev(sb);
1867 return ret;
1868 }
1869
1870 /* get the information of a file system volume */
1871 s32 fscore_statfs(struct super_block *sb, VOL_INFO_T *info)
1872 {
1873 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1874
1875 if (fsi->used_clusters == (u32) ~0) {
1876 if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters))
1877 return -EIO;
1878 }
1879
1880 info->FatType = fsi->vol_type;
1881 info->ClusterSize = fsi->cluster_size;
1882 info->NumClusters = fsi->num_clusters - 2; /* clu 0 & 1 */
1883 info->UsedClusters = fsi->used_clusters + fsi->reserved_clusters;
1884 info->FreeClusters = info->NumClusters - info->UsedClusters;
1885
1886 return 0;
1887 }
1888
1889 /* synchronize all file system volumes */
1890 s32 fscore_sync_fs(struct super_block *sb, s32 do_sync)
1891 {
1892 /* synchronize the file system */
1893 if (fs_sync(sb, do_sync))
1894 return -EIO;
1895
1896 if (fs_set_vol_flags(sb, VOL_CLEAN))
1897 return -EIO;
1898
1899 return 0;
1900 }
1901
1902 /* stat allocation unit of a file system volume */
1903 u32 fscore_get_au_stat(struct super_block *sb, s32 mode)
1904 {
1905 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1906
1907 if (fsi->fs_func->get_au_stat)
1908 return fsi->fs_func->get_au_stat(sb, mode);
1909
1910 /* No error, just returns 0 */
1911 return 0;
1912 }
1913
1914
1915 /*----------------------------------------------------------------------*/
1916 /* File Operation Functions */
1917 /*----------------------------------------------------------------------*/
1918 /* lookup a file */
1919 s32 fscore_lookup(struct inode *inode, u8 *path, FILE_ID_T *fid)
1920 {
1921 s32 ret, dentry, num_entries;
1922 CHAIN_T dir;
1923 UNI_NAME_T uni_name;
1924 DOS_NAME_T dos_name;
1925 DENTRY_T *ep, *ep2;
1926 ENTRY_SET_CACHE_T *es = NULL;
1927 struct super_block *sb = inode->i_sb;
1928 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
1929 FILE_ID_T *dir_fid = &(SDFAT_I(inode)->fid);
1930
1931 TMSG("%s entered\n", __func__);
1932
1933 /* check the validity of directory name in the given pathname */
1934 ret = resolve_path_for_lookup(inode, path, &dir, &uni_name);
1935 if (ret)
1936 return ret;
1937
1938 ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name, 1);
1939 if (ret)
1940 return ret;
1941
1942 /* check the validation of hint_stat and initialize it if required */
1943 if (dir_fid->version != (u32)(inode->i_version & 0xffffffff)) {
1944 dir_fid->hint_stat.clu = dir.dir;
1945 dir_fid->hint_stat.eidx = 0;
1946 dir_fid->version = (u32)(inode->i_version & 0xffffffff);
1947 dir_fid->hint_femp.eidx = -1;
1948 }
1949
1950 /* search the file name for directories */
1951 dentry = fsi->fs_func->find_dir_entry(sb, dir_fid, &dir, &uni_name,
1952 num_entries, &dos_name, TYPE_ALL);
1953
1954 if ((dentry < 0) && (dentry != -EEXIST))
1955 return dentry; /* -error value */
1956
1957 fid->dir.dir = dir.dir;
1958 fid->dir.size = dir.size;
1959 fid->dir.flags = dir.flags;
1960 fid->entry = dentry;
1961
1962 /* root directory itself */
1963 if (unlikely(dentry == -EEXIST)) {
1964 fid->type = TYPE_DIR;
1965 fid->rwoffset = 0;
1966 fid->hint_bmap.off = -1;
1967
1968 fid->attr = ATTR_SUBDIR;
1969 fid->flags = 0x01;
1970 fid->size = 0;
1971 fid->start_clu = fsi->root_dir;
1972 } else {
1973 if (fsi->vol_type == EXFAT) {
1974 es = get_dentry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep);
1975 if (!es)
1976 return -EIO;
1977 ep2 = ep+1;
1978 } else {
1979 ep = get_dentry_in_dir(sb, &dir, dentry, NULL);
1980 if (!ep)
1981 return -EIO;
1982 ep2 = ep;
1983 }
1984
1985 fid->type = fsi->fs_func->get_entry_type(ep);
1986 fid->rwoffset = 0;
1987 fid->hint_bmap.off = -1;
1988 fid->attr = fsi->fs_func->get_entry_attr(ep);
1989
1990 fid->size = fsi->fs_func->get_entry_size(ep2);
1991 if ((fid->type == TYPE_FILE) && (fid->size == 0)) {
1992 fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
1993 fid->start_clu = CLUS_EOF;
1994 } else {
1995 fid->flags = fsi->fs_func->get_entry_flag(ep2);
1996 fid->start_clu = fsi->fs_func->get_entry_clu0(ep2);
1997 }
1998
1999 if ((fid->type == TYPE_DIR) && (fsi->vol_type != EXFAT)) {
2000 s32 num_clu = 0;
2001 CHAIN_T tmp_dir;
2002
2003 tmp_dir.dir = fid->start_clu;
2004 tmp_dir.flags = fid->flags;
2005 tmp_dir.size = 0; /* UNUSED */
2006
2007 if (__count_num_clusters(sb, &tmp_dir, &num_clu))
2008 return -EIO;
2009 fid->size = (u64)num_clu << fsi->cluster_size_bits;
2010 }
2011
2012 /* FOR GRACEFUL ERROR HANDLING */
2013 if (IS_CLUS_FREE(fid->start_clu)) {
2014 sdfat_fs_error(sb,
2015 "non-zero size file starts with zero cluster "
2016 "(size : %llu, p_dir : %u, entry : 0x%08x)",
2017 fid->size, fid->dir.dir, fid->entry);
2018 sdfat_debug_bug_on(1);
2019 return -EIO;
2020 }
2021
2022 if (fsi->vol_type == EXFAT)
2023 release_dentry_set(es);
2024 }
2025
2026 /* hint_stat will be used if this is directory. */
2027 fid->version = 0;
2028 fid->hint_stat.eidx = 0;
2029 fid->hint_stat.clu = fid->start_clu;
2030 fid->hint_femp.eidx = -1;
2031
2032 TMSG("%s exited successfully\n", __func__);
2033 return 0;
2034 } /* end of fscore_lookup */
2035
2036 /* create a file */
2037 s32 fscore_create(struct inode *inode, u8 *path, u8 mode, FILE_ID_T *fid)
2038 {
2039 s32 ret/*, dentry*/;
2040 CHAIN_T dir;
2041 UNI_NAME_T uni_name;
2042 struct super_block *sb = inode->i_sb;
2043
2044 /* check the validity of directory name in the given pathname */
2045 ret = resolve_path(inode, path, &dir, &uni_name);
2046 if (ret)
2047 return ret;
2048
2049 fs_set_vol_flags(sb, VOL_DIRTY);
2050
2051 /* create a new file */
2052 ret = create_file(inode, &dir, &uni_name, mode, fid);
2053
2054 fs_sync(sb, 0);
2055 fs_set_vol_flags(sb, VOL_CLEAN);
2056
2057 return ret;
2058 }
2059
2060 /* read data from a opened file */
2061 s32 fscore_read_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *rcount)
2062 {
2063 s32 ret = 0;
2064 s32 offset, sec_offset, clu_offset;
2065 u32 clu, LogSector;
2066 u64 oneblkread, read_bytes;
2067 struct buffer_head *tmp_bh = NULL;
2068 struct super_block *sb = inode->i_sb;
2069 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2070
2071 /* check if the given file ID is opened */
2072 if (fid->type != TYPE_FILE)
2073 return -EPERM;
2074
2075 if (fid->rwoffset > fid->size)
2076 fid->rwoffset = fid->size;
2077
2078 if (count > (fid->size - fid->rwoffset))
2079 count = fid->size - fid->rwoffset;
2080
2081 if (count == 0) {
2082 if (rcount)
2083 *rcount = 0;
2084 return 0;
2085 }
2086
2087 read_bytes = 0;
2088
2089 while (count > 0) {
2090 clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits);
2091 clu = fid->start_clu;
2092
2093 if (fid->flags == 0x03) {
2094 clu += clu_offset;
2095 } else {
2096 /* hint information */
2097 if ((clu_offset > 0) && (fid->hint_bmap.off > 0) &&
2098 (clu_offset >= fid->hint_bmap.off)) {
2099 clu_offset -= fid->hint_bmap.off;
2100 clu = fid->hint_bmap.clu;
2101 }
2102
2103 while (clu_offset > 0) {
2104 ret = get_next_clus_safe(sb, &clu);
2105 if (ret)
2106 goto err_out;
2107
2108 clu_offset--;
2109 }
2110 }
2111
2112 /* hint information */
2113 fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits);
2114 fid->hint_bmap.clu = clu;
2115
2116 offset = (s32)(fid->rwoffset & (fsi->cluster_size - 1)); /* byte offset in cluster */
2117 sec_offset = offset >> sb->s_blocksize_bits; /* sector offset in cluster */
2118 offset &= (sb->s_blocksize - 1); /* byte offset in sector */
2119
2120 LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset;
2121
2122 oneblkread = (u64)(sb->s_blocksize - offset);
2123 if (oneblkread > count)
2124 oneblkread = count;
2125
2126 if ((offset == 0) && (oneblkread == sb->s_blocksize)) {
2127 ret = read_sect(sb, LogSector, &tmp_bh, 1);
2128 if (ret)
2129 goto err_out;
2130 memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data), (s32) oneblkread);
2131 } else {
2132 ret = read_sect(sb, LogSector, &tmp_bh, 1);
2133 if (ret)
2134 goto err_out;
2135 memcpy(((s8 *) buffer)+read_bytes, ((s8 *) tmp_bh->b_data)+offset, (s32) oneblkread);
2136 }
2137 count -= oneblkread;
2138 read_bytes += oneblkread;
2139 fid->rwoffset += oneblkread;
2140 }
2141
2142 err_out:
2143 brelse(tmp_bh);
2144
2145 /* set the size of read bytes */
2146 if (rcount != NULL)
2147 *rcount = read_bytes;
2148
2149 return ret;
2150 } /* end of fscore_read_link */
2151
2152 /* write data into a opened file */
2153 s32 fscore_write_link(struct inode *inode, FILE_ID_T *fid, void *buffer, u64 count, u64 *wcount)
2154 {
2155 s32 ret = 0;
2156 s32 modified = false, offset, sec_offset, clu_offset;
2157 s32 num_clusters, num_alloc, num_alloced = (s32) ~0;
2158 u32 clu, last_clu, LogSector, sector;
2159 u64 oneblkwrite, write_bytes;
2160 CHAIN_T new_clu;
2161 TIMESTAMP_T tm;
2162 DENTRY_T *ep, *ep2;
2163 ENTRY_SET_CACHE_T *es = NULL;
2164 struct buffer_head *tmp_bh = NULL;
2165 struct super_block *sb = inode->i_sb;
2166 u32 blksize = (u32)sb->s_blocksize;
2167 u32 blksize_mask = (u32)(sb->s_blocksize-1);
2168 u8 blksize_bits = sb->s_blocksize_bits;
2169 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2170
2171 /* check if the given file ID is opened */
2172 if (fid->type != TYPE_FILE)
2173 return -EPERM;
2174
2175 if (fid->rwoffset > fid->size)
2176 fid->rwoffset = fid->size;
2177
2178 if (count == 0) {
2179 if (wcount)
2180 *wcount = 0;
2181 return 0;
2182 }
2183
2184 fs_set_vol_flags(sb, VOL_DIRTY);
2185
2186 if (fid->size == 0)
2187 num_clusters = 0;
2188 else
2189 num_clusters = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1;
2190
2191 write_bytes = 0;
2192
2193 while (count > 0) {
2194 clu_offset = (s32)(fid->rwoffset >> fsi->cluster_size_bits);
2195 clu = last_clu = fid->start_clu;
2196
2197 if (fid->flags == 0x03) {
2198 if ((clu_offset > 0) && (!IS_CLUS_EOF(clu))) {
2199 last_clu += clu_offset - 1;
2200
2201 if (clu_offset == num_clusters)
2202 clu = CLUS_EOF;
2203 else
2204 clu += clu_offset;
2205 }
2206 } else {
2207 /* hint information */
2208 if ((clu_offset > 0) && (fid->hint_bmap.off > 0) &&
2209 (clu_offset >= fid->hint_bmap.off)) {
2210 clu_offset -= fid->hint_bmap.off;
2211 clu = fid->hint_bmap.clu;
2212 }
2213
2214 while ((clu_offset > 0) && (!IS_CLUS_EOF(clu))) {
2215 last_clu = clu;
2216 ret = get_next_clus_safe(sb, &clu);
2217 if (ret)
2218 goto err_out;
2219
2220 clu_offset--;
2221 }
2222 }
2223
2224 if (IS_CLUS_EOF(clu)) {
2225 num_alloc = (s32)((count-1) >> fsi->cluster_size_bits) + 1;
2226 new_clu.dir = IS_CLUS_EOF(last_clu) ? CLUS_EOF : last_clu+1;
2227 new_clu.size = 0;
2228 new_clu.flags = fid->flags;
2229
2230 /* (1) allocate a chain of clusters */
2231 num_alloced = fsi->fs_func->alloc_cluster(sb, num_alloc, &new_clu, ALLOC_COLD);
2232 if (!num_alloced)
2233 break;
2234
2235 if (num_alloced < 0) {
2236 ret = -EIO;
2237 goto err_out;
2238 }
2239
2240 /* (2) append to the FAT chain */
2241 if (IS_CLUS_EOF(last_clu)) {
2242 if (new_clu.flags == 0x01)
2243 fid->flags = 0x01;
2244 fid->start_clu = new_clu.dir;
2245 modified = true;
2246 } else {
2247 if (new_clu.flags != fid->flags) {
2248 /* no-fat-chain bit is disabled,
2249 * so fat-chain should be synced with
2250 * alloc-bmp
2251 */
2252 chain_cont_cluster(sb, fid->start_clu, num_clusters);
2253 fid->flags = 0x01;
2254 modified = true;
2255 }
2256 if (new_clu.flags == 0x01) {
2257 ret = fat_ent_set(sb, last_clu, new_clu.dir);
2258 if (ret)
2259 goto err_out;
2260 }
2261 }
2262
2263 num_clusters += num_alloced;
2264 clu = new_clu.dir;
2265 }
2266
2267 /* hint information */
2268 fid->hint_bmap.off = (s32)(fid->rwoffset >> fsi->cluster_size_bits);
2269 fid->hint_bmap.clu = clu;
2270
2271 /* byte offset in cluster */
2272 offset = (s32)(fid->rwoffset & (fsi->cluster_size-1));
2273 /* sector offset in cluster */
2274 sec_offset = offset >> blksize_bits;
2275 /* byte offset in sector */
2276 offset &= blksize_mask;
2277 LogSector = CLUS_TO_SECT(fsi, clu) + sec_offset;
2278
2279 oneblkwrite = (u64)(blksize - offset);
2280 if (oneblkwrite > count)
2281 oneblkwrite = count;
2282
2283 if ((offset == 0) && (oneblkwrite == blksize)) {
2284 ret = read_sect(sb, LogSector, &tmp_bh, 0);
2285 if (ret)
2286 goto err_out;
2287
2288 memcpy(((s8 *)tmp_bh->b_data),
2289 ((s8 *)buffer)+write_bytes,
2290 (s32)oneblkwrite);
2291
2292 ret = write_sect(sb, LogSector, tmp_bh, 0);
2293 if (ret) {
2294 brelse(tmp_bh);
2295 goto err_out;
2296 }
2297 } else {
2298 if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) {
2299 ret = read_sect(sb, LogSector, &tmp_bh, 1);
2300 if (ret)
2301 goto err_out;
2302 } else {
2303 ret = read_sect(sb, LogSector, &tmp_bh, 0);
2304 if (ret)
2305 goto err_out;
2306 }
2307
2308 memcpy(((s8 *) tmp_bh->b_data)+offset, ((s8 *) buffer)+write_bytes, (s32) oneblkwrite);
2309 ret = write_sect(sb, LogSector, tmp_bh, 0);
2310 if (ret) {
2311 brelse(tmp_bh);
2312 goto err_out;
2313 }
2314 }
2315
2316 count -= oneblkwrite;
2317 write_bytes += oneblkwrite;
2318 fid->rwoffset += oneblkwrite;
2319
2320 fid->attr |= ATTR_ARCHIVE;
2321
2322 if (fid->size < fid->rwoffset) {
2323 fid->size = fid->rwoffset;
2324 modified = true;
2325 }
2326 }
2327
2328 brelse(tmp_bh);
2329
2330 /* (3) update the direcoty entry */
2331 /* get_entry_(set_)in_dir shoulb be check DIR_DELETED flag. */
2332 if (fsi->vol_type == EXFAT) {
2333 es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
2334 if (!es) {
2335 ret = -EIO;
2336 goto err_out;
2337 }
2338 ep2 = ep+1;
2339 } else {
2340 ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, &sector);
2341 if (!ep) {
2342 ret = -EIO;
2343 goto err_out;
2344 }
2345 ep2 = ep;
2346 }
2347
2348 fsi->fs_func->set_entry_time(ep, tm_now(SDFAT_SB(sb), &tm), TM_MODIFY);
2349 fsi->fs_func->set_entry_attr(ep, fid->attr);
2350
2351 if (modified) {
2352 if (fsi->fs_func->get_entry_flag(ep2) != fid->flags)
2353 fsi->fs_func->set_entry_flag(ep2, fid->flags);
2354
2355 if (fsi->fs_func->get_entry_size(ep2) != fid->size)
2356 fsi->fs_func->set_entry_size(ep2, fid->size);
2357
2358 if (fsi->fs_func->get_entry_clu0(ep2) != fid->start_clu)
2359 fsi->fs_func->set_entry_clu0(ep2, fid->start_clu);
2360 }
2361
2362 if (fsi->vol_type == EXFAT) {
2363 if (update_dir_chksum_with_entry_set(sb, es)) {
2364 ret = -EIO;
2365 goto err_out;
2366 }
2367 release_dentry_set(es);
2368 } else {
2369 if (dcache_modify(sb, sector)) {
2370 ret = -EIO;
2371 goto err_out;
2372 }
2373 }
2374
2375 fs_sync(sb, 0);
2376 fs_set_vol_flags(sb, VOL_CLEAN);
2377
2378 err_out:
2379 /* set the size of written bytes */
2380 if (wcount)
2381 *wcount = write_bytes;
2382
2383 if (!num_alloced)
2384 return -ENOSPC;
2385
2386 return ret;
2387 } /* end of fscore_write_link */
2388
2389 /* resize the file length */
2390 s32 fscore_truncate(struct inode *inode, u64 old_size, u64 new_size)
2391 {
2392 s32 num_clusters_new, num_clusters_da, num_clusters_phys;
2393 u32 last_clu = CLUS_FREE, sector;
2394 CHAIN_T clu;
2395 TIMESTAMP_T tm;
2396 DENTRY_T *ep, *ep2;
2397 struct super_block *sb = inode->i_sb;
2398 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2399 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
2400 ENTRY_SET_CACHE_T *es = NULL;
2401 s32 evict = (fid->dir.dir == DIR_DELETED) ? 1 : 0;
2402
2403 /* check if the given file ID is opened */
2404 if ((fid->type != TYPE_FILE) && (fid->type != TYPE_DIR))
2405 return -EPERM;
2406
2407 /* TO CHECK inode type and size */
2408 MMSG("%s: inode(%p) type(%s) size:%lld->%lld\n", __func__, inode,
2409 (fid->type == TYPE_FILE) ? "file" : "dir", old_size, new_size);
2410
2411 /* XXX : This is for debugging. */
2412
2413 /* It can be when write failed */
2414 #if 0
2415 if (fid->size != old_size) {
2416 DMSG("%s: inode(%p) size-mismatch(old:%lld != fid:%lld)\n",
2417 __func__, inode, old_size, fid->size);
2418 WARN_ON(1);
2419 }
2420 #endif
2421 /*
2422 * There is no lock to protect fid->size.
2423 * So, we should get old_size and use it.
2424 */
2425 if (old_size <= new_size)
2426 return 0;
2427
2428 fs_set_vol_flags(sb, VOL_DIRTY);
2429
2430 /* Reserved count update */
2431 #define num_clusters(v) ((v) ? (s32)(((v) - 1) >> fsi->cluster_size_bits) + 1 : 0)
2432 num_clusters_da = num_clusters(SDFAT_I(inode)->i_size_aligned);
2433 num_clusters_new = num_clusters(i_size_read(inode));
2434 num_clusters_phys = num_clusters(SDFAT_I(inode)->i_size_ondisk);
2435
2436 /* num_clusters(i_size_old) should be equal to num_clusters_da */
2437 BUG_ON((num_clusters(old_size)) != (num_clusters(SDFAT_I(inode)->i_size_aligned)));
2438
2439 /* for debugging (FIXME: is okay on no-da case?) */
2440 BUG_ON(num_clusters_da < num_clusters_phys);
2441
2442 if ((num_clusters_da != num_clusters_phys) &&
2443 (num_clusters_new < num_clusters_da)) {
2444 /* Decrement reserved clusters
2445 * n_reserved = num_clusters_da - max(new,phys)
2446 */
2447 int n_reserved = (num_clusters_new > num_clusters_phys) ?
2448 (num_clusters_da - num_clusters_new) :
2449 (num_clusters_da - num_clusters_phys);
2450
2451 fsi->reserved_clusters -= n_reserved;
2452 BUG_ON(fsi->reserved_clusters < 0);
2453 }
2454
2455 clu.dir = fid->start_clu;
2456 /* In no-da case, num_clusters_phys is equal to below value
2457 * clu.size = (s32)((old_size-1) >> fsi->cluster_size_bits) + 1;
2458 */
2459 clu.size = num_clusters_phys;
2460 clu.flags = fid->flags;
2461
2462 /* For bigdata */
2463 sdfat_statistics_set_trunc(clu.flags, &clu);
2464
2465 if (new_size > 0) {
2466 /* Truncate FAT chain num_clusters after the first cluster
2467 * num_clusters = min(new, phys);
2468 */
2469 s32 num_clusters = (num_clusters_new < num_clusters_phys) ?
2470 num_clusters_new : num_clusters_phys;
2471
2472 /* Follow FAT chain
2473 * (defensive coding - works fine even with corrupted FAT table
2474 */
2475 if (clu.flags == 0x03) {
2476 clu.dir += num_clusters;
2477 clu.size -= num_clusters;
2478 #if 0
2479 /* extent_get_clus can`t know last_cluster
2480 * when find target cluster in cache.
2481 */
2482 } else if (fid->type == TYPE_FILE) {
2483 s32 fclus = 0;
2484 s32 err = extent_get_clus(inode, num_clusters,
2485 &fclus, &(clu.dir), &last_clu, 0);
2486 if (err)
2487 return -EIO;
2488 ASSERT(fclus == num_clusters);
2489
2490 if ((num_clusters > 1) && (last_clu == fid->start_clu)) {
2491 s32 fclus_tmp = 0;
2492 u32 temp = 0;
2493
2494 err = extent_get_clus(inode, num_clusters - 1,
2495 &fclus_tmp, &last_clu, &temp, 0);
2496 if (err)
2497 return -EIO;
2498 ASSERT(fclus_tmp == (num_clusters - 1));
2499 }
2500
2501 num_clusters -= fclus;
2502 clu.size -= fclus;
2503 #endif
2504 } else {
2505 while (num_clusters > 0) {
2506 last_clu = clu.dir;
2507 if (get_next_clus_safe(sb, &(clu.dir)))
2508 return -EIO;
2509
2510 num_clusters--;
2511 clu.size--;
2512 }
2513 }
2514
2515 /* Optimization avialable: */
2516 #if 0
2517 if (num_clusters_new < num_clusters) {
2518 < loop >
2519 } else {
2520 // num_clusters_new >= num_clusters_phys
2521 // FAT truncation is not necessary
2522
2523 clu.dir = CLUS_EOF;
2524 clu.size = 0;
2525 }
2526 #endif
2527 } else if (new_size == 0) {
2528 fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
2529 fid->start_clu = CLUS_EOF;
2530 }
2531 BUG_ON(clu.size < 0);
2532 fid->size = new_size;
2533
2534 if (fid->type == TYPE_FILE)
2535 fid->attr |= ATTR_ARCHIVE;
2536
2537 /*
2538 * clu.dir: free from
2539 * clu.size: # of clusters to free (exFAT, 0x03 only), no fat_free if 0
2540 * clu.flags: fid->flags (exFAT only)
2541 */
2542
2543 /* (1) update the directory entry */
2544 if (!evict) {
2545
2546 if (fsi->vol_type == EXFAT) {
2547 es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
2548 if (!es)
2549 return -EIO;
2550 ep2 = ep+1;
2551 } else {
2552 ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, &sector);
2553 if (!ep)
2554 return -EIO;
2555 ep2 = ep;
2556 }
2557
2558 fsi->fs_func->set_entry_time(ep, tm_now(SDFAT_SB(sb), &tm), TM_MODIFY);
2559 fsi->fs_func->set_entry_attr(ep, fid->attr);
2560
2561 /*
2562 * if (fsi->vol_type != EXFAT)
2563 * dcache_modify(sb, sector);
2564 */
2565
2566 /* File size should be zero if there is no cluster allocated */
2567 if (IS_CLUS_EOF(fid->start_clu))
2568 fsi->fs_func->set_entry_size(ep2, 0);
2569 else
2570 fsi->fs_func->set_entry_size(ep2, new_size);
2571
2572 if (new_size == 0) {
2573 /* Any directory can not be truncated to zero */
2574 BUG_ON(fid->type != TYPE_FILE);
2575
2576 fsi->fs_func->set_entry_flag(ep2, 0x01);
2577 fsi->fs_func->set_entry_clu0(ep2, CLUS_FREE);
2578 }
2579
2580 if (fsi->vol_type == EXFAT) {
2581 if (update_dir_chksum_with_entry_set(sb, es))
2582 return -EIO;
2583 release_dentry_set(es);
2584 } else {
2585 if (dcache_modify(sb, sector))
2586 return -EIO;
2587 }
2588
2589 } /* end of if(fid->dir.dir != DIR_DELETED) */
2590
2591 /* (2) cut off from the FAT chain */
2592 if ((fid->flags == 0x01) &&
2593 (!IS_CLUS_FREE(last_clu)) && (!IS_CLUS_EOF(last_clu))) {
2594 if (fat_ent_set(sb, last_clu, CLUS_EOF))
2595 return -EIO;
2596 }
2597
2598 /* (3) invalidate cache and free the clusters */
2599 /* clear extent cache */
2600 extent_cache_inval_inode(inode);
2601
2602 /* hint information */
2603 fid->hint_bmap.off = -1;
2604 fid->hint_bmap.clu = CLUS_EOF;
2605 if (fid->rwoffset > fid->size)
2606 fid->rwoffset = fid->size;
2607
2608 /* hint_stat will be used if this is directory. */
2609 fid->hint_stat.eidx = 0;
2610 fid->hint_stat.clu = fid->start_clu;
2611 fid->hint_femp.eidx = -1;
2612
2613 /* free the clusters */
2614 if (fsi->fs_func->free_cluster(sb, &clu, evict))
2615 return -EIO;
2616
2617 fs_sync(sb, 0);
2618 fs_set_vol_flags(sb, VOL_CLEAN);
2619
2620 return 0;
2621 } /* end of fscore_truncate */
2622
2623 static void update_parent_info(FILE_ID_T *fid, struct inode *parent_inode)
2624 {
2625 FS_INFO_T *fsi = &(SDFAT_SB(parent_inode->i_sb)->fsi);
2626 FILE_ID_T *parent_fid = &(SDFAT_I(parent_inode)->fid);
2627
2628 /*
2629 * the problem that FILE_ID_T caches wrong parent info.
2630 *
2631 * because of flag-mismatch of fid->dir,
2632 * there is abnormal traversing cluster chain.
2633 */
2634 if (unlikely((parent_fid->flags != fid->dir.flags)
2635 || (parent_fid->size != (fid->dir.size<<fsi->cluster_size_bits))
2636 || (parent_fid->start_clu != fid->dir.dir))) {
2637
2638 fid->dir.dir = parent_fid->start_clu;
2639 fid->dir.flags = parent_fid->flags;
2640 fid->dir.size = ((parent_fid->size + (fsi->cluster_size-1))
2641 >> fsi->cluster_size_bits);
2642 }
2643 }
2644
2645 /* rename or move a old file into a new file */
2646 s32 fscore_rename(struct inode *old_parent_inode, FILE_ID_T *fid,
2647 struct inode *new_parent_inode, struct dentry *new_dentry)
2648 {
2649 s32 ret;
2650 s32 dentry;
2651 CHAIN_T olddir, newdir;
2652 CHAIN_T *p_dir = NULL;
2653 UNI_NAME_T uni_name;
2654 DENTRY_T *ep;
2655 struct super_block *sb = old_parent_inode->i_sb;
2656 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2657 u8 *new_path = (u8 *) new_dentry->d_name.name;
2658 struct inode *new_inode = new_dentry->d_inode;
2659 int num_entries;
2660 FILE_ID_T *new_fid = NULL;
2661 u32 new_entry_type = TYPE_UNUSED;
2662 s32 new_entry = 0;
2663
2664 /* check the validity of pointer parameters */
2665 if ((new_path == NULL) || (strlen(new_path) == 0))
2666 return -EINVAL;
2667
2668 if (fid->dir.dir == DIR_DELETED) {
2669 EMSG("%s : abnormal access to deleted source dentry\n", __func__);
2670 return -ENOENT;
2671 }
2672
2673 /* patch 1.2.4 : the problem that FILE_ID_T caches wrong parent info. */
2674 update_parent_info(fid, old_parent_inode);
2675
2676 olddir.dir = fid->dir.dir;
2677 olddir.size = fid->dir.size;
2678 olddir.flags = fid->dir.flags;
2679
2680 dentry = fid->entry;
2681
2682 /* check if the old file is "." or ".." */
2683 if (fsi->vol_type != EXFAT) {
2684 if ((olddir.dir != fsi->root_dir) && (dentry < 2))
2685 return -EPERM;
2686 }
2687
2688 ep = get_dentry_in_dir(sb, &olddir, dentry, NULL);
2689 if (!ep)
2690 return -EIO;
2691
2692 #ifdef CONFIG_SDFAT_CHECK_RO_ATTR
2693 if (fsi->fs_func->get_entry_attr(ep) & ATTR_READONLY)
2694 return -EPERM;
2695 #endif
2696
2697 /* check whether new dir is existing directory and empty */
2698 if (new_inode) {
2699 ret = -EIO;
2700 new_fid = &SDFAT_I(new_inode)->fid;
2701
2702 if (new_fid->dir.dir == DIR_DELETED) {
2703 EMSG("%s : abnormal access to deleted target dentry\n", __func__);
2704 goto out;
2705 }
2706
2707 /* patch 1.2.4 :
2708 * the problem that FILE_ID_T caches wrong parent info.
2709 *
2710 * FIXME : is needed?
2711 */
2712 update_parent_info(new_fid, new_parent_inode);
2713
2714 p_dir = &(new_fid->dir);
2715 new_entry = new_fid->entry;
2716 ep = get_dentry_in_dir(sb, p_dir, new_entry, NULL);
2717 if (!ep)
2718 goto out;
2719
2720 new_entry_type = fsi->fs_func->get_entry_type(ep);
2721
2722 /* if new_inode exists, update fid */
2723 new_fid->size = i_size_read(new_inode);
2724
2725 if (new_entry_type == TYPE_DIR) {
2726 CHAIN_T new_clu;
2727
2728 new_clu.dir = new_fid->start_clu;
2729 new_clu.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1;
2730 new_clu.flags = new_fid->flags;
2731
2732 ret = check_dir_empty(sb, &new_clu);
2733 if (ret)
2734 return ret;
2735 }
2736 }
2737
2738 /* check the validity of directory name in the given new pathname */
2739 ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name);
2740 if (ret)
2741 return ret;
2742
2743 fs_set_vol_flags(sb, VOL_DIRTY);
2744
2745 if (olddir.dir == newdir.dir)
2746 ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid);
2747 else
2748 ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid);
2749
2750 if ((!ret) && new_inode) {
2751 /* delete entries of new_dir */
2752 ep = get_dentry_in_dir(sb, p_dir, new_entry, NULL);
2753 if (!ep) {
2754 ret = -EIO;
2755 goto del_out;
2756 }
2757
2758 num_entries = fsi->fs_func->count_ext_entries(sb, p_dir, new_entry, ep);
2759 if (num_entries < 0) {
2760 ret = -EIO;
2761 goto del_out;
2762 }
2763
2764
2765 if (fsi->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1)) {
2766 ret = -EIO;
2767 goto del_out;
2768 }
2769
2770 /* Free the clusters if new_inode is a dir(as if fscore_rmdir) */
2771 if (new_entry_type == TYPE_DIR) {
2772 /* new_fid, new_clu_to_free */
2773 CHAIN_T new_clu_to_free;
2774
2775 new_clu_to_free.dir = new_fid->start_clu;
2776 new_clu_to_free.size = (s32)((new_fid->size-1) >> fsi->cluster_size_bits) + 1;
2777 new_clu_to_free.flags = new_fid->flags;
2778
2779 if (fsi->fs_func->free_cluster(sb, &new_clu_to_free, 1)) {
2780 /* just set I/O error only */
2781 ret = -EIO;
2782 }
2783
2784 new_fid->size = 0;
2785 new_fid->start_clu = CLUS_EOF;
2786 new_fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
2787 }
2788 del_out:
2789 /* Update new_inode fid
2790 * Prevent syncing removed new_inode
2791 * (new_fid is already initialized above code ("if (new_inode)")
2792 */
2793 new_fid->dir.dir = DIR_DELETED;
2794 }
2795 out:
2796 fs_sync(sb, 0);
2797 fs_set_vol_flags(sb, VOL_CLEAN);
2798
2799 return ret;
2800 } /* end of fscore_rename */
2801
2802 /* remove a file */
2803 s32 fscore_remove(struct inode *inode, FILE_ID_T *fid)
2804 {
2805 s32 ret;
2806 s32 dentry;
2807 CHAIN_T dir, clu_to_free;
2808 DENTRY_T *ep;
2809 struct super_block *sb = inode->i_sb;
2810 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2811
2812 dir.dir = fid->dir.dir;
2813 dir.size = fid->dir.size;
2814 dir.flags = fid->dir.flags;
2815
2816 dentry = fid->entry;
2817
2818 if (fid->dir.dir == DIR_DELETED) {
2819 EMSG("%s : abnormal access to deleted dentry\n", __func__);
2820 return -ENOENT;
2821 }
2822
2823 ep = get_dentry_in_dir(sb, &dir, dentry, NULL);
2824 if (!ep)
2825 return -EIO;
2826
2827
2828 #ifdef CONFIG_SDFAT_CHECK_RO_ATTR
2829 if (fsi->fs_func->get_entry_attr(ep) & ATTR_READONLY)
2830 return -EPERM;
2831 #endif
2832
2833 fs_set_vol_flags(sb, VOL_DIRTY);
2834
2835 /* (1) update the directory entry */
2836 ret = remove_file(inode, &dir, dentry);
2837 if (ret)
2838 goto out;
2839
2840 clu_to_free.dir = fid->start_clu;
2841 clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1;
2842 clu_to_free.flags = fid->flags;
2843
2844 /* (2) invalidate extent cache and free the clusters
2845 */
2846 /* clear extent cache */
2847 extent_cache_inval_inode(inode);
2848 ret = fsi->fs_func->free_cluster(sb, &clu_to_free, 0);
2849 /* WARN : DO NOT RETURN ERROR IN HERE */
2850
2851 /* (3) update FILE_ID_T */
2852 fid->size = 0;
2853 fid->start_clu = CLUS_EOF;
2854 fid->flags = (fsi->vol_type == EXFAT) ? 0x03 : 0x01;
2855 fid->dir.dir = DIR_DELETED;
2856
2857 fs_sync(sb, 0);
2858 fs_set_vol_flags(sb, VOL_CLEAN);
2859 out:
2860 return ret;
2861 } /* end of fscore_remove */
2862
2863
2864 /*
2865 * Get the information of a given file
2866 * REMARK : This function does not need any file name on linux
2867 *
2868 * info.Size means the value saved on disk.
2869 * But root directory doesn`t have real dentry,
2870 * so the size of root directory returns calculated one exceptively.
2871 */
2872 s32 fscore_read_inode(struct inode *inode, DIR_ENTRY_T *info)
2873 {
2874 u32 sector;
2875 s32 count;
2876 CHAIN_T dir;
2877 TIMESTAMP_T tm;
2878 DENTRY_T *ep, *ep2;
2879 struct super_block *sb = inode->i_sb;
2880 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
2881 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
2882 ENTRY_SET_CACHE_T *es = NULL;
2883 u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
2884
2885 TMSG("%s entered\n", __func__);
2886
2887 extent_cache_init_inode(inode);
2888
2889 /* if root directory */
2890 if (is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1)) {
2891 info->Attr = ATTR_SUBDIR;
2892 memset((s8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T));
2893 memset((s8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T));
2894 memset((s8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
2895 //strcpy(info->NameBuf.sfn, ".");
2896 //strcpy(info->NameBuf.lfn, ".");
2897
2898 dir.dir = fsi->root_dir;
2899 dir.flags = 0x01;
2900 dir.size = 0; /* UNUSED */
2901
2902 /* FAT16 root_dir */
2903 if (IS_CLUS_FREE(fsi->root_dir)) {
2904 info->Size = fsi->dentries_in_root << DENTRY_SIZE_BITS;
2905 } else {
2906 s32 num_clu;
2907
2908 if (__count_num_clusters(sb, &dir, &num_clu))
2909 return -EIO;
2910 info->Size = (u64)num_clu << fsi->cluster_size_bits;
2911 }
2912
2913 count = __count_dos_name_entries(sb, &dir, TYPE_DIR, NULL);
2914 if (count < 0)
2915 return -EIO;
2916 info->NumSubdirs = count;
2917
2918 return 0;
2919 }
2920
2921 /* get the directory entry of given file or directory */
2922 if (fsi->vol_type == EXFAT) {
2923 /* es should be released */
2924 es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep);
2925 if (!es)
2926 return -EIO;
2927 ep2 = ep+1;
2928 } else {
2929 ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, &sector);
2930 if (!ep)
2931 return -EIO;
2932 ep2 = ep;
2933 /* dcache should be unlocked */
2934 dcache_lock(sb, sector);
2935 }
2936
2937 /* set FILE_INFO structure using the acquired DENTRY_T */
2938 info->Attr = fsi->fs_func->get_entry_attr(ep);
2939
2940 fsi->fs_func->get_entry_time(ep, &tm, TM_CREATE);
2941 info->CreateTimestamp.Year = tm.year;
2942 info->CreateTimestamp.Month = tm.mon;
2943 info->CreateTimestamp.Day = tm.day;
2944 info->CreateTimestamp.Hour = tm.hour;
2945 info->CreateTimestamp.Minute = tm.min;
2946 info->CreateTimestamp.Second = tm.sec;
2947 info->CreateTimestamp.MilliSecond = 0;
2948
2949 fsi->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
2950 info->ModifyTimestamp.Year = tm.year;
2951 info->ModifyTimestamp.Month = tm.mon;
2952 info->ModifyTimestamp.Day = tm.day;
2953 info->ModifyTimestamp.Hour = tm.hour;
2954 info->ModifyTimestamp.Minute = tm.min;
2955 info->ModifyTimestamp.Second = tm.sec;
2956 info->ModifyTimestamp.MilliSecond = 0;
2957
2958 memset((s8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
2959
2960 info->NumSubdirs = 0;
2961 info->Size = fsi->fs_func->get_entry_size(ep2);
2962
2963 if (fsi->vol_type == EXFAT)
2964 release_dentry_set(es);
2965 else
2966 dcache_unlock(sb, sector);
2967
2968 if (is_dir) {
2969 u32 dotcnt = 0;
2970
2971 dir.dir = fid->start_clu;
2972 dir.flags = fid->flags;
2973 dir.size = fid->size >> fsi->cluster_size_bits;
2974 /*
2975 * NOTE :
2976 * If "dir.flags" has 0x01, "dir.size" is meaningless.
2977 */
2978 #if 0
2979 if (info->Size == 0) {
2980 s32 num_clu;
2981
2982 if (__count_num_clusters(sb, &dir, &num_clu))
2983 return -EIO;
2984 info->Size = (u64)num_clu << fsi->cluster_size_bits;
2985 }
2986 #endif
2987 count = __count_dos_name_entries(sb, &dir, TYPE_DIR, &dotcnt);
2988 if (count < 0)
2989 return -EIO;
2990
2991 if (fsi->vol_type == EXFAT) {
2992 count += SDFAT_MIN_SUBDIR;
2993 } else {
2994 /*
2995 * if directory has been corrupted,
2996 * we have to adjust subdir count.
2997 */
2998 BUG_ON(dotcnt > SDFAT_MIN_SUBDIR);
2999 if (dotcnt < SDFAT_MIN_SUBDIR) {
3000 EMSG("%s: contents of the directory has been "
3001 "corrupted (parent clus : %08x, idx : %d)",
3002 __func__, fid->dir.dir, fid->entry);
3003 }
3004 count += (SDFAT_MIN_SUBDIR - dotcnt);
3005 }
3006 info->NumSubdirs = count;
3007 }
3008
3009 TMSG("%s exited successfully\n", __func__);
3010 return 0;
3011 } /* end of fscore_read_inode */
3012
3013 /* set the information of a given file
3014 * REMARK : This function does not need any file name on linux
3015 */
3016 s32 fscore_write_inode(struct inode *inode, DIR_ENTRY_T *info, s32 sync)
3017 {
3018 s32 ret = -EIO;
3019 u32 sector;
3020 TIMESTAMP_T tm;
3021 DENTRY_T *ep, *ep2;
3022 ENTRY_SET_CACHE_T *es = NULL;
3023 struct super_block *sb = inode->i_sb;
3024 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
3025 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
3026 u8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
3027
3028
3029 /* SKIP WRITING INODE :
3030 * if the indoe is already unlinked,
3031 * there is no need for updating inode
3032 */
3033 if (fid->dir.dir == DIR_DELETED)
3034 return 0;
3035
3036 if (is_dir && (fid->dir.dir == fsi->root_dir) && (fid->entry == -1))
3037 return 0;
3038
3039 fs_set_vol_flags(sb, VOL_DIRTY);
3040
3041 /* get the directory entry of given file or directory */
3042 if (fsi->vol_type == EXFAT) {
3043 es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
3044 if (!es)
3045 return -EIO;
3046 ep2 = ep+1;
3047 } else {
3048 /* for other than exfat */
3049 ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, &sector);
3050 if (!ep)
3051 return -EIO;
3052 ep2 = ep;
3053 }
3054
3055
3056 fsi->fs_func->set_entry_attr(ep, info->Attr);
3057
3058 /* set FILE_INFO structure using the acquired DENTRY_T */
3059 tm.sec = info->CreateTimestamp.Second;
3060 tm.min = info->CreateTimestamp.Minute;
3061 tm.hour = info->CreateTimestamp.Hour;
3062 tm.day = info->CreateTimestamp.Day;
3063 tm.mon = info->CreateTimestamp.Month;
3064 tm.year = info->CreateTimestamp.Year;
3065 fsi->fs_func->set_entry_time(ep, &tm, TM_CREATE);
3066
3067 tm.sec = info->ModifyTimestamp.Second;
3068 tm.min = info->ModifyTimestamp.Minute;
3069 tm.hour = info->ModifyTimestamp.Hour;
3070 tm.day = info->ModifyTimestamp.Day;
3071 tm.mon = info->ModifyTimestamp.Month;
3072 tm.year = info->ModifyTimestamp.Year;
3073 fsi->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
3074
3075 if (is_dir && fsi->vol_type != EXFAT) {
3076 /* overwirte dirsize if FAT32 and dir size != 0 */
3077 if (fsi->fs_func->get_entry_size(ep2))
3078 fsi->fs_func->set_entry_size(ep2, 0);
3079 } else {
3080 /* File size should be zero if there is no cluster allocated */
3081 u64 on_disk_size = info->Size;
3082
3083 if (IS_CLUS_EOF(fid->start_clu))
3084 on_disk_size = 0;
3085
3086 fsi->fs_func->set_entry_size(ep2, on_disk_size);
3087 }
3088
3089 if (fsi->vol_type == EXFAT) {
3090 ret = update_dir_chksum_with_entry_set(sb, es);
3091 release_dentry_set(es);
3092 } else {
3093 ret = dcache_modify(sb, sector);
3094 }
3095
3096 fs_sync(sb, sync);
3097 /* Comment below code to prevent super block update frequently */
3098 //fs_set_vol_flags(sb, VOL_CLEAN);
3099
3100 return ret;
3101 } /* end of fscore_write_inode */
3102
3103
3104 /*
3105 * Input: inode, (logical) clu_offset, target allocation area
3106 * Output: errcode, cluster number
3107 * *clu = (~0), if it's unable to allocate a new cluster
3108 */
3109 s32 fscore_map_clus(struct inode *inode, s32 clu_offset, u32 *clu, int dest)
3110 {
3111 s32 num_clusters, num_alloced, num_to_be_allocated, modified = false;
3112 u32 last_clu, sector;
3113 CHAIN_T new_clu;
3114 DENTRY_T *ep;
3115 ENTRY_SET_CACHE_T *es = NULL;
3116 struct super_block *sb = inode->i_sb;
3117 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
3118 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
3119 s32 local_clu_offset = clu_offset;
3120 s32 reserved_clusters = fsi->reserved_clusters;
3121
3122 fid->rwoffset = (s64)(clu_offset) << fsi->cluster_size_bits;
3123
3124 if (SDFAT_I(inode)->i_size_ondisk == 0)
3125 num_clusters = 0;
3126 else
3127 num_clusters = (s32)((SDFAT_I(inode)->i_size_ondisk-1) >> fsi->cluster_size_bits) + 1;
3128
3129 num_to_be_allocated = clu_offset - num_clusters + 1;
3130 if ((dest == ALLOC_NOWHERE) && (num_to_be_allocated > 0)) {
3131 *clu = CLUS_EOF;
3132 return 0;
3133 }
3134
3135 sdfat_debug_check_clusters(inode);
3136
3137 *clu = last_clu = fid->start_clu;
3138
3139 /* XXX: Defensive code needed.
3140 * what if i_size_ondisk != # of allocated clusters
3141 */
3142 if (fid->flags == 0x03) {
3143 if ((clu_offset > 0) && (!IS_CLUS_EOF(*clu))) {
3144 last_clu += clu_offset - 1;
3145
3146 if (clu_offset == num_clusters)
3147 *clu = CLUS_EOF;
3148 else
3149 *clu += clu_offset;
3150 }
3151 } else if (fid->type == TYPE_FILE) {
3152 s32 fclus = 0;
3153 s32 err = extent_get_clus(inode, clu_offset,
3154 &fclus, clu, &last_clu, 1);
3155 if (err)
3156 return -EIO;
3157
3158 clu_offset -= fclus;
3159 } else {
3160 /* hint information */
3161 if ((clu_offset > 0) && (fid->hint_bmap.off > 0) &&
3162 (clu_offset >= fid->hint_bmap.off)) {
3163 clu_offset -= fid->hint_bmap.off;
3164 /* hint_bmap.clu should be valid */
3165 ASSERT(fid->hint_bmap.clu >= 2);
3166 *clu = fid->hint_bmap.clu;
3167 }
3168
3169 while ((clu_offset > 0) && (!IS_CLUS_EOF(*clu))) {
3170 last_clu = *clu;
3171 if (get_next_clus_safe(sb, clu))
3172 return -EIO;
3173 clu_offset--;
3174 }
3175 }
3176
3177 if (IS_CLUS_EOF(*clu)) {
3178 fs_set_vol_flags(sb, VOL_DIRTY);
3179
3180 new_clu.dir = (IS_CLUS_EOF(last_clu)) ? CLUS_EOF : last_clu + 1;
3181 new_clu.size = 0;
3182 new_clu.flags = fid->flags;
3183
3184 /* (1) allocate a cluster */
3185 if (num_to_be_allocated < 1) {
3186 /* Broken FAT (i_sze > allocated FAT) */
3187 EMSG("%s: invalid fat chain : inode(%p) "
3188 "num_to_be_allocated(%d) "
3189 "i_size_ondisk(%lld) fid->flags(%02x) "
3190 "fid->start(%08x) fid->hint_off(%d) "
3191 "fid->hint_clu(%u) fid->rwoffset(%llu) "
3192 "modified_clu_off(%d) last_clu(%08x) "
3193 "new_clu(%08x)", __func__, inode,
3194 num_to_be_allocated,
3195 (SDFAT_I(inode)->i_size_ondisk),
3196 fid->flags, fid->start_clu,
3197 fid->hint_bmap.off, fid->hint_bmap.clu,
3198 fid->rwoffset, clu_offset,
3199 last_clu, new_clu.dir);
3200 sdfat_fs_error(sb, "broken FAT chain.");
3201 return -EIO;
3202 }
3203
3204 num_alloced = fsi->fs_func->alloc_cluster(sb, num_to_be_allocated, &new_clu, ALLOC_COLD);
3205 if (num_alloced < 0) {
3206 return -EIO;
3207 } else if (num_alloced < num_to_be_allocated) {
3208 if (num_to_be_allocated == 1) {
3209 ASSERT(!num_alloced);
3210 } else {
3211 DMSG("%s : ENOSPC (requested:%d, alloced:%d)\n",
3212 __func__, num_alloced,
3213 num_to_be_allocated);
3214 }
3215 return -ENOSPC;
3216 }
3217
3218 if (IS_CLUS_EOF(new_clu.dir) || IS_CLUS_FREE(new_clu.dir)) {
3219 sdfat_fs_error(sb, "bogus cluster new allocated"
3220 "(last_clu : %u, new_clu : %u)",
3221 last_clu, new_clu.dir);
3222 ASSERT(0);
3223 return -EIO;
3224 }
3225
3226 /* Reserved cluster dec. */
3227 // XXX: Inode DA flag needed
3228 if (SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY) {
3229 BUG_ON(reserved_clusters < num_alloced);
3230 reserved_clusters -= num_alloced;
3231
3232 }
3233
3234 /* (2) append to the FAT chain */
3235 if (IS_CLUS_EOF(last_clu)) {
3236 if (new_clu.flags == 0x01)
3237 fid->flags = 0x01;
3238 fid->start_clu = new_clu.dir;
3239 modified = true;
3240 } else {
3241 if (new_clu.flags != fid->flags) {
3242 /* no-fat-chain bit is disabled,
3243 * so fat-chain should be synced with alloc-bmp
3244 */
3245 chain_cont_cluster(sb, fid->start_clu, num_clusters);
3246 fid->flags = 0x01;
3247 modified = true;
3248 }
3249 if (new_clu.flags == 0x01)
3250 if (fat_ent_set(sb, last_clu, new_clu.dir))
3251 return -EIO;
3252 }
3253
3254 num_clusters += num_alloced;
3255 *clu = new_clu.dir;
3256
3257 if (fid->dir.dir != DIR_DELETED) {
3258
3259 if (fsi->vol_type == EXFAT) {
3260 es = get_dentry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
3261 if (!es)
3262 return -EIO;
3263 /* get stream entry */
3264 ep++;
3265 }
3266
3267 /* (3) update directory entry */
3268 if (modified) {
3269 if (fsi->vol_type != EXFAT) {
3270 ep = get_dentry_in_dir(sb, &(fid->dir), fid->entry, &sector);
3271 if (!ep)
3272 return -EIO;
3273 }
3274
3275 if (fsi->fs_func->get_entry_flag(ep) != fid->flags)
3276 fsi->fs_func->set_entry_flag(ep, fid->flags);
3277
3278 if (fsi->fs_func->get_entry_clu0(ep) != fid->start_clu)
3279 fsi->fs_func->set_entry_clu0(ep, fid->start_clu);
3280
3281 fsi->fs_func->set_entry_size(ep, fid->size);
3282
3283 if (fsi->vol_type != EXFAT) {
3284 if (dcache_modify(sb, sector))
3285 return -EIO;
3286 }
3287 }
3288
3289 if (fsi->vol_type == EXFAT) {
3290 if (update_dir_chksum_with_entry_set(sb, es))
3291 return -EIO;
3292 release_dentry_set(es);
3293 }
3294
3295 } /* end of if != DIR_DELETED */
3296
3297
3298 /* add number of new blocks to inode (non-DA only) */
3299 if (!(SDFAT_SB(sb)->options.improved_allocation & SDFAT_ALLOC_DELAY)) {
3300 inode->i_blocks += num_alloced << (fsi->cluster_size_bits - sb->s_blocksize_bits);
3301 } else {
3302 // DA의 경우, i_blocks가 이미 증가해있어야 함.
3303 BUG_ON(clu_offset >= (inode->i_blocks >> (fsi->cluster_size_bits - sb->s_blocksize_bits)));
3304 }
3305 #if 0
3306 fs_sync(sb, 0);
3307 fs_set_vol_flags(sb, VOL_CLEAN);
3308 #endif
3309 /* (4) Move *clu pointer along FAT chains (hole care)
3310 * because the caller of this function expect *clu to be the last cluster.
3311 * This only works when num_to_be_allocated >= 2,
3312 * *clu = (the first cluster of the allocated chain) => (the last cluster of ...)
3313 */
3314 if (fid->flags == 0x03) {
3315 *clu += num_to_be_allocated - 1;
3316 } else {
3317 while (num_to_be_allocated > 1) {
3318 if (get_next_clus_safe(sb, clu))
3319 return -EIO;
3320 num_to_be_allocated--;
3321 }
3322 }
3323
3324 }
3325
3326 /* update reserved_clusters */
3327 fsi->reserved_clusters = reserved_clusters;
3328
3329 /* hint information */
3330 fid->hint_bmap.off = local_clu_offset;
3331 fid->hint_bmap.clu = *clu;
3332
3333 return 0;
3334 } /* end of fscore_map_clus */
3335
3336 /* allocate reserved cluster */
3337 s32 fscore_reserve_clus(struct inode *inode)
3338 {
3339 struct super_block *sb = inode->i_sb;
3340 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
3341
3342 /* used cluster check */
3343 if (fsi->used_clusters == (u32) ~0) {
3344 if (fsi->fs_func->count_used_clusters(sb, &fsi->used_clusters))
3345 return -EIO;
3346 }
3347
3348 if ((fsi->used_clusters + fsi->reserved_clusters) >= (fsi->num_clusters - 2))
3349 return -ENOSPC;
3350
3351 if (bdev_check_bdi_valid(sb))
3352 return -EIO;
3353
3354 fsi->reserved_clusters++;
3355
3356 /* inode->i_blocks update */
3357 inode->i_blocks += 1 << (fsi->cluster_size_bits - sb->s_blocksize_bits);
3358
3359 sdfat_debug_check_clusters(inode);
3360
3361 return 0;
3362 }
3363
3364 /* remove an entry, BUT don't truncate */
3365 s32 fscore_unlink(struct inode *inode, FILE_ID_T *fid)
3366 {
3367 s32 dentry;
3368 CHAIN_T dir;
3369 DENTRY_T *ep;
3370 struct super_block *sb = inode->i_sb;
3371
3372 dir.dir = fid->dir.dir;
3373 dir.size = fid->dir.size;
3374 dir.flags = fid->dir.flags;
3375
3376 dentry = fid->entry;
3377
3378 if (fid->dir.dir == DIR_DELETED) {
3379 EMSG("%s : abnormal access to deleted dentry\n", __func__);
3380 return -ENOENT;
3381 }
3382
3383 ep = get_dentry_in_dir(sb, &dir, dentry, NULL);
3384 if (!ep)
3385 return -EIO;
3386
3387 #ifdef CONFIG_SDFAT_CHECK_RO_ATTR
3388 if (SDFAT_SB(sb)->fsi.fs_func->get_entry_attr(ep) & ATTR_READONLY)
3389 return -EPERM;
3390 #endif
3391
3392 fs_set_vol_flags(sb, VOL_DIRTY);
3393
3394 /* (1) update the directory entry */
3395 if (remove_file(inode, &dir, dentry))
3396 return -EIO;
3397
3398 /* This doesn't modify fid */
3399 fid->dir.dir = DIR_DELETED;
3400
3401 fs_sync(sb, 0);
3402 fs_set_vol_flags(sb, VOL_CLEAN);
3403
3404 return 0;
3405 }
3406
3407 /*----------------------------------------------------------------------*/
3408 /* Directory Operation Functions */
3409 /*----------------------------------------------------------------------*/
3410
3411 /* create a directory */
3412 s32 fscore_mkdir(struct inode *inode, u8 *path, FILE_ID_T *fid)
3413 {
3414 s32 ret/*, dentry*/;
3415 CHAIN_T dir;
3416 UNI_NAME_T uni_name;
3417 struct super_block *sb = inode->i_sb;
3418
3419 TMSG("%s entered\n", __func__);
3420
3421 /* check the validity of directory name in the given old pathname */
3422 ret = resolve_path(inode, path, &dir, &uni_name);
3423 if (ret)
3424 goto out;
3425
3426 fs_set_vol_flags(sb, VOL_DIRTY);
3427
3428 ret = create_dir(inode, &dir, &uni_name, fid);
3429
3430 fs_sync(sb, 0);
3431 fs_set_vol_flags(sb, VOL_CLEAN);
3432 out:
3433 TMSG("%s exited with err(%d)\n", __func__, ret);
3434 return ret;
3435 }
3436
3437 /* read a directory entry from the opened directory */
3438 s32 fscore_readdir(struct inode *inode, DIR_ENTRY_T *dir_entry)
3439 {
3440 s32 i, clu_offset;
3441 s32 dentries_per_clu, dentries_per_clu_bits = 0;
3442 u32 type, sector;
3443 CHAIN_T dir, clu;
3444 UNI_NAME_T uni_name;
3445 TIMESTAMP_T tm;
3446 DENTRY_T *ep;
3447 struct super_block *sb = inode->i_sb;
3448 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
3449 FILE_ID_T *fid = &(SDFAT_I(inode)->fid);
3450 s32 dentry = (s32) fid->rwoffset;
3451
3452 /* check if the given file ID is opened */
3453 if (fid->type != TYPE_DIR)
3454 return -EPERM;
3455
3456 if (fid->entry == -1) {
3457 dir.dir = fsi->root_dir;
3458 dir.size = 0; /* just initialize, but will not use */
3459 dir.flags = 0x01;
3460 } else {
3461 dir.dir = fid->start_clu;
3462 dir.size = (s32)(fid->size >> fsi->cluster_size_bits);
3463 dir.flags = fid->flags;
3464 sdfat_debug_bug_on(dentry >= (dir.size * fsi->dentries_per_clu));
3465 }
3466
3467 if (IS_CLUS_FREE(dir.dir)) { /* FAT16 root_dir */
3468 dentries_per_clu = fsi->dentries_in_root;
3469
3470 /* Prevent readdir over directory size */
3471 if (dentry >= dentries_per_clu) {
3472 clu.dir = CLUS_EOF;
3473 } else {
3474 clu.dir = dir.dir;
3475 clu.size = dir.size;
3476 clu.flags = dir.flags;
3477 }
3478 } else {
3479 dentries_per_clu = fsi->dentries_per_clu;
3480 dentries_per_clu_bits = ilog2(dentries_per_clu);
3481
3482 clu_offset = dentry >> dentries_per_clu_bits;
3483 clu.dir = dir.dir;
3484 clu.size = dir.size;
3485 clu.flags = dir.flags;
3486
3487 if (clu.flags == 0x03) {
3488 clu.dir += clu_offset;
3489 clu.size -= clu_offset;
3490 } else {
3491 /* hint_information */
3492 if ((clu_offset > 0) && (fid->hint_bmap.off > 0) &&
3493 (clu_offset >= fid->hint_bmap.off)) {
3494 clu_offset -= fid->hint_bmap.off;
3495 clu.dir = fid->hint_bmap.clu;
3496 }
3497
3498 while (clu_offset > 0) {
3499 if (get_next_clus_safe(sb, &(clu.dir)))
3500 return -EIO;
3501
3502 clu_offset--;
3503 }
3504 }
3505 }
3506
3507 while (!IS_CLUS_EOF(clu.dir)) {
3508 if (IS_CLUS_FREE(dir.dir)) /* FAT16 root_dir */
3509 i = dentry % dentries_per_clu;
3510 else
3511 i = dentry & (dentries_per_clu-1);
3512
3513 for ( ; i < dentries_per_clu; i++, dentry++) {
3514 ep = get_dentry_in_dir(sb, &clu, i, &sector);
3515 if (!ep)
3516 return -EIO;
3517
3518 type = fsi->fs_func->get_entry_type(ep);
3519
3520 if (type == TYPE_UNUSED)
3521 break;
3522
3523 if ((type != TYPE_FILE) && (type != TYPE_DIR))
3524 continue;
3525
3526 dcache_lock(sb, sector);
3527 dir_entry->Attr = fsi->fs_func->get_entry_attr(ep);
3528
3529 fsi->fs_func->get_entry_time(ep, &tm, TM_CREATE);
3530 dir_entry->CreateTimestamp.Year = tm.year;
3531 dir_entry->CreateTimestamp.Month = tm.mon;
3532 dir_entry->CreateTimestamp.Day = tm.day;
3533 dir_entry->CreateTimestamp.Hour = tm.hour;
3534 dir_entry->CreateTimestamp.Minute = tm.min;
3535 dir_entry->CreateTimestamp.Second = tm.sec;
3536 dir_entry->CreateTimestamp.MilliSecond = 0;
3537
3538 fsi->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
3539 dir_entry->ModifyTimestamp.Year = tm.year;
3540 dir_entry->ModifyTimestamp.Month = tm.mon;
3541 dir_entry->ModifyTimestamp.Day = tm.day;
3542 dir_entry->ModifyTimestamp.Hour = tm.hour;
3543 dir_entry->ModifyTimestamp.Minute = tm.min;
3544 dir_entry->ModifyTimestamp.Second = tm.sec;
3545 dir_entry->ModifyTimestamp.MilliSecond = 0;
3546
3547 memset((s8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T));
3548
3549 *(uni_name.name) = 0x0;
3550 fsi->fs_func->get_uniname_from_ext_entry(sb, &dir, dentry, uni_name.name);
3551 if (*(uni_name.name) == 0x0)
3552 get_uniname_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
3553 nls_uni16s_to_vfsname(sb, &uni_name,
3554 dir_entry->NameBuf.lfn,
3555 dir_entry->NameBuf.lfnbuf_len);
3556 dcache_unlock(sb, sector);
3557
3558 if (fsi->vol_type == EXFAT) {
3559 ep = get_dentry_in_dir(sb, &clu, i+1, NULL);
3560 if (!ep)
3561 return -EIO;
3562 } else {
3563 get_uniname_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0);
3564 nls_uni16s_to_vfsname(sb, &uni_name,
3565 dir_entry->NameBuf.sfn,
3566 dir_entry->NameBuf.sfnbuf_len);
3567 }
3568
3569 dir_entry->Size = fsi->fs_func->get_entry_size(ep);
3570
3571 /*
3572 * Update hint information :
3573 * fat16 root directory does not need it.
3574 */
3575 if (!IS_CLUS_FREE(dir.dir)) {
3576 fid->hint_bmap.off = dentry >> dentries_per_clu_bits;
3577 fid->hint_bmap.clu = clu.dir;
3578 }
3579
3580 fid->rwoffset = (s64) ++dentry;
3581
3582 return 0;
3583 }
3584
3585 /* fat16 root directory */
3586 if (IS_CLUS_FREE(dir.dir))
3587 break;
3588
3589 if (clu.flags == 0x03) {
3590 if ((--clu.size) > 0)
3591 clu.dir++;
3592 else
3593 clu.dir = CLUS_EOF;
3594 } else {
3595 if (get_next_clus_safe(sb, &(clu.dir)))
3596 return -EIO;
3597 }
3598 }
3599
3600 dir_entry->NameBuf.lfn[0] = '\0';
3601
3602 fid->rwoffset = (s64) dentry;
3603
3604 return 0;
3605 } /* end of fscore_readdir */
3606
3607 /* remove a directory */
3608 s32 fscore_rmdir(struct inode *inode, FILE_ID_T *fid)
3609 {
3610 s32 ret;
3611 s32 dentry;
3612 DENTRY_T *ep;
3613 CHAIN_T dir, clu_to_free;
3614 struct super_block *sb = inode->i_sb;
3615 FS_INFO_T *fsi = &(SDFAT_SB(sb)->fsi);
3616
3617 dir.dir = fid->dir.dir;
3618 dir.size = fid->dir.size;
3619 dir.flags = fid->dir.flags;
3620
3621 dentry = fid->entry;
3622
3623 if (fid->dir.dir == DIR_DELETED) {
3624 EMSG("%s : abnormal access to deleted dentry\n", __func__);
3625 return -ENOENT;
3626 }
3627
3628 /* check if the file is "." or ".." */
3629 if (fsi->vol_type != EXFAT) {
3630 if ((dir.dir != fsi->root_dir) && (dentry < 2))
3631 return -EPERM;
3632 }
3633
3634 ep = get_dentry_in_dir(sb, &dir, dentry, NULL);
3635 if (!ep)
3636 return -EIO;
3637
3638 #ifdef CONFIG_SDFAT_CHECK_RO_ATTR
3639 if (SDFAT_SB(sb)->fsi.fs_func->get_entry_attr(ep) & ATTR_READONLY)
3640 return -EPERM;
3641 #endif
3642
3643 clu_to_free.dir = fid->start_clu;
3644 clu_to_free.size = (s32)((fid->size-1) >> fsi->cluster_size_bits) + 1;
3645 clu_to_free.flags = fid->flags;
3646
3647 ret = check_dir_empty(sb, &clu_to_free);
3648 if (ret) {
3649 if (ret == -EIO)
3650 EMSG("%s : failed to check_dir_empty : err(%d)\n",
3651 __func__, ret);
3652 return ret;
3653 }
3654
3655 fs_set_vol_flags(sb, VOL_DIRTY);
3656
3657 /* (1) update the directory entry */
3658 ret = remove_file(inode, &dir, dentry);
3659 if (ret) {
3660 EMSG("%s : failed to remove_file : err(%d)\n", __func__, ret);
3661 return ret;
3662 }
3663
3664 fid->dir.dir = DIR_DELETED;
3665
3666 fs_sync(sb, 0);
3667 fs_set_vol_flags(sb, VOL_CLEAN);
3668
3669 return ret;
3670 } /* end of fscore_rmdir */
3671
3672 /* end of core.c */