diff options
Diffstat (limited to 'fs/fat/inode.c')
-rw-r--r-- | fs/fat/inode.c | 152 |
1 files changed, 112 insertions, 40 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index f8f491677a4a..dfce656ddb33 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/mpage.h> | 19 | #include <linux/mpage.h> |
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/exportfs.h> | ||
22 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
22 | #include <linux/aio.h> | ||
23 | #include <linux/vfs.h> | 23 | #include <linux/vfs.h> |
24 | #include <linux/parser.h> | 24 | #include <linux/parser.h> |
25 | #include <linux/uio.h> | 25 | #include <linux/uio.h> |
@@ -341,12 +341,11 @@ struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | |||
341 | { | 341 | { |
342 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 342 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
343 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); | 343 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
344 | struct hlist_node *_p; | ||
345 | struct msdos_inode_info *i; | 344 | struct msdos_inode_info *i; |
346 | struct inode *inode = NULL; | 345 | struct inode *inode = NULL; |
347 | 346 | ||
348 | spin_lock(&sbi->inode_hash_lock); | 347 | spin_lock(&sbi->inode_hash_lock); |
349 | hlist_for_each_entry(i, _p, head, i_fat_hash) { | 348 | hlist_for_each_entry(i, head, i_fat_hash) { |
350 | BUG_ON(i->vfs_inode.i_sb != sb); | 349 | BUG_ON(i->vfs_inode.i_sb != sb); |
351 | if (i->i_pos != i_pos) | 350 | if (i->i_pos != i_pos) |
352 | continue; | 351 | continue; |
@@ -386,7 +385,7 @@ static int fat_calc_dir_size(struct inode *inode) | |||
386 | } | 385 | } |
387 | 386 | ||
388 | /* doesn't deal with root inode */ | 387 | /* doesn't deal with root inode */ |
389 | static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | 388 | int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) |
390 | { | 389 | { |
391 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 390 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
392 | int error; | 391 | int error; |
@@ -445,12 +444,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
445 | return 0; | 444 | return 0; |
446 | } | 445 | } |
447 | 446 | ||
447 | static inline void fat_lock_build_inode(struct msdos_sb_info *sbi) | ||
448 | { | ||
449 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
450 | mutex_lock(&sbi->nfs_build_inode_lock); | ||
451 | } | ||
452 | |||
453 | static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi) | ||
454 | { | ||
455 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
456 | mutex_unlock(&sbi->nfs_build_inode_lock); | ||
457 | } | ||
458 | |||
448 | struct inode *fat_build_inode(struct super_block *sb, | 459 | struct inode *fat_build_inode(struct super_block *sb, |
449 | struct msdos_dir_entry *de, loff_t i_pos) | 460 | struct msdos_dir_entry *de, loff_t i_pos) |
450 | { | 461 | { |
451 | struct inode *inode; | 462 | struct inode *inode; |
452 | int err; | 463 | int err; |
453 | 464 | ||
465 | fat_lock_build_inode(MSDOS_SB(sb)); | ||
454 | inode = fat_iget(sb, i_pos); | 466 | inode = fat_iget(sb, i_pos); |
455 | if (inode) | 467 | if (inode) |
456 | goto out; | 468 | goto out; |
@@ -470,6 +482,7 @@ struct inode *fat_build_inode(struct super_block *sb, | |||
470 | fat_attach(inode, i_pos); | 482 | fat_attach(inode, i_pos); |
471 | insert_inode_hash(inode); | 483 | insert_inode_hash(inode); |
472 | out: | 484 | out: |
485 | fat_unlock_build_inode(MSDOS_SB(sb)); | ||
473 | return inode; | 486 | return inode; |
474 | } | 487 | } |
475 | 488 | ||
@@ -488,10 +501,59 @@ static void fat_evict_inode(struct inode *inode) | |||
488 | fat_detach(inode); | 501 | fat_detach(inode); |
489 | } | 502 | } |
490 | 503 | ||
504 | static void fat_set_state(struct super_block *sb, | ||
505 | unsigned int set, unsigned int force) | ||
506 | { | ||
507 | struct buffer_head *bh; | ||
508 | struct fat_boot_sector *b; | ||
509 | struct msdos_sb_info *sbi = sb->s_fs_info; | ||
510 | |||
511 | /* do not change any thing if mounted read only */ | ||
512 | if ((sb->s_flags & MS_RDONLY) && !force) | ||
513 | return; | ||
514 | |||
515 | /* do not change state if fs was dirty */ | ||
516 | if (sbi->dirty) { | ||
517 | /* warn only on set (mount). */ | ||
518 | if (set) | ||
519 | fat_msg(sb, KERN_WARNING, "Volume was not properly " | ||
520 | "unmounted. Some data may be corrupt. " | ||
521 | "Please run fsck."); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | bh = sb_bread(sb, 0); | ||
526 | if (bh == NULL) { | ||
527 | fat_msg(sb, KERN_ERR, "unable to read boot sector " | ||
528 | "to mark fs as dirty"); | ||
529 | return; | ||
530 | } | ||
531 | |||
532 | b = (struct fat_boot_sector *) bh->b_data; | ||
533 | |||
534 | if (sbi->fat_bits == 32) { | ||
535 | if (set) | ||
536 | b->fat32.state |= FAT_STATE_DIRTY; | ||
537 | else | ||
538 | b->fat32.state &= ~FAT_STATE_DIRTY; | ||
539 | } else /* fat 16 and 12 */ { | ||
540 | if (set) | ||
541 | b->fat16.state |= FAT_STATE_DIRTY; | ||
542 | else | ||
543 | b->fat16.state &= ~FAT_STATE_DIRTY; | ||
544 | } | ||
545 | |||
546 | mark_buffer_dirty(bh); | ||
547 | sync_dirty_buffer(bh); | ||
548 | brelse(bh); | ||
549 | } | ||
550 | |||
491 | static void fat_put_super(struct super_block *sb) | 551 | static void fat_put_super(struct super_block *sb) |
492 | { | 552 | { |
493 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 553 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
494 | 554 | ||
555 | fat_set_state(sb, 0, 0); | ||
556 | |||
495 | iput(sbi->fsinfo_inode); | 557 | iput(sbi->fsinfo_inode); |
496 | iput(sbi->fat_inode); | 558 | iput(sbi->fat_inode); |
497 | 559 | ||
@@ -566,8 +628,18 @@ static void __exit fat_destroy_inodecache(void) | |||
566 | 628 | ||
567 | static int fat_remount(struct super_block *sb, int *flags, char *data) | 629 | static int fat_remount(struct super_block *sb, int *flags, char *data) |
568 | { | 630 | { |
631 | int new_rdonly; | ||
569 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 632 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
570 | *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); | 633 | *flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME); |
634 | |||
635 | /* make sure we update state on remount. */ | ||
636 | new_rdonly = *flags & MS_RDONLY; | ||
637 | if (new_rdonly != (sb->s_flags & MS_RDONLY)) { | ||
638 | if (new_rdonly) | ||
639 | fat_set_state(sb, 0, 0); | ||
640 | else | ||
641 | fat_set_state(sb, 1, 1); | ||
642 | } | ||
571 | return 0; | 643 | return 0; |
572 | } | 644 | } |
573 | 645 | ||
@@ -597,20 +669,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
597 | return 0; | 669 | return 0; |
598 | } | 670 | } |
599 | 671 | ||
600 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
601 | struct inode *inode) | ||
602 | { | ||
603 | loff_t i_pos; | ||
604 | #if BITS_PER_LONG == 32 | ||
605 | spin_lock(&sbi->inode_hash_lock); | ||
606 | #endif | ||
607 | i_pos = MSDOS_I(inode)->i_pos; | ||
608 | #if BITS_PER_LONG == 32 | ||
609 | spin_unlock(&sbi->inode_hash_lock); | ||
610 | #endif | ||
611 | return i_pos; | ||
612 | } | ||
613 | |||
614 | static int __fat_write_inode(struct inode *inode, int wait) | 672 | static int __fat_write_inode(struct inode *inode, int wait) |
615 | { | 673 | { |
616 | struct super_block *sb = inode->i_sb; | 674 | struct super_block *sb = inode->i_sb; |
@@ -618,7 +676,8 @@ static int __fat_write_inode(struct inode *inode, int wait) | |||
618 | struct buffer_head *bh; | 676 | struct buffer_head *bh; |
619 | struct msdos_dir_entry *raw_entry; | 677 | struct msdos_dir_entry *raw_entry; |
620 | loff_t i_pos; | 678 | loff_t i_pos; |
621 | int err; | 679 | sector_t blocknr; |
680 | int err, offset; | ||
622 | 681 | ||
623 | if (inode->i_ino == MSDOS_ROOT_INO) | 682 | if (inode->i_ino == MSDOS_ROOT_INO) |
624 | return 0; | 683 | return 0; |
@@ -628,7 +687,8 @@ retry: | |||
628 | if (!i_pos) | 687 | if (!i_pos) |
629 | return 0; | 688 | return 0; |
630 | 689 | ||
631 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 690 | fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset); |
691 | bh = sb_bread(sb, blocknr); | ||
632 | if (!bh) { | 692 | if (!bh) { |
633 | fat_msg(sb, KERN_ERR, "unable to read inode block " | 693 | fat_msg(sb, KERN_ERR, "unable to read inode block " |
634 | "for updating (i_pos %lld)", i_pos); | 694 | "for updating (i_pos %lld)", i_pos); |
@@ -641,8 +701,7 @@ retry: | |||
641 | goto retry; | 701 | goto retry; |
642 | } | 702 | } |
643 | 703 | ||
644 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) | 704 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset]; |
645 | [i_pos & (sbi->dir_per_block - 1)]; | ||
646 | if (S_ISDIR(inode->i_mode)) | 705 | if (S_ISDIR(inode->i_mode)) |
647 | raw_entry->size = 0; | 706 | raw_entry->size = 0; |
648 | else | 707 | else |
@@ -703,12 +762,6 @@ static const struct super_operations fat_sops = { | |||
703 | .show_options = fat_show_options, | 762 | .show_options = fat_show_options, |
704 | }; | 763 | }; |
705 | 764 | ||
706 | static const struct export_operations fat_export_ops = { | ||
707 | .fh_to_dentry = fat_fh_to_dentry, | ||
708 | .fh_to_parent = fat_fh_to_parent, | ||
709 | .get_parent = fat_get_parent, | ||
710 | }; | ||
711 | |||
712 | static int fat_show_options(struct seq_file *m, struct dentry *root) | 765 | static int fat_show_options(struct seq_file *m, struct dentry *root) |
713 | { | 766 | { |
714 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); | 767 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); |
@@ -756,8 +809,6 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
756 | seq_puts(m, ",usefree"); | 809 | seq_puts(m, ",usefree"); |
757 | if (opts->quiet) | 810 | if (opts->quiet) |
758 | seq_puts(m, ",quiet"); | 811 | seq_puts(m, ",quiet"); |
759 | if (opts->nfs) | ||
760 | seq_puts(m, ",nfs"); | ||
761 | if (opts->showexec) | 812 | if (opts->showexec) |
762 | seq_puts(m, ",showexec"); | 813 | seq_puts(m, ",showexec"); |
763 | if (opts->sys_immutable) | 814 | if (opts->sys_immutable) |
@@ -791,6 +842,10 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
791 | seq_puts(m, ",errors=panic"); | 842 | seq_puts(m, ",errors=panic"); |
792 | else | 843 | else |
793 | seq_puts(m, ",errors=remount-ro"); | 844 | seq_puts(m, ",errors=remount-ro"); |
845 | if (opts->nfs == FAT_NFS_NOSTALE_RO) | ||
846 | seq_puts(m, ",nfs=nostale_ro"); | ||
847 | else if (opts->nfs) | ||
848 | seq_puts(m, ",nfs=stale_rw"); | ||
794 | if (opts->discard) | 849 | if (opts->discard) |
795 | seq_puts(m, ",discard"); | 850 | seq_puts(m, ",discard"); |
796 | 851 | ||
@@ -807,7 +862,7 @@ enum { | |||
807 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 862 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
808 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, | 863 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, |
809 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, | 864 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, |
810 | Opt_err, | 865 | Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, |
811 | }; | 866 | }; |
812 | 867 | ||
813 | static const match_table_t fat_tokens = { | 868 | static const match_table_t fat_tokens = { |
@@ -837,7 +892,9 @@ static const match_table_t fat_tokens = { | |||
837 | {Opt_err_panic, "errors=panic"}, | 892 | {Opt_err_panic, "errors=panic"}, |
838 | {Opt_err_ro, "errors=remount-ro"}, | 893 | {Opt_err_ro, "errors=remount-ro"}, |
839 | {Opt_discard, "discard"}, | 894 | {Opt_discard, "discard"}, |
840 | {Opt_nfs, "nfs"}, | 895 | {Opt_nfs_stale_rw, "nfs"}, |
896 | {Opt_nfs_stale_rw, "nfs=stale_rw"}, | ||
897 | {Opt_nfs_nostale_ro, "nfs=nostale_ro"}, | ||
841 | {Opt_obsolete, "conv=binary"}, | 898 | {Opt_obsolete, "conv=binary"}, |
842 | {Opt_obsolete, "conv=text"}, | 899 | {Opt_obsolete, "conv=text"}, |
843 | {Opt_obsolete, "conv=auto"}, | 900 | {Opt_obsolete, "conv=auto"}, |
@@ -1034,6 +1091,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1034 | case Opt_err_ro: | 1091 | case Opt_err_ro: |
1035 | opts->errors = FAT_ERRORS_RO; | 1092 | opts->errors = FAT_ERRORS_RO; |
1036 | break; | 1093 | break; |
1094 | case Opt_nfs_stale_rw: | ||
1095 | opts->nfs = FAT_NFS_STALE_RW; | ||
1096 | break; | ||
1097 | case Opt_nfs_nostale_ro: | ||
1098 | opts->nfs = FAT_NFS_NOSTALE_RO; | ||
1099 | break; | ||
1037 | 1100 | ||
1038 | /* msdos specific */ | 1101 | /* msdos specific */ |
1039 | case Opt_dots: | 1102 | case Opt_dots: |
@@ -1092,9 +1155,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1092 | case Opt_discard: | 1155 | case Opt_discard: |
1093 | opts->discard = 1; | 1156 | opts->discard = 1; |
1094 | break; | 1157 | break; |
1095 | case Opt_nfs: | ||
1096 | opts->nfs = 1; | ||
1097 | break; | ||
1098 | 1158 | ||
1099 | /* obsolete mount options */ | 1159 | /* obsolete mount options */ |
1100 | case Opt_obsolete: | 1160 | case Opt_obsolete: |
@@ -1125,6 +1185,10 @@ out: | |||
1125 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); | 1185 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); |
1126 | if (opts->unicode_xlate) | 1186 | if (opts->unicode_xlate) |
1127 | opts->utf8 = 0; | 1187 | opts->utf8 = 0; |
1188 | if (opts->nfs == FAT_NFS_NOSTALE_RO) { | ||
1189 | sb->s_flags |= MS_RDONLY; | ||
1190 | sb->s_export_op = &fat_export_ops_nostale; | ||
1191 | } | ||
1128 | 1192 | ||
1129 | return 0; | 1193 | return 0; |
1130 | } | 1194 | } |
@@ -1135,7 +1199,7 @@ static int fat_read_root(struct inode *inode) | |||
1135 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1199 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1136 | int error; | 1200 | int error; |
1137 | 1201 | ||
1138 | MSDOS_I(inode)->i_pos = 0; | 1202 | MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO; |
1139 | inode->i_uid = sbi->options.fs_uid; | 1203 | inode->i_uid = sbi->options.fs_uid; |
1140 | inode->i_gid = sbi->options.fs_gid; | 1204 | inode->i_gid = sbi->options.fs_gid; |
1141 | inode->i_version++; | 1205 | inode->i_version++; |
@@ -1198,6 +1262,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1198 | sb->s_magic = MSDOS_SUPER_MAGIC; | 1262 | sb->s_magic = MSDOS_SUPER_MAGIC; |
1199 | sb->s_op = &fat_sops; | 1263 | sb->s_op = &fat_sops; |
1200 | sb->s_export_op = &fat_export_ops; | 1264 | sb->s_export_op = &fat_export_ops; |
1265 | mutex_init(&sbi->nfs_build_inode_lock); | ||
1201 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, | 1266 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, |
1202 | DEFAULT_RATELIMIT_BURST); | 1267 | DEFAULT_RATELIMIT_BURST); |
1203 | 1268 | ||
@@ -1298,17 +1363,17 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1298 | sbi->prev_free = FAT_START_ENT; | 1363 | sbi->prev_free = FAT_START_ENT; |
1299 | sb->s_maxbytes = 0xffffffff; | 1364 | sb->s_maxbytes = 0xffffffff; |
1300 | 1365 | ||
1301 | if (!sbi->fat_length && b->fat32_length) { | 1366 | if (!sbi->fat_length && b->fat32.length) { |
1302 | struct fat_boot_fsinfo *fsinfo; | 1367 | struct fat_boot_fsinfo *fsinfo; |
1303 | struct buffer_head *fsinfo_bh; | 1368 | struct buffer_head *fsinfo_bh; |
1304 | 1369 | ||
1305 | /* Must be FAT32 */ | 1370 | /* Must be FAT32 */ |
1306 | sbi->fat_bits = 32; | 1371 | sbi->fat_bits = 32; |
1307 | sbi->fat_length = le32_to_cpu(b->fat32_length); | 1372 | sbi->fat_length = le32_to_cpu(b->fat32.length); |
1308 | sbi->root_cluster = le32_to_cpu(b->root_cluster); | 1373 | sbi->root_cluster = le32_to_cpu(b->fat32.root_cluster); |
1309 | 1374 | ||
1310 | /* MC - if info_sector is 0, don't multiply by 0 */ | 1375 | /* MC - if info_sector is 0, don't multiply by 0 */ |
1311 | sbi->fsinfo_sector = le16_to_cpu(b->info_sector); | 1376 | sbi->fsinfo_sector = le16_to_cpu(b->fat32.info_sector); |
1312 | if (sbi->fsinfo_sector == 0) | 1377 | if (sbi->fsinfo_sector == 0) |
1313 | sbi->fsinfo_sector = 1; | 1378 | sbi->fsinfo_sector = 1; |
1314 | 1379 | ||
@@ -1362,6 +1427,12 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1362 | if (sbi->fat_bits != 32) | 1427 | if (sbi->fat_bits != 32) |
1363 | sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; | 1428 | sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; |
1364 | 1429 | ||
1430 | /* some OSes set FAT_STATE_DIRTY and clean it on unmount. */ | ||
1431 | if (sbi->fat_bits == 32) | ||
1432 | sbi->dirty = b->fat32.state & FAT_STATE_DIRTY; | ||
1433 | else /* fat 16 or 12 */ | ||
1434 | sbi->dirty = b->fat16.state & FAT_STATE_DIRTY; | ||
1435 | |||
1365 | /* check that FAT table does not overflow */ | 1436 | /* check that FAT table does not overflow */ |
1366 | fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; | 1437 | fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; |
1367 | total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); | 1438 | total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); |
@@ -1456,6 +1527,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1456 | "the device does not support discard"); | 1527 | "the device does not support discard"); |
1457 | } | 1528 | } |
1458 | 1529 | ||
1530 | fat_set_state(sb, 1, 0); | ||
1459 | return 0; | 1531 | return 0; |
1460 | 1532 | ||
1461 | out_invalid: | 1533 | out_invalid: |