diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 17:36:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-11 17:36:55 -0500 |
commit | 40c73abbb37e399eba274fe49e520ffa3dd65bdb (patch) | |
tree | 11ee28f09a2455c7134964f7f09e16a93d058c13 /fs/ext3 | |
parent | 0945f352ce1520765296fc2b07e50055c847d39d (diff) | |
parent | d96336b05d718b03ff03c94c0dc0cc283a29d534 (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6:
ext2: Resolve 'dereferencing pointer to incomplete type' when enabling EXT2_XATTR_DEBUG
ext3: Remove redundant unlikely()
ext2: Remove redundant unlikely()
ext3: speed up file creates by optimizing rec_len functions
ext2: speed up file creates by optimizing rec_len functions
ext3: Add more journal error check
ext3: Add journal error check in resize.c
quota: Use %pV and __attribute__((format (printf in __quota_error and fix fallout
ext3: Add FITRIM handling
ext3: Add batched discard support for ext3
ext3: Add journal error check into ext3_rename()
ext3: Use search_dirblock() in ext3_dx_find_entry()
ext3: Avoid uninitialized memory references with a corrupted htree directory
ext3: Return error code from generic_check_addressable
ext3: Add journal error check into ext3_delete_entry()
ext3: Add error check in ext3_mkdir()
fs/ext3/super.c: Use printf extension %pV
fs/ext2/super.c: Use printf extension %pV
ext3: don't update sb journal_devnum when RO dev
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/balloc.c | 266 | ||||
-rw-r--r-- | fs/ext3/dir.c | 15 | ||||
-rw-r--r-- | fs/ext3/inode.c | 6 | ||||
-rw-r--r-- | fs/ext3/ioctl.c | 22 | ||||
-rw-r--r-- | fs/ext3/namei.c | 138 | ||||
-rw-r--r-- | fs/ext3/resize.c | 65 | ||||
-rw-r--r-- | fs/ext3/super.c | 64 |
7 files changed, 473 insertions, 103 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index b3db22649426..045995c8ce5a 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/ext3_jbd.h> | 20 | #include <linux/ext3_jbd.h> |
21 | #include <linux/quotaops.h> | 21 | #include <linux/quotaops.h> |
22 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
23 | #include <linux/blkdev.h> | ||
23 | 24 | ||
24 | /* | 25 | /* |
25 | * balloc.c contains the blocks allocation and deallocation routines | 26 | * balloc.c contains the blocks allocation and deallocation routines |
@@ -39,6 +40,21 @@ | |||
39 | 40 | ||
40 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) | 41 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) |
41 | 42 | ||
43 | /* | ||
44 | * Calculate the block group number and offset, given a block number | ||
45 | */ | ||
46 | static void ext3_get_group_no_and_offset(struct super_block *sb, | ||
47 | ext3_fsblk_t blocknr, unsigned long *blockgrpp, ext3_grpblk_t *offsetp) | ||
48 | { | ||
49 | struct ext3_super_block *es = EXT3_SB(sb)->s_es; | ||
50 | |||
51 | blocknr = blocknr - le32_to_cpu(es->s_first_data_block); | ||
52 | if (offsetp) | ||
53 | *offsetp = blocknr % EXT3_BLOCKS_PER_GROUP(sb); | ||
54 | if (blockgrpp) | ||
55 | *blockgrpp = blocknr / EXT3_BLOCKS_PER_GROUP(sb); | ||
56 | } | ||
57 | |||
42 | /** | 58 | /** |
43 | * ext3_get_group_desc() -- load group descriptor from disk | 59 | * ext3_get_group_desc() -- load group descriptor from disk |
44 | * @sb: super block | 60 | * @sb: super block |
@@ -1885,3 +1901,253 @@ unsigned long ext3_bg_num_gdb(struct super_block *sb, int group) | |||
1885 | return ext3_bg_num_gdb_meta(sb,group); | 1901 | return ext3_bg_num_gdb_meta(sb,group); |
1886 | 1902 | ||
1887 | } | 1903 | } |
1904 | |||
1905 | /** | ||
1906 | * ext3_trim_all_free -- function to trim all free space in alloc. group | ||
1907 | * @sb: super block for file system | ||
1908 | * @group: allocation group to trim | ||
1909 | * @start: first group block to examine | ||
1910 | * @max: last group block to examine | ||
1911 | * @gdp: allocation group description structure | ||
1912 | * @minblocks: minimum extent block count | ||
1913 | * | ||
1914 | * ext3_trim_all_free walks through group's block bitmap searching for free | ||
1915 | * blocks. When the free block is found, it tries to allocate this block and | ||
1916 | * consequent free block to get the biggest free extent possible, until it | ||
1917 | * reaches any used block. Then issue a TRIM command on this extent and free | ||
1918 | * the extent in the block bitmap. This is done until whole group is scanned. | ||
1919 | */ | ||
1920 | ext3_grpblk_t ext3_trim_all_free(struct super_block *sb, unsigned int group, | ||
1921 | ext3_grpblk_t start, ext3_grpblk_t max, | ||
1922 | ext3_grpblk_t minblocks) | ||
1923 | { | ||
1924 | handle_t *handle; | ||
1925 | ext3_grpblk_t next, free_blocks, bit, freed, count = 0; | ||
1926 | ext3_fsblk_t discard_block; | ||
1927 | struct ext3_sb_info *sbi; | ||
1928 | struct buffer_head *gdp_bh, *bitmap_bh = NULL; | ||
1929 | struct ext3_group_desc *gdp; | ||
1930 | int err = 0, ret = 0; | ||
1931 | |||
1932 | /* | ||
1933 | * We will update one block bitmap, and one group descriptor | ||
1934 | */ | ||
1935 | handle = ext3_journal_start_sb(sb, 2); | ||
1936 | if (IS_ERR(handle)) | ||
1937 | return PTR_ERR(handle); | ||
1938 | |||
1939 | bitmap_bh = read_block_bitmap(sb, group); | ||
1940 | if (!bitmap_bh) { | ||
1941 | err = -EIO; | ||
1942 | goto err_out; | ||
1943 | } | ||
1944 | |||
1945 | BUFFER_TRACE(bitmap_bh, "getting undo access"); | ||
1946 | err = ext3_journal_get_undo_access(handle, bitmap_bh); | ||
1947 | if (err) | ||
1948 | goto err_out; | ||
1949 | |||
1950 | gdp = ext3_get_group_desc(sb, group, &gdp_bh); | ||
1951 | if (!gdp) { | ||
1952 | err = -EIO; | ||
1953 | goto err_out; | ||
1954 | } | ||
1955 | |||
1956 | BUFFER_TRACE(gdp_bh, "get_write_access"); | ||
1957 | err = ext3_journal_get_write_access(handle, gdp_bh); | ||
1958 | if (err) | ||
1959 | goto err_out; | ||
1960 | |||
1961 | free_blocks = le16_to_cpu(gdp->bg_free_blocks_count); | ||
1962 | sbi = EXT3_SB(sb); | ||
1963 | |||
1964 | /* Walk through the whole group */ | ||
1965 | while (start < max) { | ||
1966 | start = bitmap_search_next_usable_block(start, bitmap_bh, max); | ||
1967 | if (start < 0) | ||
1968 | break; | ||
1969 | next = start; | ||
1970 | |||
1971 | /* | ||
1972 | * Allocate contiguous free extents by setting bits in the | ||
1973 | * block bitmap | ||
1974 | */ | ||
1975 | while (next < max | ||
1976 | && claim_block(sb_bgl_lock(sbi, group), | ||
1977 | next, bitmap_bh)) { | ||
1978 | next++; | ||
1979 | } | ||
1980 | |||
1981 | /* We did not claim any blocks */ | ||
1982 | if (next == start) | ||
1983 | continue; | ||
1984 | |||
1985 | discard_block = (ext3_fsblk_t)start + | ||
1986 | ext3_group_first_block_no(sb, group); | ||
1987 | |||
1988 | /* Update counters */ | ||
1989 | spin_lock(sb_bgl_lock(sbi, group)); | ||
1990 | le16_add_cpu(&gdp->bg_free_blocks_count, start - next); | ||
1991 | spin_unlock(sb_bgl_lock(sbi, group)); | ||
1992 | percpu_counter_sub(&sbi->s_freeblocks_counter, next - start); | ||
1993 | |||
1994 | /* Do not issue a TRIM on extents smaller than minblocks */ | ||
1995 | if ((next - start) < minblocks) | ||
1996 | goto free_extent; | ||
1997 | |||
1998 | /* Send the TRIM command down to the device */ | ||
1999 | err = sb_issue_discard(sb, discard_block, next - start, | ||
2000 | GFP_NOFS, 0); | ||
2001 | count += (next - start); | ||
2002 | free_extent: | ||
2003 | freed = 0; | ||
2004 | |||
2005 | /* | ||
2006 | * Clear bits in the bitmap | ||
2007 | */ | ||
2008 | for (bit = start; bit < next; bit++) { | ||
2009 | BUFFER_TRACE(bitmap_bh, "clear bit"); | ||
2010 | if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, group), | ||
2011 | bit, bitmap_bh->b_data)) { | ||
2012 | ext3_error(sb, __func__, | ||
2013 | "bit already cleared for block "E3FSBLK, | ||
2014 | (unsigned long)bit); | ||
2015 | BUFFER_TRACE(bitmap_bh, "bit already cleared"); | ||
2016 | } else { | ||
2017 | freed++; | ||
2018 | } | ||
2019 | } | ||
2020 | |||
2021 | /* Update couters */ | ||
2022 | spin_lock(sb_bgl_lock(sbi, group)); | ||
2023 | le16_add_cpu(&gdp->bg_free_blocks_count, freed); | ||
2024 | spin_unlock(sb_bgl_lock(sbi, group)); | ||
2025 | percpu_counter_add(&sbi->s_freeblocks_counter, freed); | ||
2026 | |||
2027 | start = next; | ||
2028 | if (err < 0) { | ||
2029 | if (err != -EOPNOTSUPP) | ||
2030 | ext3_warning(sb, __func__, "Discard command " | ||
2031 | "returned error %d\n", err); | ||
2032 | break; | ||
2033 | } | ||
2034 | |||
2035 | if (fatal_signal_pending(current)) { | ||
2036 | err = -ERESTARTSYS; | ||
2037 | break; | ||
2038 | } | ||
2039 | |||
2040 | cond_resched(); | ||
2041 | |||
2042 | /* No more suitable extents */ | ||
2043 | if ((free_blocks - count) < minblocks) | ||
2044 | break; | ||
2045 | } | ||
2046 | |||
2047 | /* We dirtied the bitmap block */ | ||
2048 | BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); | ||
2049 | ret = ext3_journal_dirty_metadata(handle, bitmap_bh); | ||
2050 | if (!err) | ||
2051 | err = ret; | ||
2052 | |||
2053 | /* And the group descriptor block */ | ||
2054 | BUFFER_TRACE(gdp_bh, "dirtied group descriptor block"); | ||
2055 | ret = ext3_journal_dirty_metadata(handle, gdp_bh); | ||
2056 | if (!err) | ||
2057 | err = ret; | ||
2058 | |||
2059 | ext3_debug("trimmed %d blocks in the group %d\n", | ||
2060 | count, group); | ||
2061 | |||
2062 | err_out: | ||
2063 | if (err) | ||
2064 | count = err; | ||
2065 | ext3_journal_stop(handle); | ||
2066 | brelse(bitmap_bh); | ||
2067 | |||
2068 | return count; | ||
2069 | } | ||
2070 | |||
2071 | /** | ||
2072 | * ext3_trim_fs() -- trim ioctl handle function | ||
2073 | * @sb: superblock for filesystem | ||
2074 | * @start: First Byte to trim | ||
2075 | * @len: number of Bytes to trim from start | ||
2076 | * @minlen: minimum extent length in Bytes | ||
2077 | * | ||
2078 | * ext3_trim_fs goes through all allocation groups containing Bytes from | ||
2079 | * start to start+len. For each such a group ext3_trim_all_free function | ||
2080 | * is invoked to trim all free space. | ||
2081 | */ | ||
2082 | int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range) | ||
2083 | { | ||
2084 | ext3_grpblk_t last_block, first_block, free_blocks; | ||
2085 | unsigned long first_group, last_group; | ||
2086 | unsigned long group, ngroups; | ||
2087 | struct ext3_group_desc *gdp; | ||
2088 | struct ext3_super_block *es = EXT3_SB(sb)->s_es; | ||
2089 | uint64_t start, len, minlen, trimmed; | ||
2090 | ext3_fsblk_t max_blks = le32_to_cpu(es->s_blocks_count); | ||
2091 | int ret = 0; | ||
2092 | |||
2093 | start = range->start >> sb->s_blocksize_bits; | ||
2094 | len = range->len >> sb->s_blocksize_bits; | ||
2095 | minlen = range->minlen >> sb->s_blocksize_bits; | ||
2096 | trimmed = 0; | ||
2097 | |||
2098 | if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb))) | ||
2099 | return -EINVAL; | ||
2100 | if (start >= max_blks) | ||
2101 | goto out; | ||
2102 | if (start < le32_to_cpu(es->s_first_data_block)) { | ||
2103 | len -= le32_to_cpu(es->s_first_data_block) - start; | ||
2104 | start = le32_to_cpu(es->s_first_data_block); | ||
2105 | } | ||
2106 | if (start + len > max_blks) | ||
2107 | len = max_blks - start; | ||
2108 | |||
2109 | ngroups = EXT3_SB(sb)->s_groups_count; | ||
2110 | smp_rmb(); | ||
2111 | |||
2112 | /* Determine first and last group to examine based on start and len */ | ||
2113 | ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) start, | ||
2114 | &first_group, &first_block); | ||
2115 | ext3_get_group_no_and_offset(sb, (ext3_fsblk_t) (start + len), | ||
2116 | &last_group, &last_block); | ||
2117 | last_group = (last_group > ngroups - 1) ? ngroups - 1 : last_group; | ||
2118 | last_block = EXT3_BLOCKS_PER_GROUP(sb); | ||
2119 | |||
2120 | if (first_group > last_group) | ||
2121 | return -EINVAL; | ||
2122 | |||
2123 | for (group = first_group; group <= last_group; group++) { | ||
2124 | gdp = ext3_get_group_desc(sb, group, NULL); | ||
2125 | if (!gdp) | ||
2126 | break; | ||
2127 | |||
2128 | free_blocks = le16_to_cpu(gdp->bg_free_blocks_count); | ||
2129 | if (free_blocks < minlen) | ||
2130 | continue; | ||
2131 | |||
2132 | if (len >= EXT3_BLOCKS_PER_GROUP(sb)) | ||
2133 | len -= (EXT3_BLOCKS_PER_GROUP(sb) - first_block); | ||
2134 | else | ||
2135 | last_block = first_block + len; | ||
2136 | |||
2137 | ret = ext3_trim_all_free(sb, group, first_block, | ||
2138 | last_block, minlen); | ||
2139 | if (ret < 0) | ||
2140 | break; | ||
2141 | |||
2142 | trimmed += ret; | ||
2143 | first_block = 0; | ||
2144 | } | ||
2145 | |||
2146 | if (ret >= 0) | ||
2147 | ret = 0; | ||
2148 | |||
2149 | out: | ||
2150 | range->len = trimmed * sb->s_blocksize; | ||
2151 | |||
2152 | return ret; | ||
2153 | } | ||
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index e2e72c367cf6..34f0a072b935 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -69,25 +69,26 @@ int ext3_check_dir_entry (const char * function, struct inode * dir, | |||
69 | const char * error_msg = NULL; | 69 | const char * error_msg = NULL; |
70 | const int rlen = ext3_rec_len_from_disk(de->rec_len); | 70 | const int rlen = ext3_rec_len_from_disk(de->rec_len); |
71 | 71 | ||
72 | if (rlen < EXT3_DIR_REC_LEN(1)) | 72 | if (unlikely(rlen < EXT3_DIR_REC_LEN(1))) |
73 | error_msg = "rec_len is smaller than minimal"; | 73 | error_msg = "rec_len is smaller than minimal"; |
74 | else if (rlen % 4 != 0) | 74 | else if (unlikely(rlen % 4 != 0)) |
75 | error_msg = "rec_len % 4 != 0"; | 75 | error_msg = "rec_len % 4 != 0"; |
76 | else if (rlen < EXT3_DIR_REC_LEN(de->name_len)) | 76 | else if (unlikely(rlen < EXT3_DIR_REC_LEN(de->name_len))) |
77 | error_msg = "rec_len is too small for name_len"; | 77 | error_msg = "rec_len is too small for name_len"; |
78 | else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize) | 78 | else if (unlikely((((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize))) |
79 | error_msg = "directory entry across blocks"; | 79 | error_msg = "directory entry across blocks"; |
80 | else if (le32_to_cpu(de->inode) > | 80 | else if (unlikely(le32_to_cpu(de->inode) > |
81 | le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count)) | 81 | le32_to_cpu(EXT3_SB(dir->i_sb)->s_es->s_inodes_count))) |
82 | error_msg = "inode out of bounds"; | 82 | error_msg = "inode out of bounds"; |
83 | 83 | ||
84 | if (error_msg != NULL) | 84 | if (unlikely(error_msg != NULL)) |
85 | ext3_error (dir->i_sb, function, | 85 | ext3_error (dir->i_sb, function, |
86 | "bad entry in directory #%lu: %s - " | 86 | "bad entry in directory #%lu: %s - " |
87 | "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", | 87 | "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", |
88 | dir->i_ino, error_msg, offset, | 88 | dir->i_ino, error_msg, offset, |
89 | (unsigned long) le32_to_cpu(de->inode), | 89 | (unsigned long) le32_to_cpu(de->inode), |
90 | rlen, de->name_len); | 90 | rlen, de->name_len); |
91 | |||
91 | return error_msg == NULL ? 1 : 0; | 92 | return error_msg == NULL ? 1 : 0; |
92 | } | 93 | } |
93 | 94 | ||
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a9580617edd2..ae94f6d949f5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -2145,13 +2145,15 @@ static void ext3_clear_blocks(handle_t *handle, struct inode *inode, | |||
2145 | if (try_to_extend_transaction(handle, inode)) { | 2145 | if (try_to_extend_transaction(handle, inode)) { |
2146 | if (bh) { | 2146 | if (bh) { |
2147 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); | 2147 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); |
2148 | ext3_journal_dirty_metadata(handle, bh); | 2148 | if (ext3_journal_dirty_metadata(handle, bh)) |
2149 | return; | ||
2149 | } | 2150 | } |
2150 | ext3_mark_inode_dirty(handle, inode); | 2151 | ext3_mark_inode_dirty(handle, inode); |
2151 | truncate_restart_transaction(handle, inode); | 2152 | truncate_restart_transaction(handle, inode); |
2152 | if (bh) { | 2153 | if (bh) { |
2153 | BUFFER_TRACE(bh, "retaking write access"); | 2154 | BUFFER_TRACE(bh, "retaking write access"); |
2154 | ext3_journal_get_write_access(handle, bh); | 2155 | if (ext3_journal_get_write_access(handle, bh)) |
2156 | return; | ||
2155 | } | 2157 | } |
2156 | } | 2158 | } |
2157 | 2159 | ||
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 88974814783a..fc080dd561f7 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c | |||
@@ -276,7 +276,29 @@ group_add_out: | |||
276 | mnt_drop_write(filp->f_path.mnt); | 276 | mnt_drop_write(filp->f_path.mnt); |
277 | return err; | 277 | return err; |
278 | } | 278 | } |
279 | case FITRIM: { | ||
279 | 280 | ||
281 | struct super_block *sb = inode->i_sb; | ||
282 | struct fstrim_range range; | ||
283 | int ret = 0; | ||
284 | |||
285 | if (!capable(CAP_SYS_ADMIN)) | ||
286 | return -EPERM; | ||
287 | |||
288 | if (copy_from_user(&range, (struct fstrim_range *)arg, | ||
289 | sizeof(range))) | ||
290 | return -EFAULT; | ||
291 | |||
292 | ret = ext3_trim_fs(sb, &range); | ||
293 | if (ret < 0) | ||
294 | return ret; | ||
295 | |||
296 | if (copy_to_user((struct fstrim_range *)arg, &range, | ||
297 | sizeof(range))) | ||
298 | return -EFAULT; | ||
299 | |||
300 | return 0; | ||
301 | } | ||
280 | 302 | ||
281 | default: | 303 | default: |
282 | return -ENOTTY; | 304 | return -ENOTTY; |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index bce9dce639b8..b27ba71810ec 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -858,6 +858,7 @@ static struct buffer_head *ext3_find_entry(struct inode *dir, | |||
858 | struct buffer_head * bh_use[NAMEI_RA_SIZE]; | 858 | struct buffer_head * bh_use[NAMEI_RA_SIZE]; |
859 | struct buffer_head * bh, *ret = NULL; | 859 | struct buffer_head * bh, *ret = NULL; |
860 | unsigned long start, block, b; | 860 | unsigned long start, block, b; |
861 | const u8 *name = entry->name; | ||
861 | int ra_max = 0; /* Number of bh's in the readahead | 862 | int ra_max = 0; /* Number of bh's in the readahead |
862 | buffer, bh_use[] */ | 863 | buffer, bh_use[] */ |
863 | int ra_ptr = 0; /* Current index into readahead | 864 | int ra_ptr = 0; /* Current index into readahead |
@@ -871,6 +872,16 @@ static struct buffer_head *ext3_find_entry(struct inode *dir, | |||
871 | namelen = entry->len; | 872 | namelen = entry->len; |
872 | if (namelen > EXT3_NAME_LEN) | 873 | if (namelen > EXT3_NAME_LEN) |
873 | return NULL; | 874 | return NULL; |
875 | if ((namelen <= 2) && (name[0] == '.') && | ||
876 | (name[1] == '.' || name[1] == 0)) { | ||
877 | /* | ||
878 | * "." or ".." will only be in the first block | ||
879 | * NFS may look up ".."; "." should be handled by the VFS | ||
880 | */ | ||
881 | block = start = 0; | ||
882 | nblocks = 1; | ||
883 | goto restart; | ||
884 | } | ||
874 | if (is_dx(dir)) { | 885 | if (is_dx(dir)) { |
875 | bh = ext3_dx_find_entry(dir, entry, res_dir, &err); | 886 | bh = ext3_dx_find_entry(dir, entry, res_dir, &err); |
876 | /* | 887 | /* |
@@ -961,55 +972,35 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir, | |||
961 | struct qstr *entry, struct ext3_dir_entry_2 **res_dir, | 972 | struct qstr *entry, struct ext3_dir_entry_2 **res_dir, |
962 | int *err) | 973 | int *err) |
963 | { | 974 | { |
964 | struct super_block * sb; | 975 | struct super_block *sb = dir->i_sb; |
965 | struct dx_hash_info hinfo; | 976 | struct dx_hash_info hinfo; |
966 | u32 hash; | ||
967 | struct dx_frame frames[2], *frame; | 977 | struct dx_frame frames[2], *frame; |
968 | struct ext3_dir_entry_2 *de, *top; | ||
969 | struct buffer_head *bh; | 978 | struct buffer_head *bh; |
970 | unsigned long block; | 979 | unsigned long block; |
971 | int retval; | 980 | int retval; |
972 | int namelen = entry->len; | ||
973 | const u8 *name = entry->name; | ||
974 | 981 | ||
975 | sb = dir->i_sb; | 982 | if (!(frame = dx_probe(entry, dir, &hinfo, frames, err))) |
976 | /* NFS may look up ".." - look at dx_root directory block */ | 983 | return NULL; |
977 | if (namelen > 2 || name[0] != '.'|| (namelen == 2 && name[1] != '.')) { | ||
978 | if (!(frame = dx_probe(entry, dir, &hinfo, frames, err))) | ||
979 | return NULL; | ||
980 | } else { | ||
981 | frame = frames; | ||
982 | frame->bh = NULL; /* for dx_release() */ | ||
983 | frame->at = (struct dx_entry *)frames; /* hack for zero entry*/ | ||
984 | dx_set_block(frame->at, 0); /* dx_root block is 0 */ | ||
985 | } | ||
986 | hash = hinfo.hash; | ||
987 | do { | 984 | do { |
988 | block = dx_get_block(frame->at); | 985 | block = dx_get_block(frame->at); |
989 | if (!(bh = ext3_bread (NULL,dir, block, 0, err))) | 986 | if (!(bh = ext3_bread (NULL,dir, block, 0, err))) |
990 | goto errout; | 987 | goto errout; |
991 | de = (struct ext3_dir_entry_2 *) bh->b_data; | ||
992 | top = (struct ext3_dir_entry_2 *) ((char *) de + sb->s_blocksize - | ||
993 | EXT3_DIR_REC_LEN(0)); | ||
994 | for (; de < top; de = ext3_next_entry(de)) { | ||
995 | int off = (block << EXT3_BLOCK_SIZE_BITS(sb)) | ||
996 | + ((char *) de - bh->b_data); | ||
997 | |||
998 | if (!ext3_check_dir_entry(__func__, dir, de, bh, off)) { | ||
999 | brelse(bh); | ||
1000 | *err = ERR_BAD_DX_DIR; | ||
1001 | goto errout; | ||
1002 | } | ||
1003 | 988 | ||
1004 | if (ext3_match(namelen, name, de)) { | 989 | retval = search_dirblock(bh, dir, entry, |
1005 | *res_dir = de; | 990 | block << EXT3_BLOCK_SIZE_BITS(sb), |
1006 | dx_release(frames); | 991 | res_dir); |
1007 | return bh; | 992 | if (retval == 1) { |
1008 | } | 993 | dx_release(frames); |
994 | return bh; | ||
1009 | } | 995 | } |
1010 | brelse (bh); | 996 | brelse(bh); |
997 | if (retval == -1) { | ||
998 | *err = ERR_BAD_DX_DIR; | ||
999 | goto errout; | ||
1000 | } | ||
1001 | |||
1011 | /* Check to see if we should continue to search */ | 1002 | /* Check to see if we should continue to search */ |
1012 | retval = ext3_htree_next_block(dir, hash, frame, | 1003 | retval = ext3_htree_next_block(dir, hinfo.hash, frame, |
1013 | frames, NULL); | 1004 | frames, NULL); |
1014 | if (retval < 0) { | 1005 | if (retval < 0) { |
1015 | ext3_warning(sb, __func__, | 1006 | ext3_warning(sb, __func__, |
@@ -1047,7 +1038,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str | |||
1047 | return ERR_PTR(-EIO); | 1038 | return ERR_PTR(-EIO); |
1048 | } | 1039 | } |
1049 | inode = ext3_iget(dir->i_sb, ino); | 1040 | inode = ext3_iget(dir->i_sb, ino); |
1050 | if (unlikely(IS_ERR(inode))) { | 1041 | if (IS_ERR(inode)) { |
1051 | if (PTR_ERR(inode) == -ESTALE) { | 1042 | if (PTR_ERR(inode) == -ESTALE) { |
1052 | ext3_error(dir->i_sb, __func__, | 1043 | ext3_error(dir->i_sb, __func__, |
1053 | "deleted inode referenced: %lu", | 1044 | "deleted inode referenced: %lu", |
@@ -1607,7 +1598,9 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1607 | if (err) | 1598 | if (err) |
1608 | goto journal_error; | 1599 | goto journal_error; |
1609 | } | 1600 | } |
1610 | ext3_journal_dirty_metadata(handle, frames[0].bh); | 1601 | err = ext3_journal_dirty_metadata(handle, frames[0].bh); |
1602 | if (err) | ||
1603 | goto journal_error; | ||
1611 | } | 1604 | } |
1612 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); | 1605 | de = do_split(handle, dir, &bh, frame, &hinfo, &err); |
1613 | if (!de) | 1606 | if (!de) |
@@ -1644,8 +1637,13 @@ static int ext3_delete_entry (handle_t *handle, | |||
1644 | if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i)) | 1637 | if (!ext3_check_dir_entry("ext3_delete_entry", dir, de, bh, i)) |
1645 | return -EIO; | 1638 | return -EIO; |
1646 | if (de == de_del) { | 1639 | if (de == de_del) { |
1640 | int err; | ||
1641 | |||
1647 | BUFFER_TRACE(bh, "get_write_access"); | 1642 | BUFFER_TRACE(bh, "get_write_access"); |
1648 | ext3_journal_get_write_access(handle, bh); | 1643 | err = ext3_journal_get_write_access(handle, bh); |
1644 | if (err) | ||
1645 | goto journal_error; | ||
1646 | |||
1649 | if (pde) | 1647 | if (pde) |
1650 | pde->rec_len = ext3_rec_len_to_disk( | 1648 | pde->rec_len = ext3_rec_len_to_disk( |
1651 | ext3_rec_len_from_disk(pde->rec_len) + | 1649 | ext3_rec_len_from_disk(pde->rec_len) + |
@@ -1654,7 +1652,12 @@ static int ext3_delete_entry (handle_t *handle, | |||
1654 | de->inode = 0; | 1652 | de->inode = 0; |
1655 | dir->i_version++; | 1653 | dir->i_version++; |
1656 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); | 1654 | BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata"); |
1657 | ext3_journal_dirty_metadata(handle, bh); | 1655 | err = ext3_journal_dirty_metadata(handle, bh); |
1656 | if (err) { | ||
1657 | journal_error: | ||
1658 | ext3_std_error(dir->i_sb, err); | ||
1659 | return err; | ||
1660 | } | ||
1658 | return 0; | 1661 | return 0; |
1659 | } | 1662 | } |
1660 | i += ext3_rec_len_from_disk(de->rec_len); | 1663 | i += ext3_rec_len_from_disk(de->rec_len); |
@@ -1762,7 +1765,7 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode) | |||
1762 | { | 1765 | { |
1763 | handle_t *handle; | 1766 | handle_t *handle; |
1764 | struct inode * inode; | 1767 | struct inode * inode; |
1765 | struct buffer_head * dir_block; | 1768 | struct buffer_head * dir_block = NULL; |
1766 | struct ext3_dir_entry_2 * de; | 1769 | struct ext3_dir_entry_2 * de; |
1767 | int err, retries = 0; | 1770 | int err, retries = 0; |
1768 | 1771 | ||
@@ -1790,15 +1793,14 @@ retry: | |||
1790 | inode->i_fop = &ext3_dir_operations; | 1793 | inode->i_fop = &ext3_dir_operations; |
1791 | inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; | 1794 | inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; |
1792 | dir_block = ext3_bread (handle, inode, 0, 1, &err); | 1795 | dir_block = ext3_bread (handle, inode, 0, 1, &err); |
1793 | if (!dir_block) { | 1796 | if (!dir_block) |
1794 | drop_nlink(inode); /* is this nlink == 0? */ | 1797 | goto out_clear_inode; |
1795 | unlock_new_inode(inode); | 1798 | |
1796 | ext3_mark_inode_dirty(handle, inode); | ||
1797 | iput (inode); | ||
1798 | goto out_stop; | ||
1799 | } | ||
1800 | BUFFER_TRACE(dir_block, "get_write_access"); | 1799 | BUFFER_TRACE(dir_block, "get_write_access"); |
1801 | ext3_journal_get_write_access(handle, dir_block); | 1800 | err = ext3_journal_get_write_access(handle, dir_block); |
1801 | if (err) | ||
1802 | goto out_clear_inode; | ||
1803 | |||
1802 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; | 1804 | de = (struct ext3_dir_entry_2 *) dir_block->b_data; |
1803 | de->inode = cpu_to_le32(inode->i_ino); | 1805 | de->inode = cpu_to_le32(inode->i_ino); |
1804 | de->name_len = 1; | 1806 | de->name_len = 1; |
@@ -1814,11 +1816,16 @@ retry: | |||
1814 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); | 1816 | ext3_set_de_type(dir->i_sb, de, S_IFDIR); |
1815 | inode->i_nlink = 2; | 1817 | inode->i_nlink = 2; |
1816 | BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); | 1818 | BUFFER_TRACE(dir_block, "call ext3_journal_dirty_metadata"); |
1817 | ext3_journal_dirty_metadata(handle, dir_block); | 1819 | err = ext3_journal_dirty_metadata(handle, dir_block); |
1818 | brelse (dir_block); | 1820 | if (err) |
1819 | ext3_mark_inode_dirty(handle, inode); | 1821 | goto out_clear_inode; |
1820 | err = ext3_add_entry (handle, dentry, inode); | 1822 | |
1823 | err = ext3_mark_inode_dirty(handle, inode); | ||
1824 | if (!err) | ||
1825 | err = ext3_add_entry (handle, dentry, inode); | ||
1826 | |||
1821 | if (err) { | 1827 | if (err) { |
1828 | out_clear_inode: | ||
1822 | inode->i_nlink = 0; | 1829 | inode->i_nlink = 0; |
1823 | unlock_new_inode(inode); | 1830 | unlock_new_inode(inode); |
1824 | ext3_mark_inode_dirty(handle, inode); | 1831 | ext3_mark_inode_dirty(handle, inode); |
@@ -1827,10 +1834,14 @@ retry: | |||
1827 | } | 1834 | } |
1828 | inc_nlink(dir); | 1835 | inc_nlink(dir); |
1829 | ext3_update_dx_flag(dir); | 1836 | ext3_update_dx_flag(dir); |
1830 | ext3_mark_inode_dirty(handle, dir); | 1837 | err = ext3_mark_inode_dirty(handle, dir); |
1838 | if (err) | ||
1839 | goto out_clear_inode; | ||
1840 | |||
1831 | d_instantiate(dentry, inode); | 1841 | d_instantiate(dentry, inode); |
1832 | unlock_new_inode(inode); | 1842 | unlock_new_inode(inode); |
1833 | out_stop: | 1843 | out_stop: |
1844 | brelse(dir_block); | ||
1834 | ext3_journal_stop(handle); | 1845 | ext3_journal_stop(handle); |
1835 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) | 1846 | if (err == -ENOSPC && ext3_should_retry_alloc(dir->i_sb, &retries)) |
1836 | goto retry; | 1847 | goto retry; |
@@ -2353,7 +2364,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, | |||
2353 | goto end_rename; | 2364 | goto end_rename; |
2354 | } else { | 2365 | } else { |
2355 | BUFFER_TRACE(new_bh, "get write access"); | 2366 | BUFFER_TRACE(new_bh, "get write access"); |
2356 | ext3_journal_get_write_access(handle, new_bh); | 2367 | retval = ext3_journal_get_write_access(handle, new_bh); |
2368 | if (retval) | ||
2369 | goto journal_error; | ||
2357 | new_de->inode = cpu_to_le32(old_inode->i_ino); | 2370 | new_de->inode = cpu_to_le32(old_inode->i_ino); |
2358 | if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb, | 2371 | if (EXT3_HAS_INCOMPAT_FEATURE(new_dir->i_sb, |
2359 | EXT3_FEATURE_INCOMPAT_FILETYPE)) | 2372 | EXT3_FEATURE_INCOMPAT_FILETYPE)) |
@@ -2362,7 +2375,9 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, | |||
2362 | new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME_SEC; | 2375 | new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME_SEC; |
2363 | ext3_mark_inode_dirty(handle, new_dir); | 2376 | ext3_mark_inode_dirty(handle, new_dir); |
2364 | BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata"); | 2377 | BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata"); |
2365 | ext3_journal_dirty_metadata(handle, new_bh); | 2378 | retval = ext3_journal_dirty_metadata(handle, new_bh); |
2379 | if (retval) | ||
2380 | goto journal_error; | ||
2366 | brelse(new_bh); | 2381 | brelse(new_bh); |
2367 | new_bh = NULL; | 2382 | new_bh = NULL; |
2368 | } | 2383 | } |
@@ -2411,10 +2426,17 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, | |||
2411 | ext3_update_dx_flag(old_dir); | 2426 | ext3_update_dx_flag(old_dir); |
2412 | if (dir_bh) { | 2427 | if (dir_bh) { |
2413 | BUFFER_TRACE(dir_bh, "get_write_access"); | 2428 | BUFFER_TRACE(dir_bh, "get_write_access"); |
2414 | ext3_journal_get_write_access(handle, dir_bh); | 2429 | retval = ext3_journal_get_write_access(handle, dir_bh); |
2430 | if (retval) | ||
2431 | goto journal_error; | ||
2415 | PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); | 2432 | PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); |
2416 | BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); | 2433 | BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); |
2417 | ext3_journal_dirty_metadata(handle, dir_bh); | 2434 | retval = ext3_journal_dirty_metadata(handle, dir_bh); |
2435 | if (retval) { | ||
2436 | journal_error: | ||
2437 | ext3_std_error(new_dir->i_sb, retval); | ||
2438 | goto end_rename; | ||
2439 | } | ||
2418 | drop_nlink(old_dir); | 2440 | drop_nlink(old_dir); |
2419 | if (new_inode) { | 2441 | if (new_inode) { |
2420 | drop_nlink(new_inode); | 2442 | drop_nlink(new_inode); |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index e746d30b1232..108b142e11ed 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -249,7 +249,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
249 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); | 249 | memcpy(gdb->b_data, sbi->s_group_desc[i]->b_data, gdb->b_size); |
250 | set_buffer_uptodate(gdb); | 250 | set_buffer_uptodate(gdb); |
251 | unlock_buffer(gdb); | 251 | unlock_buffer(gdb); |
252 | ext3_journal_dirty_metadata(handle, gdb); | 252 | err = ext3_journal_dirty_metadata(handle, gdb); |
253 | if (err) { | ||
254 | brelse(gdb); | ||
255 | goto exit_bh; | ||
256 | } | ||
253 | ext3_set_bit(bit, bh->b_data); | 257 | ext3_set_bit(bit, bh->b_data); |
254 | brelse(gdb); | 258 | brelse(gdb); |
255 | } | 259 | } |
@@ -269,7 +273,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
269 | err = PTR_ERR(gdb); | 273 | err = PTR_ERR(gdb); |
270 | goto exit_bh; | 274 | goto exit_bh; |
271 | } | 275 | } |
272 | ext3_journal_dirty_metadata(handle, gdb); | 276 | err = ext3_journal_dirty_metadata(handle, gdb); |
277 | if (err) { | ||
278 | brelse(gdb); | ||
279 | goto exit_bh; | ||
280 | } | ||
273 | ext3_set_bit(bit, bh->b_data); | 281 | ext3_set_bit(bit, bh->b_data); |
274 | brelse(gdb); | 282 | brelse(gdb); |
275 | } | 283 | } |
@@ -295,7 +303,11 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
295 | err = PTR_ERR(it); | 303 | err = PTR_ERR(it); |
296 | goto exit_bh; | 304 | goto exit_bh; |
297 | } | 305 | } |
298 | ext3_journal_dirty_metadata(handle, it); | 306 | err = ext3_journal_dirty_metadata(handle, it); |
307 | if (err) { | ||
308 | brelse(it); | ||
309 | goto exit_bh; | ||
310 | } | ||
299 | brelse(it); | 311 | brelse(it); |
300 | ext3_set_bit(bit, bh->b_data); | 312 | ext3_set_bit(bit, bh->b_data); |
301 | } | 313 | } |
@@ -306,7 +318,9 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
306 | 318 | ||
307 | mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), | 319 | mark_bitmap_end(input->blocks_count, EXT3_BLOCKS_PER_GROUP(sb), |
308 | bh->b_data); | 320 | bh->b_data); |
309 | ext3_journal_dirty_metadata(handle, bh); | 321 | err = ext3_journal_dirty_metadata(handle, bh); |
322 | if (err) | ||
323 | goto exit_bh; | ||
310 | brelse(bh); | 324 | brelse(bh); |
311 | 325 | ||
312 | /* Mark unused entries in inode bitmap used */ | 326 | /* Mark unused entries in inode bitmap used */ |
@@ -319,7 +333,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
319 | 333 | ||
320 | mark_bitmap_end(EXT3_INODES_PER_GROUP(sb), EXT3_BLOCKS_PER_GROUP(sb), | 334 | mark_bitmap_end(EXT3_INODES_PER_GROUP(sb), EXT3_BLOCKS_PER_GROUP(sb), |
321 | bh->b_data); | 335 | bh->b_data); |
322 | ext3_journal_dirty_metadata(handle, bh); | 336 | err = ext3_journal_dirty_metadata(handle, bh); |
323 | exit_bh: | 337 | exit_bh: |
324 | brelse(bh); | 338 | brelse(bh); |
325 | 339 | ||
@@ -503,12 +517,19 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
503 | * reserved inode, and will become GDT blocks (primary and backup). | 517 | * reserved inode, and will become GDT blocks (primary and backup). |
504 | */ | 518 | */ |
505 | data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)] = 0; | 519 | data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)] = 0; |
506 | ext3_journal_dirty_metadata(handle, dind); | 520 | err = ext3_journal_dirty_metadata(handle, dind); |
521 | if (err) | ||
522 | goto exit_group_desc; | ||
507 | brelse(dind); | 523 | brelse(dind); |
524 | dind = NULL; | ||
508 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; | 525 | inode->i_blocks -= (gdbackups + 1) * sb->s_blocksize >> 9; |
509 | ext3_mark_iloc_dirty(handle, inode, &iloc); | 526 | err = ext3_mark_iloc_dirty(handle, inode, &iloc); |
527 | if (err) | ||
528 | goto exit_group_desc; | ||
510 | memset((*primary)->b_data, 0, sb->s_blocksize); | 529 | memset((*primary)->b_data, 0, sb->s_blocksize); |
511 | ext3_journal_dirty_metadata(handle, *primary); | 530 | err = ext3_journal_dirty_metadata(handle, *primary); |
531 | if (err) | ||
532 | goto exit_group_desc; | ||
512 | 533 | ||
513 | o_group_desc = EXT3_SB(sb)->s_group_desc; | 534 | o_group_desc = EXT3_SB(sb)->s_group_desc; |
514 | memcpy(n_group_desc, o_group_desc, | 535 | memcpy(n_group_desc, o_group_desc, |
@@ -519,10 +540,14 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, | |||
519 | kfree(o_group_desc); | 540 | kfree(o_group_desc); |
520 | 541 | ||
521 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); | 542 | le16_add_cpu(&es->s_reserved_gdt_blocks, -1); |
522 | ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); | 543 | err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); |
544 | if (err) | ||
545 | goto exit_inode; | ||
523 | 546 | ||
524 | return 0; | 547 | return 0; |
525 | 548 | ||
549 | exit_group_desc: | ||
550 | kfree(n_group_desc); | ||
526 | exit_inode: | 551 | exit_inode: |
527 | //ext3_journal_release_buffer(handle, iloc.bh); | 552 | //ext3_journal_release_buffer(handle, iloc.bh); |
528 | brelse(iloc.bh); | 553 | brelse(iloc.bh); |
@@ -706,16 +731,20 @@ static void update_backups(struct super_block *sb, | |||
706 | } | 731 | } |
707 | ext3_debug("update metadata backup %#04lx\n", | 732 | ext3_debug("update metadata backup %#04lx\n", |
708 | (unsigned long)bh->b_blocknr); | 733 | (unsigned long)bh->b_blocknr); |
709 | if ((err = ext3_journal_get_write_access(handle, bh))) | 734 | if ((err = ext3_journal_get_write_access(handle, bh))) { |
735 | brelse(bh); | ||
710 | break; | 736 | break; |
737 | } | ||
711 | lock_buffer(bh); | 738 | lock_buffer(bh); |
712 | memcpy(bh->b_data, data, size); | 739 | memcpy(bh->b_data, data, size); |
713 | if (rest) | 740 | if (rest) |
714 | memset(bh->b_data + size, 0, rest); | 741 | memset(bh->b_data + size, 0, rest); |
715 | set_buffer_uptodate(bh); | 742 | set_buffer_uptodate(bh); |
716 | unlock_buffer(bh); | 743 | unlock_buffer(bh); |
717 | ext3_journal_dirty_metadata(handle, bh); | 744 | err = ext3_journal_dirty_metadata(handle, bh); |
718 | brelse(bh); | 745 | brelse(bh); |
746 | if (err) | ||
747 | break; | ||
719 | } | 748 | } |
720 | if ((err2 = ext3_journal_stop(handle)) && !err) | 749 | if ((err2 = ext3_journal_stop(handle)) && !err) |
721 | err = err2; | 750 | err = err2; |
@@ -922,7 +951,9 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) | |||
922 | /* Update the global fs size fields */ | 951 | /* Update the global fs size fields */ |
923 | sbi->s_groups_count++; | 952 | sbi->s_groups_count++; |
924 | 953 | ||
925 | ext3_journal_dirty_metadata(handle, primary); | 954 | err = ext3_journal_dirty_metadata(handle, primary); |
955 | if (err) | ||
956 | goto exit_journal; | ||
926 | 957 | ||
927 | /* Update the reserved block counts only once the new group is | 958 | /* Update the reserved block counts only once the new group is |
928 | * active. */ | 959 | * active. */ |
@@ -934,7 +965,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) | |||
934 | percpu_counter_add(&sbi->s_freeinodes_counter, | 965 | percpu_counter_add(&sbi->s_freeinodes_counter, |
935 | EXT3_INODES_PER_GROUP(sb)); | 966 | EXT3_INODES_PER_GROUP(sb)); |
936 | 967 | ||
937 | ext3_journal_dirty_metadata(handle, sbi->s_sbh); | 968 | err = ext3_journal_dirty_metadata(handle, sbi->s_sbh); |
938 | 969 | ||
939 | exit_journal: | 970 | exit_journal: |
940 | mutex_unlock(&sbi->s_resize_lock); | 971 | mutex_unlock(&sbi->s_resize_lock); |
@@ -1064,8 +1095,14 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, | |||
1064 | goto exit_put; | 1095 | goto exit_put; |
1065 | } | 1096 | } |
1066 | es->s_blocks_count = cpu_to_le32(o_blocks_count + add); | 1097 | es->s_blocks_count = cpu_to_le32(o_blocks_count + add); |
1067 | ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); | 1098 | err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh); |
1068 | mutex_unlock(&EXT3_SB(sb)->s_resize_lock); | 1099 | mutex_unlock(&EXT3_SB(sb)->s_resize_lock); |
1100 | if (err) { | ||
1101 | ext3_warning(sb, __func__, | ||
1102 | "error %d on journal dirty metadata", err); | ||
1103 | ext3_journal_stop(handle); | ||
1104 | goto exit_put; | ||
1105 | } | ||
1069 | ext3_debug("freeing blocks "E3FSBLK" through "E3FSBLK"\n", | 1106 | ext3_debug("freeing blocks "E3FSBLK" through "E3FSBLK"\n", |
1070 | o_blocks_count, o_blocks_count + add); | 1107 | o_blocks_count, o_blocks_count + add); |
1071 | ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); | 1108 | ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 77ce1616f725..b7d0554631e4 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -143,12 +143,16 @@ void ext3_journal_abort_handle(const char *caller, const char *err_fn, | |||
143 | void ext3_msg(struct super_block *sb, const char *prefix, | 143 | void ext3_msg(struct super_block *sb, const char *prefix, |
144 | const char *fmt, ...) | 144 | const char *fmt, ...) |
145 | { | 145 | { |
146 | struct va_format vaf; | ||
146 | va_list args; | 147 | va_list args; |
147 | 148 | ||
148 | va_start(args, fmt); | 149 | va_start(args, fmt); |
149 | printk("%sEXT3-fs (%s): ", prefix, sb->s_id); | 150 | |
150 | vprintk(fmt, args); | 151 | vaf.fmt = fmt; |
151 | printk("\n"); | 152 | vaf.va = &args; |
153 | |||
154 | printk("%sEXT3-fs (%s): %pV\n", prefix, sb->s_id, &vaf); | ||
155 | |||
152 | va_end(args); | 156 | va_end(args); |
153 | } | 157 | } |
154 | 158 | ||
@@ -195,15 +199,20 @@ static void ext3_handle_error(struct super_block *sb) | |||
195 | sb->s_id); | 199 | sb->s_id); |
196 | } | 200 | } |
197 | 201 | ||
198 | void ext3_error (struct super_block * sb, const char * function, | 202 | void ext3_error(struct super_block *sb, const char *function, |
199 | const char * fmt, ...) | 203 | const char *fmt, ...) |
200 | { | 204 | { |
205 | struct va_format vaf; | ||
201 | va_list args; | 206 | va_list args; |
202 | 207 | ||
203 | va_start(args, fmt); | 208 | va_start(args, fmt); |
204 | printk(KERN_CRIT "EXT3-fs error (device %s): %s: ",sb->s_id, function); | 209 | |
205 | vprintk(fmt, args); | 210 | vaf.fmt = fmt; |
206 | printk("\n"); | 211 | vaf.va = &args; |
212 | |||
213 | printk(KERN_CRIT "EXT3-fs error (device %s): %s: %pV\n", | ||
214 | sb->s_id, function, &vaf); | ||
215 | |||
207 | va_end(args); | 216 | va_end(args); |
208 | 217 | ||
209 | ext3_handle_error(sb); | 218 | ext3_handle_error(sb); |
@@ -274,15 +283,20 @@ void __ext3_std_error (struct super_block * sb, const char * function, | |||
274 | * case we take the easy way out and panic immediately. | 283 | * case we take the easy way out and panic immediately. |
275 | */ | 284 | */ |
276 | 285 | ||
277 | void ext3_abort (struct super_block * sb, const char * function, | 286 | void ext3_abort(struct super_block *sb, const char *function, |
278 | const char * fmt, ...) | 287 | const char *fmt, ...) |
279 | { | 288 | { |
289 | struct va_format vaf; | ||
280 | va_list args; | 290 | va_list args; |
281 | 291 | ||
282 | va_start(args, fmt); | 292 | va_start(args, fmt); |
283 | printk(KERN_CRIT "EXT3-fs (%s): error: %s: ", sb->s_id, function); | 293 | |
284 | vprintk(fmt, args); | 294 | vaf.fmt = fmt; |
285 | printk("\n"); | 295 | vaf.va = &args; |
296 | |||
297 | printk(KERN_CRIT "EXT3-fs (%s): error: %s: %pV\n", | ||
298 | sb->s_id, function, &vaf); | ||
299 | |||
286 | va_end(args); | 300 | va_end(args); |
287 | 301 | ||
288 | if (test_opt(sb, ERRORS_PANIC)) | 302 | if (test_opt(sb, ERRORS_PANIC)) |
@@ -300,16 +314,20 @@ void ext3_abort (struct super_block * sb, const char * function, | |||
300 | journal_abort(EXT3_SB(sb)->s_journal, -EIO); | 314 | journal_abort(EXT3_SB(sb)->s_journal, -EIO); |
301 | } | 315 | } |
302 | 316 | ||
303 | void ext3_warning (struct super_block * sb, const char * function, | 317 | void ext3_warning(struct super_block *sb, const char *function, |
304 | const char * fmt, ...) | 318 | const char *fmt, ...) |
305 | { | 319 | { |
320 | struct va_format vaf; | ||
306 | va_list args; | 321 | va_list args; |
307 | 322 | ||
308 | va_start(args, fmt); | 323 | va_start(args, fmt); |
309 | printk(KERN_WARNING "EXT3-fs (%s): warning: %s: ", | 324 | |
310 | sb->s_id, function); | 325 | vaf.fmt = fmt; |
311 | vprintk(fmt, args); | 326 | vaf.va = &args; |
312 | printk("\n"); | 327 | |
328 | printk(KERN_WARNING "EXT3-fs (%s): warning: %s: %pV\n", | ||
329 | sb->s_id, function, &vaf); | ||
330 | |||
313 | va_end(args); | 331 | va_end(args); |
314 | } | 332 | } |
315 | 333 | ||
@@ -1848,13 +1866,15 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1848 | goto failed_mount; | 1866 | goto failed_mount; |
1849 | } | 1867 | } |
1850 | 1868 | ||
1851 | if (generic_check_addressable(sb->s_blocksize_bits, | 1869 | err = generic_check_addressable(sb->s_blocksize_bits, |
1852 | le32_to_cpu(es->s_blocks_count))) { | 1870 | le32_to_cpu(es->s_blocks_count)); |
1871 | if (err) { | ||
1853 | ext3_msg(sb, KERN_ERR, | 1872 | ext3_msg(sb, KERN_ERR, |
1854 | "error: filesystem is too large to mount safely"); | 1873 | "error: filesystem is too large to mount safely"); |
1855 | if (sizeof(sector_t) < 8) | 1874 | if (sizeof(sector_t) < 8) |
1856 | ext3_msg(sb, KERN_ERR, | 1875 | ext3_msg(sb, KERN_ERR, |
1857 | "error: CONFIG_LBDAF not enabled"); | 1876 | "error: CONFIG_LBDAF not enabled"); |
1877 | ret = err; | ||
1858 | goto failed_mount; | 1878 | goto failed_mount; |
1859 | } | 1879 | } |
1860 | 1880 | ||
@@ -2297,7 +2317,7 @@ static int ext3_load_journal(struct super_block *sb, | |||
2297 | EXT3_SB(sb)->s_journal = journal; | 2317 | EXT3_SB(sb)->s_journal = journal; |
2298 | ext3_clear_journal_err(sb, es); | 2318 | ext3_clear_journal_err(sb, es); |
2299 | 2319 | ||
2300 | if (journal_devnum && | 2320 | if (!really_read_only && journal_devnum && |
2301 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { | 2321 | journal_devnum != le32_to_cpu(es->s_journal_dev)) { |
2302 | es->s_journal_dev = cpu_to_le32(journal_devnum); | 2322 | es->s_journal_dev = cpu_to_le32(journal_devnum); |
2303 | 2323 | ||