file.c 14.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9
/*
 *  linux/fs/fat/file.c
 *
 *  Written 1992,1993 by Werner Almesberger
 *
 *  regular file handling primitives for fat-based filesystems
 */

10
#include <linux/capability.h>
L
Linus Torvalds 已提交
11
#include <linux/module.h>
A
Arnd Bergmann 已提交
12
#include <linux/compat.h>
13
#include <linux/mount.h>
C
Chris Mason 已提交
14
#include <linux/blkdev.h>
15
#include <linux/backing-dev.h>
16 17
#include <linux/fsnotify.h>
#include <linux/security.h>
N
Namjae Jeon 已提交
18
#include <linux/falloc.h>
O
OGAWA Hirofumi 已提交
19
#include "fat.h"
L
Linus Torvalds 已提交
20

N
Namjae Jeon 已提交
21 22 23
static long fat_fallocate(struct file *file, int mode,
			  loff_t offset, loff_t len);

C
Christoph Hellwig 已提交
24 25 26 27
static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
{
	u32 attr;

28
	inode_lock_shared(inode);
C
Christoph Hellwig 已提交
29
	attr = fat_make_attrs(inode);
30
	inode_unlock_shared(inode);
C
Christoph Hellwig 已提交
31 32 33 34 35

	return put_user(attr, user_attr);
}

static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
L
Linus Torvalds 已提交
36
{
A
Al Viro 已提交
37
	struct inode *inode = file_inode(file);
L
Linus Torvalds 已提交
38
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
C
Christoph Hellwig 已提交
39 40 41 42
	int is_dir = S_ISDIR(inode->i_mode);
	u32 attr, oldattr;
	struct iattr ia;
	int err;
L
Linus Torvalds 已提交
43

C
Christoph Hellwig 已提交
44 45 46
	err = get_user(attr, user_attr);
	if (err)
		goto out;
L
Linus Torvalds 已提交
47

48
	err = mnt_want_write_file(file);
C
Christoph Hellwig 已提交
49
	if (err)
50
		goto out;
A
Al Viro 已提交
51
	inode_lock(inode);
C
Christoph Hellwig 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

	/*
	 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
	 * prevents the user from turning us into a VFAT
	 * longname entry.  Also, we obviously can't set
	 * any of the NTFS attributes in the high 24 bits.
	 */
	attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
	/* Merge in ATTR_VOLUME and ATTR_DIR */
	attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
		(is_dir ? ATTR_DIR : 0);
	oldattr = fat_make_attrs(inode);

	/* Equivalent to a chmod() */
	ia.ia_valid = ATTR_MODE | ATTR_CTIME;
67
	ia.ia_ctime = current_time(inode);
C
Christoph Hellwig 已提交
68 69 70 71 72 73
	if (is_dir)
		ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
	else {
		ia.ia_mode = fat_make_mode(sbi, attr,
			S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
	}
L
Linus Torvalds 已提交
74

C
Christoph Hellwig 已提交
75 76 77
	/* The root directory has no attributes */
	if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
		err = -EINVAL;
78
		goto out_unlock_inode;
L
Linus Torvalds 已提交
79 80
	}

C
Christoph Hellwig 已提交
81 82 83 84
	if (sbi->options.sys_immutable &&
	    ((attr | oldattr) & ATTR_SYS) &&
	    !capable(CAP_LINUX_IMMUTABLE)) {
		err = -EPERM;
85
		goto out_unlock_inode;
C
Christoph Hellwig 已提交
86
	}
L
Linus Torvalds 已提交
87

C
Christoph Hellwig 已提交
88 89 90 91 92 93 94
	/*
	 * The security check is questionable...  We single
	 * out the RO attribute for checking by the security
	 * module, just because it maps to a file mode.
	 */
	err = security_inode_setattr(file->f_path.dentry, &ia);
	if (err)
95
		goto out_unlock_inode;
L
Linus Torvalds 已提交
96

C
Christoph Hellwig 已提交
97
	/* This MUST be done before doing anything irreversible... */
98
	err = fat_setattr(file_mnt_user_ns(file), file->f_path.dentry, &ia);
C
Christoph Hellwig 已提交
99
	if (err)
100
		goto out_unlock_inode;
C
Christoph Hellwig 已提交
101 102 103 104 105 106

	fsnotify_change(file->f_path.dentry, ia.ia_valid);
	if (sbi->options.sys_immutable) {
		if (attr & ATTR_SYS)
			inode->i_flags |= S_IMMUTABLE;
		else
107
			inode->i_flags &= ~S_IMMUTABLE;
C
Christoph Hellwig 已提交
108
	}
L
Linus Torvalds 已提交
109

C
Christoph Hellwig 已提交
110 111 112
	fat_save_attrs(inode, attr);
	mark_inode_dirty(inode);
out_unlock_inode:
A
Al Viro 已提交
113
	inode_unlock(inode);
114
	mnt_drop_write_file(file);
C
Christoph Hellwig 已提交
115 116 117
out:
	return err;
}
L
Linus Torvalds 已提交
118

