diff options
| -rw-r--r-- | fs/ext3/super.c | 8 | ||||
| -rw-r--r-- | fs/jbd/commit.c | 45 | ||||
| -rw-r--r-- | fs/jbd/transaction.c | 64 | ||||
| -rw-r--r-- | fs/reiserfs/xattr.c | 2 | ||||
| -rw-r--r-- | fs/udf/file.c | 9 | ||||
| -rw-r--r-- | fs/udf/inode.c | 59 |
6 files changed, 136 insertions, 51 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index bd29894c8fbc..17ae5c83d234 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -980,7 +980,7 @@ static int parse_options (char *options, struct super_block *sb, | |||
| 980 | * Initialize args struct so we know whether arg was | 980 | * Initialize args struct so we know whether arg was |
| 981 | * found; some options take optional arguments. | 981 | * found; some options take optional arguments. |
| 982 | */ | 982 | */ |
| 983 | args[0].to = args[0].from = 0; | 983 | args[0].to = args[0].from = NULL; |
| 984 | token = match_token(p, tokens, args); | 984 | token = match_token(p, tokens, args); |
| 985 | switch (token) { | 985 | switch (token) { |
| 986 | case Opt_bsd_df: | 986 | case Opt_bsd_df: |
| @@ -1484,10 +1484,12 @@ static void ext3_orphan_cleanup (struct super_block * sb, | |||
| 1484 | } | 1484 | } |
| 1485 | 1485 | ||
| 1486 | if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) { | 1486 | if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) { |
| 1487 | if (es->s_last_orphan) | 1487 | /* don't clear list on RO mount w/ errors */ |
| 1488 | if (es->s_last_orphan && !(s_flags & MS_RDONLY)) { | ||
| 1488 | jbd_debug(1, "Errors on filesystem, " | 1489 | jbd_debug(1, "Errors on filesystem, " |
| 1489 | "clearing orphan list.\n"); | 1490 | "clearing orphan list.\n"); |
| 1490 | es->s_last_orphan = 0; | 1491 | es->s_last_orphan = 0; |
| 1492 | } | ||
| 1491 | jbd_debug(1, "Skipping orphan recovery on fs with errors.\n"); | 1493 | jbd_debug(1, "Skipping orphan recovery on fs with errors.\n"); |
| 1492 | return; | 1494 | return; |
| 1493 | } | 1495 | } |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 52c15c776029..86b39b167c23 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -86,7 +86,12 @@ nope: | |||
| 86 | static void release_data_buffer(struct buffer_head *bh) | 86 | static void release_data_buffer(struct buffer_head *bh) |
| 87 | { | 87 | { |
| 88 | if (buffer_freed(bh)) { | 88 | if (buffer_freed(bh)) { |
| 89 | WARN_ON_ONCE(buffer_dirty(bh)); | ||
| 89 | clear_buffer_freed(bh); | 90 | clear_buffer_freed(bh); |
| 91 | clear_buffer_mapped(bh); | ||
| 92 | clear_buffer_new(bh); | ||
| 93 | clear_buffer_req(bh); | ||
| 94 | bh->b_bdev = NULL; | ||
| 90 | release_buffer_page(bh); | 95 | release_buffer_page(bh); |
| 91 | } else | 96 | } else |
| 92 | put_bh(bh); | 97 | put_bh(bh); |
| @@ -866,17 +871,35 @@ restart_loop: | |||
| 866 | * there's no point in keeping a checkpoint record for | 871 | * there's no point in keeping a checkpoint record for |
| 867 | * it. */ | 872 | * it. */ |
| 868 | 873 | ||
| 869 | /* A buffer which has been freed while still being | 874 | /* |
| 870 | * journaled by a previous transaction may end up still | 875 | * A buffer which has been freed while still being journaled by |
| 871 | * being dirty here, but we want to avoid writing back | 876 | * a previous transaction. |
| 872 | * that buffer in the future after the "add to orphan" | 877 | */ |
| 873 | * operation been committed, That's not only a performance | 878 | if (buffer_freed(bh)) { |
| 874 | * gain, it also stops aliasing problems if the buffer is | 879 | /* |
| 875 | * left behind for writeback and gets reallocated for another | 880 | * If the running transaction is the one containing |
| 876 | * use in a different page. */ | 881 | * "add to orphan" operation (b_next_transaction != |
| 877 | if (buffer_freed(bh) && !jh->b_next_transaction) { | 882 | * NULL), we have to wait for that transaction to |
| 878 | clear_buffer_freed(bh); | 883 | * commit before we can really get rid of the buffer. |
| 879 | clear_buffer_jbddirty(bh); | 884 | * So just clear b_modified to not confuse transaction |
| 885 | * credit accounting and refile the buffer to | ||
| 886 | * BJ_Forget of the running transaction. If the just | ||
| 887 | * committed transaction contains "add to orphan" | ||
| 888 | * operation, we can completely invalidate the buffer | ||
| 889 | * now. We are rather throughout in that since the | ||
| 890 | * buffer may be still accessible when blocksize < | ||
| 891 | * pagesize and it is attached to the last partial | ||
| 892 | * page. | ||
| 893 | */ | ||
| 894 | jh->b_modified = 0; | ||
| 895 | if (!jh->b_next_transaction) { | ||
| 896 | clear_buffer_freed(bh); | ||
| 897 | clear_buffer_jbddirty(bh); | ||
| 898 | clear_buffer_mapped(bh); | ||
| 899 | clear_buffer_new(bh); | ||
| 900 | clear_buffer_req(bh); | ||
| 901 | bh->b_bdev = NULL; | ||
| 902 | } | ||
| 880 | } | 903 | } |
| 881 | 904 | ||
| 882 | if (buffer_jbddirty(bh)) { | 905 | if (buffer_jbddirty(bh)) { |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index febc10db5ced..78b7f84241d4 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
| @@ -1843,15 +1843,16 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) | |||
| 1843 | * We're outside-transaction here. Either or both of j_running_transaction | 1843 | * We're outside-transaction here. Either or both of j_running_transaction |
| 1844 | * and j_committing_transaction may be NULL. | 1844 | * and j_committing_transaction may be NULL. |
| 1845 | */ | 1845 | */ |
| 1846 | static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | 1846 | static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, |
| 1847 | int partial_page) | ||
| 1847 | { | 1848 | { |
| 1848 | transaction_t *transaction; | 1849 | transaction_t *transaction; |
| 1849 | struct journal_head *jh; | 1850 | struct journal_head *jh; |
| 1850 | int may_free = 1; | 1851 | int may_free = 1; |
| 1851 | int ret; | ||
| 1852 | 1852 | ||
| 1853 | BUFFER_TRACE(bh, "entry"); | 1853 | BUFFER_TRACE(bh, "entry"); |
| 1854 | 1854 | ||
| 1855 | retry: | ||
| 1855 | /* | 1856 | /* |
| 1856 | * It is safe to proceed here without the j_list_lock because the | 1857 | * It is safe to proceed here without the j_list_lock because the |
| 1857 | * buffers cannot be stolen by try_to_free_buffers as long as we are | 1858 | * buffers cannot be stolen by try_to_free_buffers as long as we are |
| @@ -1879,10 +1880,18 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1879 | * clear the buffer dirty bit at latest at the moment when the | 1880 | * clear the buffer dirty bit at latest at the moment when the |
| 1880 | * transaction marking the buffer as freed in the filesystem | 1881 | * transaction marking the buffer as freed in the filesystem |
| 1881 | * structures is committed because from that moment on the | 1882 | * structures is committed because from that moment on the |
| 1882 | * buffer can be reallocated and used by a different page. | 1883 | * block can be reallocated and used by a different page. |
| 1883 | * Since the block hasn't been freed yet but the inode has | 1884 | * Since the block hasn't been freed yet but the inode has |
| 1884 | * already been added to orphan list, it is safe for us to add | 1885 | * already been added to orphan list, it is safe for us to add |
| 1885 | * the buffer to BJ_Forget list of the newest transaction. | 1886 | * the buffer to BJ_Forget list of the newest transaction. |
| 1887 | * | ||
| 1888 | * Also we have to clear buffer_mapped flag of a truncated buffer | ||
| 1889 | * because the buffer_head may be attached to the page straddling | ||
| 1890 | * i_size (can happen only when blocksize < pagesize) and thus the | ||
| 1891 | * buffer_head can be reused when the file is extended again. So we end | ||
| 1892 | * up keeping around invalidated buffers attached to transactions' | ||
| 1893 | * BJ_Forget list just to stop checkpointing code from cleaning up | ||
| 1894 | * the transaction this buffer was modified in. | ||
| 1886 | */ | 1895 | */ |
| 1887 | transaction = jh->b_transaction; | 1896 | transaction = jh->b_transaction; |
| 1888 | if (transaction == NULL) { | 1897 | if (transaction == NULL) { |
| @@ -1909,13 +1918,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1909 | * committed, the buffer won't be needed any | 1918 | * committed, the buffer won't be needed any |
| 1910 | * longer. */ | 1919 | * longer. */ |
| 1911 | JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); | 1920 | JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); |
| 1912 | ret = __dispose_buffer(jh, | 1921 | may_free = __dispose_buffer(jh, |
| 1913 | journal->j_running_transaction); | 1922 | journal->j_running_transaction); |
| 1914 | journal_put_journal_head(jh); | 1923 | goto zap_buffer; |
| 1915 | spin_unlock(&journal->j_list_lock); | ||
| 1916 | jbd_unlock_bh_state(bh); | ||
| 1917 | spin_unlock(&journal->j_state_lock); | ||
| 1918 | return ret; | ||
| 1919 | } else { | 1924 | } else { |
| 1920 | /* There is no currently-running transaction. So the | 1925 | /* There is no currently-running transaction. So the |
| 1921 | * orphan record which we wrote for this file must have | 1926 | * orphan record which we wrote for this file must have |
| @@ -1923,13 +1928,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1923 | * the committing transaction, if it exists. */ | 1928 | * the committing transaction, if it exists. */ |
| 1924 | if (journal->j_committing_transaction) { | 1929 | if (journal->j_committing_transaction) { |
| 1925 | JBUFFER_TRACE(jh, "give to committing trans"); | 1930 | JBUFFER_TRACE(jh, "give to committing trans"); |
| 1926 | ret = __dispose_buffer(jh, | 1931 | may_free = __dispose_buffer(jh, |
| 1927 | journal->j_committing_transaction); | 1932 | journal->j_committing_transaction); |
| 1928 | journal_put_journal_head(jh); | 1933 | goto zap_buffer; |
| 1929 | spin_unlock(&journal->j_list_lock); | ||
| 1930 | jbd_unlock_bh_state(bh); | ||
| 1931 | spin_unlock(&journal->j_state_lock); | ||
| 1932 | return ret; | ||
| 1933 | } else { | 1934 | } else { |
| 1934 | /* The orphan record's transaction has | 1935 | /* The orphan record's transaction has |
| 1935 | * committed. We can cleanse this buffer */ | 1936 | * committed. We can cleanse this buffer */ |
| @@ -1950,10 +1951,24 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1950 | } | 1951 | } |
| 1951 | /* | 1952 | /* |
| 1952 | * The buffer is committing, we simply cannot touch | 1953 | * The buffer is committing, we simply cannot touch |
| 1953 | * it. So we just set j_next_transaction to the | 1954 | * it. If the page is straddling i_size we have to wait |
| 1954 | * running transaction (if there is one) and mark | 1955 | * for commit and try again. |
| 1955 | * buffer as freed so that commit code knows it should | 1956 | */ |
| 1956 | * clear dirty bits when it is done with the buffer. | 1957 | if (partial_page) { |
| 1958 | tid_t tid = journal->j_committing_transaction->t_tid; | ||
| 1959 | |||
| 1960 | journal_put_journal_head(jh); | ||
| 1961 | spin_unlock(&journal->j_list_lock); | ||
| 1962 | jbd_unlock_bh_state(bh); | ||
| 1963 | spin_unlock(&journal->j_state_lock); | ||
| 1964 | log_wait_commit(journal, tid); | ||
| 1965 | goto retry; | ||
| 1966 | } | ||
| 1967 | /* | ||
| 1968 | * OK, buffer won't be reachable after truncate. We just set | ||
| 1969 | * j_next_transaction to the running transaction (if there is | ||
| 1970 | * one) and mark buffer as freed so that commit code knows it | ||
| 1971 | * should clear dirty bits when it is done with the buffer. | ||
| 1957 | */ | 1972 | */ |
| 1958 | set_buffer_freed(bh); | 1973 | set_buffer_freed(bh); |
| 1959 | if (journal->j_running_transaction && buffer_jbddirty(bh)) | 1974 | if (journal->j_running_transaction && buffer_jbddirty(bh)) |
| @@ -1976,6 +1991,14 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1976 | } | 1991 | } |
| 1977 | 1992 | ||
| 1978 | zap_buffer: | 1993 | zap_buffer: |
| 1994 | /* | ||
| 1995 | * This is tricky. Although the buffer is truncated, it may be reused | ||
| 1996 | * if blocksize < pagesize and it is attached to the page straddling | ||
| 1997 | * EOF. Since the buffer might have been added to BJ_Forget list of the | ||
| 1998 | * running transaction, journal_get_write_access() won't clear | ||
| 1999 | * b_modified and credit accounting gets confused. So clear b_modified | ||
| 2000 | * here. */ | ||
| 2001 | jh->b_modified = 0; | ||
| 1979 | journal_put_journal_head(jh); | 2002 | journal_put_journal_head(jh); |
| 1980 | zap_buffer_no_jh: | 2003 | zap_buffer_no_jh: |
| 1981 | spin_unlock(&journal->j_list_lock); | 2004 | spin_unlock(&journal->j_list_lock); |
| @@ -2024,7 +2047,8 @@ void journal_invalidatepage(journal_t *journal, | |||
| 2024 | if (offset <= curr_off) { | 2047 | if (offset <= curr_off) { |
| 2025 | /* This block is wholly outside the truncation point */ | 2048 | /* This block is wholly outside the truncation point */ |
| 2026 | lock_buffer(bh); | 2049 | lock_buffer(bh); |
| 2027 | may_free &= journal_unmap_buffer(journal, bh); | 2050 | may_free &= journal_unmap_buffer(journal, bh, |
| 2051 | offset > 0); | ||
| 2028 | unlock_buffer(bh); | 2052 | unlock_buffer(bh); |
| 2029 | } | 2053 | } |
| 2030 | curr_off = next_off; | 2054 | curr_off = next_off; |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index d319963aeb11..c196369fe408 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -896,7 +896,7 @@ static int create_privroot(struct dentry *dentry) { return 0; } | |||
| 896 | #endif | 896 | #endif |
| 897 | 897 | ||
| 898 | /* Actual operations that are exported to VFS-land */ | 898 | /* Actual operations that are exported to VFS-land */ |
| 899 | const struct xattr_handler *reiserfs_xattr_handlers[] = { | 899 | static const struct xattr_handler *reiserfs_xattr_handlers[] = { |
| 900 | #ifdef CONFIG_REISERFS_FS_XATTR | 900 | #ifdef CONFIG_REISERFS_FS_XATTR |
| 901 | &reiserfs_xattr_user_handler, | 901 | &reiserfs_xattr_user_handler, |
| 902 | &reiserfs_xattr_trusted_handler, | 902 | &reiserfs_xattr_trusted_handler, |
diff --git a/fs/udf/file.c b/fs/udf/file.c index d1c6093fd3d3..77b5953eaac8 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -118,11 +118,20 @@ static int udf_adinicb_write_end(struct file *file, | |||
| 118 | return simple_write_end(file, mapping, pos, len, copied, page, fsdata); | 118 | return simple_write_end(file, mapping, pos, len, copied, page, fsdata); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, | ||
| 122 | const struct iovec *iov, | ||
| 123 | loff_t offset, unsigned long nr_segs) | ||
| 124 | { | ||
| 125 | /* Fallback to buffered I/O. */ | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 121 | const struct address_space_operations udf_adinicb_aops = { | 129 | const struct address_space_operations udf_adinicb_aops = { |
| 122 | .readpage = udf_adinicb_readpage, | 130 | .readpage = udf_adinicb_readpage, |
| 123 | .writepage = udf_adinicb_writepage, | 131 | .writepage = udf_adinicb_writepage, |
| 124 | .write_begin = udf_adinicb_write_begin, | 132 | .write_begin = udf_adinicb_write_begin, |
| 125 | .write_end = udf_adinicb_write_end, | 133 | .write_end = udf_adinicb_write_end, |
| 134 | .direct_IO = udf_adinicb_direct_IO, | ||
| 126 | }; | 135 | }; |
| 127 | 136 | ||
| 128 | static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | 137 | static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 287ef9f587b7..df88b957ccf0 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -95,11 +95,33 @@ void udf_evict_inode(struct inode *inode) | |||
| 95 | } | 95 | } |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static void udf_write_failed(struct address_space *mapping, loff_t to) | ||
| 99 | { | ||
| 100 | struct inode *inode = mapping->host; | ||
| 101 | struct udf_inode_info *iinfo = UDF_I(inode); | ||
| 102 | loff_t isize = inode->i_size; | ||
| 103 | |||
| 104 | if (to > isize) { | ||
| 105 | truncate_pagecache(inode, to, isize); | ||
| 106 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | ||
| 107 | down_write(&iinfo->i_data_sem); | ||
| 108 | udf_truncate_extents(inode); | ||
| 109 | up_write(&iinfo->i_data_sem); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 98 | static int udf_writepage(struct page *page, struct writeback_control *wbc) | 114 | static int udf_writepage(struct page *page, struct writeback_control *wbc) |
| 99 | { | 115 | { |
| 100 | return block_write_full_page(page, udf_get_block, wbc); | 116 | return block_write_full_page(page, udf_get_block, wbc); |
| 101 | } | 117 | } |
| 102 | 118 | ||
| 119 | static int udf_writepages(struct address_space *mapping, | ||
| 120 | struct writeback_control *wbc) | ||
| 121 | { | ||
| 122 | return mpage_writepages(mapping, wbc, udf_get_block); | ||
| 123 | } | ||
| 124 | |||
| 103 | static int udf_readpage(struct file *file, struct page *page) | 125 | static int udf_readpage(struct file *file, struct page *page) |
| 104 | { | 126 | { |
| 105 | return mpage_readpage(page, udf_get_block); | 127 | return mpage_readpage(page, udf_get_block); |
| @@ -118,21 +140,24 @@ static int udf_write_begin(struct file *file, struct address_space *mapping, | |||
| 118 | int ret; | 140 | int ret; |
| 119 | 141 | ||
| 120 | ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); | 142 | ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); |
| 121 | if (unlikely(ret)) { | 143 | if (unlikely(ret)) |
| 122 | struct inode *inode = mapping->host; | 144 | udf_write_failed(mapping, pos + len); |
| 123 | struct udf_inode_info *iinfo = UDF_I(inode); | 145 | return ret; |
| 124 | loff_t isize = inode->i_size; | 146 | } |
| 125 | |||
| 126 | if (pos + len > isize) { | ||
| 127 | truncate_pagecache(inode, pos + len, isize); | ||
| 128 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | ||
| 129 | down_write(&iinfo->i_data_sem); | ||
| 130 | udf_truncate_extents(inode); | ||
| 131 | up_write(&iinfo->i_data_sem); | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } | ||
| 135 | 147 | ||
| 148 | static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, | ||
| 149 | const struct iovec *iov, | ||
| 150 | loff_t offset, unsigned long nr_segs) | ||
| 151 | { | ||
| 152 | struct file *file = iocb->ki_filp; | ||
| 153 | struct address_space *mapping = file->f_mapping; | ||
| 154 | struct inode *inode = mapping->host; | ||
| 155 | ssize_t ret; | ||
| 156 | |||
| 157 | ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, | ||
| 158 | udf_get_block); | ||
| 159 | if (unlikely(ret < 0 && (rw & WRITE))) | ||
| 160 | udf_write_failed(mapping, offset + iov_length(iov, nr_segs)); | ||
| 136 | return ret; | 161 | return ret; |
| 137 | } | 162 | } |
| 138 | 163 | ||
| @@ -145,8 +170,10 @@ const struct address_space_operations udf_aops = { | |||
| 145 | .readpage = udf_readpage, | 170 | .readpage = udf_readpage, |
| 146 | .readpages = udf_readpages, | 171 | .readpages = udf_readpages, |
| 147 | .writepage = udf_writepage, | 172 | .writepage = udf_writepage, |
| 148 | .write_begin = udf_write_begin, | 173 | .writepages = udf_writepages, |
| 149 | .write_end = generic_write_end, | 174 | .write_begin = udf_write_begin, |
| 175 | .write_end = generic_write_end, | ||
| 176 | .direct_IO = udf_direct_IO, | ||
| 150 | .bmap = udf_bmap, | 177 | .bmap = udf_bmap, |
| 151 | }; | 178 | }; |
| 152 | 179 | ||
