diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-16 09:22:45 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-16 09:22:45 -0400 |
commit | 6567e837df07e43bffc08ac40858af8133a007bf (patch) | |
tree | 3bf186544e5cd5d4ef5c755e1e3b8f678f6df198 /fs/btrfs/super.c | |
parent | b4100d64241fed93a3f821ddf59d11ab4443a3ba (diff) |
Btrfs: early work to file_write in big extents
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 75 |
1 files changed, 59 insertions, 16 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8dcf600e39ef..ec689992fdf4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1027,8 +1027,10 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1027 | path = btrfs_alloc_path(); | 1027 | path = btrfs_alloc_path(); |
1028 | BUG_ON(!path); | 1028 | BUG_ON(!path); |
1029 | btrfs_init_path(path); | 1029 | btrfs_init_path(path); |
1030 | if (create) | 1030 | if (create) { |
1031 | trans = btrfs_start_transaction(root, 1); | 1031 | trans = btrfs_start_transaction(root, 1); |
1032 | WARN_ON(1); | ||
1033 | } | ||
1032 | 1034 | ||
1033 | ret = btrfs_lookup_file_extent(trans, root, path, | 1035 | ret = btrfs_lookup_file_extent(trans, root, path, |
1034 | inode->i_ino, | 1036 | inode->i_ino, |
@@ -1055,9 +1057,8 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1055 | /* exact match found, use it, FIXME, deal with extents | 1057 | /* exact match found, use it, FIXME, deal with extents |
1056 | * other than the page size | 1058 | * other than the page size |
1057 | */ | 1059 | */ |
1058 | if (ret == 0) { | 1060 | if (0 && ret == 0) { |
1059 | err = 0; | 1061 | err = 0; |
1060 | BUG_ON(btrfs_file_extent_disk_num_blocks(item) != 1); | ||
1061 | if (create && | 1062 | if (create && |
1062 | btrfs_file_extent_generation(item) != trans->transid) { | 1063 | btrfs_file_extent_generation(item) != trans->transid) { |
1063 | struct btrfs_key ins; | 1064 | struct btrfs_key ins; |
@@ -1072,7 +1073,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, | |||
1072 | blocknr = ins.objectid; | 1073 | blocknr = ins.objectid; |
1073 | 1074 | ||
1074 | } | 1075 | } |
1075 | map_bh(result, inode->i_sb, blocknr); | ||
1076 | btrfs_map_bh_to_logical(root, result, blocknr); | 1076 | btrfs_map_bh_to_logical(root, result, blocknr); |
1077 | goto out; | 1077 | goto out; |
1078 | } | 1078 | } |
@@ -1231,6 +1231,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
1231 | struct file *file, | 1231 | struct file *file, |
1232 | struct page **pages, | 1232 | struct page **pages, |
1233 | size_t num_pages, | 1233 | size_t num_pages, |
1234 | u64 extent_offset, | ||
1234 | loff_t pos, | 1235 | loff_t pos, |
1235 | size_t write_bytes) | 1236 | size_t write_bytes) |
1236 | { | 1237 | { |
@@ -1250,6 +1251,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
1250 | trans = btrfs_start_transaction(root, 1); | 1251 | trans = btrfs_start_transaction(root, 1); |
1251 | btrfs_csum_file_block(trans, root, inode->i_ino, | 1252 | btrfs_csum_file_block(trans, root, inode->i_ino, |
1252 | pages[i]->index << PAGE_CACHE_SHIFT, | 1253 | pages[i]->index << PAGE_CACHE_SHIFT, |
1254 | extent_offset, | ||
1253 | kmap(pages[i]), PAGE_CACHE_SIZE); | 1255 | kmap(pages[i]), PAGE_CACHE_SIZE); |
1254 | kunmap(pages[i]); | 1256 | kunmap(pages[i]); |
1255 | SetPageChecked(pages[i]); | 1257 | SetPageChecked(pages[i]); |
@@ -1279,7 +1281,8 @@ static int prepare_pages(struct btrfs_trans_handle *trans, | |||
1279 | loff_t pos, | 1281 | loff_t pos, |
1280 | unsigned long first_index, | 1282 | unsigned long first_index, |
1281 | unsigned long last_index, | 1283 | unsigned long last_index, |
1282 | size_t write_bytes) | 1284 | size_t write_bytes, |
1285 | u64 alloc_extent_start) | ||
1283 | { | 1286 | { |
1284 | int i; | 1287 | int i; |
1285 | unsigned long index = pos >> PAGE_CACHE_SHIFT; | 1288 | unsigned long index = pos >> PAGE_CACHE_SHIFT; |
@@ -1288,6 +1291,8 @@ static int prepare_pages(struct btrfs_trans_handle *trans, | |||
1288 | int err = 0; | 1291 | int err = 0; |
1289 | int ret; | 1292 | int ret; |
1290 | int this_write; | 1293 | int this_write; |
1294 | struct buffer_head *bh; | ||
1295 | struct buffer_head *head; | ||
1291 | loff_t isize = i_size_read(inode); | 1296 | loff_t isize = i_size_read(inode); |
1292 | 1297 | ||
1293 | memset(pages, 0, num_pages * sizeof(struct page *)); | 1298 | memset(pages, 0, num_pages * sizeof(struct page *)); |
@@ -1307,14 +1312,20 @@ static int prepare_pages(struct btrfs_trans_handle *trans, | |||
1307 | BUG_ON(ret); | 1312 | BUG_ON(ret); |
1308 | lock_page(pages[i]); | 1313 | lock_page(pages[i]); |
1309 | } | 1314 | } |
1310 | ret = nobh_prepare_write(pages[i], offset, | 1315 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, |
1311 | offset + this_write, | 1316 | (1 << BH_Uptodate)); |
1312 | btrfs_get_block); | 1317 | head = page_buffers(pages[i]); |
1318 | bh = head; | ||
1319 | do { | ||
1320 | err = btrfs_map_bh_to_logical(root, bh, | ||
1321 | alloc_extent_start); | ||
1322 | BUG_ON(err); | ||
1323 | if (err) | ||
1324 | goto failed_truncate; | ||
1325 | bh = bh->b_this_page; | ||
1326 | alloc_extent_start++; | ||
1327 | } while (bh != head); | ||
1313 | pos += this_write; | 1328 | pos += this_write; |
1314 | if (ret) { | ||
1315 | err = ret; | ||
1316 | goto failed_truncate; | ||
1317 | } | ||
1318 | WARN_ON(this_write > write_bytes); | 1329 | WARN_ON(this_write > write_bytes); |
1319 | write_bytes -= this_write; | 1330 | write_bytes -= this_write; |
1320 | } | 1331 | } |
@@ -1343,11 +1354,23 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1343 | struct page *pages[1]; | 1354 | struct page *pages[1]; |
1344 | unsigned long first_index; | 1355 | unsigned long first_index; |
1345 | unsigned long last_index; | 1356 | unsigned long last_index; |
1357 | u64 start_pos; | ||
1358 | u64 num_blocks; | ||
1359 | u64 alloc_extent_start; | ||
1360 | u64 orig_extent_start; | ||
1361 | struct btrfs_trans_handle *trans; | ||
1346 | 1362 | ||
1347 | if (file->f_flags & O_DIRECT) | 1363 | if (file->f_flags & O_DIRECT) |
1348 | return -EINVAL; | 1364 | return -EINVAL; |
1349 | pos = *ppos; | 1365 | pos = *ppos; |
1350 | 1366 | ||
1367 | start_pos = pos & ~(root->blocksize - 1); | ||
1368 | /* FIXME */ | ||
1369 | if (start_pos != pos) | ||
1370 | return -EINVAL; | ||
1371 | num_blocks = (count + pos - start_pos + root->blocksize - 1) >> | ||
1372 | inode->i_blkbits; | ||
1373 | |||
1351 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 1374 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
1352 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 1375 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
1353 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 1376 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
@@ -1362,20 +1385,41 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1362 | mutex_lock(&inode->i_mutex); | 1385 | mutex_lock(&inode->i_mutex); |
1363 | first_index = pos >> PAGE_CACHE_SHIFT; | 1386 | first_index = pos >> PAGE_CACHE_SHIFT; |
1364 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; | 1387 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; |
1388 | |||
1389 | mutex_lock(&root->fs_info->fs_mutex); | ||
1390 | trans = btrfs_start_transaction(root, 1); | ||
1391 | if (!trans) { | ||
1392 | err = -ENOMEM; | ||
1393 | goto out_unlock; | ||
1394 | } | ||
1395 | ret = btrfs_alloc_file_extent(trans, root, inode->i_ino, | ||
1396 | start_pos, num_blocks, 1, | ||
1397 | &alloc_extent_start); | ||
1398 | BUG_ON(ret); | ||
1399 | |||
1400 | orig_extent_start = start_pos; | ||
1401 | ret = btrfs_end_transaction(trans, root); | ||
1402 | BUG_ON(ret); | ||
1403 | mutex_unlock(&root->fs_info->fs_mutex); | ||
1404 | |||
1365 | while(count > 0) { | 1405 | while(count > 0) { |
1366 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); | 1406 | size_t offset = pos & (PAGE_CACHE_SIZE - 1); |
1367 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); | 1407 | size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); |
1368 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> | 1408 | size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> |
1369 | PAGE_CACHE_SHIFT; | 1409 | PAGE_CACHE_SHIFT; |
1370 | ret = prepare_pages(NULL, root, file, pages, num_pages, | 1410 | ret = prepare_pages(NULL, root, file, pages, num_pages, |
1371 | pos, first_index, last_index, write_bytes); | 1411 | pos, first_index, last_index, |
1412 | write_bytes, alloc_extent_start); | ||
1372 | BUG_ON(ret); | 1413 | BUG_ON(ret); |
1414 | /* FIXME blocks != pagesize */ | ||
1415 | alloc_extent_start += num_pages; | ||
1373 | ret = btrfs_copy_from_user(pos, num_pages, | 1416 | ret = btrfs_copy_from_user(pos, num_pages, |
1374 | write_bytes, pages, buf); | 1417 | write_bytes, pages, buf); |
1375 | BUG_ON(ret); | 1418 | BUG_ON(ret); |
1376 | 1419 | ||
1377 | ret = dirty_and_release_pages(NULL, root, file, pages, | 1420 | ret = dirty_and_release_pages(NULL, root, file, pages, |
1378 | num_pages, pos, write_bytes); | 1421 | num_pages, orig_extent_start, |
1422 | pos, write_bytes); | ||
1379 | BUG_ON(ret); | 1423 | BUG_ON(ret); |
1380 | btrfs_drop_pages(pages, num_pages); | 1424 | btrfs_drop_pages(pages, num_pages); |
1381 | 1425 | ||
@@ -1387,6 +1431,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1387 | balance_dirty_pages_ratelimited(inode->i_mapping); | 1431 | balance_dirty_pages_ratelimited(inode->i_mapping); |
1388 | cond_resched(); | 1432 | cond_resched(); |
1389 | } | 1433 | } |
1434 | out_unlock: | ||
1390 | mutex_unlock(&inode->i_mutex); | 1435 | mutex_unlock(&inode->i_mutex); |
1391 | out: | 1436 | out: |
1392 | *ppos = pos; | 1437 | *ppos = pos; |
@@ -1806,8 +1851,6 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
1806 | &new_root_item); | 1851 | &new_root_item); |
1807 | BUG_ON(ret); | 1852 | BUG_ON(ret); |
1808 | 1853 | ||
1809 | printk("adding snapshot name %.*s root %Lu %Lu %u\n", namelen, name, key.objectid, key.offset, key.flags); | ||
1810 | |||
1811 | /* | 1854 | /* |
1812 | * insert the directory item | 1855 | * insert the directory item |
1813 | */ | 1856 | */ |