diff options
Diffstat (limited to 'fs/btrfs/file.c')
| -rw-r--r-- | fs/btrfs/file.c | 78 |
1 files changed, 54 insertions, 24 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 53bf2d764bbc..70dc8ca73e25 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -65,6 +65,21 @@ struct inode_defrag { | |||
| 65 | int cycled; | 65 | int cycled; |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | static int __compare_inode_defrag(struct inode_defrag *defrag1, | ||
| 69 | struct inode_defrag *defrag2) | ||
| 70 | { | ||
| 71 | if (defrag1->root > defrag2->root) | ||
| 72 | return 1; | ||
| 73 | else if (defrag1->root < defrag2->root) | ||
| 74 | return -1; | ||
| 75 | else if (defrag1->ino > defrag2->ino) | ||
| 76 | return 1; | ||
| 77 | else if (defrag1->ino < defrag2->ino) | ||
| 78 | return -1; | ||
| 79 | else | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 68 | /* pop a record for an inode into the defrag tree. The lock | 83 | /* pop a record for an inode into the defrag tree. The lock |
| 69 | * must be held already | 84 | * must be held already |
| 70 | * | 85 | * |
| @@ -81,15 +96,17 @@ static void __btrfs_add_inode_defrag(struct inode *inode, | |||
| 81 | struct inode_defrag *entry; | 96 | struct inode_defrag *entry; |
| 82 | struct rb_node **p; | 97 | struct rb_node **p; |
| 83 | struct rb_node *parent = NULL; | 98 | struct rb_node *parent = NULL; |
| 99 | int ret; | ||
| 84 | 100 | ||
| 85 | p = &root->fs_info->defrag_inodes.rb_node; | 101 | p = &root->fs_info->defrag_inodes.rb_node; |
| 86 | while (*p) { | 102 | while (*p) { |
| 87 | parent = *p; | 103 | parent = *p; |
| 88 | entry = rb_entry(parent, struct inode_defrag, rb_node); | 104 | entry = rb_entry(parent, struct inode_defrag, rb_node); |
| 89 | 105 | ||
| 90 | if (defrag->ino < entry->ino) | 106 | ret = __compare_inode_defrag(defrag, entry); |
| 107 | if (ret < 0) | ||
| 91 | p = &parent->rb_left; | 108 | p = &parent->rb_left; |
| 92 | else if (defrag->ino > entry->ino) | 109 | else if (ret > 0) |
| 93 | p = &parent->rb_right; | 110 | p = &parent->rb_right; |
| 94 | else { | 111 | else { |
| 95 | /* if we're reinserting an entry for | 112 | /* if we're reinserting an entry for |
| @@ -103,7 +120,7 @@ static void __btrfs_add_inode_defrag(struct inode *inode, | |||
| 103 | goto exists; | 120 | goto exists; |
| 104 | } | 121 | } |
| 105 | } | 122 | } |
| 106 | BTRFS_I(inode)->in_defrag = 1; | 123 | set_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); |
| 107 | rb_link_node(&defrag->rb_node, parent, p); | 124 | rb_link_node(&defrag->rb_node, parent, p); |
| 108 | rb_insert_color(&defrag->rb_node, &root->fs_info->defrag_inodes); | 125 | rb_insert_color(&defrag->rb_node, &root->fs_info->defrag_inodes); |
| 109 | return; | 126 | return; |
| @@ -131,7 +148,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | |||
| 131 | if (btrfs_fs_closing(root->fs_info)) | 148 | if (btrfs_fs_closing(root->fs_info)) |
| 132 | return 0; | 149 | return 0; |
| 133 | 150 | ||
| 134 | if (BTRFS_I(inode)->in_defrag) | 151 | if (test_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags)) |
| 135 | return 0; | 152 | return 0; |
| 136 | 153 | ||
| 137 | if (trans) | 154 | if (trans) |
| @@ -148,7 +165,7 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | |||
| 148 | defrag->root = root->root_key.objectid; | 165 | defrag->root = root->root_key.objectid; |
| 149 | 166 | ||
| 150 | spin_lock(&root->fs_info->defrag_inodes_lock); | 167 | spin_lock(&root->fs_info->defrag_inodes_lock); |
| 151 | if (!BTRFS_I(inode)->in_defrag) | 168 | if (!test_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags)) |
| 152 | __btrfs_add_inode_defrag(inode, defrag); | 169 | __btrfs_add_inode_defrag(inode, defrag); |
| 153 | else | 170 | else |
| 154 | kfree(defrag); | 171 | kfree(defrag); |
| @@ -159,28 +176,35 @@ int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans, | |||
| 159 | /* | 176 | /* |
| 160 | * must be called with the defrag_inodes lock held | 177 | * must be called with the defrag_inodes lock held |
| 161 | */ | 178 | */ |
| 162 | struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info, u64 ino, | 179 | struct inode_defrag *btrfs_find_defrag_inode(struct btrfs_fs_info *info, |
| 180 | u64 root, u64 ino, | ||
| 163 | struct rb_node **next) | 181 | struct rb_node **next) |
| 164 | { | 182 | { |
| 165 | struct inode_defrag *entry = NULL; | 183 | struct inode_defrag *entry = NULL; |
| 184 | struct inode_defrag tmp; | ||
| 166 | struct rb_node *p; | 185 | struct rb_node *p; |
| 167 | struct rb_node *parent = NULL; | 186 | struct rb_node *parent = NULL; |
| 187 | int ret; | ||
| 188 | |||
| 189 | tmp.ino = ino; | ||
| 190 | tmp.root = root; | ||
| 168 | 191 | ||
| 169 | p = info->defrag_inodes.rb_node; | 192 | p = info->defrag_inodes.rb_node; |
| 170 | while (p) { | 193 | while (p) { |
| 171 | parent = p; | 194 | parent = p; |
| 172 | entry = rb_entry(parent, struct inode_defrag, rb_node); | 195 | entry = rb_entry(parent, struct inode_defrag, rb_node); |
| 173 | 196 | ||
| 174 | if (ino < entry->ino) | 197 | ret = __compare_inode_defrag(&tmp, entry); |
| 198 | if (ret < 0) | ||
| 175 | p = parent->rb_left; | 199 | p = parent->rb_left; |
| 176 | else if (ino > entry->ino) | 200 | else if (ret > 0) |
| 177 | p = parent->rb_right; | 201 | p = parent->rb_right; |
| 178 | else | 202 | else |
| 179 | return entry; | 203 | return entry; |
| 180 | } | 204 | } |
| 181 | 205 | ||
| 182 | if (next) { | 206 | if (next) { |
| 183 | while (parent && ino > entry->ino) { | 207 | while (parent && __compare_inode_defrag(&tmp, entry) > 0) { |
| 184 | parent = rb_next(parent); | 208 | parent = rb_next(parent); |
| 185 | entry = rb_entry(parent, struct inode_defrag, rb_node); | 209 | entry = rb_entry(parent, struct inode_defrag, rb_node); |
| 186 | } | 210 | } |
| @@ -202,6 +226,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
| 202 | struct btrfs_key key; | 226 | struct btrfs_key key; |
| 203 | struct btrfs_ioctl_defrag_range_args range; | 227 | struct btrfs_ioctl_defrag_range_args range; |
| 204 | u64 first_ino = 0; | 228 | u64 first_ino = 0; |
| 229 | u64 root_objectid = 0; | ||
| 205 | int num_defrag; | 230 | int num_defrag; |
| 206 | int defrag_batch = 1024; | 231 | int defrag_batch = 1024; |
| 207 | 232 | ||
| @@ -214,11 +239,14 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
| 214 | n = NULL; | 239 | n = NULL; |
| 215 | 240 | ||
| 216 | /* find an inode to defrag */ | 241 | /* find an inode to defrag */ |
| 217 | defrag = btrfs_find_defrag_inode(fs_info, first_ino, &n); | 242 | defrag = btrfs_find_defrag_inode(fs_info, root_objectid, |
| 243 | first_ino, &n); | ||
| 218 | if (!defrag) { | 244 | if (!defrag) { |
| 219 | if (n) | 245 | if (n) { |
| 220 | defrag = rb_entry(n, struct inode_defrag, rb_node); | 246 | defrag = rb_entry(n, struct inode_defrag, |
| 221 | else if (first_ino) { | 247 | rb_node); |
| 248 | } else if (root_objectid || first_ino) { | ||
| 249 | root_objectid = 0; | ||
| 222 | first_ino = 0; | 250 | first_ino = 0; |
| 223 | continue; | 251 | continue; |
| 224 | } else { | 252 | } else { |
| @@ -228,6 +256,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
| 228 | 256 | ||
| 229 | /* remove it from the rbtree */ | 257 | /* remove it from the rbtree */ |
| 230 | first_ino = defrag->ino + 1; | 258 | first_ino = defrag->ino + 1; |
| 259 | root_objectid = defrag->root; | ||
| 231 | rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); | 260 | rb_erase(&defrag->rb_node, &fs_info->defrag_inodes); |
| 232 | 261 | ||
| 233 | if (btrfs_fs_closing(fs_info)) | 262 | if (btrfs_fs_closing(fs_info)) |
| @@ -252,7 +281,7 @@ int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info) | |||
| 252 | goto next; | 281 | goto next; |
| 253 | 282 | ||
| 254 | /* do a chunk of defrag */ | 283 | /* do a chunk of defrag */ |
| 255 | BTRFS_I(inode)->in_defrag = 0; | 284 | clear_bit(BTRFS_INODE_IN_DEFRAG, &BTRFS_I(inode)->runtime_flags); |
| 256 | range.start = defrag->last_offset; | 285 | range.start = defrag->last_offset; |
| 257 | num_defrag = btrfs_defrag_file(inode, NULL, &range, defrag->transid, | 286 | num_defrag = btrfs_defrag_file(inode, NULL, &range, defrag->transid, |
| 258 | defrag_batch); | 287 | defrag_batch); |
| @@ -1404,12 +1433,11 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
| 1404 | goto out; | 1433 | goto out; |
| 1405 | } | 1434 | } |
| 1406 | 1435 | ||
| 1407 | err = btrfs_update_time(file); | 1436 | err = file_update_time(file); |
| 1408 | if (err) { | 1437 | if (err) { |
| 1409 | mutex_unlock(&inode->i_mutex); | 1438 | mutex_unlock(&inode->i_mutex); |
| 1410 | goto out; | 1439 | goto out; |
| 1411 | } | 1440 | } |
| 1412 | BTRFS_I(inode)->sequence++; | ||
| 1413 | 1441 | ||
| 1414 | start_pos = round_down(pos, root->sectorsize); | 1442 | start_pos = round_down(pos, root->sectorsize); |
| 1415 | if (start_pos > i_size_read(inode)) { | 1443 | if (start_pos > i_size_read(inode)) { |
| @@ -1466,8 +1494,8 @@ int btrfs_release_file(struct inode *inode, struct file *filp) | |||
| 1466 | * flush down new bytes that may have been written if the | 1494 | * flush down new bytes that may have been written if the |
| 1467 | * application were using truncate to replace a file in place. | 1495 | * application were using truncate to replace a file in place. |
| 1468 | */ | 1496 | */ |
| 1469 | if (BTRFS_I(inode)->ordered_data_close) { | 1497 | if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, |
| 1470 | BTRFS_I(inode)->ordered_data_close = 0; | 1498 | &BTRFS_I(inode)->runtime_flags)) { |
| 1471 | btrfs_add_ordered_operation(NULL, BTRFS_I(inode)->root, inode); | 1499 | btrfs_add_ordered_operation(NULL, BTRFS_I(inode)->root, inode); |
| 1472 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) | 1500 | if (inode->i_size > BTRFS_ORDERED_OPERATIONS_FLUSH_LIMIT) |
| 1473 | filemap_flush(inode->i_mapping); | 1501 | filemap_flush(inode->i_mapping); |
| @@ -1498,14 +1526,15 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 1498 | 1526 | ||
| 1499 | trace_btrfs_sync_file(file, datasync); | 1527 | trace_btrfs_sync_file(file, datasync); |
| 1500 | 1528 | ||
| 1501 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
| 1502 | if (ret) | ||
| 1503 | return ret; | ||
| 1504 | mutex_lock(&inode->i_mutex); | 1529 | mutex_lock(&inode->i_mutex); |
| 1505 | 1530 | ||
| 1506 | /* we wait first, since the writeback may change the inode */ | 1531 | /* |
| 1532 | * we wait first, since the writeback may change the inode, also wait | ||
| 1533 | * ordered range does a filemape_write_and_wait_range which is why we | ||
| 1534 | * don't do it above like other file systems. | ||
| 1535 | */ | ||
| 1507 | root->log_batch++; | 1536 | root->log_batch++; |
| 1508 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 1537 | btrfs_wait_ordered_range(inode, start, end); |
| 1509 | root->log_batch++; | 1538 | root->log_batch++; |
| 1510 | 1539 | ||
| 1511 | /* | 1540 | /* |
| @@ -1523,7 +1552,8 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
| 1523 | * syncing | 1552 | * syncing |
| 1524 | */ | 1553 | */ |
| 1525 | smp_mb(); | 1554 | smp_mb(); |
| 1526 | if (BTRFS_I(inode)->last_trans <= | 1555 | if (btrfs_inode_in_log(inode, root->fs_info->generation) || |
| 1556 | BTRFS_I(inode)->last_trans <= | ||
| 1527 | root->fs_info->last_trans_committed) { | 1557 | root->fs_info->last_trans_committed) { |
| 1528 | BTRFS_I(inode)->last_trans = 0; | 1558 | BTRFS_I(inode)->last_trans = 0; |
| 1529 | mutex_unlock(&inode->i_mutex); | 1559 | mutex_unlock(&inode->i_mutex); |
