diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-18 16:15:28 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-18 16:15:28 -0400 |
commit | a429e51371eee3c989160c003ee40bc3947c6a76 (patch) | |
tree | 863b55de8823be579264260a51407cd90aac103d /fs/btrfs/super.c | |
parent | 70b2befd0c8a4064715d8b340270650cc9d15af8 (diff) |
Btrfs: working file_write, reorganized key flags
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 118 |
1 files changed, 63 insertions, 55 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index b2a2220d1352..583cd87a62e2 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -150,11 +150,6 @@ static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, | |||
150 | BUG_ON(ret); | 150 | BUG_ON(ret); |
151 | 151 | ||
152 | btrfs_release_path(root, path); | 152 | btrfs_release_path(root, path); |
153 | ret = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | ||
154 | objectid, -1); | ||
155 | BUG_ON(ret); | ||
156 | ret = btrfs_del_item(trans, root, path); | ||
157 | BUG_ON(ret); | ||
158 | dentry->d_inode->i_ctime = dir->i_ctime; | 153 | dentry->d_inode->i_ctime = dir->i_ctime; |
159 | err: | 154 | err: |
160 | btrfs_release_path(root, path); | 155 | btrfs_release_path(root, path); |
@@ -329,8 +324,9 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
329 | extent_start = btrfs_file_extent_disk_blocknr(fi); | 324 | extent_start = btrfs_file_extent_disk_blocknr(fi); |
330 | extent_num_blocks = | 325 | extent_num_blocks = |
331 | btrfs_file_extent_disk_num_blocks(fi); | 326 | btrfs_file_extent_disk_num_blocks(fi); |
327 | /* FIXME blocksize != 4096 */ | ||
332 | inode->i_blocks -= | 328 | inode->i_blocks -= |
333 | btrfs_file_extent_num_blocks(fi) >> 9; | 329 | btrfs_file_extent_num_blocks(fi) << 3; |
334 | found_extent = 1; | 330 | found_extent = 1; |
335 | } else { | 331 | } else { |
336 | found_extent = 0; | 332 | found_extent = 0; |
@@ -562,7 +558,7 @@ static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
562 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) | 558 | if (btrfs_disk_key_objectid(&item->key) != key.objectid) |
563 | break; | 559 | break; |
564 | if (btrfs_disk_key_type(&item->key) != key_type) | 560 | if (btrfs_disk_key_type(&item->key) != key_type) |
565 | continue; | 561 | break; |
566 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) | 562 | if (btrfs_disk_key_offset(&item->key) < filp->f_pos) |
567 | continue; | 563 | continue; |
568 | filp->f_pos = btrfs_disk_key_offset(&item->key); | 564 | filp->f_pos = btrfs_disk_key_offset(&item->key); |
@@ -1285,29 +1281,27 @@ static int drop_extents(struct btrfs_trans_handle *trans, | |||
1285 | struct btrfs_path *path; | 1281 | struct btrfs_path *path; |
1286 | u64 search_start = start; | 1282 | u64 search_start = start; |
1287 | int bookend; | 1283 | int bookend; |
1288 | |||
1289 | path = btrfs_alloc_path(); | 1284 | path = btrfs_alloc_path(); |
1290 | if (!path) | 1285 | if (!path) |
1291 | return -ENOMEM; | 1286 | return -ENOMEM; |
1292 | search_again: | 1287 | while(1) { |
1293 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, | 1288 | btrfs_release_path(root, path); |
1294 | search_start, -1); | 1289 | ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, |
1295 | if (ret < 0) | 1290 | search_start, -1); |
1296 | goto out; | 1291 | if (ret < 0) |
1297 | if (ret > 0) { | ||
1298 | if (path->slots[0] == 0) { | ||
1299 | ret = -ENOENT; | ||
1300 | goto out; | 1292 | goto out; |
1293 | if (ret > 0) { | ||
1294 | if (path->slots[0] == 0) { | ||
1295 | ret = -ENOENT; | ||
1296 | goto out; | ||
1297 | } | ||
1298 | path->slots[0]--; | ||
1301 | } | 1299 | } |
1302 | path->slots[0]--; | ||
1303 | } | ||
1304 | while(1) { | ||
1305 | keep = 0; | 1300 | keep = 0; |
1306 | bookend = 0; | 1301 | bookend = 0; |
1307 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 1302 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
1308 | slot = path->slots[0]; | 1303 | slot = path->slots[0]; |
1309 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 1304 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); |
1310 | |||
1311 | extent = btrfs_item_ptr(leaf, slot, | 1305 | extent = btrfs_item_ptr(leaf, slot, |
1312 | struct btrfs_file_extent_item); | 1306 | struct btrfs_file_extent_item); |
1313 | extent_end = key.offset + | 1307 | extent_end = key.offset + |
@@ -1318,7 +1312,10 @@ search_again: | |||
1318 | goto out; | 1312 | goto out; |
1319 | } | 1313 | } |
1320 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) | 1314 | if (btrfs_key_type(&key) != BTRFS_EXTENT_DATA_KEY) |
1321 | goto next_leaf; | 1315 | goto out; |
1316 | if (search_start >= extent_end) | ||
1317 | goto out; | ||
1318 | search_start = extent_end; | ||
1322 | 1319 | ||
1323 | if (end < extent_end && end >= key.offset) { | 1320 | if (end < extent_end && end >= key.offset) { |
1324 | memcpy(&old, extent, sizeof(old)); | 1321 | memcpy(&old, extent, sizeof(old)); |
@@ -1331,10 +1328,13 @@ search_again: | |||
1331 | 1328 | ||
1332 | if (start > key.offset) { | 1329 | if (start > key.offset) { |
1333 | u64 new_num; | 1330 | u64 new_num; |
1331 | u64 old_num; | ||
1334 | /* truncate existing extent */ | 1332 | /* truncate existing extent */ |
1335 | keep = 1; | 1333 | keep = 1; |
1336 | WARN_ON(start & (root->blocksize - 1)); | 1334 | WARN_ON(start & (root->blocksize - 1)); |
1337 | new_num = (start - key.offset) >> inode->i_blkbits; | 1335 | new_num = (start - key.offset) >> inode->i_blkbits; |
1336 | old_num = btrfs_file_extent_num_blocks(extent); | ||
1337 | inode->i_blocks -= (old_num - new_num) << 3; | ||
1338 | btrfs_set_file_extent_num_blocks(extent, new_num); | 1338 | btrfs_set_file_extent_num_blocks(extent, new_num); |
1339 | mark_buffer_dirty(path->nodes[0]); | 1339 | mark_buffer_dirty(path->nodes[0]); |
1340 | } | 1340 | } |
@@ -1344,13 +1344,11 @@ search_again: | |||
1344 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); | 1344 | disk_blocknr = btrfs_file_extent_disk_blocknr(extent); |
1345 | disk_num_blocks = | 1345 | disk_num_blocks = |
1346 | btrfs_file_extent_disk_num_blocks(extent); | 1346 | btrfs_file_extent_disk_num_blocks(extent); |
1347 | search_start = key.offset + | ||
1348 | (btrfs_file_extent_num_blocks(extent) << | ||
1349 | inode->i_blkbits); | ||
1350 | ret = btrfs_del_item(trans, root, path); | 1347 | ret = btrfs_del_item(trans, root, path); |
1351 | BUG_ON(ret); | 1348 | BUG_ON(ret); |
1349 | inode->i_blocks -= | ||
1350 | btrfs_file_extent_num_blocks(extent) << 3; | ||
1352 | btrfs_release_path(root, path); | 1351 | btrfs_release_path(root, path); |
1353 | |||
1354 | ret = btrfs_free_extent(trans, root, disk_blocknr, | 1352 | ret = btrfs_free_extent(trans, root, disk_blocknr, |
1355 | disk_num_blocks, 0); | 1353 | disk_num_blocks, 0); |
1356 | 1354 | ||
@@ -1360,7 +1358,7 @@ search_again: | |||
1360 | goto out; | 1358 | goto out; |
1361 | } | 1359 | } |
1362 | if (!bookend) | 1360 | if (!bookend) |
1363 | goto search_again; | 1361 | continue; |
1364 | } | 1362 | } |
1365 | if (bookend) { | 1363 | if (bookend) { |
1366 | /* create bookend */ | 1364 | /* create bookend */ |
@@ -1395,21 +1393,12 @@ search_again: | |||
1395 | btrfs_set_file_extent_generation(extent, | 1393 | btrfs_set_file_extent_generation(extent, |
1396 | btrfs_file_extent_generation(&old)); | 1394 | btrfs_file_extent_generation(&old)); |
1397 | btrfs_mark_buffer_dirty(path->nodes[0]); | 1395 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1396 | inode->i_blocks += | ||
1397 | btrfs_file_extent_num_blocks(extent) << 3; | ||
1398 | ret = 0; | 1398 | ret = 0; |
1399 | goto out; | 1399 | goto out; |
1400 | } | 1400 | } |
1401 | next_leaf: | ||
1402 | if (slot >= btrfs_header_nritems(&leaf->header) - 1) { | ||
1403 | ret = btrfs_next_leaf(root, path); | ||
1404 | if (ret) { | ||
1405 | ret = 0; | ||
1406 | goto out; | ||
1407 | } | ||
1408 | } else { | ||
1409 | path->slots[0]++; | ||
1410 | } | ||
1411 | } | 1401 | } |
1412 | |||
1413 | out: | 1402 | out: |
1414 | btrfs_free_path(path); | 1403 | btrfs_free_path(path); |
1415 | return ret; | 1404 | return ret; |
@@ -1445,15 +1434,6 @@ static int prepare_pages(struct btrfs_root *root, | |||
1445 | } | 1434 | } |
1446 | offset = pos & (PAGE_CACHE_SIZE -1); | 1435 | offset = pos & (PAGE_CACHE_SIZE -1); |
1447 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); | 1436 | this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); |
1448 | #if 0 | ||
1449 | if ((pages[i]->index == first_index || | ||
1450 | pages[i]->index == last_index) && pos < isize && | ||
1451 | !PageUptodate(pages[i])) { | ||
1452 | ret = mpage_readpage(pages[i], btrfs_get_block); | ||
1453 | BUG_ON(ret); | ||
1454 | lock_page(pages[i]); | ||
1455 | } | ||
1456 | #endif | ||
1457 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, | 1437 | create_empty_buffers(pages[i], root->fs_info->sb->s_blocksize, |
1458 | (1 << BH_Uptodate)); | 1438 | (1 << BH_Uptodate)); |
1459 | head = page_buffers(pages[i]); | 1439 | head = page_buffers(pages[i]); |
@@ -1494,6 +1474,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1494 | struct inode *inode = file->f_path.dentry->d_inode; | 1474 | struct inode *inode = file->f_path.dentry->d_inode; |
1495 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1475 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1496 | struct page *pages[8]; | 1476 | struct page *pages[8]; |
1477 | struct page *pinned[2] = { NULL, NULL }; | ||
1497 | unsigned long first_index; | 1478 | unsigned long first_index; |
1498 | unsigned long last_index; | 1479 | unsigned long last_index; |
1499 | u64 start_pos; | 1480 | u64 start_pos; |
@@ -1505,14 +1486,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1505 | if (file->f_flags & O_DIRECT) | 1486 | if (file->f_flags & O_DIRECT) |
1506 | return -EINVAL; | 1487 | return -EINVAL; |
1507 | pos = *ppos; | 1488 | pos = *ppos; |
1508 | |||
1509 | start_pos = pos & ~(root->blocksize - 1); | ||
1510 | /* FIXME */ | ||
1511 | if (start_pos != pos) | ||
1512 | return -EINVAL; | ||
1513 | num_blocks = (count + pos - start_pos + root->blocksize - 1) >> | ||
1514 | inode->i_blkbits; | ||
1515 | |||
1516 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); | 1489 | vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
1517 | current->backing_dev_info = inode->i_mapping->backing_dev_info; | 1490 | current->backing_dev_info = inode->i_mapping->backing_dev_info; |
1518 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); | 1491 | err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode)); |
@@ -1524,10 +1497,37 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1524 | if (err) | 1497 | if (err) |
1525 | goto out; | 1498 | goto out; |
1526 | file_update_time(file); | 1499 | file_update_time(file); |
1500 | |||
1501 | start_pos = pos & ~((u64)PAGE_CACHE_SIZE - 1); | ||
1502 | num_blocks = (count + pos - start_pos + root->blocksize - 1) >> | ||
1503 | inode->i_blkbits; | ||
1504 | |||
1527 | mutex_lock(&inode->i_mutex); | 1505 | mutex_lock(&inode->i_mutex); |
1528 | first_index = pos >> PAGE_CACHE_SHIFT; | 1506 | first_index = pos >> PAGE_CACHE_SHIFT; |
1529 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; | 1507 | last_index = (pos + count) >> PAGE_CACHE_SHIFT; |
1530 | 1508 | ||
1509 | if ((first_index << PAGE_CACHE_SHIFT) < inode->i_size && | ||
1510 | (pos & (PAGE_CACHE_SIZE - 1))) { | ||
1511 | pinned[0] = grab_cache_page(inode->i_mapping, first_index); | ||
1512 | if (!PageUptodate(pinned[0])) { | ||
1513 | ret = mpage_readpage(pinned[0], btrfs_get_block); | ||
1514 | BUG_ON(ret); | ||
1515 | } else { | ||
1516 | unlock_page(pinned[0]); | ||
1517 | } | ||
1518 | } | ||
1519 | if (first_index != last_index && | ||
1520 | (last_index << PAGE_CACHE_SHIFT) < inode->i_size && | ||
1521 | (count & (PAGE_CACHE_SIZE - 1))) { | ||
1522 | pinned[1] = grab_cache_page(inode->i_mapping, last_index); | ||
1523 | if (!PageUptodate(pinned[1])) { | ||
1524 | ret = mpage_readpage(pinned[1], btrfs_get_block); | ||
1525 | BUG_ON(ret); | ||
1526 | } else { | ||
1527 | unlock_page(pinned[1]); | ||
1528 | } | ||
1529 | } | ||
1530 | |||
1531 | mutex_lock(&root->fs_info->fs_mutex); | 1531 | mutex_lock(&root->fs_info->fs_mutex); |
1532 | trans = btrfs_start_transaction(root, 1); | 1532 | trans = btrfs_start_transaction(root, 1); |
1533 | if (!trans) { | 1533 | if (!trans) { |
@@ -1535,11 +1535,14 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1535 | mutex_unlock(&root->fs_info->fs_mutex); | 1535 | mutex_unlock(&root->fs_info->fs_mutex); |
1536 | goto out_unlock; | 1536 | goto out_unlock; |
1537 | } | 1537 | } |
1538 | /* FIXME blocksize != 4096 */ | ||
1539 | inode->i_blocks += num_blocks << 3; | ||
1538 | if (start_pos < inode->i_size) { | 1540 | if (start_pos < inode->i_size) { |
1541 | /* FIXME blocksize != pagesize */ | ||
1539 | ret = drop_extents(trans, root, inode, | 1542 | ret = drop_extents(trans, root, inode, |
1540 | start_pos, | 1543 | start_pos, |
1541 | (pos + count + root->blocksize -1) & | 1544 | (pos + count + root->blocksize -1) & |
1542 | ~(root->blocksize - 1)); | 1545 | ~((u64)root->blocksize - 1)); |
1543 | } | 1546 | } |
1544 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, | 1547 | ret = btrfs_alloc_extent(trans, root, num_blocks, 1, |
1545 | (u64)-1, &ins); | 1548 | (u64)-1, &ins); |
@@ -1585,8 +1588,13 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1585 | out_unlock: | 1588 | out_unlock: |
1586 | mutex_unlock(&inode->i_mutex); | 1589 | mutex_unlock(&inode->i_mutex); |
1587 | out: | 1590 | out: |
1591 | if (pinned[0]) | ||
1592 | page_cache_release(pinned[0]); | ||
1593 | if (pinned[1]) | ||
1594 | page_cache_release(pinned[1]); | ||
1588 | *ppos = pos; | 1595 | *ppos = pos; |
1589 | current->backing_dev_info = NULL; | 1596 | current->backing_dev_info = NULL; |
1597 | mark_inode_dirty(inode); | ||
1590 | return num_written ? num_written : err; | 1598 | return num_written ? num_written : err; |
1591 | } | 1599 | } |
1592 | 1600 | ||