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) };