aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/ctree.c18
-rw-r--r--fs/btrfs/super.c240
2 files changed, 248 insertions, 10 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 453ce835209a..9ef65e2ecf51 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -16,19 +16,24 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct
16static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, 16static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
17 struct btrfs_path *path, int level, int slot); 17 struct btrfs_path *path, int level, int slot);
18 18
19struct btrfs_path *btrfs_alloc_path(void) 19inline void btrfs_init_path(struct btrfs_path *p)
20{ 20{
21 return kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); 21 memset(p, 0, sizeof(*p));
22} 22}
23 23
24void btrfs_free_path(struct btrfs_path *p) 24struct btrfs_path *btrfs_alloc_path(void)
25{ 25{
26 kmem_cache_free(btrfs_path_cachep, p); 26 struct btrfs_path *path;
27 path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
28 if (path)
29 btrfs_init_path(path);
30 return path;
27} 31}
28 32
29inline void btrfs_init_path(struct btrfs_path *p) 33void btrfs_free_path(struct btrfs_path *p)
30{ 34{
31 memset(p, 0, sizeof(*p)); 35 btrfs_release_path(NULL, p);
36 kmem_cache_free(btrfs_path_cachep, p);
32} 37}
33 38
34void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) 39void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
@@ -77,6 +82,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
77 btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); 82 btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1);
78 } 83 }
79 btrfs_block_release(root, buf); 84 btrfs_block_release(root, buf);
85 mark_buffer_dirty(cow);
80 *cow_ret = cow; 86 *cow_ret = cow;
81 return 0; 87 return 0;
82} 88}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fbc26eafc58c..68127b8462ab 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -816,6 +816,73 @@ printk("btrfs sync_fs\n");
816 return 0; 816 return 0;
817} 817}
818 818
819static int btrfs_get_block_inline(struct inode *inode, sector_t iblock,
820 struct buffer_head *result, int create)
821{
822 struct btrfs_root *root = btrfs_sb(inode->i_sb);
823 struct btrfs_path *path;
824 struct btrfs_key key;
825 struct btrfs_leaf *leaf;
826 int num_bytes = result->b_size;
827 int item_size;
828 int ret;
829 u64 pos;
830 char *ptr;
831 int copy_size;
832 int err = 0;
833 char *safe_ptr;
834 char *data_ptr;
835
836 path = btrfs_alloc_path();
837 BUG_ON(!path);
838
839 WARN_ON(create);
840 if (create) {
841 return 0;
842 }
843 pos = iblock << inode->i_blkbits;
844 key.objectid = inode->i_ino;
845 key.flags = 0;
846 btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY);
847 ptr = kmap(result->b_page);
848 safe_ptr = ptr;
849 ptr += (pos & (PAGE_CACHE_SIZE -1));
850again:
851 key.offset = pos;
852 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
853 if (ret) {
854 if (ret < 0)
855 err = ret;
856 else
857 err = 0;
858 goto out;
859 }
860 leaf = btrfs_buffer_leaf(path->nodes[0]);
861 item_size = btrfs_item_size(leaf->items + path->slots[0]);
862 copy_size = min(num_bytes, item_size);
863 data_ptr = btrfs_item_ptr(leaf, path->slots[0], char);
864 WARN_ON(safe_ptr + PAGE_CACHE_SIZE < ptr + copy_size);
865 memcpy(ptr, data_ptr, copy_size);
866 pos += copy_size;
867 num_bytes -= copy_size;
868 WARN_ON(num_bytes < 0);
869 ptr += copy_size;
870 btrfs_release_path(root, path);
871 if (num_bytes != 0) {
872 if (pos >= i_size_read(inode))
873 memset(ptr, 0, num_bytes);
874 else
875 goto again;
876 }
877 set_buffer_uptodate(result);
878 map_bh(result, inode->i_sb, 0);
879 err = 0;
880out:
881 btrfs_free_path(path);
882 kunmap(result->b_page);
883 return err;
884}
885
819static int btrfs_get_block_lock(struct inode *inode, sector_t iblock, 886static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
820 struct buffer_head *result, int create) 887 struct buffer_head *result, int create)
821{ 888{
@@ -918,7 +985,8 @@ static int btrfs_get_block(struct inode *inode, sector_t iblock,
918 int err; 985 int err;
919 struct btrfs_root *root = btrfs_sb(inode->i_sb); 986 struct btrfs_root *root = btrfs_sb(inode->i_sb);
920 mutex_lock(&root->fs_info->fs_mutex); 987 mutex_lock(&root->fs_info->fs_mutex);
921 err = btrfs_get_block_lock(inode, iblock, result, create); 988 // err = btrfs_get_block_lock(inode, iblock, result, create);
989 err = btrfs_get_block_inline(inode, iblock, result, create);
922 mutex_unlock(&root->fs_info->fs_mutex); 990 mutex_unlock(&root->fs_info->fs_mutex);
923 return err; 991 return err;
924} 992}
@@ -1177,6 +1245,170 @@ out:
1177 return num_written ? num_written : err; 1245 return num_written ? num_written : err;
1178} 1246}
1179 1247
1248static ssize_t inline_one_page(struct btrfs_root *root, struct inode *inode,
1249 struct page *page, loff_t pos,
1250 size_t offset, size_t write_bytes)
1251{
1252 struct btrfs_path *path;
1253 struct btrfs_trans_handle *trans;
1254 struct btrfs_key key;
1255 struct btrfs_leaf *leaf;
1256 struct btrfs_key found_key;
1257 int ret;
1258 size_t copy_size = 0;
1259 char *dst = NULL;
1260 int err = 0;
1261 size_t num_written = 0;
1262
1263 path = btrfs_alloc_path();
1264 BUG_ON(!path);
1265 mutex_lock(&root->fs_info->fs_mutex);
1266 trans = btrfs_start_transaction(root, 1);
1267 key.objectid = inode->i_ino;
1268 key.flags = 0;
1269 btrfs_set_key_type(&key, BTRFS_INLINE_DATA_KEY);
1270
1271again:
1272 key.offset = pos;
1273 ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
1274 if (ret < 0) {
1275 err = ret;
1276 goto out;
1277 }
1278 if (ret == 0) {
1279 leaf = btrfs_buffer_leaf(path->nodes[0]);
1280 btrfs_disk_key_to_cpu(&found_key,
1281 &leaf->items[path->slots[0]].key);
1282 copy_size = btrfs_item_size(leaf->items + path->slots[0]);
1283 dst = btrfs_item_ptr(leaf, path->slots[0], char);
1284 copy_size = min(write_bytes, copy_size);
1285 goto copyit;
1286 } else {
1287 int slot = path->slots[0];
1288 if (slot > 0) {
1289 slot--;
1290 }
1291 // FIXME find max key
1292 leaf = btrfs_buffer_leaf(path->nodes[0]);
1293 btrfs_disk_key_to_cpu(&found_key,
1294 &leaf->items[slot].key);
1295 if (found_key.objectid != inode->i_ino)
1296 goto insert;
1297 if (btrfs_key_type(&found_key) != BTRFS_INLINE_DATA_KEY)
1298 goto insert;
1299 copy_size = btrfs_item_size(leaf->items + slot);
1300 if (found_key.offset + copy_size <= pos)
1301 goto insert;
1302 dst = btrfs_item_ptr(leaf, path->slots[0], char);
1303 dst += pos - found_key.offset;
1304 copy_size = copy_size - (pos - found_key.offset);
1305 BUG_ON(copy_size < 0);
1306 copy_size = min(write_bytes, copy_size);
1307 WARN_ON(copy_size == 0);
1308 goto copyit;
1309 }
1310insert:
1311 btrfs_release_path(root, path);
1312 copy_size = min(write_bytes, (size_t)512);
1313 ret = btrfs_insert_empty_item(trans, root, path, &key, copy_size);
1314 BUG_ON(ret);
1315 dst = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
1316 path->slots[0], char);
1317copyit:
1318 WARN_ON(copy_size == 0);
1319 WARN_ON(dst + copy_size >
1320 btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
1321 path->slots[0], char) +
1322 btrfs_item_size(btrfs_buffer_leaf(path->nodes[0])->items +
1323 path->slots[0]));
1324 btrfs_memcpy(root, path->nodes[0]->b_data, dst,
1325 page_address(page) + offset, copy_size);
1326 mark_buffer_dirty(path->nodes[0]);
1327 btrfs_release_path(root, path);
1328 pos += copy_size;
1329 offset += copy_size;
1330 num_written += copy_size;
1331 write_bytes -= copy_size;
1332 if (write_bytes)
1333 goto again;
1334out:
1335 btrfs_free_path(path);
1336 ret = btrfs_end_transaction(trans, root);
1337 BUG_ON(ret);
1338 mutex_unlock(&root->fs_info->fs_mutex);
1339 return num_written ? num_written : err;
1340}
1341
1342static ssize_t btrfs_file_inline_write(struct file *file,
1343 const char __user *buf,
1344 size_t count, loff_t *ppos)
1345{
1346 loff_t pos;
1347 size_t num_written = 0;
1348 int err = 0;
1349 int ret = 0;
1350 struct inode *inode = file->f_path.dentry->d_inode;
1351 struct btrfs_root *root = btrfs_sb(inode->i_sb);
1352 unsigned long page_index;
1353
1354 if (file->f_flags & O_DIRECT)
1355 return -EINVAL;
1356 pos = *ppos;
1357
1358 vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
1359 current->backing_dev_info = inode->i_mapping->backing_dev_info;
1360 err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
1361 if (err)
1362 goto out;
1363 if (count == 0)
1364 goto out;
1365 err = remove_suid(file->f_path.dentry);
1366 if (err)
1367 goto out;
1368 file_update_time(file);
1369 mutex_lock(&inode->i_mutex);
1370 while(count > 0) {
1371 size_t offset = pos & (PAGE_CACHE_SIZE - 1);
1372 size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset);
1373 struct page *page;
1374
1375 page_index = pos >> PAGE_CACHE_SHIFT;
1376 page = grab_cache_page(inode->i_mapping, page_index);
1377 if (!PageUptodate(page)) {
1378 ret = mpage_readpage(page, btrfs_get_block);
1379 BUG_ON(ret);
1380 lock_page(page);
1381 }
1382 ret = btrfs_copy_from_user(pos, 1,
1383 write_bytes, &page, buf);
1384 BUG_ON(ret);
1385 write_bytes = inline_one_page(root, inode, page, pos,
1386 offset, write_bytes);
1387 SetPageUptodate(page);
1388 if (write_bytes > 0 && pos + write_bytes > inode->i_size) {
1389 i_size_write(inode, pos + write_bytes);
1390 mark_inode_dirty(inode);
1391 }
1392 page_cache_release(page);
1393 unlock_page(page);
1394 if (write_bytes < 0)
1395 goto out_unlock;
1396 buf += write_bytes;
1397 count -= write_bytes;
1398 pos += write_bytes;
1399 num_written += write_bytes;
1400
1401 balance_dirty_pages_ratelimited(inode->i_mapping);
1402 cond_resched();
1403 }
1404out_unlock:
1405 mutex_unlock(&inode->i_mutex);
1406out:
1407 *ppos = pos;
1408 current->backing_dev_info = NULL;
1409 return num_written ? num_written : err;
1410}
1411
1180static int btrfs_read_actor(read_descriptor_t *desc, struct page *page, 1412static int btrfs_read_actor(read_descriptor_t *desc, struct page *page,
1181 unsigned long offset, unsigned long size) 1413 unsigned long offset, unsigned long size)
1182{ 1414{
@@ -1420,7 +1652,7 @@ static struct file_operations btrfs_dir_file_operations = {
1420 1652
1421static struct address_space_operations btrfs_aops = { 1653static struct address_space_operations btrfs_aops = {
1422 .readpage = btrfs_readpage, 1654 .readpage = btrfs_readpage,
1423 .readpages = btrfs_readpages, 1655 // .readpages = btrfs_readpages,
1424 .writepage = btrfs_writepage, 1656 .writepage = btrfs_writepage,
1425 .sync_page = block_sync_page, 1657 .sync_page = block_sync_page,
1426 .prepare_write = btrfs_prepare_write, 1658 .prepare_write = btrfs_prepare_write,
@@ -1434,8 +1666,8 @@ static struct inode_operations btrfs_file_inode_operations = {
1434static struct file_operations btrfs_file_operations = { 1666static struct file_operations btrfs_file_operations = {
1435 .llseek = generic_file_llseek, 1667 .llseek = generic_file_llseek,
1436 .read = do_sync_read, 1668 .read = do_sync_read,
1437 .aio_read = btrfs_file_aio_read, 1669 .aio_read = generic_file_aio_read,
1438 .write = btrfs_file_write, 1670 .write = btrfs_file_inline_write,
1439 .mmap = generic_file_mmap, 1671 .mmap = generic_file_mmap,
1440 .open = generic_file_open, 1672 .open = generic_file_open,
1441}; 1673};