119 120 121 122 123 124
static int fat_ioctl_get_volume_id(struct inode *inode, u32 __user *user_attr)
{
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
	return put_user(sbi->vol_id, user_attr);
}

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
static int fat_ioctl_fitrim(struct inode *inode, unsigned long arg)
{
	struct super_block *sb = inode->i_sb;
	struct fstrim_range __user *user_range;
	struct fstrim_range range;
	struct request_queue *q = bdev_get_queue(sb->s_bdev);
	int err;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (!blk_queue_discard(q))
		return -EOPNOTSUPP;

	user_range = (struct fstrim_range __user *)arg;
	if (copy_from_user(&range, user_range, sizeof(range)))
		return -EFAULT;

	range.minlen = max_t(unsigned int, range.minlen,
			     q->limits.discard_granularity);

	err = fat_trim_fs(inode, &range);
	if (err < 0)
		return err;

	if (copy_to_user(user_range, &range, sizeof(range)))
		return -EFAULT;

	return 0;
}

A
Arnd Bergmann 已提交
156
long fat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
157
{
A
Al Viro 已提交
158
	struct inode *inode = file_inode(filp);
L
Linus Torvalds 已提交
159 160 161 162
	u32 __user *user_attr = (u32 __user *)arg;

	switch (cmd) {
	case FAT_IOCTL_GET_ATTRIBUTES:
C
Christoph Hellwig 已提交
163
		return fat_ioctl_get_attributes(inode, user_attr);
L
Linus Torvalds 已提交
164
	case FAT_IOCTL_SET_ATTRIBUTES:
C
Christoph Hellwig 已提交
165
		return fat_ioctl_set_attributes(filp, user_attr);
166 167
	case FAT_IOCTL_GET_VOLUME_ID:
		return fat_ioctl_get_volume_id(inode, user_attr);
168 169
	case FITRIM:
		return fat_ioctl_fitrim(inode, arg);
L
Linus Torvalds 已提交
170 171 172 173 174
	default:
		return -ENOTTY;	/* Inappropriate ioctl for device */
	}
}

C
Chris Mason 已提交
175 176 177
static int fat_file_release(struct inode *inode, struct file *filp)
{
	if ((filp->f_mode & FMODE_WRITE) &&
178
	    MSDOS_SB(inode->i_sb)->options.flush) {
C
Chris Mason 已提交
179
		fat_flush_inodes(inode->i_sb, inode, NULL);
180 181
		set_current_state(TASK_UNINTERRUPTIBLE);
		io_schedule_timeout(HZ/10);
C
Chris Mason 已提交
182 183 184 185
	}
	return 0;
}

186
int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
A
Al Viro 已提交
187
{
188
	struct inode *inode = filp->f_mapping->host;
189 190 191 192 193
	int err;

	err = __generic_file_fsync(filp, start, end, datasync);
	if (err)
		return err;
A
Al Viro 已提交
194 195

	err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping);
