diff options
Diffstat (limited to 'fs/fat/file.c')
| -rw-r--r-- | fs/fat/file.c | 62 | 
1 files changed, 39 insertions, 23 deletions
diff --git a/fs/fat/file.c b/fs/fat/file.c index 7257752b6d5..85f79a89e74 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -32,7 +32,7 @@ static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)  static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)  { -	struct inode *inode = file->f_path.dentry->d_inode; +	struct inode *inode = file_inode(file);  	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);  	int is_dir = S_ISDIR(inode->i_mode);  	u32 attr, oldattr; @@ -43,10 +43,10 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)  	if (err)  		goto out; -	mutex_lock(&inode->i_mutex); -	err = mnt_want_write(file->f_path.mnt); +	err = mnt_want_write_file(file);  	if (err) -		goto out_unlock_inode; +		goto out; +	mutex_lock(&inode->i_mutex);  	/*  	 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also @@ -73,14 +73,14 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)  	/* The root directory has no attributes */  	if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {  		err = -EINVAL; -		goto out_drop_write; +		goto out_unlock_inode;  	}  	if (sbi->options.sys_immutable &&  	    ((attr | oldattr) & ATTR_SYS) &&  	    !capable(CAP_LINUX_IMMUTABLE)) {  		err = -EPERM; -		goto out_drop_write; +		goto out_unlock_inode;  	}  	/* @@ -90,34 +90,39 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)  	 */  	err = security_inode_setattr(file->f_path.dentry, &ia);  	if (err) -		goto out_drop_write; +		goto out_unlock_inode;  	/* This MUST be done before doing anything irreversible... */  	err = fat_setattr(file->f_path.dentry, &ia);  	if (err) -		goto out_drop_write; +		goto out_unlock_inode;  	fsnotify_change(file->f_path.dentry, ia.ia_valid);  	if (sbi->options.sys_immutable) {  		if (attr & ATTR_SYS)  			inode->i_flags |= S_IMMUTABLE;  		else -			inode->i_flags &= S_IMMUTABLE; +			inode->i_flags &= ~S_IMMUTABLE;  	}  	fat_save_attrs(inode, attr);  	mark_inode_dirty(inode); -out_drop_write: -	mnt_drop_write(file->f_path.mnt);  out_unlock_inode:  	mutex_unlock(&inode->i_mutex); +	mnt_drop_write_file(file);  out:  	return err;  } +static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr) +{ +	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); +	return put_user(sbi->vol_id, user_attr); +} +  long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  { -	struct inode *inode = filp->f_path.dentry->d_inode; +	struct inode *inode = file_inode(filp);  	u32 __user *user_attr = (u32 __user *)arg;  	switch (cmd) { @@ -125,6 +130,8 @@ long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		return fat_ioctl_get_attributes(inode, user_attr);  	case FAT_IOCTL_SET_ATTRIBUTES:  		return fat_ioctl_set_attributes(filp, user_attr); +	case FAT_IOCTL_GET_VOLUME_ID: +		return fat_ioctl_get_volume_id(inode, user_attr);  	default:  		return -ENOTTY;	/* Inappropriate ioctl for device */  	} @@ -149,12 +156,12 @@ static int fat_file_release(struct inode *inode, struct file *filp)  	return 0;  } -int fat_file_fsync(struct file *filp, int datasync) +int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)  {  	struct inode *inode = filp->f_mapping->host;  	int res, err; -	res = generic_file_fsync(filp, datasync); +	res = generic_file_fsync(filp, start, end, datasync);  	err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);  	return res ? res : err; @@ -163,10 +170,10 @@ int fat_file_fsync(struct file *filp, int datasync)  const struct file_operations fat_file_operations = {  	.llseek		= generic_file_llseek, -	.read		= do_sync_read, -	.write		= do_sync_write, -	.aio_read	= generic_file_aio_read, -	.aio_write	= generic_file_aio_write, +	.read		= new_sync_read, +	.write		= new_sync_write, +	.read_iter	= generic_file_read_iter, +	.write_iter	= generic_file_write_iter,  	.mmap		= generic_file_mmap,  	.release	= fat_file_release,  	.unlocked_ioctl	= fat_generic_ioctl, @@ -307,6 +314,11 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)  	struct inode *inode = dentry->d_inode;  	generic_fillattr(inode, stat);  	stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size; + +	if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) { +		/* Use i_pos for ino. This is used as fileid of nfs. */ +		stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode); +	}  	return 0;  }  EXPORT_SYMBOL_GPL(fat_getattr); @@ -314,7 +326,7 @@ EXPORT_SYMBOL_GPL(fat_getattr);  static int fat_sanitize_mode(const struct msdos_sb_info *sbi,  			     struct inode *inode, umode_t *mode_ptr)  { -	mode_t mask, perm; +	umode_t mask, perm;  	/*  	 * Note, the basic check is already done by a caller of @@ -351,9 +363,9 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi,  static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode)  { -	mode_t allow_utime = sbi->options.allow_utime; +	umode_t allow_utime = sbi->options.allow_utime; -	if (current_fsuid() != inode->i_uid) { +	if (!uid_eq(current_fsuid(), inode->i_uid)) {  		if (in_group_p(inode->i_gid))  			allow_utime >>= 3;  		if (allow_utime & MAY_WRITE) @@ -397,6 +409,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)  	 * sequence.  	 */  	if (attr->ia_valid & ATTR_SIZE) { +		inode_dio_wait(inode); +  		if (attr->ia_size > inode->i_size) {  			error = fat_cont_expand(inode, attr->ia_size);  			if (error || attr->ia_valid == ATTR_SIZE) @@ -406,9 +420,9 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)  	}  	if (((attr->ia_valid & ATTR_UID) && -	     (attr->ia_uid != sbi->options.fs_uid)) || +	     (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||  	    ((attr->ia_valid & ATTR_GID) && -	     (attr->ia_gid != sbi->options.fs_gid)) || +	     (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||  	    ((attr->ia_valid & ATTR_MODE) &&  	     (attr->ia_mode & ~FAT_VALID_MODE)))  		error = -EPERM; @@ -429,8 +443,10 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr)  	}  	if (attr->ia_valid & ATTR_SIZE) { +		down_write(&MSDOS_I(inode)->truncate_lock);  		truncate_setsize(inode, attr->ia_size);  		fat_truncate_blocks(inode, attr->ia_size); +		up_write(&MSDOS_I(inode)->truncate_lock);  	}  	setattr_copy(inode, attr);  | 
