VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
457c899653991 (Thomas Gleixner   2019-05-19 13:08:55 +0100   1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   2) /*
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   3)  *  linux/fs/fat/file.c
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   4)  *
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   5)  *  Written 1992,1993 by Werner Almesberger
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   6)  *
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   7)  *  regular file handling primitives for fat-based filesystems
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   8)  */
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700   9) 
16f7e0fe2ecc3 (Randy Dunlap      2006-01-11 12:17:46 -0800  10) #include <linux/capability.h>
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  11) #include <linux/module.h>
7845bc3e13260 (Arnd Bergmann     2010-05-17 08:13:47 +0900  12) #include <linux/compat.h>
42a74f206b914 (Dave Hansen       2008-02-15 14:37:46 -0800  13) #include <linux/mount.h>
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700  14) #include <linux/blkdev.h>
66114cad64bf7 (Tejun Heo         2015-05-22 17:13:32 -0400  15) #include <linux/backing-dev.h>
b1da47e29e467 (Miklos Szeredi    2008-07-01 15:01:28 +0200  16) #include <linux/fsnotify.h>
b1da47e29e467 (Miklos Szeredi    2008-07-01 15:01:28 +0200  17) #include <linux/security.h>
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800  18) #include <linux/falloc.h>
9e975dae2970d (OGAWA Hirofumi    2008-11-06 12:53:46 -0800  19) #include "fat.h"
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  20) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800  21) static long fat_fallocate(struct file *file, int mode,
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800  22) 			  loff_t offset, loff_t len);
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800  23) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  24) static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  25) {
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  26) 	u32 attr;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  27) 
e348e65a081d7 (Yubo Feng         2020-08-11 18:35:56 -0700  28) 	inode_lock_shared(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  29) 	attr = fat_make_attrs(inode);
e348e65a081d7 (Yubo Feng         2020-08-11 18:35:56 -0700  30) 	inode_unlock_shared(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  31) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  32) 	return put_user(attr, user_attr);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  33) }
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  34) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  35) static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  36) {
496ad9aa8ef44 (Al Viro           2013-01-23 17:07:38 -0500  37) 	struct inode *inode = file_inode(file);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  38) 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  39) 	int is_dir = S_ISDIR(inode->i_mode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  40) 	u32 attr, oldattr;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  41) 	struct iattr ia;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  42) 	int err;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  43) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  44) 	err = get_user(attr, user_attr);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  45) 	if (err)
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  46) 		goto out;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  47) 
a561be7100cd6 (Al Viro           2011-11-23 11:57:51 -0500  48) 	err = mnt_want_write_file(file);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  49) 	if (err)
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200  50) 		goto out;
5955102c9984f (Al Viro           2016-01-22 15:40:57 -0500  51) 	inode_lock(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  52) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  53) 	/*
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  54) 	 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  55) 	 * prevents the user from turning us into a VFAT
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  56) 	 * longname entry.  Also, we obviously can't set
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  57) 	 * any of the NTFS attributes in the high 24 bits.
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  58) 	 */
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  59) 	attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  60) 	/* Merge in ATTR_VOLUME and ATTR_DIR */
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  61) 	attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  62) 		(is_dir ? ATTR_DIR : 0);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  63) 	oldattr = fat_make_attrs(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  64) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  65) 	/* Equivalent to a chmod() */
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  66) 	ia.ia_valid = ATTR_MODE | ATTR_CTIME;
c2050a454c7f1 (Deepa Dinamani    2016-09-14 07:48:06 -0700  67) 	ia.ia_ctime = current_time(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  68) 	if (is_dir)
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  69) 		ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  70) 	else {
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  71) 		ia.ia_mode = fat_make_mode(sbi, attr,
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  72) 			S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  73) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  74) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  75) 	/* The root directory has no attributes */
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  76) 	if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  77) 		err = -EINVAL;
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200  78) 		goto out_unlock_inode;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  79) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  80) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  81) 	if (sbi->options.sys_immutable &&
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  82) 	    ((attr | oldattr) & ATTR_SYS) &&
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  83) 	    !capable(CAP_LINUX_IMMUTABLE)) {
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  84) 		err = -EPERM;
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200  85) 		goto out_unlock_inode;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  86) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  87) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  88) 	/*
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  89) 	 * The security check is questionable...  We single
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  90) 	 * out the RO attribute for checking by the security
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  91) 	 * module, just because it maps to a file mode.
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  92) 	 */
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  93) 	err = security_inode_setattr(file->f_path.dentry, &ia);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  94) 	if (err)
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200  95) 		goto out_unlock_inode;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700  96) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  97) 	/* This MUST be done before doing anything irreversible... */
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100  98) 	err = fat_setattr(file_mnt_user_ns(file), file->f_path.dentry, &ia);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900  99) 	if (err)
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200 100) 		goto out_unlock_inode;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 101) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 102) 	fsnotify_change(file->f_path.dentry, ia.ia_valid);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 103) 	if (sbi->options.sys_immutable) {
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 104) 		if (attr & ATTR_SYS)
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 105) 			inode->i_flags |= S_IMMUTABLE;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 106) 		else
1adffbae22332 (OGAWA Hirofumi    2011-05-31 19:38:07 +0900 107) 			inode->i_flags &= ~S_IMMUTABLE;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 108) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 109) 
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 110) 	fat_save_attrs(inode, attr);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 111) 	mark_inode_dirty(inode);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 112) out_unlock_inode:
5955102c9984f (Al Viro           2016-01-22 15:40:57 -0500 113) 	inode_unlock(inode);
e24f17da35607 (Jan Kara          2012-06-12 16:20:31 +0200 114) 	mnt_drop_write_file(file);
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 115) out:
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 116) 	return err;
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 117) }
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 118) 
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 119) static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr)
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 120) {
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 121) 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 122) 	return put_user(sbi->vol_id, user_attr);
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 123) }
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 124) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 125) static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 126) {
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 127) 	struct super_block *sb = inode->i_sb;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 128) 	struct fstrim_range __user *user_range;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 129) 	struct fstrim_range range;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 130) 	struct request_queue *q = bdev_get_queue(sb->s_bdev);
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 131) 	int err;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 132) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 133) 	if (!capable(CAP_SYS_ADMIN))
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 134) 		return -EPERM;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 135) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 136) 	if (!blk_queue_discard(q))
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 137) 		return -EOPNOTSUPP;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 138) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 139) 	user_range = (struct fstrim_range __user *)arg;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 140) 	if (copy_from_user(&range, user_range, sizeof(range)))
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 141) 		return -EFAULT;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 142) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 143) 	range.minlen = max_t(unsigned int, range.minlen,
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 144) 			     q->limits.discard_granularity);
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 145) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 146) 	err = fat_trim_fs(inode, &range);
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 147) 	if (err < 0)
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 148) 		return err;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 149) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 150) 	if (copy_to_user(user_range, &range, sizeof(range)))
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 151) 		return -EFAULT;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 152) 
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 153) 	return 0;
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 154) }
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 155) 
7845bc3e13260 (Arnd Bergmann     2010-05-17 08:13:47 +0900 156) long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 157) {
496ad9aa8ef44 (Al Viro           2013-01-23 17:07:38 -0500 158) 	struct inode *inode = file_inode(filp);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 159) 	u32 __user *user_attr = (u32 __user *)arg;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 160) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 161) 	switch (cmd) {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 162) 	case FAT_IOCTL_GET_ATTRIBUTES:
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 163) 		return fat_ioctl_get_attributes(inode, user_attr);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 164) 	case FAT_IOCTL_SET_ATTRIBUTES:
21bea495943f9 (Christoph Hellwig 2009-06-08 21:38:31 +0900 165) 		return fat_ioctl_set_attributes(filp, user_attr);
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 166) 	case FAT_IOCTL_GET_VOLUME_ID:
6e5b93ee55d40 (Mike Lockwood     2013-07-08 16:00:46 -0700 167) 		return fat_ioctl_get_volume_id(inode, user_attr);
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 168) 	case FITRIM:
f663b5b38fffe (Wentao Wang       2018-08-21 21:59:41 -0700 169) 		return fat_ioctl_fitrim(inode, arg);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 170) 	default:
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 171) 		return -ENOTTY;	/* Inappropriate ioctl for device */
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 172) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 173) }
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 174) 
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 175) static int fat_file_release(struct inode *inode, struct file *filp)
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 176) {
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 177) 	if ((filp->f_mode & FMODE_WRITE) &&
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 178) 	     MSDOS_SB(inode->i_sb)->options.flush) {
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 179) 		fat_flush_inodes(inode->i_sb, inode, NULL);
8aa7e847d834e (Jens Axboe        2009-07-09 14:52:32 +0200 180) 		congestion_wait(BLK_RW_ASYNC, HZ/10);
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 181) 	}
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 182) 	return 0;
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 183) }
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 184) 
02c24a82187d5 (Josef Bacik       2011-07-16 20:44:56 -0400 185) int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 186) {
7ea8085910ef3 (Christoph Hellwig 2010-05-26 17:53:25 +0200 187) 	struct inode *inode = filp->f_mapping->host;
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 188) 	int err;
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 189) 
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 190) 	err = __generic_file_fsync(filp, start, end, datasync);
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 191) 	if (err)
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 192) 		return err;
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 193) 
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 194) 	err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 195) 	if (err)
bd8309de0d608 (Hou Tao           2019-05-14 15:44:32 -0700 196) 		return err;
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 197) 
c6bf3f0e25f4c (Christoph Hellwig 2021-01-26 15:52:35 +0100 198) 	return blkdev_issue_flush(inode->i_sb->s_bdev);
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 199) }
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 200) 
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 201) 
4b6f5d20b04dc (Arjan van de Ven  2006-03-28 01:56:42 -0800 202) const struct file_operations fat_file_operations = {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 203) 	.llseek		= generic_file_llseek,
aad4f8bb42af0 (Al Viro           2014-04-02 14:33:16 -0400 204) 	.read_iter	= generic_file_read_iter,
8174202b34c30 (Al Viro           2014-04-03 03:17:43 -0400 205) 	.write_iter	= generic_file_write_iter,
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 206) 	.mmap		= generic_file_mmap,
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 207) 	.release	= fat_file_release,
7845bc3e13260 (Arnd Bergmann     2010-05-17 08:13:47 +0900 208) 	.unlocked_ioctl	= fat_generic_ioctl,
407e9ef72476e (Arnd Bergmann     2018-09-11 17:23:00 +0200 209) 	.compat_ioctl	= compat_ptr_ioctl,
b522412aeabad (Al Viro           2009-06-07 13:44:36 -0400 210) 	.fsync		= fat_file_fsync,
5ffc4ef45b3b0 (Jens Axboe        2007-06-01 11:49:19 +0200 211) 	.splice_read	= generic_file_splice_read,
67ceb1eca0acc (Hou Tao           2019-03-07 16:29:19 -0800 212) 	.splice_write	= iter_file_splice_write,
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 213) 	.fallocate	= fat_fallocate,
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 214) };
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 215) 
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 216) static int fat_cont_expand(struct inode *inode, loff_t size)
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 217) {
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 218) 	struct address_space *mapping = inode->i_mapping;
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 219) 	loff_t start = inode->i_size, count = size - inode->i_size;
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 220) 	int err;
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 221) 
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 222) 	err = generic_cont_expand_simple(inode, size);
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 223) 	if (err)
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 224) 		goto out;
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 225) 
cd83f6b194e95 (Frank Sorenson    2018-10-30 15:06:57 -0700 226) 	fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 227) 	mark_inode_dirty(inode);
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 228) 	if (IS_SYNC(inode)) {
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 229) 		int err2;
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 230) 
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 231) 		/*
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 232) 		 * Opencode syncing since we don't have a file open to use
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 233) 		 * standard fsync path.
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 234) 		 */
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 235) 		err = filemap_fdatawrite_range(mapping, start,
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 236) 					       start + count - 1);
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 237) 		err2 = sync_mapping_buffers(mapping);
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 238) 		if (!err)
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 239) 			err = err2;
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 240) 		err2 = write_inode_now(inode, 1);
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 241) 		if (!err)
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 242) 			err = err2;
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 243) 		if (!err) {
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 244) 			err =  filemap_fdatawait_range(mapping, start,
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 245) 						       start + count - 1);
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 246) 		}
2f3d675bcd4a8 (Jan Kara          2009-08-17 17:00:02 +0200 247) 	}
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 248) out:
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 249) 	return err;
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 250) }
05eb0b51fb464 (OGAWA Hirofumi    2006-01-08 01:02:13 -0800 251) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 252) /*
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 253)  * Preallocate space for a file. This implements fat's fallocate file
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 254)  * operation, which gets called from sys_fallocate system call. User
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 255)  * space requests len bytes at offset. If FALLOC_FL_KEEP_SIZE is set
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 256)  * we just allocate clusters without zeroing them out. Otherwise we
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 257)  * allocate and zero out clusters via an expanding truncate.
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 258)  */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 259) static long fat_fallocate(struct file *file, int mode,
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 260) 			  loff_t offset, loff_t len)
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 261) {
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 262) 	int nr_cluster; /* Number of clusters to be allocated */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 263) 	loff_t mm_bytes; /* Number of bytes to be allocated for file */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 264) 	loff_t ondisksize; /* block aligned on-disk size in bytes*/
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 265) 	struct inode *inode = file->f_mapping->host;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 266) 	struct super_block *sb = inode->i_sb;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 267) 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 268) 	int err = 0;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 269) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 270) 	/* No support for hole punch or other fallocate flags. */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 271) 	if (mode & ~FALLOC_FL_KEEP_SIZE)
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 272) 		return -EOPNOTSUPP;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 273) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 274) 	/* No support for dir */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 275) 	if (!S_ISREG(inode->i_mode))
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 276) 		return -EOPNOTSUPP;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 277) 
5955102c9984f (Al Viro           2016-01-22 15:40:57 -0500 278) 	inode_lock(inode);
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 279) 	if (mode & FALLOC_FL_KEEP_SIZE) {
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 280) 		ondisksize = inode->i_blocks << 9;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 281) 		if ((offset + len) <= ondisksize)
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 282) 			goto error;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 283) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 284) 		/* First compute the number of clusters to be allocated */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 285) 		mm_bytes = offset + len - ondisksize;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 286) 		nr_cluster = (mm_bytes + (sbi->cluster_size - 1)) >>
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 287) 			sbi->cluster_bits;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 288) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 289) 		/* Start the allocation.We are not zeroing out the clusters */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 290) 		while (nr_cluster-- > 0) {
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 291) 			err = fat_add_cluster(inode);
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 292) 			if (err)
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 293) 				goto error;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 294) 		}
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 295) 	} else {
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 296) 		if ((offset + len) <= i_size_read(inode))
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 297) 			goto error;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 298) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 299) 		/* This is just an expanding truncate */
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 300) 		err = fat_cont_expand(inode, (offset + len));
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 301) 	}
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 302) 
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 303) error:
5955102c9984f (Al Viro           2016-01-22 15:40:57 -0500 304) 	inode_unlock(inode);
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 305) 	return err;
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 306) }
b13bb33eacb72 (Namjae Jeon       2016-01-20 14:59:41 -0800 307) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 308) /* Free all clusters after the skip'th cluster. */
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 309) static int fat_free(struct inode *inode, int skip)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 310) {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 311) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 312) 	int err, wait, free_start, i_start, i_logstart;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 313) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 314) 	if (MSDOS_I(inode)->i_start == 0)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 315) 		return 0;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 316) 
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 317) 	fat_cache_inval_inode(inode);
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 318) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 319) 	wait = IS_DIRSYNC(inode);
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 320) 	i_start = free_start = MSDOS_I(inode)->i_start;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 321) 	i_logstart = MSDOS_I(inode)->i_logstart;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 322) 
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 323) 	/* First, we write the new file size. */
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 324) 	if (!skip) {
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 325) 		MSDOS_I(inode)->i_start = 0;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 326) 		MSDOS_I(inode)->i_logstart = 0;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 327) 	}
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 328) 	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
cd83f6b194e95 (Frank Sorenson    2018-10-30 15:06:57 -0700 329) 	fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 330) 	if (wait) {
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 331) 		err = fat_sync_inode(inode);
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 332) 		if (err) {
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 333) 			MSDOS_I(inode)->i_start = i_start;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 334) 			MSDOS_I(inode)->i_logstart = i_logstart;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 335) 			return err;
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 336) 		}
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 337) 	} else
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 338) 		mark_inode_dirty(inode);
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 339) 
3b641407a1447 (OGAWA Hirofumi    2006-02-03 03:04:44 -0800 340) 	/* Write a new EOF, and get the remaining cluster chain for freeing. */
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 341) 	if (skip) {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 342) 		struct fat_entry fatent;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 343) 		int ret, fclus, dclus;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 344) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 345) 		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 346) 		if (ret < 0)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 347) 			return ret;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 348) 		else if (ret == FAT_ENT_EOF)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 349) 			return 0;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 350) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 351) 		fatent_init(&fatent);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 352) 		ret = fat_ent_read(inode, &fatent, dclus);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 353) 		if (ret == FAT_ENT_EOF) {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 354) 			fatent_brelse(&fatent);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 355) 			return 0;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 356) 		} else if (ret == FAT_ENT_FREE) {
85c7859190c41 (Denis Karpov      2009-06-04 02:34:22 +0900 357) 			fat_fs_error(sb,
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 358) 				     "%s: invalid cluster chain (i_pos %lld)",
8e24eea728068 (Harvey Harrison   2008-04-30 00:55:09 -0700 359) 				     __func__, MSDOS_I(inode)->i_pos);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 360) 			ret = -EIO;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 361) 		} else if (ret > 0) {
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 362) 			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 363) 			if (err)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 364) 				ret = err;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 365) 		}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 366) 		fatent_brelse(&fatent);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 367) 		if (ret < 0)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 368) 			return ret;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 369) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 370) 		free_start = ret;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 371) 	}
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 372) 	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 373) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 374) 	/* Freeing the remained cluster chain */
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 375) 	return fat_free_clusters(inode, free_start);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 376) }
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 377) 
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 378) void fat_truncate_blocks(struct inode *inode, loff_t offset)
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 379) {
9c20616c385eb (Jonathan Corbet   2008-05-29 17:14:05 -0600 380) 	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 381) 	const unsigned int cluster_size = sbi->cluster_size;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 382) 	int nr_clusters;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 383) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 384) 	/*
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 385) 	 * This protects against truncating a file bigger than it was then
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 386) 	 * trying to write into the hole.
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 387) 	 */
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 388) 	if (MSDOS_I(inode)->mmu_private > offset)
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 389) 		MSDOS_I(inode)->mmu_private = offset;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 390) 
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 391) 	nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 392) 
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 393) 	fat_free(inode, nr_clusters);
ae78bf9c4f5fd (Chris Mason       2006-09-29 02:00:03 -0700 394) 	fat_flush_inodes(inode->i_sb, inode, NULL);
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 395) }
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 396) 
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 397) int fat_getattr(struct user_namespace *mnt_userns, const struct path *path,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 398) 		struct kstat *stat, u32 request_mask, unsigned int flags)
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 399) {
a528d35e8bfcc (David Howells     2017-01-31 16:46:22 +0000 400) 	struct inode *inode = d_inode(path->dentry);
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 401) 	generic_fillattr(mnt_userns, inode, stat);
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 402) 	stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
ea3983ace6b79 (Namjae Jeon       2013-04-29 16:21:11 -0700 403) 
ea3983ace6b79 (Namjae Jeon       2013-04-29 16:21:11 -0700 404) 	if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
ea3983ace6b79 (Namjae Jeon       2013-04-29 16:21:11 -0700 405) 		/* Use i_pos for ino. This is used as fileid of nfs. */
ea3983ace6b79 (Namjae Jeon       2013-04-29 16:21:11 -0700 406) 		stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode);
ea3983ace6b79 (Namjae Jeon       2013-04-29 16:21:11 -0700 407) 	}
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 408) 	return 0;
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 409) }
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 410) EXPORT_SYMBOL_GPL(fat_getattr);
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 411) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 412) static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 413) 			     struct inode *inode, umode_t *mode_ptr)
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 414) {
dacd0e7b392df (Al Viro           2011-07-26 03:21:30 -0400 415) 	umode_t mask, perm;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 416) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 417) 	/*
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 418) 	 * Note, the basic check is already done by a caller of
9c0aa1b87bf54 (OGAWA Hirofumi    2008-11-06 12:53:54 -0800 419) 	 * (attr->ia_mode & ~FAT_VALID_MODE)
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 420) 	 */
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 421) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 422) 	if (S_ISREG(inode->i_mode))
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 423) 		mask = sbi->options.fs_fmask;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 424) 	else
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 425) 		mask = sbi->options.fs_dmask;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 426) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 427) 	perm = *mode_ptr & ~(S_IFMT | mask);
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 428) 
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 429) 	/*
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 430) 	 * Of the r and x bits, all (subject to umask) must be present. Of the
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 431) 	 * w bits, either all (subject to umask) or none must be present.
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 432) 	 *
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 433) 	 * If fat_mode_can_hold_ro(inode) is false, can't change w bits.
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 434) 	 */
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 435) 	if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 436) 		return -EPERM;
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 437) 	if (fat_mode_can_hold_ro(inode)) {
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 438) 		if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 439) 			return -EPERM;
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 440) 	} else {
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 441) 		if ((perm & S_IWUGO) != (S_IWUGO & ~mask))
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 442) 			return -EPERM;
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 443) 	}
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 444) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 445) 	*mode_ptr &= S_IFMT | perm;
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 446) 
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 447) 	return 0;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 448) }
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 449) 
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 450) static int fat_allow_set_time(struct user_namespace *mnt_userns,
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 451) 			      struct msdos_sb_info *sbi, struct inode *inode)
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 452) {
dacd0e7b392df (Al Viro           2011-07-26 03:21:30 -0400 453) 	umode_t allow_utime = sbi->options.allow_utime;
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 454) 
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 455) 	if (!uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) {
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 456) 		if (in_group_p(i_gid_into_mnt(mnt_userns, inode)))
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 457) 			allow_utime >>= 3;
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 458) 		if (allow_utime & MAY_WRITE)
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 459) 			return 1;
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 460) 	}
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 461) 
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 462) 	/* use a default check */
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 463) 	return 0;
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 464) }
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 465) 
17263849c7ad2 (OGAWA Hirofumi    2008-08-02 13:59:37 +0900 466) #define TIMES_SET_FLAGS	(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
9c0aa1b87bf54 (OGAWA Hirofumi    2008-11-06 12:53:54 -0800 467) /* valid file mode bits */
9c0aa1b87bf54 (OGAWA Hirofumi    2008-11-06 12:53:54 -0800 468) #define FAT_VALID_MODE	(S_IFREG | S_IFDIR | S_IRWXUGO)
17263849c7ad2 (OGAWA Hirofumi    2008-08-02 13:59:37 +0900 469) 
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 470) int fat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 471) 		struct iattr *attr)
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 472) {
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 473) 	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
2b0143b5c986b (David Howells     2015-03-17 22:25:59 +0000 474) 	struct inode *inode = d_inode(dentry);
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 475) 	unsigned int ia_valid;
dfc209c0064ef (OGAWA Hirofumi    2008-11-06 12:53:55 -0800 476) 	int error;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 477) 
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 478) 	/* Check for setting the inode time. */
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 479) 	ia_valid = attr->ia_valid;
17263849c7ad2 (OGAWA Hirofumi    2008-08-02 13:59:37 +0900 480) 	if (ia_valid & TIMES_SET_FLAGS) {
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 481) 		if (fat_allow_set_time(mnt_userns, sbi, inode))
17263849c7ad2 (OGAWA Hirofumi    2008-08-02 13:59:37 +0900 482) 			attr->ia_valid &= ~TIMES_SET_FLAGS;
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 483) 	}
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 484) 
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 485) 	error = setattr_prepare(mnt_userns, dentry, attr);
1ae43f826b6cb (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 486) 	attr->ia_valid = ia_valid;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 487) 	if (error) {
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 488) 		if (sbi->options.quiet)
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 489) 			error = 0;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 490) 		goto out;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 491) 	}
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 492) 
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 493) 	/*
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 494) 	 * Expand the file. Since inode_setattr() updates ->i_size
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 495) 	 * before calling the ->truncate(), but FAT needs to fill the
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 496) 	 * hole before it. XXX: this is no longer true with new truncate
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 497) 	 * sequence.
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 498) 	 */
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 499) 	if (attr->ia_valid & ATTR_SIZE) {
562c72aa57c36 (Christoph Hellwig 2011-06-24 14:29:45 -0400 500) 		inode_dio_wait(inode);
562c72aa57c36 (Christoph Hellwig 2011-06-24 14:29:45 -0400 501) 
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 502) 		if (attr->ia_size > inode->i_size) {
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 503) 			error = fat_cont_expand(inode, attr->ia_size);
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 504) 			if (error || attr->ia_valid == ATTR_SIZE)
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 505) 				goto out;
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 506) 			attr->ia_valid &= ~ATTR_SIZE;
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 507) 		}
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 508) 	}
db78b877f7744 (Christoph Hellwig 2010-06-04 11:30:03 +0200 509) 
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 510) 	if (((attr->ia_valid & ATTR_UID) &&
170782eb89462 (Eric W. Biederman 2012-02-07 16:25:39 -0800 511) 	     (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 512) 	    ((attr->ia_valid & ATTR_GID) &&
170782eb89462 (Eric W. Biederman 2012-02-07 16:25:39 -0800 513) 	     (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
e97e8de388723 (OGAWA Hirofumi    2008-04-28 02:16:26 -0700 514) 	    ((attr->ia_valid & ATTR_MODE) &&
9c0aa1b87bf54 (OGAWA Hirofumi    2008-11-06 12:53:54 -0800 515) 	     (attr->ia_mode & ~FAT_VALID_MODE)))
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 516) 		error = -EPERM;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 517) 
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 518) 	if (error) {
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 519) 		if (sbi->options.quiet)
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 520) 			error = 0;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 521) 		goto out;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 522) 	}
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 523) 
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 524) 	/*
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 525) 	 * We don't return -EPERM here. Yes, strange, but this is too
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 526) 	 * old behavior.
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 527) 	 */
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 528) 	if (attr->ia_valid & ATTR_MODE) {
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 529) 		if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 530) 			attr->ia_valid &= ~ATTR_MODE;
2d518f84e5ecd (OGAWA Hirofumi    2008-06-12 15:21:28 -0700 531) 	}
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 532) 
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 533) 	if (attr->ia_valid & ATTR_SIZE) {
c0ef0cc9d277f (Namjae Jeon       2014-12-12 16:57:26 -0800 534) 		error = fat_block_truncate_page(inode, attr->ia_size);
c0ef0cc9d277f (Namjae Jeon       2014-12-12 16:57:26 -0800 535) 		if (error)
c0ef0cc9d277f (Namjae Jeon       2014-12-12 16:57:26 -0800 536) 			goto out;
582686915803e (Christoph Hellwig 2011-06-24 14:29:40 -0400 537) 		down_write(&MSDOS_I(inode)->truncate_lock);
2c27c65ed0696 (Christoph Hellwig 2010-06-04 11:30:04 +0200 538) 		truncate_setsize(inode, attr->ia_size);
2c27c65ed0696 (Christoph Hellwig 2010-06-04 11:30:04 +0200 539) 		fat_truncate_blocks(inode, attr->ia_size);
582686915803e (Christoph Hellwig 2011-06-24 14:29:40 -0400 540) 		up_write(&MSDOS_I(inode)->truncate_lock);
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 541) 	}
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 542) 
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 543) 	/*
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 544) 	 * setattr_copy can't truncate these appropriately, so we'll
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 545) 	 * copy them ourselves
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 546) 	 */
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 547) 	if (attr->ia_valid & ATTR_ATIME)
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 548) 		fat_truncate_time(inode, &attr->ia_atime, S_ATIME);
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 549) 	if (attr->ia_valid & ATTR_CTIME)
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 550) 		fat_truncate_time(inode, &attr->ia_ctime, S_CTIME);
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 551) 	if (attr->ia_valid & ATTR_MTIME)
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 552) 		fat_truncate_time(inode, &attr->ia_mtime, S_MTIME);
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 553) 	attr->ia_valid &= ~(ATTR_ATIME|ATTR_CTIME|ATTR_MTIME);
22ea4eba63410 (Frank Sorenson    2018-10-30 15:07:01 -0700 554) 
4b78993681083 (Christian Brauner 2021-01-21 14:19:56 +0100 555) 	setattr_copy(mnt_userns, inode, attr);
459f6ed3b8c74 (Nicholas Piggin   2010-05-27 01:05:38 +1000 556) 	mark_inode_dirty(inode);
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 557) out:
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 558) 	return error;
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 559) }
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 560) EXPORT_SYMBOL_GPL(fat_setattr);
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 561) 
754661f143e70 (Arjan van de Ven  2007-02-12 00:55:38 -0800 562) const struct inode_operations fat_file_inode_operations = {
1278fdd34b122 (OGAWA Hirofumi    2008-04-28 02:16:25 -0700 563) 	.setattr	= fat_setattr,
da63fc7ce63b4 (OGAWA Hirofumi    2006-11-16 01:19:28 -0800 564) 	.getattr	= fat_getattr,
6bb885ecd7467 (Frank Sorenson    2018-10-30 15:06:53 -0700 565) 	.update_time	= fat_update_time,
^1da177e4c3f4 (Linus Torvalds    2005-04-16 15:20:36 -0700 566) };