196 197
	if (err)
		return err;
A
Al Viro 已提交
198

199
	return blkdev_issue_flush(inode->i_sb->s_bdev);
A
Al Viro 已提交
200 201 202
}


203
const struct file_operations fat_file_operations = {
L
Linus Torvalds 已提交
204
	.llseek		= generic_file_llseek,
205
	.read_iter	= generic_file_read_iter,
206
	.write_iter	= generic_file_write_iter,
L
Linus Torvalds 已提交
207
	.mmap		= generic_file_mmap,
C
Chris Mason 已提交
208
	.release	= fat_file_release,
A
Arnd Bergmann 已提交
209
	.unlocked_ioctl	= fat_generic_ioctl,
210
	.compat_ioctl	= compat_ptr_ioctl,
A
Al Viro 已提交
211
	.fsync		= fat_file_fsync,
212
	.splice_read	= generic_file_splice_read,
213
	.splice_write	= iter_file_splice_write,
N
Namjae Jeon 已提交
214
	.fallocate	= fat_fallocate,
L
Linus Torvalds 已提交
215 216
};

217 218 219 220 221 222 223 224 225 226
static int fat_cont_expand(struct inode *inode, loff_t size)
{
	struct address_space *mapping = inode->i_mapping;
	loff_t start = inode->i_size, count = size - inode->i_size;
	int err;

	err = generic_cont_expand_simple(inode, size);
	if (err)
		goto out;

227
	fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
228
	mark_inode_dirty(inode);
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
	if (IS_SYNC(inode)) {
		int err2;

		/*
		 * Opencode syncing since we don't have a file open to use
		 * standard fsync path.
		 */
		err = filemap_fdatawrite_range(mapping, start,
					       start + count - 1);
		err2 = sync_mapping_buffers(mapping);
		if (!err)
			err = err2;
		err2 = write_inode_now(inode, 1);
		if (!err)
			err = err2;
		if (!err) {
			err =  filemap_fdatawait_range(mapping, start,
						       start + count - 1);
		}
	}
249 250 251 252
out:
	return err;
}

N
Namjae Jeon 已提交
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
/*
 * Preallocate space for a file. This implements fat's fallocate file
 * operation, which gets called from sys_fallocate system call. User
 * space requests len bytes at offset. If FALLOC_FL_KEEP_SIZE is set
 * we just allocate clusters without zeroing them out. Otherwise we
 * allocate and zero out clusters via an expanding truncate.
 */
static long fat_fallocate(struct file *file, int mode,
			  loff_t offset, loff_t len)
{
	int nr_cluster; /* Number of clusters to be allocated */
	loff_t mm_bytes; /* Number of bytes to be allocated for file */
	loff_t ondisksize; /* block aligned on-disk size in bytes*/
	struct inode *inode = file->f_mapping->host;
	struct super_block *sb = inode->i_sb;
	struct msdos_sb_info *sbi = MSDOS_SB(sb);
	int err = 0;

	/* No support for hole punch or other fallocate flags. */
	if (mode & ~FALLOC_FL_KEEP_SIZE)
		return -EOPNOTSUPP;

	/* No support for dir */
	if (!S_ISREG(inode->i_mode))
		return -EOPNOTSUPP;

A
Al Viro 已提交
279
	inode_lock(inode);
N
Namjae Jeon 已提交
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
	if (mode & FALLOC_FL_KEEP_SIZE) {
		ondisksize = inode->i_blocks << 9;
		if ((offset + len) <= ondisksize)
			goto error;

		/* First compute the number of clusters to be allocated */
		mm_bytes = offset + len - ondisksize;
		nr_cluster = (mm_bytes + (sbi->cluster_size - 1)) >>
			sbi->cluster_bits;

		/* Start the allocation.We are not zeroing out the clusters */
		while (nr_cluster-- > 0) {
			err = fat_add_cluster(inode);
			if (err)
				goto error;
		}
	} else {
		if ((offset + len) <= i_size_read(inode))
			goto error;

		/* This is just an expanding truncate */
		err = fat_cont_expand(inode, (offset + len));
	}

error:
A
Al Viro 已提交
305
	inode_unlock(inode);
N
Namjae Jeon 已提交
306 307 308
	return err;
}

