diff options
-rw-r--r-- | fs/ext2/dir.c | 55 | ||||
-rw-r--r-- | fs/ext2/ext2.h | 3 | ||||
-rw-r--r-- | fs/ext2/inode.c | 24 |
3 files changed, 53 insertions, 29 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 2bf49d7ef841..05d9342bb64e 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -22,7 +22,9 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include "ext2.h" | 24 | #include "ext2.h" |
25 | #include <linux/buffer_head.h> | ||
25 | #include <linux/pagemap.h> | 26 | #include <linux/pagemap.h> |
27 | #include <linux/swap.h> | ||
26 | 28 | ||
27 | typedef struct ext2_dir_entry_2 ext2_dirent; | 29 | typedef struct ext2_dir_entry_2 ext2_dirent; |
28 | 30 | ||
@@ -61,16 +63,25 @@ ext2_last_byte(struct inode *inode, unsigned long page_nr) | |||
61 | return last_byte; | 63 | return last_byte; |
62 | } | 64 | } |
63 | 65 | ||
64 | static int ext2_commit_chunk(struct page *page, unsigned from, unsigned to) | 66 | static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len) |
65 | { | 67 | { |
66 | struct inode *dir = page->mapping->host; | 68 | struct address_space *mapping = page->mapping; |
69 | struct inode *dir = mapping->host; | ||
67 | int err = 0; | 70 | int err = 0; |
71 | |||
68 | dir->i_version++; | 72 | dir->i_version++; |
69 | page->mapping->a_ops->commit_write(NULL, page, from, to); | 73 | block_write_end(NULL, mapping, pos, len, len, page, NULL); |
74 | |||
75 | if (pos+len > dir->i_size) { | ||
76 | i_size_write(dir, pos+len); | ||
77 | mark_inode_dirty(dir); | ||
78 | } | ||
79 | |||
70 | if (IS_DIRSYNC(dir)) | 80 | if (IS_DIRSYNC(dir)) |
71 | err = write_one_page(page, 1); | 81 | err = write_one_page(page, 1); |
72 | else | 82 | else |
73 | unlock_page(page); | 83 | unlock_page(page); |
84 | |||
74 | return err; | 85 | return err; |
75 | } | 86 | } |
76 | 87 | ||
@@ -412,16 +423,18 @@ ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry) | |||
412 | void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, | 423 | void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, |
413 | struct page *page, struct inode *inode) | 424 | struct page *page, struct inode *inode) |
414 | { | 425 | { |
415 | unsigned from = (char *) de - (char *) page_address(page); | 426 | loff_t pos = page_offset(page) + |
416 | unsigned to = from + le16_to_cpu(de->rec_len); | 427 | (char *) de - (char *) page_address(page); |
428 | unsigned len = le16_to_cpu(de->rec_len); | ||
417 | int err; | 429 | int err; |
418 | 430 | ||
419 | lock_page(page); | 431 | lock_page(page); |
420 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 432 | err = __ext2_write_begin(NULL, page->mapping, pos, len, |
433 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
421 | BUG_ON(err); | 434 | BUG_ON(err); |
422 | de->inode = cpu_to_le32(inode->i_ino); | 435 | de->inode = cpu_to_le32(inode->i_ino); |
423 | ext2_set_de_type (de, inode); | 436 | ext2_set_de_type(de, inode); |
424 | err = ext2_commit_chunk(page, from, to); | 437 | err = ext2_commit_chunk(page, pos, len); |
425 | ext2_put_page(page); | 438 | ext2_put_page(page); |
426 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 439 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
427 | EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; | 440 | EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; |
@@ -444,7 +457,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
444 | unsigned long npages = dir_pages(dir); | 457 | unsigned long npages = dir_pages(dir); |
445 | unsigned long n; | 458 | unsigned long n; |
446 | char *kaddr; | 459 | char *kaddr; |
447 | unsigned from, to; | 460 | loff_t pos; |
448 | int err; | 461 | int err; |
449 | 462 | ||
450 | /* | 463 | /* |
@@ -497,9 +510,10 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) | |||
497 | return -EINVAL; | 510 | return -EINVAL; |
498 | 511 | ||
499 | got_it: | 512 | got_it: |
500 | from = (char*)de - (char*)page_address(page); | 513 | pos = page_offset(page) + |
501 | to = from + rec_len; | 514 | (char*)de - (char*)page_address(page); |
502 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 515 | err = __ext2_write_begin(NULL, page->mapping, pos, rec_len, 0, |
516 | &page, NULL); | ||
503 | if (err) | 517 | if (err) |
504 | goto out_unlock; | 518 | goto out_unlock; |
505 | if (de->inode) { | 519 | if (de->inode) { |
@@ -509,10 +523,10 @@ got_it: | |||
509 | de = de1; | 523 | de = de1; |
510 | } | 524 | } |
511 | de->name_len = namelen; | 525 | de->name_len = namelen; |
512 | memcpy (de->name, name, namelen); | 526 | memcpy(de->name, name, namelen); |
513 | de->inode = cpu_to_le32(inode->i_ino); | 527 | de->inode = cpu_to_le32(inode->i_ino); |
514 | ext2_set_de_type (de, inode); | 528 | ext2_set_de_type (de, inode); |
515 | err = ext2_commit_chunk(page, from, to); | 529 | err = ext2_commit_chunk(page, pos, rec_len); |
516 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 530 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
517 | EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; | 531 | EXT2_I(dir)->i_flags &= ~EXT2_BTREE_FL; |
518 | mark_inode_dirty(dir); | 532 | mark_inode_dirty(dir); |
@@ -537,6 +551,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
537 | char *kaddr = page_address(page); | 551 | char *kaddr = page_address(page); |
538 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); | 552 | unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); |
539 | unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); | 553 | unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); |
554 | loff_t pos; | ||
540 | ext2_dirent * pde = NULL; | 555 | ext2_dirent * pde = NULL; |
541 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); | 556 | ext2_dirent * de = (ext2_dirent *) (kaddr + from); |
542 | int err; | 557 | int err; |
@@ -553,13 +568,15 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) | |||
553 | } | 568 | } |
554 | if (pde) | 569 | if (pde) |
555 | from = (char*)pde - (char*)page_address(page); | 570 | from = (char*)pde - (char*)page_address(page); |
571 | pos = page_offset(page) + from; | ||
556 | lock_page(page); | 572 | lock_page(page); |
557 | err = mapping->a_ops->prepare_write(NULL, page, from, to); | 573 | err = __ext2_write_begin(NULL, page->mapping, pos, to - from, 0, |
574 | &page, NULL); | ||
558 | BUG_ON(err); | 575 | BUG_ON(err); |
559 | if (pde) | 576 | if (pde) |
560 | pde->rec_len = cpu_to_le16(to-from); | 577 | pde->rec_len = cpu_to_le16(to - from); |
561 | dir->inode = 0; | 578 | dir->inode = 0; |
562 | err = ext2_commit_chunk(page, from, to); | 579 | err = ext2_commit_chunk(page, pos, to - from); |
563 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; | 580 | inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; |
564 | EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; | 581 | EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; |
565 | mark_inode_dirty(inode); | 582 | mark_inode_dirty(inode); |
@@ -582,7 +599,9 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) | |||
582 | 599 | ||
583 | if (!page) | 600 | if (!page) |
584 | return -ENOMEM; | 601 | return -ENOMEM; |
585 | err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size); | 602 | |
603 | err = __ext2_write_begin(NULL, page->mapping, 0, chunk_size, 0, | ||
604 | &page, NULL); | ||
586 | if (err) { | 605 | if (err) { |
587 | unlock_page(page); | 606 | unlock_page(page); |
588 | goto fail; | 607 | goto fail; |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 9fd0ec5ba0d0..a08052d2c008 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
@@ -134,6 +134,9 @@ extern void ext2_truncate (struct inode *); | |||
134 | extern int ext2_setattr (struct dentry *, struct iattr *); | 134 | extern int ext2_setattr (struct dentry *, struct iattr *); |
135 | extern void ext2_set_inode_flags(struct inode *inode); | 135 | extern void ext2_set_inode_flags(struct inode *inode); |
136 | extern void ext2_get_inode_flags(struct ext2_inode_info *); | 136 | extern void ext2_get_inode_flags(struct ext2_inode_info *); |
137 | int __ext2_write_begin(struct file *file, struct address_space *mapping, | ||
138 | loff_t pos, unsigned len, unsigned flags, | ||
139 | struct page **pagep, void **fsdata); | ||
137 | 140 | ||
138 | /* ioctl.c */ | 141 | /* ioctl.c */ |
139 | extern int ext2_ioctl (struct inode *, struct file *, unsigned int, | 142 | extern int ext2_ioctl (struct inode *, struct file *, unsigned int, |
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 0079b2cd5314..63ab02aa4c52 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c | |||
@@ -642,18 +642,21 @@ ext2_readpages(struct file *file, struct address_space *mapping, | |||
642 | return mpage_readpages(mapping, pages, nr_pages, ext2_get_block); | 642 | return mpage_readpages(mapping, pages, nr_pages, ext2_get_block); |
643 | } | 643 | } |
644 | 644 | ||
645 | static int | 645 | int __ext2_write_begin(struct file *file, struct address_space *mapping, |
646 | ext2_prepare_write(struct file *file, struct page *page, | 646 | loff_t pos, unsigned len, unsigned flags, |
647 | unsigned from, unsigned to) | 647 | struct page **pagep, void **fsdata) |
648 | { | 648 | { |
649 | return block_prepare_write(page,from,to,ext2_get_block); | 649 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
650 | ext2_get_block); | ||
650 | } | 651 | } |
651 | 652 | ||
652 | static int | 653 | static int |
653 | ext2_nobh_prepare_write(struct file *file, struct page *page, | 654 | ext2_write_begin(struct file *file, struct address_space *mapping, |
654 | unsigned from, unsigned to) | 655 | loff_t pos, unsigned len, unsigned flags, |
656 | struct page **pagep, void **fsdata) | ||
655 | { | 657 | { |
656 | return nobh_prepare_write(page,from,to,ext2_get_block); | 658 | *pagep = NULL; |
659 | return __ext2_write_begin(file, mapping, pos, len, flags, pagep,fsdata); | ||
657 | } | 660 | } |
658 | 661 | ||
659 | static int ext2_nobh_writepage(struct page *page, | 662 | static int ext2_nobh_writepage(struct page *page, |
@@ -689,8 +692,8 @@ const struct address_space_operations ext2_aops = { | |||
689 | .readpages = ext2_readpages, | 692 | .readpages = ext2_readpages, |
690 | .writepage = ext2_writepage, | 693 | .writepage = ext2_writepage, |
691 | .sync_page = block_sync_page, | 694 | .sync_page = block_sync_page, |
692 | .prepare_write = ext2_prepare_write, | 695 | .write_begin = ext2_write_begin, |
693 | .commit_write = generic_commit_write, | 696 | .write_end = generic_write_end, |
694 | .bmap = ext2_bmap, | 697 | .bmap = ext2_bmap, |
695 | .direct_IO = ext2_direct_IO, | 698 | .direct_IO = ext2_direct_IO, |
696 | .writepages = ext2_writepages, | 699 | .writepages = ext2_writepages, |
@@ -707,8 +710,7 @@ const struct address_space_operations ext2_nobh_aops = { | |||
707 | .readpages = ext2_readpages, | 710 | .readpages = ext2_readpages, |
708 | .writepage = ext2_nobh_writepage, | 711 | .writepage = ext2_nobh_writepage, |
709 | .sync_page = block_sync_page, | 712 | .sync_page = block_sync_page, |
710 | .prepare_write = ext2_nobh_prepare_write, | 713 | /* XXX: todo */ |
711 | .commit_write = nobh_commit_write, | ||
712 | .bmap = ext2_bmap, | 714 | .bmap = ext2_bmap, |
713 | .direct_IO = ext2_direct_IO, | 715 | .direct_IO = ext2_direct_IO, |
714 | .writepages = ext2_writepages, | 716 | .writepages = ext2_writepages, |