aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-18 16:15:28 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-18 16:15:28 -0400
commita429e51371eee3c989160c003ee40bc3947c6a76 (patch)
tree863b55de8823be579264260a51407cd90aac103d /fs/btrfs/super.c
parent70b2befd0c8a4064715d8b340270650cc9d15af8 (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.c118
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;
159err: 154err:
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;
1292search_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 }
1401next_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
1413out: 1402out:
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,
1585out_unlock: 1588out_unlock:
1586 mutex_unlock(&inode->i_mutex); 1589 mutex_unlock(&inode->i_mutex);
1587out: 1590out:
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