diff options
Diffstat (limited to 'fs/fat/inode.c')
-rw-r--r-- | fs/fat/inode.c | 131 |
1 files changed, 71 insertions, 60 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index cf621acd9e9a..d937aaf77374 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/msdos_fs.h> | ||
20 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
21 | #include <linux/mpage.h> | 20 | #include <linux/mpage.h> |
22 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
@@ -27,7 +26,9 @@ | |||
27 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
28 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
29 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
29 | #include <linux/hash.h> | ||
30 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
31 | #include "fat.h" | ||
31 | 32 | ||
32 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 33 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
33 | /* if user don't select VFAT, this is undefined. */ | 34 | /* if user don't select VFAT, this is undefined. */ |
@@ -63,7 +64,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
63 | sector_t phys; | 64 | sector_t phys; |
64 | int err, offset; | 65 | int err, offset; |
65 | 66 | ||
66 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 67 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
67 | if (err) | 68 | if (err) |
68 | return err; | 69 | return err; |
69 | if (phys) { | 70 | if (phys) { |
@@ -93,7 +94,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
93 | *max_blocks = min(mapped_blocks, *max_blocks); | 94 | *max_blocks = min(mapped_blocks, *max_blocks); |
94 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; | 95 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; |
95 | 96 | ||
96 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 97 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
97 | if (err) | 98 | if (err) |
98 | return err; | 99 | return err; |
99 | 100 | ||
@@ -198,7 +199,14 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
198 | 199 | ||
199 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 200 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
200 | { | 201 | { |
201 | return generic_block_bmap(mapping, block, fat_get_block); | 202 | sector_t blocknr; |
203 | |||
204 | /* fat_get_cluster() assumes the requested blocknr isn't truncated. */ | ||
205 | mutex_lock(&mapping->host->i_mutex); | ||
206 | blocknr = generic_block_bmap(mapping, block, fat_get_block); | ||
207 | mutex_unlock(&mapping->host->i_mutex); | ||
208 | |||
209 | return blocknr; | ||
202 | } | 210 | } |
203 | 211 | ||
204 | static const struct address_space_operations fat_aops = { | 212 | static const struct address_space_operations fat_aops = { |
@@ -247,25 +255,21 @@ static void fat_hash_init(struct super_block *sb) | |||
247 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); | 255 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); |
248 | } | 256 | } |
249 | 257 | ||
250 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) | 258 | static inline unsigned long fat_hash(loff_t i_pos) |
251 | { | 259 | { |
252 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; | 260 | return hash_32(i_pos, FAT_HASH_BITS); |
253 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); | ||
254 | return tmp & FAT_HASH_MASK; | ||
255 | } | 261 | } |
256 | 262 | ||
257 | void fat_attach(struct inode *inode, loff_t i_pos) | 263 | void fat_attach(struct inode *inode, loff_t i_pos) |
258 | { | 264 | { |
259 | struct super_block *sb = inode->i_sb; | 265 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
260 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 266 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
261 | 267 | ||
262 | spin_lock(&sbi->inode_hash_lock); | 268 | spin_lock(&sbi->inode_hash_lock); |
263 | MSDOS_I(inode)->i_pos = i_pos; | 269 | MSDOS_I(inode)->i_pos = i_pos; |
264 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, | 270 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head); |
265 | sbi->inode_hashtable + fat_hash(sb, i_pos)); | ||
266 | spin_unlock(&sbi->inode_hash_lock); | 271 | spin_unlock(&sbi->inode_hash_lock); |
267 | } | 272 | } |
268 | |||
269 | EXPORT_SYMBOL_GPL(fat_attach); | 273 | EXPORT_SYMBOL_GPL(fat_attach); |
270 | 274 | ||
271 | void fat_detach(struct inode *inode) | 275 | void fat_detach(struct inode *inode) |
@@ -276,13 +280,12 @@ void fat_detach(struct inode *inode) | |||
276 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 280 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
277 | spin_unlock(&sbi->inode_hash_lock); | 281 | spin_unlock(&sbi->inode_hash_lock); |
278 | } | 282 | } |
279 | |||
280 | EXPORT_SYMBOL_GPL(fat_detach); | 283 | EXPORT_SYMBOL_GPL(fat_detach); |
281 | 284 | ||
282 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | 285 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) |
283 | { | 286 | { |
284 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 287 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
285 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); | 288 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
286 | struct hlist_node *_p; | 289 | struct hlist_node *_p; |
287 | struct msdos_inode_info *i; | 290 | struct msdos_inode_info *i; |
288 | struct inode *inode = NULL; | 291 | struct inode *inode = NULL; |
@@ -341,8 +344,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
341 | 344 | ||
342 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { | 345 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { |
343 | inode->i_generation &= ~1; | 346 | inode->i_generation &= ~1; |
344 | inode->i_mode = MSDOS_MKMODE(de->attr, | 347 | inode->i_mode = fat_make_mode(sbi, de->attr, S_IRWXUGO); |
345 | S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | ||
346 | inode->i_op = sbi->dir_ops; | 348 | inode->i_op = sbi->dir_ops; |
347 | inode->i_fop = &fat_dir_operations; | 349 | inode->i_fop = &fat_dir_operations; |
348 | 350 | ||
@@ -359,10 +361,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
359 | inode->i_nlink = fat_subdirs(inode); | 361 | inode->i_nlink = fat_subdirs(inode); |
360 | } else { /* not a directory */ | 362 | } else { /* not a directory */ |
361 | inode->i_generation |= 1; | 363 | inode->i_generation |= 1; |
362 | inode->i_mode = MSDOS_MKMODE(de->attr, | 364 | inode->i_mode = fat_make_mode(sbi, de->attr, |
363 | ((sbi->options.showexec && !is_exec(de->name + 8)) | 365 | ((sbi->options.showexec && !is_exec(de->name + 8)) |
364 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) | 366 | ? S_IRUGO|S_IWUGO : S_IRWXUGO)); |
365 | & ~sbi->options.fs_fmask) | S_IFREG; | ||
366 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 367 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
367 | if (sbi->fat_bits == 32) | 368 | if (sbi->fat_bits == 32) |
368 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); | 369 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); |
@@ -378,25 +379,16 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
378 | if (sbi->options.sys_immutable) | 379 | if (sbi->options.sys_immutable) |
379 | inode->i_flags |= S_IMMUTABLE; | 380 | inode->i_flags |= S_IMMUTABLE; |
380 | } | 381 | } |
381 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; | 382 | fat_save_attrs(inode, de->attr); |
383 | |||
382 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 384 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
383 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 385 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
384 | inode->i_mtime.tv_sec = | 386 | |
385 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date), | 387 | fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0); |
386 | sbi->options.tz_utc); | ||
387 | inode->i_mtime.tv_nsec = 0; | ||
388 | if (sbi->options.isvfat) { | 388 | if (sbi->options.isvfat) { |
389 | int secs = de->ctime_cs / 100; | 389 | fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime, |
390 | int csecs = de->ctime_cs % 100; | 390 | de->cdate, de->ctime_cs); |
391 | inode->i_ctime.tv_sec = | 391 | fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0); |
392 | date_dos2unix(le16_to_cpu(de->ctime), | ||
393 | le16_to_cpu(de->cdate), | ||
394 | sbi->options.tz_utc) + secs; | ||
395 | inode->i_ctime.tv_nsec = csecs * 10000000; | ||
396 | inode->i_atime.tv_sec = | ||
397 | date_dos2unix(0, le16_to_cpu(de->adate), | ||
398 | sbi->options.tz_utc); | ||
399 | inode->i_atime.tv_nsec = 0; | ||
400 | } else | 392 | } else |
401 | inode->i_ctime = inode->i_atime = inode->i_mtime; | 393 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
402 | 394 | ||
@@ -443,13 +435,8 @@ static void fat_delete_inode(struct inode *inode) | |||
443 | 435 | ||
444 | static void fat_clear_inode(struct inode *inode) | 436 | static void fat_clear_inode(struct inode *inode) |
445 | { | 437 | { |
446 | struct super_block *sb = inode->i_sb; | ||
447 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
448 | |||
449 | spin_lock(&sbi->inode_hash_lock); | ||
450 | fat_cache_inval_inode(inode); | 438 | fat_cache_inval_inode(inode); |
451 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 439 | fat_detach(inode); |
452 | spin_unlock(&sbi->inode_hash_lock); | ||
453 | } | 440 | } |
454 | 441 | ||
455 | static void fat_write_super(struct super_block *sb) | 442 | static void fat_write_super(struct super_block *sb) |
@@ -555,6 +542,20 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
555 | return 0; | 542 | return 0; |
556 | } | 543 | } |
557 | 544 | ||
545 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
546 | struct inode *inode) | ||
547 | { | ||
548 | loff_t i_pos; | ||
549 | #if BITS_PER_LONG == 32 | ||
550 | spin_lock(&sbi->inode_hash_lock); | ||
551 | #endif | ||
552 | i_pos = MSDOS_I(inode)->i_pos; | ||
553 | #if BITS_PER_LONG == 32 | ||
554 | spin_unlock(&sbi->inode_hash_lock); | ||
555 | #endif | ||
556 | return i_pos; | ||
557 | } | ||
558 | |||
558 | static int fat_write_inode(struct inode *inode, int wait) | 559 | static int fat_write_inode(struct inode *inode, int wait) |
559 | { | 560 | { |
560 | struct super_block *sb = inode->i_sb; | 561 | struct super_block *sb = inode->i_sb; |
@@ -564,9 +565,12 @@ static int fat_write_inode(struct inode *inode, int wait) | |||
564 | loff_t i_pos; | 565 | loff_t i_pos; |
565 | int err; | 566 | int err; |
566 | 567 | ||
568 | if (inode->i_ino == MSDOS_ROOT_INO) | ||
569 | return 0; | ||
570 | |||
567 | retry: | 571 | retry: |
568 | i_pos = MSDOS_I(inode)->i_pos; | 572 | i_pos = fat_i_pos_read(sbi, inode); |
569 | if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) | 573 | if (!i_pos) |
570 | return 0; | 574 | return 0; |
571 | 575 | ||
572 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 576 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); |
@@ -588,19 +592,17 @@ retry: | |||
588 | raw_entry->size = 0; | 592 | raw_entry->size = 0; |
589 | else | 593 | else |
590 | raw_entry->size = cpu_to_le32(inode->i_size); | 594 | raw_entry->size = cpu_to_le32(inode->i_size); |
591 | raw_entry->attr = fat_attr(inode); | 595 | raw_entry->attr = fat_make_attrs(inode); |
592 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); | 596 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); |
593 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 597 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
594 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, | 598 | fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time, |
595 | &raw_entry->date, sbi->options.tz_utc); | 599 | &raw_entry->date, NULL); |
596 | if (sbi->options.isvfat) { | 600 | if (sbi->options.isvfat) { |
597 | __le16 atime; | 601 | __le16 atime; |
598 | fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime, | 602 | fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime, |
599 | &raw_entry->cdate, sbi->options.tz_utc); | 603 | &raw_entry->cdate, &raw_entry->ctime_cs); |
600 | fat_date_unix2dos(inode->i_atime.tv_sec, &atime, | 604 | fat_time_unix2fat(sbi, &inode->i_atime, &atime, |
601 | &raw_entry->adate, sbi->options.tz_utc); | 605 | &raw_entry->adate, NULL); |
602 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | ||
603 | inode->i_ctime.tv_nsec / 10000000; | ||
604 | } | 606 | } |
605 | spin_unlock(&sbi->inode_hash_lock); | 607 | spin_unlock(&sbi->inode_hash_lock); |
606 | mark_buffer_dirty(bh); | 608 | mark_buffer_dirty(bh); |
@@ -819,8 +821,10 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
819 | seq_puts(m, ",uni_xlate"); | 821 | seq_puts(m, ",uni_xlate"); |
820 | if (!opts->numtail) | 822 | if (!opts->numtail) |
821 | seq_puts(m, ",nonumtail"); | 823 | seq_puts(m, ",nonumtail"); |
824 | if (opts->rodir) | ||
825 | seq_puts(m, ",rodir"); | ||
822 | } | 826 | } |
823 | if (sbi->options.flush) | 827 | if (opts->flush) |
824 | seq_puts(m, ",flush"); | 828 | seq_puts(m, ",flush"); |
825 | if (opts->tz_utc) | 829 | if (opts->tz_utc) |
826 | seq_puts(m, ",tz=UTC"); | 830 | seq_puts(m, ",tz=UTC"); |
@@ -836,7 +840,7 @@ enum { | |||
836 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 840 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
837 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 841 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
838 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 842 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
839 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err, | 843 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err, |
840 | }; | 844 | }; |
841 | 845 | ||
842 | static const match_table_t fat_tokens = { | 846 | static const match_table_t fat_tokens = { |
@@ -908,6 +912,7 @@ static const match_table_t vfat_tokens = { | |||
908 | {Opt_nonumtail_yes, "nonumtail=yes"}, | 912 | {Opt_nonumtail_yes, "nonumtail=yes"}, |
909 | {Opt_nonumtail_yes, "nonumtail=true"}, | 913 | {Opt_nonumtail_yes, "nonumtail=true"}, |
910 | {Opt_nonumtail_yes, "nonumtail"}, | 914 | {Opt_nonumtail_yes, "nonumtail"}, |
915 | {Opt_rodir, "rodir"}, | ||
911 | {Opt_err, NULL} | 916 | {Opt_err, NULL} |
912 | }; | 917 | }; |
913 | 918 | ||
@@ -927,10 +932,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
927 | opts->allow_utime = -1; | 932 | opts->allow_utime = -1; |
928 | opts->codepage = fat_default_codepage; | 933 | opts->codepage = fat_default_codepage; |
929 | opts->iocharset = fat_default_iocharset; | 934 | opts->iocharset = fat_default_iocharset; |
930 | if (is_vfat) | 935 | if (is_vfat) { |
931 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; | 936 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; |
932 | else | 937 | opts->rodir = 0; |
938 | } else { | ||
933 | opts->shortname = 0; | 939 | opts->shortname = 0; |
940 | opts->rodir = 1; | ||
941 | } | ||
934 | opts->name_check = 'n'; | 942 | opts->name_check = 'n'; |
935 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; | 943 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; |
936 | opts->utf8 = opts->unicode_xlate = 0; | 944 | opts->utf8 = opts->unicode_xlate = 0; |
@@ -1081,6 +1089,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
1081 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ | 1089 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ |
1082 | opts->numtail = 0; /* negated option */ | 1090 | opts->numtail = 0; /* negated option */ |
1083 | break; | 1091 | break; |
1092 | case Opt_rodir: | ||
1093 | opts->rodir = 1; | ||
1094 | break; | ||
1084 | 1095 | ||
1085 | /* obsolete mount options */ | 1096 | /* obsolete mount options */ |
1086 | case Opt_obsolate: | 1097 | case Opt_obsolate: |
@@ -1126,7 +1137,7 @@ static int fat_read_root(struct inode *inode) | |||
1126 | inode->i_gid = sbi->options.fs_gid; | 1137 | inode->i_gid = sbi->options.fs_gid; |
1127 | inode->i_version++; | 1138 | inode->i_version++; |
1128 | inode->i_generation = 0; | 1139 | inode->i_generation = 0; |
1129 | inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | 1140 | inode->i_mode = fat_make_mode(sbi, ATTR_DIR, S_IRWXUGO); |
1130 | inode->i_op = sbi->dir_ops; | 1141 | inode->i_op = sbi->dir_ops; |
1131 | inode->i_fop = &fat_dir_operations; | 1142 | inode->i_fop = &fat_dir_operations; |
1132 | if (sbi->fat_bits == 32) { | 1143 | if (sbi->fat_bits == 32) { |
@@ -1143,7 +1154,7 @@ static int fat_read_root(struct inode *inode) | |||
1143 | MSDOS_I(inode)->i_logstart = 0; | 1154 | MSDOS_I(inode)->i_logstart = 0; |
1144 | MSDOS_I(inode)->mmu_private = inode->i_size; | 1155 | MSDOS_I(inode)->mmu_private = inode->i_size; |
1145 | 1156 | ||
1146 | MSDOS_I(inode)->i_attrs = ATTR_NONE; | 1157 | fat_save_attrs(inode, ATTR_DIR); |
1147 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; | 1158 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; |
1148 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; | 1159 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; |
1149 | inode->i_nlink = fat_subdirs(inode)+2; | 1160 | inode->i_nlink = fat_subdirs(inode)+2; |