History

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).

npiggin@suse.de committed 16 years ago

Commit 7bb46a61 parent 7000d3c8 files · +300 −63Browse files

Showing the changes to include/linux (2 of 8 files). Show all

Unified · Split

2 files
  1. include/linux/buffer_head.h +9 −0
  2. include/linux/fs.h +26 −1
include/linux/buffer_head.h+9−0
@@ -203,6 +203,9 @@ int block_write_full_page_endio(struct page *page, get_block_t *get_block, · 202 unmodified lines
203203 int block_read_full_page(struct page*, get_block_t*);
204204 int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
205205 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*);
206209 int block_write_begin(struct file *, struct address_space *,
207210 loff_t, unsigned, unsigned,
208211 struct page **, void **, get_block_t*);
@@ -214,6 +217,9 @@ int generic_write_end(struct file *, struct address_space *, · 5 unmodified lines
214217 struct page *, void *);
215218 void page_zero_new_buffers(struct page *page, unsigned from, unsigned to);
216219 int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
220+int cont_write_begin_newtrunc(struct file *, struct address_space *, loff_t,
221+ unsigned, unsigned, struct page **, void **,
222+ get_block_t *, loff_t *);
217223 int cont_write_begin(struct file *, struct address_space *, loff_t,
218224 unsigned, unsigned, struct page **, void **,
219225 get_block_t *, loff_t *);
@@ -225,6 +231,9 @@ void block_sync_page(struct page *); · 5 unmodified lines
225231 sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
226232 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
227233 int file_fsync(struct file *, int);
234+int nobh_write_begin_newtrunc(struct file *, struct address_space *,
235+ loff_t, unsigned, unsigned,
236+ struct page **, void **, get_block_t*);
228237 int nobh_write_begin(struct file *, struct address_space *,
229238 loff_t, unsigned, unsigned,
230239 struct page **, void **, get_block_t*);
include/linux/fs.h+26−1
@@ -2257,6 +2257,10 @@ typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, · 2256 unmodified lines
22572257 loff_t file_offset);
22582258 void dio_end_io(struct bio *bio, int error);
22592259
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);
22602264 ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
22612265 struct block_device *bdev, const struct iovec *iov, loff_t offset,
22622266 unsigned long nr_segs, get_block_t get_block, dio_iodone_t end_io,
@@ -2270,6 +2274,24 @@ enum { · 7 unmodified lines
22702274 DIO_SKIP_HOLES = 0x02,
22712275 };
22722276
2277+static inline ssize_t blockdev_direct_IO_newtrunc(int rw, struct kiocb *iocb,
2278+ struct inode *inode, struct block_device *bdev, const struct iovec *iov,
2279+ loff_t offset, unsigned long nr_segs, get_block_t get_block,
2280+ dio_iodone_t end_io)
2281+{
2282+ return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset,
2283+ nr_segs, get_block, end_io, NULL,
2284+ DIO_LOCKING | DIO_SKIP_HOLES);
2285+}
2286+
2287+static inline ssize_t blockdev_direct_IO_no_locking_newtrunc(int rw, struct kiocb *iocb,
2288+ struct inode *inode, struct block_device *bdev, const struct iovec *iov,
2289+ loff_t offset, unsigned long nr_segs, get_block_t get_block,
2290+ dio_iodone_t end_io)
2291+{
2292+ return __blockdev_direct_IO_newtrunc(rw, iocb, inode, bdev, iov, offset,
2293+ nr_segs, get_block, end_io, NULL, 0);
2294+}
22732295 static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb,
22742296 struct inode *inode, struct block_device *bdev, const struct iovec *iov,
22752297 loff_t offset, unsigned long nr_segs, get_block_t get_block,
@@ -2342,12 +2364,14 @@ extern int dcache_dir_open(struct inode *, struct file *); · 66 unmodified lines
23422364 extern int dcache_dir_close(struct inode *, struct file *);
23432365 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
23442366 extern int dcache_readdir(struct file *, void *, filldir_t);
2367+extern int simple_setattr(struct dentry *, struct iattr *);
23452368 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
23462369 extern int simple_statfs(struct dentry *, struct kstatfs *);
23472370 extern int simple_link(struct dentry *, struct inode *, struct dentry *);
23482371 extern int simple_unlink(struct inode *, struct dentry *);
23492372 extern int simple_rmdir(struct inode *, struct dentry *);
23502373 extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
2374+extern int simple_setsize(struct inode *, loff_t);
23512375 extern int noop_fsync(struct file *, int);
23522376 extern int simple_empty(struct dentry *);
23532377 extern int simple_readpage(struct file *file, struct page *page);
@@ -2384,7 +2408,8 @@ extern int buffer_migrate_page(struct address_space *, · 30 unmodified lines
23842408
23852409 extern int inode_change_ok(const struct inode *, struct iattr *);
23862410 extern int inode_newsize_ok(const struct inode *, loff_t offset);
2387−extern int __must_check inode_setattr(struct inode *, struct iattr *);
2411+extern int __must_check inode_setattr(struct inode *, const struct iattr *);
2412+extern void generic_setattr(struct inode *inode, const struct iattr *attr);
23882413
23892414 extern void file_update_time(struct file *file);
23902415

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t