aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 14:26:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 14:26:52 -0400
commit5f248c9c251c60af3403902b26e08de43964ea0b (patch)
tree6d3328e72a7e4015a64017eb30be18095c6a3c64 /fs/hfsplus
parentf6cec0ae58c17522a7bc4e2f39dae19f199ab534 (diff)
parentdca332528bc69e05f67161e1ed59929633d5e63d (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.h1
-rw-r--r--fs/hfsplus/inode.c77
-rw-r--r--fs/hfsplus/super.c10
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 */
353struct inode *hfsplus_iget(struct super_block *, unsigned long); 353struct inode *hfsplus_iget(struct super_block *, unsigned long);
354int hfsplus_sync_fs(struct super_block *sb, int wait);
354 355
355/* tables.c */ 356/* tables.c */
356extern u16 hfsplus_case_fold_table[]; 357extern 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
40static sector_t hfsplus_bmap(struct address_space *mapping, sector_t block) 49static 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
113static int hfsplus_writepages(struct address_space *mapping, 137static 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
293static 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
314static 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
269static const struct inode_operations hfsplus_file_inode_operations = { 339static 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
148static void hfsplus_clear_inode(struct inode *inode) 148static 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
157static int hfsplus_sync_fs(struct super_block *sb, int wait) 159int 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,