diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-08-26 13:22:27 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-08-26 13:22:27 -0400 |
commit | f632265d0ffb5acf331252d98c64939849d96bb2 (patch) | |
tree | 31187d9a726bf1ca6ca12e26ad8e7c609eaf4d8b /fs/affs | |
parent | 7d94784293096c0a46897acdb83be5abd9278ece (diff) | |
parent | da5cabf80e2433131bf0ed8993abc0f7ea618c73 (diff) |
Merge commit 'v2.6.36-rc1' into HEAD
Diffstat (limited to 'fs/affs')
-rw-r--r-- | fs/affs/affs.h | 3 | ||||
-rw-r--r-- | fs/affs/file.c | 11 | ||||
-rw-r--r-- | fs/affs/inode.c | 38 | ||||
-rw-r--r-- | fs/affs/super.c | 32 |
4 files changed, 46 insertions, 38 deletions
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index f05b6155ccc8..a8cbdeb34025 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
@@ -171,8 +171,7 @@ extern int affs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
171 | extern unsigned long affs_parent_ino(struct inode *dir); | 171 | extern unsigned long affs_parent_ino(struct inode *dir); |
172 | extern struct inode *affs_new_inode(struct inode *dir); | 172 | extern struct inode *affs_new_inode(struct inode *dir); |
173 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); | 173 | extern int affs_notify_change(struct dentry *dentry, struct iattr *attr); |
174 | extern void affs_delete_inode(struct inode *inode); | 174 | extern void affs_evict_inode(struct inode *inode); |
175 | extern void affs_clear_inode(struct inode *inode); | ||
176 | extern struct inode *affs_iget(struct super_block *sb, | 175 | extern struct inode *affs_iget(struct super_block *sb, |
177 | unsigned long ino); | 176 | unsigned long ino); |
178 | extern int affs_write_inode(struct inode *inode, | 177 | extern int affs_write_inode(struct inode *inode, |
diff --git a/fs/affs/file.c b/fs/affs/file.c index 322710c3eedf..c4a9875bd1a6 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -406,10 +406,19 @@ static int affs_write_begin(struct file *file, struct address_space *mapping, | |||
406 | loff_t pos, unsigned len, unsigned flags, | 406 | loff_t pos, unsigned len, unsigned flags, |
407 | struct page **pagep, void **fsdata) | 407 | struct page **pagep, void **fsdata) |
408 | { | 408 | { |
409 | int ret; | ||
410 | |||
409 | *pagep = NULL; | 411 | *pagep = NULL; |
410 | return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 412 | ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
411 | affs_get_block, | 413 | affs_get_block, |
412 | &AFFS_I(mapping->host)->mmu_private); | 414 | &AFFS_I(mapping->host)->mmu_private); |
415 | if (unlikely(ret)) { | ||
416 | loff_t isize = mapping->host->i_size; | ||
417 | if (pos + len > isize) | ||
418 | vmtruncate(mapping->host, isize); | ||
419 | } | ||
420 | |||
421 | return ret; | ||
413 | } | 422 | } |
414 | 423 | ||
415 | static sector_t _affs_bmap(struct address_space *mapping, sector_t block) | 424 | static sector_t _affs_bmap(struct address_space *mapping, sector_t block) |
diff --git a/fs/affs/inode.c b/fs/affs/inode.c index f4b2a4ee4f91..3a0fdec175ba 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c | |||
@@ -235,31 +235,36 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr) | |||
235 | goto out; | 235 | goto out; |
236 | } | 236 | } |
237 | 237 | ||
238 | error = inode_setattr(inode, attr); | 238 | if ((attr->ia_valid & ATTR_SIZE) && |
239 | if (!error && (attr->ia_valid & ATTR_MODE)) | 239 | attr->ia_size != i_size_read(inode)) { |
240 | error = vmtruncate(inode, attr->ia_size); | ||
241 | if (error) | ||
242 | return error; | ||
243 | } | ||
244 | |||
245 | setattr_copy(inode, attr); | ||
246 | mark_inode_dirty(inode); | ||
247 | |||
248 | if (attr->ia_valid & ATTR_MODE) | ||
240 | mode_to_prot(inode); | 249 | mode_to_prot(inode); |
241 | out: | 250 | out: |
242 | return error; | 251 | return error; |
243 | } | 252 | } |
244 | 253 | ||
245 | void | 254 | void |
246 | affs_delete_inode(struct inode *inode) | 255 | affs_evict_inode(struct inode *inode) |
247 | { | ||
248 | pr_debug("AFFS: delete_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | ||
249 | truncate_inode_pages(&inode->i_data, 0); | ||
250 | inode->i_size = 0; | ||
251 | affs_truncate(inode); | ||
252 | clear_inode(inode); | ||
253 | affs_free_block(inode->i_sb, inode->i_ino); | ||
254 | } | ||
255 | |||
256 | void | ||
257 | affs_clear_inode(struct inode *inode) | ||
258 | { | 256 | { |
259 | unsigned long cache_page; | 257 | unsigned long cache_page; |
258 | pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | ||
259 | truncate_inode_pages(&inode->i_data, 0); | ||
260 | 260 | ||
261 | pr_debug("AFFS: clear_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink); | 261 | if (!inode->i_nlink) { |
262 | inode->i_size = 0; | ||
263 | affs_truncate(inode); | ||
264 | } | ||
262 | 265 | ||
266 | invalidate_inode_buffers(inode); | ||
267 | end_writeback(inode); | ||
263 | affs_free_prealloc(inode); | 268 | affs_free_prealloc(inode); |
264 | cache_page = (unsigned long)AFFS_I(inode)->i_lc; | 269 | cache_page = (unsigned long)AFFS_I(inode)->i_lc; |
265 | if (cache_page) { | 270 | if (cache_page) { |
@@ -271,6 +276,9 @@ affs_clear_inode(struct inode *inode) | |||
271 | affs_brelse(AFFS_I(inode)->i_ext_bh); | 276 | affs_brelse(AFFS_I(inode)->i_ext_bh); |
272 | AFFS_I(inode)->i_ext_last = ~1; | 277 | AFFS_I(inode)->i_ext_last = ~1; |
273 | AFFS_I(inode)->i_ext_bh = NULL; | 278 | AFFS_I(inode)->i_ext_bh = NULL; |
279 | |||
280 | if (!inode->i_nlink) | ||
281 | affs_free_block(inode->i_sb, inode->i_ino); | ||
274 | } | 282 | } |
275 | 283 | ||
276 | struct inode * | 284 | struct inode * |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 16a3e4765f68..33c4e7eef470 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -26,7 +26,7 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); | |||
26 | static int affs_remount (struct super_block *sb, int *flags, char *data); | 26 | static int affs_remount (struct super_block *sb, int *flags, char *data); |
27 | 27 | ||
28 | static void | 28 | static void |
29 | affs_commit_super(struct super_block *sb, int clean) | 29 | affs_commit_super(struct super_block *sb, int wait, int clean) |
30 | { | 30 | { |
31 | struct affs_sb_info *sbi = AFFS_SB(sb); | 31 | struct affs_sb_info *sbi = AFFS_SB(sb); |
32 | struct buffer_head *bh = sbi->s_root_bh; | 32 | struct buffer_head *bh = sbi->s_root_bh; |
@@ -36,6 +36,8 @@ affs_commit_super(struct super_block *sb, int clean) | |||
36 | secs_to_datestamp(get_seconds(), &tail->disk_change); | 36 | secs_to_datestamp(get_seconds(), &tail->disk_change); |
37 | affs_fix_checksum(sb, bh); | 37 | affs_fix_checksum(sb, bh); |
38 | mark_buffer_dirty(bh); | 38 | mark_buffer_dirty(bh); |
39 | if (wait) | ||
40 | sync_dirty_buffer(bh); | ||
39 | } | 41 | } |
40 | 42 | ||
41 | static void | 43 | static void |
@@ -46,8 +48,8 @@ affs_put_super(struct super_block *sb) | |||
46 | 48 | ||
47 | lock_kernel(); | 49 | lock_kernel(); |
48 | 50 | ||
49 | if (!(sb->s_flags & MS_RDONLY)) | 51 | if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt) |
50 | affs_commit_super(sb, 1); | 52 | affs_commit_super(sb, 1, 1); |
51 | 53 | ||
52 | kfree(sbi->s_prefix); | 54 | kfree(sbi->s_prefix); |
53 | affs_free_bitmap(sb); | 55 | affs_free_bitmap(sb); |
@@ -61,27 +63,20 @@ affs_put_super(struct super_block *sb) | |||
61 | static void | 63 | static void |
62 | affs_write_super(struct super_block *sb) | 64 | affs_write_super(struct super_block *sb) |
63 | { | 65 | { |
64 | int clean = 2; | ||
65 | |||
66 | lock_super(sb); | 66 | lock_super(sb); |
67 | if (!(sb->s_flags & MS_RDONLY)) { | 67 | if (!(sb->s_flags & MS_RDONLY)) |
68 | // if (sbi->s_bitmap[i].bm_bh) { | 68 | affs_commit_super(sb, 1, 2); |
69 | // if (buffer_dirty(sbi->s_bitmap[i].bm_bh)) { | 69 | sb->s_dirt = 0; |
70 | // clean = 0; | ||
71 | affs_commit_super(sb, clean); | ||
72 | sb->s_dirt = !clean; /* redo until bitmap synced */ | ||
73 | } else | ||
74 | sb->s_dirt = 0; | ||
75 | unlock_super(sb); | 70 | unlock_super(sb); |
76 | 71 | ||
77 | pr_debug("AFFS: write_super() at %lu, clean=%d\n", get_seconds(), clean); | 72 | pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds()); |
78 | } | 73 | } |
79 | 74 | ||
80 | static int | 75 | static int |
81 | affs_sync_fs(struct super_block *sb, int wait) | 76 | affs_sync_fs(struct super_block *sb, int wait) |
82 | { | 77 | { |
83 | lock_super(sb); | 78 | lock_super(sb); |
84 | affs_commit_super(sb, 2); | 79 | affs_commit_super(sb, wait, 2); |
85 | sb->s_dirt = 0; | 80 | sb->s_dirt = 0; |
86 | unlock_super(sb); | 81 | unlock_super(sb); |
87 | return 0; | 82 | return 0; |
@@ -140,8 +135,7 @@ static const struct super_operations affs_sops = { | |||
140 | .alloc_inode = affs_alloc_inode, | 135 | .alloc_inode = affs_alloc_inode, |
141 | .destroy_inode = affs_destroy_inode, | 136 | .destroy_inode = affs_destroy_inode, |
142 | .write_inode = affs_write_inode, | 137 | .write_inode = affs_write_inode, |
143 | .delete_inode = affs_delete_inode, | 138 | .evict_inode = affs_evict_inode, |
144 | .clear_inode = affs_clear_inode, | ||
145 | .put_super = affs_put_super, | 139 | .put_super = affs_put_super, |
146 | .write_super = affs_write_super, | 140 | .write_super = affs_write_super, |
147 | .sync_fs = affs_sync_fs, | 141 | .sync_fs = affs_sync_fs, |
@@ -554,9 +548,7 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
554 | return 0; | 548 | return 0; |
555 | } | 549 | } |
556 | if (*flags & MS_RDONLY) { | 550 | if (*flags & MS_RDONLY) { |
557 | sb->s_dirt = 1; | 551 | affs_write_super(sb); |
558 | while (sb->s_dirt) | ||
559 | affs_write_super(sb); | ||
560 | affs_free_bitmap(sb); | 552 | affs_free_bitmap(sb); |
561 | } else | 553 | } else |
562 | res = affs_init_bitmap(sb, flags); | 554 | res = affs_init_bitmap(sb, flags); |