diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 14:26:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-10 14:26:52 -0400 |
commit | 5f248c9c251c60af3403902b26e08de43964ea0b (patch) | |
tree | 6d3328e72a7e4015a64017eb30be18095c6a3c64 /fs/hfsplus | |
parent | f6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff) | |
parent | dca332528bc69e05f67161e1ed59929633d5e63d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (96 commits)
no need for list_for_each_entry_safe()/resetting with superblock list
Fix sget() race with failing mount
vfs: don't hold s_umount over close_bdev_exclusive() call
sysv: do not mark superblock dirty on remount
sysv: do not mark superblock dirty on mount
btrfs: remove junk sb_dirt change
BFS: clean up the superblock usage
AFFS: wait for sb synchronization when needed
AFFS: clean up dirty flag usage
cifs: truncate fallout
mbcache: fix shrinker function return value
mbcache: Remove unused features
add f_flags to struct statfs(64)
pass a struct path to vfs_statfs
update VFS documentation for method changes.
All filesystems that need invalidate_inode_buffers() are doing that explicitly
convert remaining ->clear_inode() to ->evict_inode()
Make ->drop_inode() just return whether inode needs to be dropped
fs/inode.c:clear_inode() is gone
fs/inode.c:evict() doesn't care about delete vs. non-delete paths now
...
Fix up trivial conflicts in fs/nilfs2/super.c
Diffstat (limited to 'fs/hfsplus')
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 1 | ||||
-rw-r--r-- | fs/hfsplus/inode.c | 77 | ||||
-rw-r--r-- | fs/hfsplus/super.c | 10 |
3 files changed, 81 insertions, 7 deletions
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 6505c30ad965..dc856be3c2b0 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
@@ -351,6 +351,7 @@ int hfsplus_show_options(struct seq_file *, struct vfsmount *); | |||
351 | 351 | ||
352 | /* super.c */ | 352 | /* super.c */ |
353 | struct inode *hfsplus_iget(struct super_block *, unsigned long); | 353 | struct inode *hfsplus_iget(struct super_block *, unsigned long); |
354 | int hfsplus_sync_fs(struct super_block *sb, int wait); | ||
354 | 355 | ||
355 | /* tables.c */ | 356 | /* tables.c */ |
356 | extern u16 hfsplus_case_fold_table[]; | 357 | extern u16 hfsplus_case_fold_table[]; |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9bbb82924a22..c5a979d62c65 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
@@ -31,10 +31,19 @@ static int hfsplus_write_begin(struct file *file, struct address_space *mapping, | |||
31 | loff_t pos, unsigned len, unsigned flags, | 31 | loff_t pos, unsigned len, unsigned flags, |
32 | struct page **pagep, void **fsdata) | 32 | struct page **pagep, void **fsdata) |
33 | { | 33 | { |
34 | int ret; | ||
35 | |||
34 | *pagep = NULL; | 36 | *pagep = NULL; |
35 | return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 37 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
36 | hfsplus_get_block, | 38 | hfsplus_get_block, |
37 | &HFSPLUS_I(mapping->host).phys_size); | 39 | &HFSPLUS_I(mapping->host).phys_size); |
40 | if (unlikely(ret)) { | ||
41 | loff_t isize = mapping->host->i_size; | ||
42 | if (pos + len > isize) | ||
43 | vmtruncate(mapping->host, isize); | ||
44 | } | ||
45 | |||
46 | return ret; | ||
38 | } | 47 | } |
39 | 48 | ||
40 | static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) | 49 | static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) |
@@ -105,9 +114,24 @@ static ssize_t hfsplus_direct_IO(int rw, struct kiocb *iocb, | |||
105 | { | 114 | { |
106 | struct file *file = iocb->ki_filp; | 115 | struct file *file = iocb->ki_filp; |
107 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; | 116 | struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host; |
117 | ssize_t ret; | ||
108 | 118 | ||
109 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 119 | ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
110 | offset, nr_segs, hfsplus_get_block, NULL); | 120 | offset, nr_segs, hfsplus_get_block, NULL); |
121 | |||
122 | /* | ||
123 | * In case of error extending write may have instantiated a few | ||
124 | * blocks outside i_size. Trim these off again. | ||
125 | */ | ||
126 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
127 | loff_t isize = i_size_read(inode); | ||
128 | loff_t end = offset + iov_length(iov, nr_segs); | ||
129 | |||
130 | if (end > isize) | ||
131 | vmtruncate(inode, isize); | ||
132 | } | ||
133 | |||
134 | return ret; | ||
111 | } | 135 | } |
112 | 136 | ||
113 | static int hfsplus_writepages(struct address_space *mapping, | 137 | static int hfsplus_writepages(struct address_space *mapping, |
@@ -266,9 +290,56 @@ static int hfsplus_file_release(struct inode *inode, struct file *file) | |||
266 | return 0; | 290 | return 0; |
267 | } | 291 | } |
268 | 292 | ||
293 | static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr) | ||
294 | { | ||
295 | struct inode *inode = dentry->d_inode; | ||
296 | int error; | ||
297 | |||
298 | error = inode_change_ok(inode, attr); | ||
299 | if (error) | ||
300 | return error; | ||
301 | |||
302 | if ((attr->ia_valid & ATTR_SIZE) && | ||
303 | attr->ia_size != i_size_read(inode)) { | ||
304 | error = vmtruncate(inode, attr->ia_size); | ||
305 | if (error) | ||
306 | return error; | ||
307 | } | ||
308 | |||
309 | setattr_copy(inode, attr); | ||
310 | mark_inode_dirty(inode); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | static int hfsplus_file_fsync(struct file *filp, int datasync) | ||
315 | { | ||
316 | struct inode *inode = filp->f_mapping->host; | ||
317 | struct super_block * sb; | ||
318 | int ret, err; | ||
319 | |||
320 | /* sync the inode to buffers */ | ||
321 | ret = write_inode_now(inode, 0); | ||
322 | |||
323 | /* sync the superblock to buffers */ | ||
324 | sb = inode->i_sb; | ||
325 | if (sb->s_dirt) { | ||
326 | if (!(sb->s_flags & MS_RDONLY)) | ||
327 | hfsplus_sync_fs(sb, 1); | ||
328 | else | ||
329 | sb->s_dirt = 0; | ||
330 | } | ||
331 | |||
332 | /* .. finally sync the buffers to disk */ | ||
333 | err = sync_blockdev(sb->s_bdev); | ||
334 | if (!ret) | ||
335 | ret = err; | ||
336 | return ret; | ||
337 | } | ||
338 | |||
269 | static const struct inode_operations hfsplus_file_inode_operations = { | 339 | static const struct inode_operations hfsplus_file_inode_operations = { |
270 | .lookup = hfsplus_file_lookup, | 340 | .lookup = hfsplus_file_lookup, |
271 | .truncate = hfsplus_file_truncate, | 341 | .truncate = hfsplus_file_truncate, |
342 | .setattr = hfsplus_setattr, | ||
272 | .setxattr = hfsplus_setxattr, | 343 | .setxattr = hfsplus_setxattr, |
273 | .getxattr = hfsplus_getxattr, | 344 | .getxattr = hfsplus_getxattr, |
274 | .listxattr = hfsplus_listxattr, | 345 | .listxattr = hfsplus_listxattr, |
@@ -282,7 +353,7 @@ static const struct file_operations hfsplus_file_operations = { | |||
282 | .aio_write = generic_file_aio_write, | 353 | .aio_write = generic_file_aio_write, |
283 | .mmap = generic_file_mmap, | 354 | .mmap = generic_file_mmap, |
284 | .splice_read = generic_file_splice_read, | 355 | .splice_read = generic_file_splice_read, |
285 | .fsync = file_fsync, | 356 | .fsync = hfsplus_file_fsync, |
286 | .open = hfsplus_file_open, | 357 | .open = hfsplus_file_open, |
287 | .release = hfsplus_file_release, | 358 | .release = hfsplus_file_release, |
288 | .unlocked_ioctl = hfsplus_ioctl, | 359 | .unlocked_ioctl = hfsplus_ioctl, |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 74b473a8ef92..3b55c050c742 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -145,16 +145,18 @@ static int hfsplus_write_inode(struct inode *inode, | |||
145 | return ret; | 145 | return ret; |
146 | } | 146 | } |
147 | 147 | ||
148 | static void hfsplus_clear_inode(struct inode *inode) | 148 | static void hfsplus_evict_inode(struct inode *inode) |
149 | { | 149 | { |
150 | dprint(DBG_INODE, "hfsplus_clear_inode: %lu\n", inode->i_ino); | 150 | dprint(DBG_INODE, "hfsplus_evict_inode: %lu\n", inode->i_ino); |
151 | truncate_inode_pages(&inode->i_data, 0); | ||
152 | end_writeback(inode); | ||
151 | if (HFSPLUS_IS_RSRC(inode)) { | 153 | if (HFSPLUS_IS_RSRC(inode)) { |
152 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; | 154 | HFSPLUS_I(HFSPLUS_I(inode).rsrc_inode).rsrc_inode = NULL; |
153 | iput(HFSPLUS_I(inode).rsrc_inode); | 155 | iput(HFSPLUS_I(inode).rsrc_inode); |
154 | } | 156 | } |
155 | } | 157 | } |
156 | 158 | ||
157 | static int hfsplus_sync_fs(struct super_block *sb, int wait) | 159 | int hfsplus_sync_fs(struct super_block *sb, int wait) |
158 | { | 160 | { |
159 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 161 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; |
160 | 162 | ||
@@ -293,7 +295,7 @@ static const struct super_operations hfsplus_sops = { | |||
293 | .alloc_inode = hfsplus_alloc_inode, | 295 | .alloc_inode = hfsplus_alloc_inode, |
294 | .destroy_inode = hfsplus_destroy_inode, | 296 | .destroy_inode = hfsplus_destroy_inode, |
295 | .write_inode = hfsplus_write_inode, | 297 | .write_inode = hfsplus_write_inode, |
296 | .clear_inode = hfsplus_clear_inode, | 298 | .evict_inode = hfsplus_evict_inode, |
297 | .put_super = hfsplus_put_super, | 299 | .put_super = hfsplus_put_super, |
298 | .write_super = hfsplus_write_super, | 300 | .write_super = hfsplus_write_super, |
299 | .sync_fs = hfsplus_sync_fs, | 301 | .sync_fs = hfsplus_sync_fs, |