diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
-rw-r--r-- | fs/ext4/ialloc.c | 2 | ||||
-rw-r--r-- | fs/ext4/inode.c | 53 | ||||
-rw-r--r-- | fs/ext4/super.c | 10 | ||||
-rw-r--r-- | fs/ext4/xattr.c | 12 |
5 files changed, 49 insertions, 31 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e03841d9f30b..889ec9d5e6ad 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1643,7 +1643,8 @@ extern int ext4_write_inode(struct inode *, struct writeback_control *); | |||
1643 | extern int ext4_setattr(struct dentry *, struct iattr *); | 1643 | extern int ext4_setattr(struct dentry *, struct iattr *); |
1644 | extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, | 1644 | extern int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, |
1645 | struct kstat *stat); | 1645 | struct kstat *stat); |
1646 | extern void ext4_delete_inode(struct inode *); | 1646 | extern void ext4_evict_inode(struct inode *); |
1647 | extern void ext4_clear_inode(struct inode *); | ||
1647 | extern int ext4_sync_inode(handle_t *, struct inode *); | 1648 | extern int ext4_sync_inode(handle_t *, struct inode *); |
1648 | extern void ext4_dirty_inode(struct inode *); | 1649 | extern void ext4_dirty_inode(struct inode *); |
1649 | extern int ext4_change_inode_journal_flag(struct inode *, int); | 1650 | extern int ext4_change_inode_journal_flag(struct inode *, int); |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index ac377505ed57..45853e0d1f21 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -222,7 +222,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) | |||
222 | is_directory = S_ISDIR(inode->i_mode); | 222 | is_directory = S_ISDIR(inode->i_mode); |
223 | 223 | ||
224 | /* Do this BEFORE marking the inode not in use or returning an error */ | 224 | /* Do this BEFORE marking the inode not in use or returning an error */ |
225 | clear_inode(inode); | 225 | ext4_clear_inode(inode); |
226 | 226 | ||
227 | es = EXT4_SB(sb)->s_es; | 227 | es = EXT4_SB(sb)->s_es; |
228 | if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { | 228 | if (ino < EXT4_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) { |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a0ab3754d0d6..4b8debeb3965 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -167,11 +167,16 @@ int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, | |||
167 | /* | 167 | /* |
168 | * Called at the last iput() if i_nlink is zero. | 168 | * Called at the last iput() if i_nlink is zero. |
169 | */ | 169 | */ |
170 | void ext4_delete_inode(struct inode *inode) | 170 | void ext4_evict_inode(struct inode *inode) |
171 | { | 171 | { |
172 | handle_t *handle; | 172 | handle_t *handle; |
173 | int err; | 173 | int err; |
174 | 174 | ||
175 | if (inode->i_nlink) { | ||
176 | truncate_inode_pages(&inode->i_data, 0); | ||
177 | goto no_delete; | ||
178 | } | ||
179 | |||
175 | if (!is_bad_inode(inode)) | 180 | if (!is_bad_inode(inode)) |
176 | dquot_initialize(inode); | 181 | dquot_initialize(inode); |
177 | 182 | ||
@@ -246,13 +251,13 @@ void ext4_delete_inode(struct inode *inode) | |||
246 | */ | 251 | */ |
247 | if (ext4_mark_inode_dirty(handle, inode)) | 252 | if (ext4_mark_inode_dirty(handle, inode)) |
248 | /* If that failed, just do the required in-core inode clear. */ | 253 | /* If that failed, just do the required in-core inode clear. */ |
249 | clear_inode(inode); | 254 | ext4_clear_inode(inode); |
250 | else | 255 | else |
251 | ext4_free_inode(handle, inode); | 256 | ext4_free_inode(handle, inode); |
252 | ext4_journal_stop(handle); | 257 | ext4_journal_stop(handle); |
253 | return; | 258 | return; |
254 | no_delete: | 259 | no_delete: |
255 | clear_inode(inode); /* We must guarantee clearing of inode... */ | 260 | ext4_clear_inode(inode); /* We must guarantee clearing of inode... */ |
256 | } | 261 | } |
257 | 262 | ||
258 | typedef struct { | 263 | typedef struct { |
@@ -1602,11 +1607,9 @@ retry: | |||
1602 | *pagep = page; | 1607 | *pagep = page; |
1603 | 1608 | ||
1604 | if (ext4_should_dioread_nolock(inode)) | 1609 | if (ext4_should_dioread_nolock(inode)) |
1605 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, | 1610 | ret = __block_write_begin(page, pos, len, ext4_get_block_write); |
1606 | fsdata, ext4_get_block_write); | ||
1607 | else | 1611 | else |
1608 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, | 1612 | ret = __block_write_begin(page, pos, len, ext4_get_block); |
1609 | fsdata, ext4_get_block); | ||
1610 | 1613 | ||
1611 | if (!ret && ext4_should_journal_data(inode)) { | 1614 | if (!ret && ext4_should_journal_data(inode)) { |
1612 | ret = walk_page_buffers(handle, page_buffers(page), | 1615 | ret = walk_page_buffers(handle, page_buffers(page), |
@@ -1617,7 +1620,7 @@ retry: | |||
1617 | unlock_page(page); | 1620 | unlock_page(page); |
1618 | page_cache_release(page); | 1621 | page_cache_release(page); |
1619 | /* | 1622 | /* |
1620 | * block_write_begin may have instantiated a few blocks | 1623 | * __block_write_begin may have instantiated a few blocks |
1621 | * outside i_size. Trim these off again. Don't need | 1624 | * outside i_size. Trim these off again. Don't need |
1622 | * i_size_read because we hold i_mutex. | 1625 | * i_size_read because we hold i_mutex. |
1623 | * | 1626 | * |
@@ -3205,8 +3208,7 @@ retry: | |||
3205 | } | 3208 | } |
3206 | *pagep = page; | 3209 | *pagep = page; |
3207 | 3210 | ||
3208 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 3211 | ret = __block_write_begin(page, pos, len, ext4_da_get_block_prep); |
3209 | ext4_da_get_block_prep); | ||
3210 | if (ret < 0) { | 3212 | if (ret < 0) { |
3211 | unlock_page(page); | 3213 | unlock_page(page); |
3212 | ext4_journal_stop(handle); | 3214 | ext4_journal_stop(handle); |
@@ -3565,15 +3567,24 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb, | |||
3565 | 3567 | ||
3566 | retry: | 3568 | retry: |
3567 | if (rw == READ && ext4_should_dioread_nolock(inode)) | 3569 | if (rw == READ && ext4_should_dioread_nolock(inode)) |
3568 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, | 3570 | ret = __blockdev_direct_IO(rw, iocb, inode, |
3569 | inode->i_sb->s_bdev, iov, | 3571 | inode->i_sb->s_bdev, iov, |
3570 | offset, nr_segs, | 3572 | offset, nr_segs, |
3571 | ext4_get_block, NULL); | 3573 | ext4_get_block, NULL, NULL, 0); |
3572 | else | 3574 | else { |
3573 | ret = blockdev_direct_IO(rw, iocb, inode, | 3575 | ret = blockdev_direct_IO(rw, iocb, inode, |
3574 | inode->i_sb->s_bdev, iov, | 3576 | inode->i_sb->s_bdev, iov, |
3575 | offset, nr_segs, | 3577 | offset, nr_segs, |
3576 | ext4_get_block, NULL); | 3578 | ext4_get_block, NULL); |
3579 | |||
3580 | if (unlikely((rw & WRITE) && ret < 0)) { | ||
3581 | loff_t isize = i_size_read(inode); | ||
3582 | loff_t end = offset + iov_length(iov, nr_segs); | ||
3583 | |||
3584 | if (end > isize) | ||
3585 | vmtruncate(inode, isize); | ||
3586 | } | ||
3587 | } | ||
3577 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 3588 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
3578 | goto retry; | 3589 | goto retry; |
3579 | 3590 | ||
@@ -5536,11 +5547,19 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5536 | ext4_truncate(inode); | 5547 | ext4_truncate(inode); |
5537 | } | 5548 | } |
5538 | 5549 | ||
5539 | rc = inode_setattr(inode, attr); | 5550 | if ((attr->ia_valid & ATTR_SIZE) && |
5551 | attr->ia_size != i_size_read(inode)) | ||
5552 | rc = vmtruncate(inode, attr->ia_size); | ||
5540 | 5553 | ||
5541 | /* If inode_setattr's call to ext4_truncate failed to get a | 5554 | if (!rc) { |
5542 | * transaction handle at all, we need to clean up the in-core | 5555 | setattr_copy(inode, attr); |
5543 | * orphan list manually. */ | 5556 | mark_inode_dirty(inode); |
5557 | } | ||
5558 | |||
5559 | /* | ||
5560 | * If the call to ext4_truncate failed to get a transaction handle at | ||
5561 | * all, we need to clean up the in-core orphan list manually. | ||
5562 | */ | ||
5544 | if (inode->i_nlink) | 5563 | if (inode->i_nlink) |
5545 | ext4_orphan_del(NULL, inode); | 5564 | ext4_orphan_del(NULL, inode); |
5546 | 5565 | ||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8d65575f8c8c..26147746c272 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -868,8 +868,10 @@ static void destroy_inodecache(void) | |||
868 | kmem_cache_destroy(ext4_inode_cachep); | 868 | kmem_cache_destroy(ext4_inode_cachep); |
869 | } | 869 | } |
870 | 870 | ||
871 | static void ext4_clear_inode(struct inode *inode) | 871 | void ext4_clear_inode(struct inode *inode) |
872 | { | 872 | { |
873 | invalidate_inode_buffers(inode); | ||
874 | end_writeback(inode); | ||
873 | dquot_drop(inode); | 875 | dquot_drop(inode); |
874 | ext4_discard_preallocations(inode); | 876 | ext4_discard_preallocations(inode); |
875 | if (EXT4_JOURNAL(inode)) | 877 | if (EXT4_JOURNAL(inode)) |
@@ -1158,14 +1160,13 @@ static const struct super_operations ext4_sops = { | |||
1158 | .destroy_inode = ext4_destroy_inode, | 1160 | .destroy_inode = ext4_destroy_inode, |
1159 | .write_inode = ext4_write_inode, | 1161 | .write_inode = ext4_write_inode, |
1160 | .dirty_inode = ext4_dirty_inode, | 1162 | .dirty_inode = ext4_dirty_inode, |
1161 | .delete_inode = ext4_delete_inode, | 1163 | .evict_inode = ext4_evict_inode, |
1162 | .put_super = ext4_put_super, | 1164 | .put_super = ext4_put_super, |
1163 | .sync_fs = ext4_sync_fs, | 1165 | .sync_fs = ext4_sync_fs, |
1164 | .freeze_fs = ext4_freeze, | 1166 | .freeze_fs = ext4_freeze, |
1165 | .unfreeze_fs = ext4_unfreeze, | 1167 | .unfreeze_fs = ext4_unfreeze, |
1166 | .statfs = ext4_statfs, | 1168 | .statfs = ext4_statfs, |
1167 | .remount_fs = ext4_remount, | 1169 | .remount_fs = ext4_remount, |
1168 | .clear_inode = ext4_clear_inode, | ||
1169 | .show_options = ext4_show_options, | 1170 | .show_options = ext4_show_options, |
1170 | #ifdef CONFIG_QUOTA | 1171 | #ifdef CONFIG_QUOTA |
1171 | .quota_read = ext4_quota_read, | 1172 | .quota_read = ext4_quota_read, |
@@ -1179,12 +1180,11 @@ static const struct super_operations ext4_nojournal_sops = { | |||
1179 | .destroy_inode = ext4_destroy_inode, | 1180 | .destroy_inode = ext4_destroy_inode, |
1180 | .write_inode = ext4_write_inode, | 1181 | .write_inode = ext4_write_inode, |
1181 | .dirty_inode = ext4_dirty_inode, | 1182 | .dirty_inode = ext4_dirty_inode, |
1182 | .delete_inode = ext4_delete_inode, | 1183 | .evict_inode = ext4_evict_inode, |
1183 | .write_super = ext4_write_super, | 1184 | .write_super = ext4_write_super, |
1184 | .put_super = ext4_put_super, | 1185 | .put_super = ext4_put_super, |
1185 | .statfs = ext4_statfs, | 1186 | .statfs = ext4_statfs, |
1186 | .remount_fs = ext4_remount, | 1187 | .remount_fs = ext4_remount, |
1187 | .clear_inode = ext4_clear_inode, | ||
1188 | .show_options = ext4_show_options, | 1188 | .show_options = ext4_show_options, |
1189 | #ifdef CONFIG_QUOTA | 1189 | #ifdef CONFIG_QUOTA |
1190 | .quota_read = ext4_quota_read, | 1190 | .quota_read = ext4_quota_read, |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index a6f314249574..3a8cd8dff1ad 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -1417,7 +1417,7 @@ ext4_xattr_cache_insert(struct buffer_head *bh) | |||
1417 | ea_bdebug(bh, "out of memory"); | 1417 | ea_bdebug(bh, "out of memory"); |
1418 | return; | 1418 | return; |
1419 | } | 1419 | } |
1420 | error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, &hash); | 1420 | error = mb_cache_entry_insert(ce, bh->b_bdev, bh->b_blocknr, hash); |
1421 | if (error) { | 1421 | if (error) { |
1422 | mb_cache_entry_free(ce); | 1422 | mb_cache_entry_free(ce); |
1423 | if (error == -EBUSY) { | 1423 | if (error == -EBUSY) { |
@@ -1489,8 +1489,8 @@ ext4_xattr_cache_find(struct inode *inode, struct ext4_xattr_header *header, | |||
1489 | return NULL; /* never share */ | 1489 | return NULL; /* never share */ |
1490 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); | 1490 | ea_idebug(inode, "looking for cached blocks [%x]", (int)hash); |
1491 | again: | 1491 | again: |
1492 | ce = mb_cache_entry_find_first(ext4_xattr_cache, 0, | 1492 | ce = mb_cache_entry_find_first(ext4_xattr_cache, inode->i_sb->s_bdev, |
1493 | inode->i_sb->s_bdev, hash); | 1493 | hash); |
1494 | while (ce) { | 1494 | while (ce) { |
1495 | struct buffer_head *bh; | 1495 | struct buffer_head *bh; |
1496 | 1496 | ||
@@ -1514,7 +1514,7 @@ again: | |||
1514 | return bh; | 1514 | return bh; |
1515 | } | 1515 | } |
1516 | brelse(bh); | 1516 | brelse(bh); |
1517 | ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash); | 1517 | ce = mb_cache_entry_find_next(ce, inode->i_sb->s_bdev, hash); |
1518 | } | 1518 | } |
1519 | return NULL; | 1519 | return NULL; |
1520 | } | 1520 | } |
@@ -1590,9 +1590,7 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *header, | |||
1590 | int __init | 1590 | int __init |
1591 | init_ext4_xattr(void) | 1591 | init_ext4_xattr(void) |
1592 | { | 1592 | { |
1593 | ext4_xattr_cache = mb_cache_create("ext4_xattr", NULL, | 1593 | ext4_xattr_cache = mb_cache_create("ext4_xattr", 6); |
1594 | sizeof(struct mb_cache_entry) + | ||
1595 | sizeof(((struct mb_cache_entry *) 0)->e_indexes[0]), 1, 6); | ||
1596 | if (!ext4_xattr_cache) | 1594 | if (!ext4_xattr_cache) |
1597 | return -ENOMEM; | 1595 | return -ENOMEM; |
1598 | return 0; | 1596 | return 0; |