L
Linus Torvalds 已提交
309 310 311 312 313 314 315 316 317
/* Free all clusters after the skip'th cluster. */
static int fat_free(struct inode *inode, int skip)
{
	struct super_block *sb = inode->i_sb;
	int err, wait, free_start, i_start, i_logstart;

	if (MSDOS_I(inode)->i_start == 0)
		return 0;

318 319
	fat_cache_inval_inode(inode);

L
Linus Torvalds 已提交
320
	wait = IS_DIRSYNC(inode);
321 322 323 324 325 326 327 328 329
	i_start = free_start = MSDOS_I(inode)->i_start;
	i_logstart = MSDOS_I(inode)->i_logstart;

	/* First, we write the new file size. */
	if (!skip) {
		MSDOS_I(inode)->i_start = 0;
		MSDOS_I(inode)->i_logstart = 0;
	}
	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
330
	fat_truncate_time(inode, NULL, S_CTIME|S_MTIME);
331 332 333 334 335 336 337 338 339 340 341
	if (wait) {
		err = fat_sync_inode(inode);
		if (err) {
			MSDOS_I(inode)->i_start = i_start;
			MSDOS_I(inode)->i_logstart = i_logstart;
			return err;
		}
	} else
		mark_inode_dirty(inode);

	/* Write a new EOF, and get the remaining cluster chain for freeing. */
L
Linus Torvalds 已提交
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
	if (skip) {
		struct fat_entry fatent;
		int ret, fclus, dclus;

		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
		if (ret < 0)
			return ret;
		else if (ret == FAT_ENT_EOF)
			return 0;

		fatent_init(&fatent);
		ret = fat_ent_read(inode, &fatent, dclus);
		if (ret == FAT_ENT_EOF) {
			fatent_brelse(&fatent);
			return 0;
		} else if (ret == FAT_ENT_FREE) {
D
Denis Karpov 已提交
358
			fat_fs_error(sb,
L
Linus Torvalds 已提交
359
				     "%s: invalid cluster chain (i_pos %lld)",
360
				     __func__, MSDOS_I(inode)->i_pos);
L
Linus Torvalds 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
			ret = -EIO;
		} else if (ret > 0) {
			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
			if (err)
				ret = err;
		}
		fatent_brelse(&fatent);
		if (ret < 0)
			return ret;

		free_start = ret;
	}
	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);

	/* Freeing the remained cluster chain */
	return fat_free_clusters(inode, free_start);
}

379
void fat_truncate_blocks(struct inode *inode, loff_t offset)
L
Linus Torvalds 已提交
380
{
381
	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
L
Linus Torvalds 已提交
382 383 384 385 386 387 388
	const unsigned int cluster_size = sbi->cluster_size;
	int nr_clusters;

	/*
	 * This protects against truncating a file bigger than it was then
	 * trying to write into the hole.
	 */
389 390
	if (MSDOS_I(inode)->mmu_private > offset)
		MSDOS_I(inode)->mmu_private = offset;
L
Linus Torvalds 已提交
391

392
	nr_clusters = (offset + (cluster_size - 1)) >> sbi->cluster_bits;
L
Linus Torvalds 已提交
393 394

	fat_free(inode, nr_clusters);
C
Chris Mason 已提交
395
	fat_flush_inodes(inode->i_sb, inode, NULL);
L
Linus Torvalds 已提交
396 397
}

398 399
int fat_getattr(struct user_namespace *mnt_userns, const struct path *path,
		struct kstat *stat, u32 request_mask, unsigned int flags)
