diff options
Diffstat (limited to 'fs/fat/inode.c')
| -rw-r--r-- | fs/fat/inode.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index ed33904926ee..7bf45aee56d7 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -142,14 +142,29 @@ static int fat_readpages(struct file *file, struct address_space *mapping, | |||
| 142 | return mpage_readpages(mapping, pages, nr_pages, fat_get_block); | 142 | return mpage_readpages(mapping, pages, nr_pages, fat_get_block); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static void fat_write_failed(struct address_space *mapping, loff_t to) | ||
| 146 | { | ||
| 147 | struct inode *inode = mapping->host; | ||
| 148 | |||
| 149 | if (to > inode->i_size) { | ||
| 150 | truncate_pagecache(inode, to, inode->i_size); | ||
| 151 | fat_truncate_blocks(inode, inode->i_size); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 145 | static int fat_write_begin(struct file *file, struct address_space *mapping, | 155 | static int fat_write_begin(struct file *file, struct address_space *mapping, |
| 146 | loff_t pos, unsigned len, unsigned flags, | 156 | loff_t pos, unsigned len, unsigned flags, |
| 147 | struct page **pagep, void **fsdata) | 157 | struct page **pagep, void **fsdata) |
| 148 | { | 158 | { |
| 159 | int err; | ||
| 160 | |||
| 149 | *pagep = NULL; | 161 | *pagep = NULL; |
| 150 | return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 162 | err = cont_write_begin_newtrunc(file, mapping, pos, len, flags, |
| 151 | fat_get_block, | 163 | pagep, fsdata, fat_get_block, |
| 152 | &MSDOS_I(mapping->host)->mmu_private); | 164 | &MSDOS_I(mapping->host)->mmu_private); |
| 165 | if (err < 0) | ||
| 166 | fat_write_failed(mapping, pos + len); | ||
| 167 | return err; | ||
| 153 | } | 168 | } |
| 154 | 169 | ||
| 155 | static int fat_write_end(struct file *file, struct address_space *mapping, | 170 | static int fat_write_end(struct file *file, struct address_space *mapping, |
| @@ -159,6 +174,8 @@ static int fat_write_end(struct file *file, struct address_space *mapping, | |||
| 159 | struct inode *inode = mapping->host; | 174 | struct inode *inode = mapping->host; |
| 160 | int err; | 175 | int err; |
| 161 | err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); | 176 | err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); |
| 177 | if (err < len) | ||
| 178 | fat_write_failed(mapping, pos + len); | ||
| 162 | if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { | 179 | if (!(err < 0) && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { |
| 163 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | 180 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; |
| 164 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; | 181 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; |
| @@ -172,7 +189,9 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
| 172 | loff_t offset, unsigned long nr_segs) | 189 | loff_t offset, unsigned long nr_segs) |
| 173 | { | 190 | { |
| 174 | struct file *file = iocb->ki_filp; | 191 | struct file *file = iocb->ki_filp; |
| 175 | struct inode *inode = file->f_mapping->host; | 192 | struct address_space *mapping = file->f_mapping; |
| 193 | struct inode *inode = mapping->host; | ||
| 194 | ssize_t ret; | ||
| 176 | 195 | ||
| 177 | if (rw == WRITE) { | 196 | if (rw == WRITE) { |
| 178 | /* | 197 | /* |
| @@ -193,8 +212,12 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
| 193 | * FAT need to use the DIO_LOCKING for avoiding the race | 212 | * FAT need to use the DIO_LOCKING for avoiding the race |
| 194 | * condition of fat_get_block() and ->truncate(). | 213 | * condition of fat_get_block() and ->truncate(). |
| 195 | */ | 214 | */ |
| 196 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 215 | ret = blockdev_direct_IO_newtrunc(rw, iocb, inode, inode->i_sb->s_bdev, |
| 197 | offset, nr_segs, fat_get_block, NULL); | 216 | iov, offset, nr_segs, fat_get_block, NULL); |
| 217 | if (ret < 0 && (rw & WRITE)) | ||
| 218 | fat_write_failed(mapping, offset + iov_length(iov, nr_segs)); | ||
| 219 | |||
| 220 | return ret; | ||
| 198 | } | 221 | } |
| 199 | 222 | ||
| 200 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 223 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
| @@ -429,7 +452,7 @@ static void fat_delete_inode(struct inode *inode) | |||
| 429 | { | 452 | { |
| 430 | truncate_inode_pages(&inode->i_data, 0); | 453 | truncate_inode_pages(&inode->i_data, 0); |
| 431 | inode->i_size = 0; | 454 | inode->i_size = 0; |
| 432 | fat_truncate(inode); | 455 | fat_truncate_blocks(inode, 0); |
| 433 | clear_inode(inode); | 456 | clear_inode(inode); |
| 434 | } | 457 | } |
| 435 | 458 | ||
