Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs: introduce new truncate sequence

Introduce a new truncate calling sequence into fs/mm subsystems. Rather than
setattr > vmtruncate > truncate, have filesystems call their truncate sequence
from ->setattr if filesystem specific operations are required. vmtruncate is
deprecated, and truncate_pagecache and inode_newsize_ok helpers introduced
previously should be used.

simple_setattr is introduced for simple in-ram filesystems to implement
the new truncate sequence. Eventually all filesystems should be converted
to implement a setattr, and the default code in notify_change should go
away.

simple_setsize is also introduced to perform just the ATTR_SIZE portion
of simple_setattr (ie. changing i_size and trimming pagecache).

To implement the new truncate sequence:
- filesystem specific manipulations (eg freeing blocks) must be done in
the setattr method rather than ->truncate.
- vmtruncate can not be used by core code to trim blocks past i_size in
the event of write failure after allocation, so this must be performed
in the fs code.
- convert usage of helpers block_write_begin, nobh_write_begin,
cont_write_begin, and *blockdev_direct_IO* to use _newtrunc postfixed
variants. These avoid calling vmtruncate to trim blocks (see previous).
- inode_setattr should not be used. generic_setattr is a new function
to be used to copy simple attributes into the generic inode.
- make use of the better opportunity to handle errors with the new sequence.

Big problem with the previous calling sequence: the filesystem is not called
until i_size has already changed. This means it is not allowed to fail the
call, and also it does not know what the previous i_size was. Also, generic
code calling vmtruncate to truncate allocated blocks in case of error had
no good way to return a meaningful error (or, for example, atomically handle
block deallocation).

Cc: Christoph Hellwig <hch@lst.de>
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

authored by

npiggin@suse.de and committed by
Al Viro
7bb46a67 7000d3c4

