diff options
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 | ||||
| -rw-r--r-- | fs/ext3/xattr.c | 2 |
8 files changed, 474 insertions, 104 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 | ||
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index e69dc6dfaa89..32e6cc23bd9a 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c | |||
| @@ -925,7 +925,7 @@ ext3_xattr_ibody_set(handle_t *handle, struct inode *inode, | |||
| 925 | /* | 925 | /* |
| 926 | * ext3_xattr_set_handle() | 926 | * ext3_xattr_set_handle() |
| 927 | * | 927 | * |
| 928 | * Create, replace or remove an extended attribute for this inode. Buffer | 928 | * Create, replace or remove an extended attribute for this inode. Value |
| 929 | * is NULL to remove an existing extended attribute, and non-NULL to | 929 | * is NULL to remove an existing extended attribute, and non-NULL to |
| 930 | * either replace an existing extended attribute, or create a new extended | 930 | * either replace an existing extended attribute, or create a new extended |
| 931 | * attribute. The flags XATTR_REPLACE and XATTR_CREATE | 931 | * attribute. The flags XATTR_REPLACE and XATTR_CREATE |