O
OGAWA Hirofumi 已提交
400
{
401
	struct inode *inode = d_inode(path->dentry);
C
Christian Brauner 已提交
402
	generic_fillattr(mnt_userns, inode, stat);
O
OGAWA Hirofumi 已提交
403
	stat->blksize = MSDOS_SB(inode->i_sb)->cluster_size;
N
Namjae Jeon 已提交
404 405 406 407 408

	if (MSDOS_SB(inode->i_sb)->options.nfs == FAT_NFS_NOSTALE_RO) {
		/* Use i_pos for ino. This is used as fileid of nfs. */
		stat->ino = fat_i_pos_read(MSDOS_SB(inode->i_sb), inode);
	}
O
OGAWA Hirofumi 已提交
409 410 411 412
	return 0;
}
EXPORT_SYMBOL_GPL(fat_getattr);

413 414
static int fat_sanitize_mode(const struct msdos_sb_info *sbi,
			     struct inode *inode, umode_t *mode_ptr)
415
{
A
Al Viro 已提交
416
	umode_t mask, perm;
417

418 419
	/*
	 * Note, the basic check is already done by a caller of
O
OGAWA Hirofumi 已提交
420
	 * (attr->ia_mode & ~FAT_VALID_MODE)
421 422 423
	 */

	if (S_ISREG(inode->i_mode))
424 425 426 427
		mask = sbi->options.fs_fmask;
	else
		mask = sbi->options.fs_dmask;

428 429
	perm = *mode_ptr & ~(S_IFMT | mask);

430 431 432
	/*
	 * Of the r and x bits, all (subject to umask) must be present. Of the
	 * w bits, either all (subject to umask) or none must be present.
O
OGAWA Hirofumi 已提交
433 434
	 *
	 * If fat_mode_can_hold_ro(inode) is false, can't change w bits.
435
	 */
436
	if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO)))
437
		return -EPERM;
O
OGAWA Hirofumi 已提交
438 439 440 441 442 443 444
	if (fat_mode_can_hold_ro(inode)) {
		if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask)))
			return -EPERM;
	} else {
		if ((perm & S_IWUGO) != (S_IWUGO & ~mask))
			return -EPERM;
	}
445

446 447
	*mode_ptr &= S_IFMT | perm;

448 449 450
	return 0;
}

C
Christian Brauner 已提交
451 452
static int fat_allow_set_time(struct user_namespace *mnt_userns,
			      struct msdos_sb_info *sbi, struct inode *inode)
O
OGAWA Hirofumi 已提交
453
{
A
Al Viro 已提交
454
	umode_t allow_utime = sbi->options.allow_utime;
O
OGAWA Hirofumi 已提交
455

C
Christian Brauner 已提交
456 457
	if (!uid_eq(current_fsuid(), i_uid_into_mnt(mnt_userns, inode))) {
		if (in_group_p(i_gid_into_mnt(mnt_userns, inode)))
O
OGAWA Hirofumi 已提交
458 459 460 461 462 463 464 465 466
			allow_utime >>= 3;
		if (allow_utime & MAY_WRITE)
			return 1;
	}

	/* use a default check */
	return 0;
}

O
OGAWA Hirofumi 已提交
467
#define TIMES_SET_FLAGS	(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
O
OGAWA Hirofumi 已提交
468 469
/* valid file mode bits */
#define FAT_VALID_MODE	(S_IFREG | S_IFDIR | S_IRWXUGO)
O
OGAWA Hirofumi 已提交
470

471 472
int fat_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
		struct iattr *attr)
