diff options
-rw-r--r-- | fs/reiserfs/inode.c | 176 | ||||
-rw-r--r-- | fs/reiserfs/ioctl.c | 10 | ||||
-rw-r--r-- | fs/reiserfs/xattr.c | 16 |
3 files changed, 183 insertions, 19 deletions
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index ddde489f1cb2..21db3a705f1e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -17,11 +17,12 @@ | |||
17 | #include <linux/mpage.h> | 17 | #include <linux/mpage.h> |
18 | #include <linux/writeback.h> | 18 | #include <linux/writeback.h> |
19 | #include <linux/quotaops.h> | 19 | #include <linux/quotaops.h> |
20 | #include <linux/swap.h> | ||
20 | 21 | ||
21 | static int reiserfs_commit_write(struct file *f, struct page *page, | 22 | int reiserfs_commit_write(struct file *f, struct page *page, |
22 | unsigned from, unsigned to); | 23 | unsigned from, unsigned to); |
23 | static int reiserfs_prepare_write(struct file *f, struct page *page, | 24 | int reiserfs_prepare_write(struct file *f, struct page *page, |
24 | unsigned from, unsigned to); | 25 | unsigned from, unsigned to); |
25 | 26 | ||
26 | void reiserfs_delete_inode(struct inode *inode) | 27 | void reiserfs_delete_inode(struct inode *inode) |
27 | { | 28 | { |
@@ -2550,8 +2551,71 @@ static int reiserfs_writepage(struct page *page, struct writeback_control *wbc) | |||
2550 | return reiserfs_write_full_page(page, wbc); | 2551 | return reiserfs_write_full_page(page, wbc); |
2551 | } | 2552 | } |
2552 | 2553 | ||
2553 | static int reiserfs_prepare_write(struct file *f, struct page *page, | 2554 | static int reiserfs_write_begin(struct file *file, |
2554 | unsigned from, unsigned to) | 2555 | struct address_space *mapping, |
2556 | loff_t pos, unsigned len, unsigned flags, | ||
2557 | struct page **pagep, void **fsdata) | ||
2558 | { | ||
2559 | struct inode *inode; | ||
2560 | struct page *page; | ||
2561 | pgoff_t index; | ||
2562 | int ret; | ||
2563 | int old_ref = 0; | ||
2564 | |||
2565 | index = pos >> PAGE_CACHE_SHIFT; | ||
2566 | page = __grab_cache_page(mapping, index); | ||
2567 | if (!page) | ||
2568 | return -ENOMEM; | ||
2569 | *pagep = page; | ||
2570 | |||
2571 | inode = mapping->host; | ||
2572 | reiserfs_wait_on_write_block(inode->i_sb); | ||
2573 | fix_tail_page_for_writing(page); | ||
2574 | if (reiserfs_transaction_running(inode->i_sb)) { | ||
2575 | struct reiserfs_transaction_handle *th; | ||
2576 | th = (struct reiserfs_transaction_handle *)current-> | ||
2577 | journal_info; | ||
2578 | BUG_ON(!th->t_refcount); | ||
2579 | BUG_ON(!th->t_trans_id); | ||
2580 | old_ref = th->t_refcount; | ||
2581 | th->t_refcount++; | ||
2582 | } | ||
2583 | ret = block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | ||
2584 | reiserfs_get_block); | ||
2585 | if (ret && reiserfs_transaction_running(inode->i_sb)) { | ||
2586 | struct reiserfs_transaction_handle *th = current->journal_info; | ||
2587 | /* this gets a little ugly. If reiserfs_get_block returned an | ||
2588 | * error and left a transacstion running, we've got to close it, | ||
2589 | * and we've got to free handle if it was a persistent transaction. | ||
2590 | * | ||
2591 | * But, if we had nested into an existing transaction, we need | ||
2592 | * to just drop the ref count on the handle. | ||
2593 | * | ||
2594 | * If old_ref == 0, the transaction is from reiserfs_get_block, | ||
2595 | * and it was a persistent trans. Otherwise, it was nested above. | ||
2596 | */ | ||
2597 | if (th->t_refcount > old_ref) { | ||
2598 | if (old_ref) | ||
2599 | th->t_refcount--; | ||
2600 | else { | ||
2601 | int err; | ||
2602 | reiserfs_write_lock(inode->i_sb); | ||
2603 | err = reiserfs_end_persistent_transaction(th); | ||
2604 | reiserfs_write_unlock(inode->i_sb); | ||
2605 | if (err) | ||
2606 | ret = err; | ||
2607 | } | ||
2608 | } | ||
2609 | } | ||
2610 | if (ret) { | ||
2611 | unlock_page(page); | ||
2612 | page_cache_release(page); | ||
2613 | } | ||
2614 | return ret; | ||
2615 | } | ||
2616 | |||
2617 | int reiserfs_prepare_write(struct file *f, struct page *page, | ||
2618 | unsigned from, unsigned to) | ||
2555 | { | 2619 | { |
2556 | struct inode *inode = page->mapping->host; | 2620 | struct inode *inode = page->mapping->host; |
2557 | int ret; | 2621 | int ret; |
@@ -2604,8 +2668,100 @@ static sector_t reiserfs_aop_bmap(struct address_space *as, sector_t block) | |||
2604 | return generic_block_bmap(as, block, reiserfs_bmap); | 2668 | return generic_block_bmap(as, block, reiserfs_bmap); |
2605 | } | 2669 | } |
2606 | 2670 | ||
2607 | static int reiserfs_commit_write(struct file *f, struct page *page, | 2671 | static int reiserfs_write_end(struct file *file, struct address_space *mapping, |
2608 | unsigned from, unsigned to) | 2672 | loff_t pos, unsigned len, unsigned copied, |
2673 | struct page *page, void *fsdata) | ||
2674 | { | ||
2675 | struct inode *inode = page->mapping->host; | ||
2676 | int ret = 0; | ||
2677 | int update_sd = 0; | ||
2678 | struct reiserfs_transaction_handle *th; | ||
2679 | unsigned start; | ||
2680 | |||
2681 | |||
2682 | reiserfs_wait_on_write_block(inode->i_sb); | ||
2683 | if (reiserfs_transaction_running(inode->i_sb)) | ||
2684 | th = current->journal_info; | ||
2685 | else | ||
2686 | th = NULL; | ||
2687 | |||
2688 | start = pos & (PAGE_CACHE_SIZE - 1); | ||
2689 | if (unlikely(copied < len)) { | ||
2690 | if (!PageUptodate(page)) | ||
2691 | copied = 0; | ||
2692 | |||
2693 | page_zero_new_buffers(page, start + copied, start + len); | ||
2694 | } | ||
2695 | flush_dcache_page(page); | ||
2696 | |||
2697 | reiserfs_commit_page(inode, page, start, start + copied); | ||
2698 | |||
2699 | /* generic_commit_write does this for us, but does not update the | ||
2700 | ** transaction tracking stuff when the size changes. So, we have | ||
2701 | ** to do the i_size updates here. | ||
2702 | */ | ||
2703 | pos += copied; | ||
2704 | if (pos > inode->i_size) { | ||
2705 | struct reiserfs_transaction_handle myth; | ||
2706 | reiserfs_write_lock(inode->i_sb); | ||
2707 | /* If the file have grown beyond the border where it | ||
2708 | can have a tail, unmark it as needing a tail | ||
2709 | packing */ | ||
2710 | if ((have_large_tails(inode->i_sb) | ||
2711 | && inode->i_size > i_block_size(inode) * 4) | ||
2712 | || (have_small_tails(inode->i_sb) | ||
2713 | && inode->i_size > i_block_size(inode))) | ||
2714 | REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; | ||
2715 | |||
2716 | ret = journal_begin(&myth, inode->i_sb, 1); | ||
2717 | if (ret) { | ||
2718 | reiserfs_write_unlock(inode->i_sb); | ||
2719 | goto journal_error; | ||
2720 | } | ||
2721 | reiserfs_update_inode_transaction(inode); | ||
2722 | inode->i_size = pos; | ||
2723 | /* | ||
2724 | * this will just nest into our transaction. It's important | ||
2725 | * to use mark_inode_dirty so the inode gets pushed around on the | ||
2726 | * dirty lists, and so that O_SYNC works as expected | ||
2727 | */ | ||
2728 | mark_inode_dirty(inode); | ||
2729 | reiserfs_update_sd(&myth, inode); | ||
2730 | update_sd = 1; | ||
2731 | ret = journal_end(&myth, inode->i_sb, 1); | ||
2732 | reiserfs_write_unlock(inode->i_sb); | ||
2733 | if (ret) | ||
2734 | goto journal_error; | ||
2735 | } | ||
2736 | if (th) { | ||
2737 | reiserfs_write_lock(inode->i_sb); | ||
2738 | if (!update_sd) | ||
2739 | mark_inode_dirty(inode); | ||
2740 | ret = reiserfs_end_persistent_transaction(th); | ||
2741 | reiserfs_write_unlock(inode->i_sb); | ||
2742 | if (ret) | ||
2743 | goto out; | ||
2744 | } | ||
2745 | |||
2746 | out: | ||
2747 | unlock_page(page); | ||
2748 | page_cache_release(page); | ||
2749 | return ret == 0 ? copied : ret; | ||
2750 | |||
2751 | journal_error: | ||
2752 | if (th) { | ||
2753 | reiserfs_write_lock(inode->i_sb); | ||
2754 | if (!update_sd) | ||
2755 | reiserfs_update_sd(th, inode); | ||
2756 | ret = reiserfs_end_persistent_transaction(th); | ||
2757 | reiserfs_write_unlock(inode->i_sb); | ||
2758 | } | ||
2759 | |||
2760 | goto out; | ||
2761 | } | ||
2762 | |||
2763 | int reiserfs_commit_write(struct file *f, struct page *page, | ||
2764 | unsigned from, unsigned to) | ||
2609 | { | 2765 | { |
2610 | struct inode *inode = page->mapping->host; | 2766 | struct inode *inode = page->mapping->host; |
2611 | loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to; | 2767 | loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to; |
@@ -2999,8 +3155,8 @@ const struct address_space_operations reiserfs_address_space_operations = { | |||
2999 | .releasepage = reiserfs_releasepage, | 3155 | .releasepage = reiserfs_releasepage, |
3000 | .invalidatepage = reiserfs_invalidatepage, | 3156 | .invalidatepage = reiserfs_invalidatepage, |
3001 | .sync_page = block_sync_page, | 3157 | .sync_page = block_sync_page, |
3002 | .prepare_write = reiserfs_prepare_write, | 3158 | .write_begin = reiserfs_write_begin, |
3003 | .commit_write = reiserfs_commit_write, | 3159 | .write_end = reiserfs_write_end, |
3004 | .bmap = reiserfs_aop_bmap, | 3160 | .bmap = reiserfs_aop_bmap, |
3005 | .direct_IO = reiserfs_direct_IO, | 3161 | .direct_IO = reiserfs_direct_IO, |
3006 | .set_page_dirty = reiserfs_set_page_dirty, | 3162 | .set_page_dirty = reiserfs_set_page_dirty, |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 11a0fcc2d402..c438a8f83f26 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
@@ -128,6 +128,10 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd, | |||
128 | } | 128 | } |
129 | #endif | 129 | #endif |
130 | 130 | ||
131 | int reiserfs_commit_write(struct file *f, struct page *page, | ||
132 | unsigned from, unsigned to); | ||
133 | int reiserfs_prepare_write(struct file *f, struct page *page, | ||
134 | unsigned from, unsigned to); | ||
131 | /* | 135 | /* |
132 | ** reiserfs_unpack | 136 | ** reiserfs_unpack |
133 | ** Function try to convert tail from direct item into indirect. | 137 | ** Function try to convert tail from direct item into indirect. |
@@ -175,15 +179,13 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp) | |||
175 | if (!page) { | 179 | if (!page) { |
176 | goto out; | 180 | goto out; |
177 | } | 181 | } |
178 | retval = | 182 | retval = reiserfs_prepare_write(NULL, page, write_from, write_from); |
179 | mapping->a_ops->prepare_write(NULL, page, write_from, write_from); | ||
180 | if (retval) | 183 | if (retval) |
181 | goto out_unlock; | 184 | goto out_unlock; |
182 | 185 | ||
183 | /* conversion can change page contents, must flush */ | 186 | /* conversion can change page contents, must flush */ |
184 | flush_dcache_page(page); | 187 | flush_dcache_page(page); |
185 | retval = | 188 | retval = reiserfs_commit_write(NULL, page, write_from, write_from); |
186 | mapping->a_ops->commit_write(NULL, page, write_from, write_from); | ||
187 | REISERFS_I(inode)->i_flags |= i_nopack_mask; | 189 | REISERFS_I(inode)->i_flags |= i_nopack_mask; |
188 | 190 | ||
189 | out_unlock: | 191 | out_unlock: |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index bf6e58214538..fab4b9b2664f 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -426,6 +426,12 @@ static inline __u32 xattr_hash(const char *msg, int len) | |||
426 | return csum_partial(msg, len, 0); | 426 | return csum_partial(msg, len, 0); |
427 | } | 427 | } |
428 | 428 | ||
429 | int reiserfs_commit_write(struct file *f, struct page *page, | ||
430 | unsigned from, unsigned to); | ||
431 | int reiserfs_prepare_write(struct file *f, struct page *page, | ||
432 | unsigned from, unsigned to); | ||
433 | |||
434 | |||
429 | /* Generic extended attribute operations that can be used by xa plugins */ | 435 | /* Generic extended attribute operations that can be used by xa plugins */ |
430 | 436 | ||
431 | /* | 437 | /* |
@@ -512,15 +518,15 @@ reiserfs_xattr_set(struct inode *inode, const char *name, const void *buffer, | |||
512 | rxh->h_hash = cpu_to_le32(xahash); | 518 | rxh->h_hash = cpu_to_le32(xahash); |
513 | } | 519 | } |
514 | 520 | ||
515 | err = mapping->a_ops->prepare_write(fp, page, page_offset, | 521 | err = reiserfs_prepare_write(fp, page, page_offset, |
516 | page_offset + chunk + skip); | 522 | page_offset + chunk + skip); |
517 | if (!err) { | 523 | if (!err) { |
518 | if (buffer) | 524 | if (buffer) |
519 | memcpy(data + skip, buffer + buffer_pos, chunk); | 525 | memcpy(data + skip, buffer + buffer_pos, chunk); |
520 | err = | 526 | err = |
521 | mapping->a_ops->commit_write(fp, page, page_offset, | 527 | reiserfs_commit_write(fp, page, page_offset, |
522 | page_offset + chunk + | 528 | page_offset + chunk + |
523 | skip); | 529 | skip); |
524 | } | 530 | } |
525 | unlock_page(page); | 531 | unlock_page(page); |
526 | reiserfs_put_page(page); | 532 | reiserfs_put_page(page); |