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 acf6e479b44..4ff901632b2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -18,7 +18,6 @@  #include <linux/pagemap.h>  #include <linux/mpage.h>  #include <linux/buffer_head.h> -#include <linux/exportfs.h>  #include <linux/mount.h>  #include <linux/vfs.h>  #include <linux/parser.h> @@ -385,7 +384,7 @@ static int fat_calc_dir_size(struct inode *inode)  }  /* doesn't deal with root inode */ -static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) +int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)  {  	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);  	int error; @@ -444,12 +443,25 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)  	return 0;  } +static inline void fat_lock_build_inode(struct msdos_sb_info *sbi) +{ +	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) +		mutex_lock(&sbi->nfs_build_inode_lock); +} + +static inline void fat_unlock_build_inode(struct msdos_sb_info *sbi) +{ +	if (sbi->options.nfs == FAT_NFS_NOSTALE_RO) +		mutex_unlock(&sbi->nfs_build_inode_lock); +} +  struct inode *fat_build_inode(struct super_block *sb,  			struct msdos_dir_entry *de, loff_t i_pos)  {  	struct inode *inode;  	int err; +	fat_lock_build_inode(MSDOS_SB(sb));  	inode = fat_iget(sb, i_pos);  	if (inode)  		goto out; @@ -469,6 +481,7 @@ struct inode *fat_build_inode(struct super_block *sb,  	fat_attach(inode, i_pos);  	insert_inode_hash(inode);  out: +	fat_unlock_build_inode(MSDOS_SB(sb));  	return inode;  } @@ -655,20 +668,6 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)  	return 0;  } -static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, -				    struct inode *inode) -{ -	loff_t i_pos; -#if BITS_PER_LONG == 32 -	spin_lock(&sbi->inode_hash_lock); -#endif -	i_pos = MSDOS_I(inode)->i_pos; -#if BITS_PER_LONG == 32 -	spin_unlock(&sbi->inode_hash_lock); -#endif -	return i_pos; -} -  static int __fat_write_inode(struct inode *inode, int wait)  {  	struct super_block *sb = inode->i_sb; @@ -676,7 +675,8 @@ static int __fat_write_inode(struct inode *inode, int wait)  	struct buffer_head *bh;  	struct msdos_dir_entry *raw_entry;  	loff_t i_pos; -	int err; +	sector_t blocknr; +	int err, offset;  	if (inode->i_ino == MSDOS_ROOT_INO)  		return 0; @@ -686,7 +686,8 @@ retry:  	if (!i_pos)  		return 0; -	bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); +	fat_get_blknr_offset(sbi, i_pos, &blocknr, &offset); +	bh = sb_bread(sb, blocknr);  	if (!bh) {  		fat_msg(sb, KERN_ERR, "unable to read inode block "  		       "for updating (i_pos %lld)", i_pos); @@ -699,8 +700,7 @@ retry:  		goto retry;  	} -	raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) -	    [i_pos & (sbi->dir_per_block - 1)]; +	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))[offset];  	if (S_ISDIR(inode->i_mode))  		raw_entry->size = 0;  	else @@ -761,12 +761,6 @@ static const struct super_operations fat_sops = {  	.show_options	= fat_show_options,  }; -static const struct export_operations fat_export_ops = { -	.fh_to_dentry	= fat_fh_to_dentry, -	.fh_to_parent	= fat_fh_to_parent, -	.get_parent	= fat_get_parent, -}; -  static int fat_show_options(struct seq_file *m, struct dentry *root)  {  	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)  		seq_puts(m, ",usefree");  	if (opts->quiet)  		seq_puts(m, ",quiet"); -	if (opts->nfs) -		seq_puts(m, ",nfs");  	if (opts->showexec)  		seq_puts(m, ",showexec");  	if (opts->sys_immutable) @@ -849,6 +841,10 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)  		seq_puts(m, ",errors=panic");  	else  		seq_puts(m, ",errors=remount-ro"); +	if (opts->nfs == FAT_NFS_NOSTALE_RO) +		seq_puts(m, ",nfs=nostale_ro"); +	else if (opts->nfs) +		seq_puts(m, ",nfs=stale_rw");  	if (opts->discard)  		seq_puts(m, ",discard"); @@ -865,7 +861,7 @@ enum {  	Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,  	Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,  	Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset, -	Opt_err, +	Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err,  };  static const match_table_t fat_tokens = { @@ -895,7 +891,9 @@ static const match_table_t fat_tokens = {  	{Opt_err_panic, "errors=panic"},  	{Opt_err_ro, "errors=remount-ro"},  	{Opt_discard, "discard"}, -	{Opt_nfs, "nfs"}, +	{Opt_nfs_stale_rw, "nfs"}, +	{Opt_nfs_stale_rw, "nfs=stale_rw"}, +	{Opt_nfs_nostale_ro, "nfs=nostale_ro"},  	{Opt_obsolete, "conv=binary"},  	{Opt_obsolete, "conv=text"},  	{Opt_obsolete, "conv=auto"}, @@ -1092,6 +1090,12 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,  		case Opt_err_ro:  			opts->errors = FAT_ERRORS_RO;  			break; +		case Opt_nfs_stale_rw: +			opts->nfs = FAT_NFS_STALE_RW; +			break; +		case Opt_nfs_nostale_ro: +			opts->nfs = FAT_NFS_NOSTALE_RO; +			break;  		/* msdos specific */  		case Opt_dots: @@ -1150,9 +1154,6 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,  		case Opt_discard:  			opts->discard = 1;  			break; -		case Opt_nfs: -			opts->nfs = 1; -			break;  		/* obsolete mount options */  		case Opt_obsolete: @@ -1183,6 +1184,10 @@ out:  		opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH);  	if (opts->unicode_xlate)  		opts->utf8 = 0; +	if (opts->nfs == FAT_NFS_NOSTALE_RO) { +		sb->s_flags |= MS_RDONLY; +		sb->s_export_op = &fat_export_ops_nostale; +	}  	return 0;  } @@ -1193,7 +1198,7 @@ static int fat_read_root(struct inode *inode)  	struct msdos_sb_info *sbi = MSDOS_SB(sb);  	int error; -	MSDOS_I(inode)->i_pos = 0; +	MSDOS_I(inode)->i_pos = MSDOS_ROOT_INO;  	inode->i_uid = sbi->options.fs_uid;  	inode->i_gid = sbi->options.fs_gid;  	inode->i_version++; @@ -1256,6 +1261,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,  	sb->s_magic = MSDOS_SUPER_MAGIC;  	sb->s_op = &fat_sops;  	sb->s_export_op = &fat_export_ops; +	mutex_init(&sbi->nfs_build_inode_lock);  	ratelimit_state_init(&sbi->ratelimit, DEFAULT_RATELIMIT_INTERVAL,  			     DEFAULT_RATELIMIT_BURST);  |