473 474
{
	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
475
	struct inode *inode = d_inode(dentry);
O
OGAWA Hirofumi 已提交
476
	unsigned int ia_valid;
O
OGAWA Hirofumi 已提交
477
	int error;
478

O
OGAWA Hirofumi 已提交
479 480
	/* Check for setting the inode time. */
	ia_valid = attr->ia_valid;
O
OGAWA Hirofumi 已提交
481
	if (ia_valid & TIMES_SET_FLAGS) {
C
Christian Brauner 已提交
482
		if (fat_allow_set_time(mnt_userns, sbi, inode))
O
OGAWA Hirofumi 已提交
483
			attr->ia_valid &= ~TIMES_SET_FLAGS;
O
OGAWA Hirofumi 已提交
484 485
	}

C
Christian Brauner 已提交
486
	error = setattr_prepare(mnt_userns, dentry, attr);
O
OGAWA Hirofumi 已提交
487
	attr->ia_valid = ia_valid;
488 489 490 491 492
	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}
493

494 495 496 497 498 499 500
	/*
	 * Expand the file. Since inode_setattr() updates ->i_size
	 * before calling the ->truncate(), but FAT needs to fill the
	 * hole before it. XXX: this is no longer true with new truncate
	 * sequence.
	 */
	if (attr->ia_valid & ATTR_SIZE) {
501 502
		inode_dio_wait(inode);

503 504 505 506 507 508 509 510
		if (attr->ia_size > inode->i_size) {
			error = fat_cont_expand(inode, attr->ia_size);
			if (error || attr->ia_valid == ATTR_SIZE)
				goto out;
			attr->ia_valid &= ~ATTR_SIZE;
		}
	}

511
	if (((attr->ia_valid & ATTR_UID) &&
512
	     (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) ||
513
	    ((attr->ia_valid & ATTR_GID) &&
514
	     (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) ||
O
OGAWA Hirofumi 已提交
515
	    ((attr->ia_valid & ATTR_MODE) &&
O
OGAWA Hirofumi 已提交
516
	     (attr->ia_mode & ~FAT_VALID_MODE)))
517 518 519 520 521 522 523 524
		error = -EPERM;

	if (error) {
		if (sbi->options.quiet)
			error = 0;
		goto out;
	}

525 526 527 528 529 530 531 532
	/*
	 * We don't return -EPERM here. Yes, strange, but this is too
	 * old behavior.
	 */
	if (attr->ia_valid & ATTR_MODE) {
		if (fat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0)
			attr->ia_valid &= ~ATTR_MODE;
	}
533

534
	if (attr->ia_valid & ATTR_SIZE) {
535 536 537
		error = fat_block_truncate_page(inode, attr->ia_size);
		if (error)
			goto out;
538
		down_write(&MSDOS_I(inode)->truncate_lock);
539 540
		truncate_setsize(inode, attr->ia_size);
		fat_truncate_blocks(inode, attr->ia_size);
541
		up_write(&MSDOS_I(inode)->truncate_lock);
542 543
	}

544 545 546 547 548 549 550 551 552 553 554 555
	/*
	 * setattr_copy can't truncate these appropriately, so we'll
	 * copy them ourselves
	 */
	if (attr->ia_valid & ATTR_ATIME)
		fat_truncate_time(inode, &attr->ia_atime, S_ATIME);
	if (attr->ia_valid & ATTR_CTIME)
		fat_truncate_time(inode, &attr->ia_ctime, S_CTIME);
	if (attr->ia_valid & ATTR_MTIME)
		fat_truncate_time(inode, &attr->ia_mtime, S_MTIME);
	attr->ia_valid &= ~(ATTR_ATIME|ATTR_CTIME|ATTR_MTIME);

C
Christian Brauner 已提交
556
	setattr_copy(mnt_userns, inode, attr);
557
	mark_inode_dirty(inode);
558 559 560 561 562
out:
	return error;
}
EXPORT_SYMBOL_GPL(fat_setattr);

563
const struct inode_operations fat_file_inode_operations = {
564
	.setattr	= fat_setattr,
O
OGAWA Hirofumi 已提交
565
	.getattr	= fat_getattr,
566
	.update_time	= fat_update_time,
L
Linus Torvalds 已提交
567
};