diff options
Diffstat (limited to 'fs/fat')
-rw-r--r-- | fs/fat/fat.h | 1 | ||||
-rw-r--r-- | fs/fat/file.c | 49 | ||||
-rw-r--r-- | fs/fat/inode.c | 26 |
3 files changed, 30 insertions, 46 deletions
diff --git a/fs/fat/fat.h b/fs/fat/fat.h index 27ac25725954..d75a77f85c28 100644 --- a/fs/fat/fat.h +++ b/fs/fat/fat.h | |||
@@ -306,7 +306,6 @@ extern long fat_generic_ioctl(struct file *filp, unsigned int cmd, | |||
306 | extern const struct file_operations fat_file_operations; | 306 | extern const struct file_operations fat_file_operations; |
307 | extern const struct inode_operations fat_file_inode_operations; | 307 | extern const struct inode_operations fat_file_inode_operations; |
308 | extern int fat_setattr(struct dentry * dentry, struct iattr * attr); | 308 | extern int fat_setattr(struct dentry * dentry, struct iattr * attr); |
309 | extern int fat_setsize(struct inode *inode, loff_t offset); | ||
310 | extern void fat_truncate_blocks(struct inode *inode, loff_t offset); | 309 | extern void fat_truncate_blocks(struct inode *inode, loff_t offset); |
311 | extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, | 310 | extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, |
312 | struct kstat *stat); | 311 | struct kstat *stat); |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 990dfae022e5..7257752b6d5d 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -364,18 +364,6 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode) | |||
364 | return 0; | 364 | return 0; |
365 | } | 365 | } |
366 | 366 | ||
367 | int fat_setsize(struct inode *inode, loff_t offset) | ||
368 | { | ||
369 | int error; | ||
370 | |||
371 | error = simple_setsize(inode, offset); | ||
372 | if (error) | ||
373 | return error; | ||
374 | fat_truncate_blocks(inode, offset); | ||
375 | |||
376 | return error; | ||
377 | } | ||
378 | |||
379 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) | 367 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) |
380 | /* valid file mode bits */ | 368 | /* valid file mode bits */ |
381 | #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO) | 369 | #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO) |
@@ -387,21 +375,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
387 | unsigned int ia_valid; | 375 | unsigned int ia_valid; |
388 | int error; | 376 | int error; |
389 | 377 | ||
390 | /* | ||
391 | * Expand the file. Since inode_setattr() updates ->i_size | ||
392 | * before calling the ->truncate(), but FAT needs to fill the | ||
393 | * hole before it. XXX: this is no longer true with new truncate | ||
394 | * sequence. | ||
395 | */ | ||
396 | if (attr->ia_valid & ATTR_SIZE) { | ||
397 | if (attr->ia_size > inode->i_size) { | ||
398 | error = fat_cont_expand(inode, attr->ia_size); | ||
399 | if (error || attr->ia_valid == ATTR_SIZE) | ||
400 | goto out; | ||
401 | attr->ia_valid &= ~ATTR_SIZE; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /* Check for setting the inode time. */ | 378 | /* Check for setting the inode time. */ |
406 | ia_valid = attr->ia_valid; | 379 | ia_valid = attr->ia_valid; |
407 | if (ia_valid & TIMES_SET_FLAGS) { | 380 | if (ia_valid & TIMES_SET_FLAGS) { |
@@ -417,6 +390,21 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
417 | goto out; | 390 | goto out; |
418 | } | 391 | } |
419 | 392 | ||
393 | /* | ||
394 | * Expand the file. Since inode_setattr() updates ->i_size | ||
395 | * before calling the ->truncate(), but FAT needs to fill the | ||
396 | * hole before it. XXX: this is no longer true with new truncate | ||
397 | * sequence. | ||
398 | */ | ||
399 | if (attr->ia_valid & ATTR_SIZE) { | ||
400 | if (attr->ia_size > inode->i_size) { | ||
401 | error = fat_cont_expand(inode, attr->ia_size); | ||
402 | if (error || attr->ia_valid == ATTR_SIZE) | ||
403 | goto out; | ||
404 | attr->ia_valid &= ~ATTR_SIZE; | ||
405 | } | ||
406 | } | ||
407 | |||
420 | if (((attr->ia_valid & ATTR_UID) && | 408 | if (((attr->ia_valid & ATTR_UID) && |
421 | (attr->ia_uid != sbi->options.fs_uid)) || | 409 | (attr->ia_uid != sbi->options.fs_uid)) || |
422 | ((attr->ia_valid & ATTR_GID) && | 410 | ((attr->ia_valid & ATTR_GID) && |
@@ -441,12 +429,11 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
441 | } | 429 | } |
442 | 430 | ||
443 | if (attr->ia_valid & ATTR_SIZE) { | 431 | if (attr->ia_valid & ATTR_SIZE) { |
444 | error = fat_setsize(inode, attr->ia_size); | 432 | truncate_setsize(inode, attr->ia_size); |
445 | if (error) | 433 | fat_truncate_blocks(inode, attr->ia_size); |
446 | goto out; | ||
447 | } | 434 | } |
448 | 435 | ||
449 | generic_setattr(inode, attr); | 436 | setattr_copy(inode, attr); |
450 | mark_inode_dirty(inode); | 437 | mark_inode_dirty(inode); |
451 | out: | 438 | out: |
452 | return error; | 439 | return error; |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 7bf45aee56d7..830058057d33 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -159,7 +159,7 @@ static int fat_write_begin(struct file *file, struct address_space *mapping, | |||
159 | int err; | 159 | int err; |
160 | 160 | ||
161 | *pagep = NULL; | 161 | *pagep = NULL; |
162 | err = cont_write_begin_newtrunc(file, mapping, pos, len, flags, | 162 | err = cont_write_begin(file, mapping, pos, len, flags, |
163 | pagep, fsdata, fat_get_block, | 163 | pagep, fsdata, fat_get_block, |
164 | &MSDOS_I(mapping->host)->mmu_private); | 164 | &MSDOS_I(mapping->host)->mmu_private); |
165 | if (err < 0) | 165 | if (err < 0) |
@@ -212,8 +212,8 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
212 | * FAT need to use the DIO_LOCKING for avoiding the race | 212 | * FAT need to use the DIO_LOCKING for avoiding the race |
213 | * condition of fat_get_block() and ->truncate(). | 213 | * condition of fat_get_block() and ->truncate(). |
214 | */ | 214 | */ |
215 | ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev, | 215 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, |
216 | iov, offset, nr_segs, fat_get_block, NULL); | 216 | iov, offset, nr_segs, fat_get_block, NULL); |
217 | if (ret < 0 && (rw & WRITE)) | 217 | if (ret < 0 && (rw & WRITE)) |
218 | fat_write_failed(mapping, offset + iov_length(iov, nr_segs)); | 218 | fat_write_failed(mapping, offset + iov_length(iov, nr_segs)); |
219 | 219 | ||
@@ -263,7 +263,7 @@ static const struct address_space_operations fat_aops = { | |||
263 | * check if the location is still valid and retry if it | 263 | * check if the location is still valid and retry if it |
264 | * isn't. Otherwise we do changes. | 264 | * isn't. Otherwise we do changes. |
265 | * 5. Spinlock is used to protect hash/unhash/location check/lookup | 265 | * 5. Spinlock is used to protect hash/unhash/location check/lookup |
266 | * 6. fat_clear_inode() unhashes the F-d-c entry. | 266 | * 6. fat_evict_inode() unhashes the F-d-c entry. |
267 | * 7. lookup() and readdir() do igrab() if they find a F-d-c entry | 267 | * 7. lookup() and readdir() do igrab() if they find a F-d-c entry |
268 | * and consider negative result as cache miss. | 268 | * and consider negative result as cache miss. |
269 | */ | 269 | */ |
@@ -448,16 +448,15 @@ out: | |||
448 | 448 | ||
449 | EXPORT_SYMBOL_GPL(fat_build_inode); | 449 | EXPORT_SYMBOL_GPL(fat_build_inode); |
450 | 450 | ||
451 | static void fat_delete_inode(struct inode *inode) | 451 | static void fat_evict_inode(struct inode *inode) |
452 | { | 452 | { |
453 | truncate_inode_pages(&inode->i_data, 0); | 453 | truncate_inode_pages(&inode->i_data, 0); |
454 | inode->i_size = 0; | 454 | if (!inode->i_nlink) { |
455 | fat_truncate_blocks(inode, 0); | 455 | inode->i_size = 0; |
456 | clear_inode(inode); | 456 | fat_truncate_blocks(inode, 0); |
457 | } | 457 | } |
458 | 458 | invalidate_inode_buffers(inode); | |
459 | static void fat_clear_inode(struct inode *inode) | 459 | end_writeback(inode); |
460 | { | ||
461 | fat_cache_inval_inode(inode); | 460 | fat_cache_inval_inode(inode); |
462 | fat_detach(inode); | 461 | fat_detach(inode); |
463 | } | 462 | } |
@@ -674,12 +673,11 @@ static const struct super_operations fat_sops = { | |||
674 | .alloc_inode = fat_alloc_inode, | 673 | .alloc_inode = fat_alloc_inode, |
675 | .destroy_inode = fat_destroy_inode, | 674 | .destroy_inode = fat_destroy_inode, |
676 | .write_inode = fat_write_inode, | 675 | .write_inode = fat_write_inode, |
677 | .delete_inode = fat_delete_inode, | 676 | .evict_inode = fat_evict_inode, |
678 | .put_super = fat_put_super, | 677 | .put_super = fat_put_super, |
679 | .write_super = fat_write_super, | 678 | .write_super = fat_write_super, |
680 | .sync_fs = fat_sync_fs, | 679 | .sync_fs = fat_sync_fs, |
681 | .statfs = fat_statfs, | 680 | .statfs = fat_statfs, |
682 | .clear_inode = fat_clear_inode, | ||
683 | .remount_fs = fat_remount, | 681 | .remount_fs = fat_remount, |
684 | 682 | ||
685 | .show_options = fat_show_options, | 683 | .show_options = fat_show_options, |