+300 -63
+6 -1
Documentation/filesystems/vfs.txt
··· 401 401 started might not be in the page cache at the end of the 402 402 walk). 403 403 404 - truncate: called by the VFS to change the size of a file. The 404 + truncate: Deprecated. This will not be called if ->setsize is defined. 405 + Called by the VFS to change the size of a file. The 405 406 i_size field of the inode is set to the desired size by the 406 407 VFS before this method is called. This method is called by 407 408 the truncate(2) system call and related functionality. 409 + 410 + Note: ->truncate and vmtruncate are deprecated. Do not add new 411 + instances/calls of these. Filesystems should be converted to do their 412 + truncate sequence via ->setattr(). 408 413 409 414 permission: called by the VFS to check for access rights on a POSIX-like 410 415 filesystem.
+40 -10
fs/attr.c
··· 67 67 * @offset: the new size to assign to the inode 68 68 * @Returns: 0 on success, -ve errno on failure 69 69 * 70 + * inode_newsize_ok must be called with i_mutex held. 71 + * 70 72 * inode_newsize_ok will check filesystem limits and ulimits to check that the 71 73 * new inode size is within limits. inode_newsize_ok will also send SIGXFSZ 72 74 * when necessary. Caller must not proceed with inode size change if failure is 73 75 * returned. @inode must be a file (not directory), with appropriate 74 76 * permissions to allow truncate (inode_newsize_ok does NOT check these 75 77 * conditions). 76 - * 77 - * inode_newsize_ok must be called with i_mutex held. 78 78 */ 79 79 int inode_newsize_ok(const struct inode *inode, loff_t offset) 80 80 { ··· 104 104 } 105 105 EXPORT_SYMBOL(inode_newsize_ok); 106 106 107 - int inode_setattr(struct inode * inode, struct iattr * attr) 107 + /** 108 + * generic_setattr - copy simple metadata updates into the generic inode 109 + * @inode: the inode to be updated 110 + * @attr: the new attributes 111 + * 112 + * generic_setattr must be called with i_mutex held. 113 + * 114 + * generic_setattr updates the inode's metadata with that specified 115 + * in attr. Noticably missing is inode size update, which is more complex 116 + * as it requires pagecache updates. See simple_setsize. 117 + * 118 + * The inode is not marked as dirty after this operation. The rationale is 119 + * that for "simple" filesystems, the struct inode is the inode storage. 120 + * The caller is free to mark the inode dirty afterwards if needed. 121 + */ 122 + void generic_setattr(struct inode *inode, const struct iattr *attr) 108 123 { 109 124 unsigned int ia_valid = attr->ia_valid; 110 - 111 - if (ia_valid & ATTR_SIZE && 112 - attr->ia_size != i_size_read(inode)) { 113 - int error = vmtruncate(inode, attr->ia_size); 114 - if (error) 115 - return error; 116 - } 117 125 118 126 if (ia_valid & ATTR_UID) 119 127 inode->i_uid = attr->ia_uid; ··· 143 135 mode &= ~S_ISGID; 144 136 inode->i_mode = mode; 145 137 } 138 + } 139 + EXPORT_SYMBOL(generic_setattr); 140 + 141 + /* 142 + * note this function is deprecated, the new truncate sequence should be 143 + * used instead -- see eg. simple_setsize, generic_setattr. 144 + */ 145 + int inode_setattr(struct inode *inode, const struct iattr *attr) 146 + { 147 + unsigned int ia_valid = attr->ia_valid; 148 + 149 + if (ia_valid & ATTR_SIZE && 150 + attr->ia_size != i_size_read(inode)) { 151 + int error; 152 + 153 + error = vmtruncate(inode, attr->ia_size); 154 + if (error) 155 + return error; 156 + } 157 + 158 + generic_setattr(inode, attr); 159 + 146 160 mark_inode_dirty(inode); 147 161 148 162 return 0;
+98 -25
fs/buffer.c
··· 1949 1949 } 1950 1950 1951 1951 /* 1952 - * block_write_begin takes care of the basic task of block allocation and 1953 - * bringing partial write blocks uptodate first. 1954 - * 1955 - * If *pagep is not NULL, then block_write_begin uses the locked page 1956 - * at *pagep rather than allocating its own. In this case, the page will 1957 - * not be unlocked or deallocated on failure. 1952 + * Filesystems implementing the new truncate sequence should use the 1953 + * _newtrunc postfix variant which won't incorrectly call vmtruncate. 1954 + * The filesystem needs to handle block truncation upon failure. 1958 1955 */ 1959 - int block_write_begin(struct file *file, struct address_space *mapping, 1956 + int block_write_begin_newtrunc(struct file *file, struct address_space *mapping, 1960 1957 loff_t pos, unsigned len, unsigned flags, 1961 1958 struct page **pagep, void **fsdata, 1962 1959 get_block_t *get_block) ··· 1989 1992 unlock_page(page); 1990 1993 page_cache_release(page); 1991 1994 *pagep = NULL; 1992 - 1993 - /* 1994 - * prepare_write() may have instantiated a few blocks 1995 - * outside i_size. Trim these off again. Don't need 1996 - * i_size_read because we hold i_mutex. 1997 - */ 1998 - if (pos + len > inode->i_size) 1999 - vmtruncate(inode, inode->i_size); 2000 1995 } 2001 1996 } 2002 1997 2003 1998 out: 2004 1999 return status; 2000 + } 2001 + EXPORT_SYMBOL(block_write_begin_newtrunc); 2002 + 2003 + /* 2004 + * block_write_begin takes care of the basic task of block allocation and 2005 + * bringing partial write blocks uptodate first. 2006 + * 2007 + * If *pagep is not NULL, then block_write_begin uses the locked page 2008 + * at *pagep rather than allocating its own. In this case, the page will 2009 + * not be unlocked or deallocated on failure. 2010 + */ 2011 + int block_write_begin(struct file *file, struct address_space *mapping, 2012 + loff_t pos, unsigned len, unsigned flags, 2013 + struct page **pagep, void **fsdata, 2014 + get_block_t *get_block) 2015 + { 2016 + int ret; 2017 + 2018 + ret = block_write_begin_newtrunc(file, mapping, pos, len, flags, 2019 + pagep, fsdata, get_block); 2020 + 2021 + /* 2022 + * prepare_write() may have instantiated a few blocks 2023 + * outside i_size. Trim these off again. Don't need 2024 + * i_size_read because we hold i_mutex. 2025 + * 2026 + * Filesystems which pass down their own page also cannot 2027 + * call into vmtruncate here because it would lead to lock 2028 + * inversion problems (*pagep is locked). This is a further 2029 + * example of where the old truncate sequence is inadequate. 2030 + */ 2031 + if (unlikely(ret) && *pagep == NULL) { 2032 + loff_t isize = mapping->host->i_size; 2033 + if (pos + len > isize) 2034 + vmtruncate(mapping->host, isize); 2035 + } 2036 + 2037 + return ret; 2005 2038 } 2006 2039 EXPORT_SYMBOL(block_write_begin); 2007 2040 ··· 2351 2324 * For moronic filesystems that do not allow holes in file. 2352 2325 * We may have to extend the file. 2353 2326 */ 2354 - int cont_write_begin(struct file *file, struct address_space *mapping, 2327 + int cont_write_begin_newtrunc(struct file *file, struct address_space *mapping, 2355 2328 loff_t pos, unsigned len, unsigned flags, 2356 2329 struct page **pagep, void **fsdata, 2357 2330 get_block_t *get_block, loff_t *bytes) ··· 2372 2345 } 2373 2346 2374 2347 *pagep = NULL; 2375 - err = block_write_begin(file, mapping, pos, len, 2348 + err = block_write_begin_newtrunc(file, mapping, pos, len, 2376 2349 flags, pagep, fsdata, get_block); 2377 2350 out: 2378 2351 return err; 2352 + } 2353 + EXPORT_SYMBOL(cont_write_begin_newtrunc); 2354 + 2355 + int cont_write_begin(struct file *file, struct address_space *mapping, 2356 + loff_t pos, unsigned len, unsigned flags, 2357 + struct page **pagep, void **fsdata, 2358 + get_block_t *get_block, loff_t *bytes) 2359 + { 2360 + int ret; 2361 + 2362 + ret = cont_write_begin_newtrunc(file, mapping, pos, len, flags, 2363 + pagep, fsdata, get_block, bytes); 2364 + if (unlikely(ret)) { 2365 + loff_t isize = mapping->host->i_size; 2366 + if (pos + len > isize) 2367 + vmtruncate(mapping->host, isize); 2368 + } 2369 + 2370 + return ret; 2379 2371 } 2380 2372 EXPORT_SYMBOL(cont_write_begin); 2381 2373 ··· 2427 2381 * 2428 2382 * We are not allowed to take the i_mutex here so we have to play games to 2429 2383 * protect against truncate races as the page could now be beyond EOF. Because 2430 - * vmtruncate() writes the inode size before removing pages, once we have the 2384 + * truncate writes the inode size before removing pages, once we have the 2431 2385 * page lock we can determine safely if the page is beyond EOF. If it is not 2432 2386 * beyond EOF, then the page is guaranteed safe against truncation until we 2433 2387 * unlock the page. ··· 2510 2464 } 2511 2465 2512 2466 /* 2513 - * On entry, the page is fully not uptodate. 2514 - * On exit the page is fully uptodate in the areas outside (from,to) 2467 + * Filesystems implementing the new truncate sequence should use the 2468 + * _newtrunc postfix variant which won't incorrectly call vmtruncate. 2469 + * The filesystem needs to handle block truncation upon failure. 2515 2470 */ 2516 - int nobh_write_begin(struct file *file, struct address_space *mapping, 2471 + int nobh_write_begin_newtrunc(struct file *file, struct address_space *mapping, 2517 2472 loff_t pos, unsigned len, unsigned flags, 2518 2473 struct page **pagep, void **fsdata, 2519 2474 get_block_t *get_block) ··· 2547 2500 unlock_page(page); 2548 2501 page_cache_release(page); 2549 2502 *pagep = NULL; 2550 - return block_write_begin(file, mapping, pos, len, flags, pagep, 2551 - fsdata, get_block); 2503 + return block_write_begin_newtrunc(file, mapping, pos, len, 2504 + flags, pagep, fsdata, get_block); 2552 2505 } 2553 2506 2554 2507 if (PageMappedToDisk(page)) ··· 2652 2605 page_cache_release(page); 2653 2606 *pagep = NULL; 2654 2607 2655 - if (pos + len > inode->i_size) 2656 - vmtruncate(inode, inode->i_size); 2608 + return ret; 2609 + } 2610 + EXPORT_SYMBOL(nobh_write_begin_newtrunc); 2611 + 2612 + /* 2613 + * On entry, the page is fully not uptodate. 2614 + * On exit the page is fully uptodate in the areas outside (from,to) 2615 + */ 2616 + int nobh_write_begin(struct file *file, struct address_space *mapping, 2617 + loff_t pos, unsigned len, unsigned flags, 2618 + struct page **pagep, void **fsdata, 2619 + get_block_t *get_block) 2620 + { 2621 + int ret; 2622 + 2623 + ret = nobh_write_begin_newtrunc(file, mapping, pos, len, flags, 2624 + pagep, fsdata, get_block); 2625 + 2626 + /* 2627 + * prepare_write() may have instantiated a few blocks 2628 + * outside i_size. Trim these off again. Don't need 2629 + * i_size_read because we hold i_mutex. 2630 + */ 2631 + if (unlikely(ret)) { 2632 + loff_t isize = mapping->host->i_size; 2633 + if (pos + len > isize) 2634 + vmtruncate(mapping->host, isize); 2635 + } 2657 2636 2658 2637 return ret; 2659 2638 }
+40 -21
fs/direct-io.c
··· 1134 1134 return ret; 1135 1135 } 1136 1136 1137 - /* 1138 - * This is a library function for use by filesystem drivers. 1139 - * 1140 - * The locking rules are governed by the flags parameter: 1141 - * - if the flags value contains DIO_LOCKING we use a fancy locking 1142 - * scheme for dumb filesystems. 1143 - * For writes this function is called under i_mutex and returns with 1144 - * i_mutex held, for reads, i_mutex is not held on entry, but it is 1145 - * taken and dropped again before returning. 1146 - * For reads and writes i_alloc_sem is taken in shared mode and released 1147 - * on I/O completion (which may happen asynchronously after returning to 1148 - * the caller). 1149 - * 1150 - * - if the flags value does NOT contain DIO_LOCKING we don't use any 1151 - * internal locking but rather rely on the filesystem to synchronize 1152 - * direct I/O reads/writes versus each other and truncate. 1153 - * For reads and writes both i_mutex and i_alloc_sem are not held on 1154 - * entry and are never taken. 1155 - */ 1156 1137 ssize_t 1157 - __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 1138 + __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, 1158 1139 struct block_device *bdev, const struct iovec *iov, loff_t offset, 1159 1140 unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, 1160 1141 dio_submit_t submit_io, int flags) ··· 1228 1247 nr_segs, blkbits, get_block, end_io, 1229 1248 submit_io, dio); 1230 1249 1250 + out: 1251 + return retval; 1252 + } 1253 + EXPORT_SYMBOL(__blockdev_direct_IO_newtrunc); 1254 + 1255 + /* 1256 + * This is a library function for use by filesystem drivers. 1257 + * 1258 + * The locking rules are governed by the flags parameter: 1259 + * - if the flags value contains DIO_LOCKING we use a fancy locking 1260 + * scheme for dumb filesystems. 1261 + * For writes this function is called under i_mutex and returns with 1262 + * i_mutex held, for reads, i_mutex is not held on entry, but it is 1263 + * taken and dropped again before returning. 1264 + * For reads and writes i_alloc_sem is taken in shared mode and released 1265 + * on I/O completion (which may happen asynchronously after returning to 1266 + * the caller). 1267 + * 1268 + * - if the flags value does NOT contain DIO_LOCKING we don't use any 1269 + * internal locking but rather rely on the filesystem to synchronize 1270 + * direct I/O reads/writes versus each other and truncate. 1271 + * For reads and writes both i_mutex and i_alloc_sem are not held on 1272 + * entry and are never taken. 1273 + */ 1274 + ssize_t 1275 + __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 1276 + struct block_device *bdev, const struct iovec *iov, loff_t offset, 1277 + unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, 1278 + dio_submit_t submit_io, int flags) 1279 + { 1280 + ssize_t retval; 1281 + 1282 + retval = __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, 1283 + offset, nr_segs, get_block, end_io, submit_io, flags); 1231 1284 /* 1232 1285 * In case of error extending write may have instantiated a few 1233 1286 * blocks outside i_size. Trim these off again for DIO_LOCKING. 1287 + * NOTE: DIO_NO_LOCK/DIO_OWN_LOCK callers have to handle this in 1288 + * their own manner. This is a further example of where the old 1289 + * truncate sequence is inadequate. 1234 1290 * 1235 1291 * NOTE: filesystems with their own locking have to handle this 1236 1292 * on their own. ··· 1275 1257 if (flags & DIO_LOCKING) { 1276 1258 if (unlikely((rw & WRITE) && retval < 0)) { 1277 1259 loff_t isize = i_size_read(inode); 1260 + loff_t end = offset + iov_length(iov, nr_segs); 1261 + 1278 1262 if (end > isize) 1279 1263 vmtruncate(inode, isize); 1280 1264 } 1281 1265 } 1282 1266 1283 - out: 1284 1267 return retval; 1285 1268 } 1286 1269 EXPORT_SYMBOL(__blockdev_direct_IO);
+76
fs/libfs.c
··· 8 8 #include <linux/slab.h> 9 9 #include <linux/mount.h> 10 10 #include <linux/vfs.h> 11 + #include <linux/quotaops.h> 11 12 #include <linux/mutex.h> 12 13 #include <linux/exportfs.h> 13 14 #include <linux/writeback.h> ··· 325 324 326 325 return 0; 327 326 } 327 + 328 + /** 329 + * simple_setsize - handle core mm and vfs requirements for file size change 330 + * @inode: inode 331 + * @newsize: new file size 332 + * 333 + * Returns 0 on success, -error on failure. 334 + * 335 + * simple_setsize must be called with inode_mutex held. 336 + * 337 + * simple_setsize will check that the requested new size is OK (see 338 + * inode_newsize_ok), and then will perform the necessary i_size update 339 + * and pagecache truncation (if necessary). It will be typically be called 340 + * from the filesystem's setattr function when ATTR_SIZE is passed in. 341 + * 342 + * The inode itself must have correct permissions and attributes to allow 343 + * i_size to be changed, this function then just checks that the new size 344 + * requested is valid. 345 + * 346 + * In the case of simple in-memory filesystems with inodes stored solely 347 + * in the inode cache, and file data in the pagecache, nothing more needs 348 + * to be done to satisfy a truncate request. Filesystems with on-disk 349 + * blocks for example will need to free them in the case of truncate, in 350 + * that case it may be easier not to use simple_setsize (but each of its 351 + * components will likely be required at some point to update pagecache 352 + * and inode etc). 353 + */ 354 + int simple_setsize(struct inode *inode, loff_t newsize) 355 + { 356 + loff_t oldsize; 357 + int error; 358 + 359 + error = inode_newsize_ok(inode, newsize); 360 + if (error) 361 + return error; 362 + 363 + oldsize = inode->i_size; 364 + i_size_write(inode, newsize); 365 + truncate_pagecache(inode, oldsize, newsize); 366 + 367 + return error; 368 + } 369 + EXPORT_SYMBOL(simple_setsize); 370 + 371 + /** 372 + * simple_setattr - setattr for simple in-memory filesystem 373 + * @dentry: dentry 374 + * @iattr: iattr structure 375 + * 376 + * Returns 0 on success, -error on failure. 377 + * 378 + * simple_setattr implements setattr for an in-memory filesystem which 379 + * does not store its own file data or metadata (eg. uses the page cache 380 + * and inode cache as its data store). 381 + */ 382 + int simple_setattr(struct dentry *dentry, struct iattr *iattr) 383 + { 384 + struct inode *inode = dentry->d_inode; 385 + int error; 386 + 387 + error = inode_change_ok(inode, iattr); 388 + if (error) 389 + return error; 390 + 391 + if (iattr->ia_valid & ATTR_SIZE) { 392 + error = simple_setsize(inode, iattr->ia_size); 393 + if (error) 394 + return error; 395 + } 396 + 397 + generic_setattr(inode, iattr); 398 + 399 + return error; 400 + } 401 + EXPORT_SYMBOL(simple_setattr); 328 402 329 403 int simple_readpage(struct file *file, struct page *page) 330 404 {
+9
include/linux/buffer_head.h
··· 203 203 int block_read_full_page(struct page*, get_block_t*); 204 204 int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc, 205 205 unsigned long from); 206 + int block_write_begin_newtrunc(struct file *, struct address_space *, 207 + loff_t, unsigned, unsigned, 208 + struct page **, void **, get_block_t*); 206 209 int block_write_begin(struct file *, struct address_space *, 207 210 loff_t, unsigned, unsigned, 208 211 struct page **, void **, get_block_t*); ··· 217 214 struct page *, void *); 218 215 void page_zero_new_buffers(struct page *page, unsigned from, unsigned to); 219 216 int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); 217 + int cont_write_begin_newtrunc(struct file *, struct address_space *, loff_t, 218 + unsigned, unsigned, struct page **, void **, 219 + get_block_t *, loff_t *); 220 220 int cont_write_begin(struct file *, struct address_space *, loff_t, 221 221 unsigned, unsigned, struct page **, void **, 222 222 get_block_t *, loff_t *); ··· 231 225 sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); 232 226 int block_truncate_page(struct address_space *, loff_t, get_block_t *); 233 227 int file_fsync(struct file *, int); 228 + int nobh_write_begin_newtrunc(struct file *, struct address_space *, 229 + loff_t, unsigned, unsigned, 230 + struct page **, void **, get_block_t*); 234 231 int nobh_write_begin(struct file *, struct address_space *, 235 232 loff_t, unsigned, unsigned, 236 233 struct page **, void **, get_block_t*);
+26 -1
include/linux/fs.h
··· 2257 2257 loff_t file_offset); 2258 2258 void dio_end_io(struct bio *bio, int error); 2259 2259 2260 + ssize_t __blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, struct inode *inode, 2261 + struct block_device *bdev, const struct iovec *iov, loff_t offset, 2262 + unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, 2263 + dio_submit_t submit_io, int lock_type); 2260 2264 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, 2261 2265 struct block_device *bdev, const struct iovec *iov, loff_t offset, 2262 2266 unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io, ··· 2274 2270 DIO_SKIP_HOLES = 0x02, 2275 2271 }; 2276 2272 2273 + static inline ssize_t blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb, 2274 + struct inode *inode, struct block_device *bdev, const struct iovec *iov, 2275 + loff_t offset, unsigned long nr_segs, get_block_t get_block, 2276 + dio_iodone_t end_io) 2277 + { 2278 + return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset, 2279 + nr_segs, get_block, end_io, NULL, 2280 + DIO_LOCKING | DIO_SKIP_HOLES); 2281 + } 2282 + 2283 + static inline ssize_t blockdev_direct_IO_no_locking_newtrunc(int rw, struct kiocb *iocb, 2284 + struct inode *inode, struct block_device *bdev, const struct iovec *iov, 2285 + loff_t offset, unsigned long nr_segs, get_block_t get_block, 2286 + dio_iodone_t end_io) 2287 + { 2288 + return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset, 2289 + nr_segs, get_block, end_io, NULL, 0); 2290 + } 2277 2291 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, 2278 2292 struct inode *inode, struct block_device *bdev, const struct iovec *iov, 2279 2293 loff_t offset, unsigned long nr_segs, get_block_t get_block, ··· 2364 2342 extern int dcache_dir_close(struct inode *, struct file *); 2365 2343 extern loff_t dcache_dir_lseek(struct file *, loff_t, int); 2366 2344 extern int dcache_readdir(struct file *, void *, filldir_t); 2345 + extern int simple_setattr(struct dentry *, struct iattr *); 2367 2346 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); 2368 2347 extern int simple_statfs(struct dentry *, struct kstatfs *); 2369 2348 extern int simple_link(struct dentry *, struct inode *, struct dentry *); 2370 2349 extern int simple_unlink(struct inode *, struct dentry *); 2371 2350 extern int simple_rmdir(struct inode *, struct dentry *); 2372 2351 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); 2352 + extern int simple_setsize(struct inode *, loff_t); 2373 2353 extern int noop_fsync(struct file *, int); 2374 2354 extern int simple_empty(struct dentry *); 2375 2355 extern int simple_readpage(struct file *file, struct page *page); ··· 2408 2384 2409 2385 extern int inode_change_ok(const struct inode *, struct iattr *); 2410 2386 extern int inode_newsize_ok(const struct inode *, loff_t offset); 2411 - extern int __must_check inode_setattr(struct inode *, struct iattr *); 2387 + extern int __must_check inode_setattr(struct inode *, const struct iattr *); 2388 + extern void generic_setattr(struct inode *inode, const struct iattr *attr); 2412 2389 2413 2390 extern void file_update_time(struct file *file); 2414 2391
+5 -5
mm/truncate.c
··· 548 548 * NOTE! We have to be ready to update the memory sharing 549 549 * between the file and the memory map for a potential last 550 550 * incomplete page. Ugly, but necessary. 551 + * 552 + * This function is deprecated and simple_setsize or truncate_pagecache 553 + * should be used instead. 551 554 */ 552 555 int vmtruncate(struct inode *inode, loff_t offset) 553 556 { 554 - loff_t oldsize; 555 557 int error; 556 558 557 - error = inode_newsize_ok(inode, offset); 559 + error = simple_setsize(inode, offset); 558 560 if (error) 559 561 return error; 560 - oldsize = inode->i_size; 561 - i_size_write(inode, offset); 562 - truncate_pagecache(inode, oldsize, offset); 562 + 563 563 if (inode->i_op->truncate) 564 564 inode->i_op->truncate(inode); 565 565