diff options
Diffstat (limited to 'fs/fat/inode.c')
-rw-r--r-- | fs/fat/inode.c | 74 |
1 files changed, 40 insertions, 34 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index acf6e479b443..4ff901632b26 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -18,7 +18,6 @@ | |||
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> |
23 | #include <linux/vfs.h> | 22 | #include <linux/vfs.h> |
24 | #include <linux/parser.h> | 23 | #include <linux/parser.h> |
@@ -385,7 +384,7 @@ static int fat_calc_dir_size(struct inode *inode) | |||
385 | } | 384 | } |
386 | 385 | ||
387 | /* doesn't deal with root inode */ | 386 | /* doesn't deal with root inode */ |
388 | static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | 387 | int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) |
389 | { | 388 | { |
390 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | 389 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
391 | int error; | 390 | int error; |
@@ -444,12 +443,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
444 | return 0; | 443 | return 0; |
445 | } | 444 | } |
446 | 445 | ||
446 | static inline void fat_lock_build_inode(struct msdos_sb_info *sbi) | ||
447 | { | ||
448 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
449 | mutex_lock(&sbi->nfs_build_inode_lock); | ||
450 | } | ||
451 | |||
452 | static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi) | ||
453 | { | ||
454 | if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) | ||
455 | mutex_unlock(&sbi->nfs_build_inode_lock); | ||
456 | } | ||
457 | |||
447 | struct inode *fat_build_inode(struct super_block *sb, | 458 | struct inode *fat_build_inode(struct super_block *sb, |
448 | struct msdos_dir_entry *de, loff_t i_pos) | 459 | struct msdos_dir_entry *de, loff_t i_pos) |
449 | { | 460 | { |
450 | struct inode *inode; | 461 | struct inode *inode; |
451 | int err; | 462 | int err; |
452 | 463 | ||
464 | fat_lock_build_inode(MSDOS_SB(sb)); | ||
453 | inode = fat_iget(sb, i_pos); | 465 | inode = fat_iget(sb, i_pos); |
454 | if (inode) | 466 | if (inode) |
455 | goto out; | 467 | goto out; |
@@ -469,6 +481,7 @@ struct inode *fat_build_inode(struct super_block *sb, | |||
469 | fat_attach(inode, i_pos); | 481 | fat_attach(inode, i_pos); |
470 | insert_inode_hash(inode); | 482 | insert_inode_hash(inode); |
471 | out: | 483 | out: |
484 | fat_unlock_build_inode(MSDOS_SB(sb)); | ||
472 | return inode; | 485 | return inode; |
473 | } | 486 | } |
474 | 487 | ||
@@ -655,20 +668,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
655 | return 0; | 668 | return 0; |
656 | } | 669 | } |
657 | 670 | ||
658 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
659 | struct inode *inode) | ||
660 | { | ||
661 | loff_t i_pos; | ||
662 | #if BITS_PER_LONG == 32 | ||
663 | spin_lock(&sbi->inode_hash_lock); | ||
664 | #endif | ||
665 | i_pos = MSDOS_I(inode)->i_pos; | ||
666 | #if BITS_PER_LONG == 32 | ||
667 | spin_unlock(&sbi->inode_hash_lock); | ||
668 | #endif | ||
669 | return i_pos; | ||
670 | } | ||
671 | |||
672 | static int __fat_write_inode(struct inode *inode, int wait) | 671 | static int __fat_write_inode(struct inode *inode, int wait) |
673 | { | 672 | { |
674 | struct super_block *sb = inode->i_sb; | 673 | struct super_block *sb = inode->i_sb; |
@@ -676,7 +675,8 @@ static int __fat_write_inode(struct inode *inode, int wait) | |||
676 | struct buffer_head *bh; | 675 | struct buffer_head *bh; |
677 | struct msdos_dir_entry *raw_entry; | 676 | struct msdos_dir_entry *raw_entry; |
678 | loff_t i_pos; | 677 | loff_t i_pos; |
679 | int err; | 678 | sector_t blocknr; |
679 | int err, offset; | ||
680 | 680 | ||
681 | if (inode->i_ino == MSDOS_ROOT_INO) | 681 | if (inode->i_ino == MSDOS_ROOT_INO) |
682 | return 0; | 682 | return 0; |
@@ -686,7 +686,8 @@ retry: | |||
686 | if (!i_pos) | 686 | if (!i_pos) |
687 | return 0; | 687 | return 0; |
688 | 688 | ||
689 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 689 | fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset); |
690 | bh = sb_bread(sb, blocknr); | ||
690 | if (!bh) { | 691 | if (!bh) { |
691 | fat_msg(sb, KERN_ERR, "unable to read inode block " | 692 | fat_msg(sb, KERN_ERR, "unable to read inode block " |
692 | "for updating (i_pos %lld)", i_pos); | 693 | "for updating (i_pos %lld)", i_pos); |
@@ -699,8 +700,7 @@ retry: | |||
699 | goto retry; | 700 | goto retry; |
700 | } | 701 | } |
701 | 702 | ||
702 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) | 703 | raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset]; |
703 | [i_pos & (sbi->dir_per_block - 1)]; | ||
704 | if (S_ISDIR(inode->i_mode)) | 704 | if (S_ISDIR(inode->i_mode)) |
705 | raw_entry->size = 0; | 705 | raw_entry->size = 0; |
706 | else | 706 | else |
@@ -761,12 +761,6 @@ static const struct super_operations fat_sops = { | |||
761 | .show_options = fat_show_options, | 761 | .show_options = fat_show_options, |
762 | }; | 762 | }; |
763 | 763 | ||
764 | static const struct export_operations fat_export_ops = { | ||
765 | .fh_to_dentry = fat_fh_to_dentry, | ||
766 | .fh_to_parent = fat_fh_to_parent, | ||
767 | .get_parent = fat_get_parent, | ||
768 | }; | ||
769 | |||
770 | static int fat_show_options(struct seq_file *m, struct dentry *root) | 764 | static int fat_show_options(struct seq_file *m, struct dentry *root) |
771 | { | 765 | { |
772 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); | 766 | struct msdos_sb_info *sbi = MSDOS_SB(root->d_sb); |
@@ -814,8 +808,6 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
814 | seq_puts(m, ",usefree"); | 808 | seq_puts(m, ",usefree"); |
815 | if (opts->quiet) | 809 | if (opts->quiet) |
816 | seq_puts(m, ",quiet"); | 810 | seq_puts(m, ",quiet"); |
817 | if (opts->nfs) | ||
818 | seq_puts(m, ",nfs"); | ||
819 | if (opts->showexec) | 811 | if (opts->showexec) |
820 | seq_puts(m, ",showexec"); | 812 | seq_puts(m, ",showexec"); |
821 | if (opts->sys_immutable) | 813 | if (opts->sys_immutable) |
@@ -849,6 +841,10 @@ static int fat_show_options(struct seq_file *m, struct dentry *root) | |||
849 | seq_puts(m, ",errors=panic"); | 841 | seq_puts(m, ",errors=panic"); |
850 | else | 842 | else |
851 | seq_puts(m, ",errors=remount-ro"); | 843 | seq_puts(m, ",errors=remount-ro"); |
844 | if (opts->nfs == FAT_NFS_NOSTALE_RO) | ||
845 | seq_puts(m, ",nfs=nostale_ro"); | ||
846 | else if (opts->nfs) | ||
847 | seq_puts(m, ",nfs=stale_rw"); | ||
852 | if (opts->discard) | 848 | if (opts->discard) |
853 | seq_puts(m, ",discard"); | 849 | seq_puts(m, ",discard"); |
854 | 850 | ||
@@ -865,7 +861,7 @@ enum { | |||
865 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 861 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
866 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, | 862 | Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont, |
867 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, | 863 | Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, |
868 | Opt_err, | 864 | Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, |
869 | }; | 865 | }; |
870 | 866 | ||
871 | static const match_table_t fat_tokens = { | 867 | static const match_table_t fat_tokens = { |
@@ -895,7 +891,9 @@ static const match_table_t fat_tokens = { | |||
895 | {Opt_err_panic, "errors=panic"}, | 891 | {Opt_err_panic, "errors=panic"}, |
896 | {Opt_err_ro, "errors=remount-ro"}, | 892 | {Opt_err_ro, "errors=remount-ro"}, |
897 | {Opt_discard, "discard"}, | 893 | {Opt_discard, "discard"}, |
898 | {Opt_nfs, "nfs"}, | 894 | {Opt_nfs_stale_rw, "nfs"}, |
895 | {Opt_nfs_stale_rw, "nfs=stale_rw"}, | ||
896 | {Opt_nfs_nostale_ro, "nfs=nostale_ro"}, | ||
899 | {Opt_obsolete, "conv=binary"}, | 897 | {Opt_obsolete, "conv=binary"}, |
900 | {Opt_obsolete, "conv=text"}, | 898 | {Opt_obsolete, "conv=text"}, |
901 | {Opt_obsolete, "conv=auto"}, | 899 | {Opt_obsolete, "conv=auto"}, |
@@ -1092,6 +1090,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1092 | case Opt_err_ro: | 1090 | case Opt_err_ro: |
1093 | opts->errors = FAT_ERRORS_RO; | 1091 | opts->errors = FAT_ERRORS_RO; |
1094 | break; | 1092 | break; |
1093 | case Opt_nfs_stale_rw: | ||
1094 | opts->nfs = FAT_NFS_STALE_RW; | ||
1095 | break; | ||
1096 | case Opt_nfs_nostale_ro: | ||
1097 | opts->nfs = FAT_NFS_NOSTALE_RO; | ||
1098 | break; | ||
1095 | 1099 | ||
1096 | /* msdos specific */ | 1100 | /* msdos specific */ |
1097 | case Opt_dots: | 1101 | case Opt_dots: |
@@ -1150,9 +1154,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, | |||
1150 | case Opt_discard: | 1154 | case Opt_discard: |
1151 | opts->discard = 1; | 1155 | opts->discard = 1; |
1152 | break; | 1156 | break; |
1153 | case Opt_nfs: | ||
1154 | opts->nfs = 1; | ||
1155 | break; | ||
1156 | 1157 | ||
1157 | /* obsolete mount options */ | 1158 | /* obsolete mount options */ |
1158 | case Opt_obsolete: | 1159 | case Opt_obsolete: |
@@ -1183,6 +1184,10 @@ out: | |||
1183 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); | 1184 | opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); |
1184 | if (opts->unicode_xlate) | 1185 | if (opts->unicode_xlate) |
1185 | opts->utf8 = 0; | 1186 | opts->utf8 = 0; |
1187 | if (opts->nfs == FAT_NFS_NOSTALE_RO) { | ||
1188 | sb->s_flags |= MS_RDONLY; | ||
1189 | sb->s_export_op = &fat_export_ops_nostale; | ||
1190 | } | ||
1186 | 1191 | ||
1187 | return 0; | 1192 | return 0; |
1188 | } | 1193 | } |
@@ -1193,7 +1198,7 @@ static int fat_read_root(struct inode *inode) | |||
1193 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 1198 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
1194 | int error; | 1199 | int error; |
1195 | 1200 | ||
1196 | MSDOS_I(inode)->i_pos = 0; | 1201 | MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO; |
1197 | inode->i_uid = sbi->options.fs_uid; | 1202 | inode->i_uid = sbi->options.fs_uid; |
1198 | inode->i_gid = sbi->options.fs_gid; | 1203 | inode->i_gid = sbi->options.fs_gid; |
1199 | inode->i_version++; | 1204 | inode->i_version++; |
@@ -1256,6 +1261,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, | |||
1256 | sb->s_magic = MSDOS_SUPER_MAGIC; | 1261 | sb->s_magic = MSDOS_SUPER_MAGIC; |
1257 | sb->s_op = &fat_sops; | 1262 | sb->s_op = &fat_sops; |
1258 | sb->s_export_op = &fat_export_ops; | 1263 | sb->s_export_op = &fat_export_ops; |
1264 | mutex_init(&sbi->nfs_build_inode_lock); | ||
1259 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, | 1265 | ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL, |
1260 | DEFAULT_RATELIMIT_BURST); | 1266 | DEFAULT_RATELIMIT_BURST); |
1261 | 1267 | ||