diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/balloc.c | 6 | ||||
-rw-r--r-- | fs/ext4/dir.c | 1 | ||||
-rw-r--r-- | fs/ext4/extents.c | 149 | ||||
-rw-r--r-- | fs/ext4/inode.c | 15 | ||||
-rw-r--r-- | fs/ext4/namei.c | 31 | ||||
-rw-r--r-- | fs/ext4/resize.c | 1 | ||||
-rw-r--r-- | fs/ext4/super.c | 12 | ||||
-rw-r--r-- | fs/ext4/xattr_security.c | 1 | ||||
-rw-r--r-- | fs/ext4/xattr_trusted.c | 1 | ||||
-rw-r--r-- | fs/ext4/xattr_user.c | 1 |
10 files changed, 133 insertions, 85 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 8a23483ca8d0..3b64bb16c727 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -30,15 +30,15 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, unsigned long *blockgrpp, ext4_grpblk_t *offsetp) { - struct ext4_super_block *es = EXT4_SB(sb)->s_es; + struct ext4_super_block *es = EXT4_SB(sb)->s_es; ext4_grpblk_t offset; - blocknr = blocknr - le32_to_cpu(es->s_first_data_block); + blocknr = blocknr - le32_to_cpu(es->s_first_data_block); offset = do_div(blocknr, EXT4_BLOCKS_PER_GROUP(sb)); if (offsetp) *offsetp = offset; if (blockgrpp) - *blockgrpp = blocknr; + *blockgrpp = blocknr; } diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index da80368b66f0..e8ad06e28318 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -25,7 +25,6 @@ #include <linux/jbd2.h> #include <linux/ext4_fs.h> #include <linux/buffer_head.h> -#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/rbtree.h> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 7916b50f9a13..b9ce24129070 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -34,7 +34,6 @@ #include <linux/time.h> #include <linux/ext4_jbd2.h> #include <linux/jbd.h> -#include <linux/smp_lock.h> #include <linux/highuid.h> #include <linux/pagemap.h> #include <linux/quotaops.h> @@ -375,7 +374,7 @@ ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int bloc le32_to_cpu(ix[-1].ei_block)); } BUG_ON(k && le32_to_cpu(ix->ei_block) - <= le32_to_cpu(ix[-1].ei_block)); + <= le32_to_cpu(ix[-1].ei_block)); if (block < le32_to_cpu(ix->ei_block)) break; chix = ix; @@ -424,8 +423,8 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) path->p_ext = l - 1; ext_debug(" -> %d:%llu:%d ", - le32_to_cpu(path->p_ext->ee_block), - ext_pblock(path->p_ext), + le32_to_cpu(path->p_ext->ee_block), + ext_pblock(path->p_ext), le16_to_cpu(path->p_ext->ee_len)); #ifdef CHECK_BINSEARCH @@ -436,7 +435,7 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) chex = ex = EXT_FIRST_EXTENT(eh); for (k = 0; k < le16_to_cpu(eh->eh_entries); k++, ex++) { BUG_ON(k && le32_to_cpu(ex->ee_block) - <= le32_to_cpu(ex[-1].ee_block)); + <= le32_to_cpu(ex[-1].ee_block)); if (block < le32_to_cpu(ex->ee_block)) break; chex = ex; @@ -578,7 +577,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1); BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries) - > le16_to_cpu(curp->p_hdr->eh_max)); + > le16_to_cpu(curp->p_hdr->eh_max)); BUG_ON(ix > EXT_LAST_INDEX(curp->p_hdr)); err = ext4_ext_dirty(handle, inode, curp); @@ -622,12 +621,12 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, border = path[depth].p_ext[1].ee_block; ext_debug("leaf will be split." " next leaf starts at %d\n", - le32_to_cpu(border)); + le32_to_cpu(border)); } else { border = newext->ee_block; ext_debug("leaf will be added." " next leaf starts at %d\n", - le32_to_cpu(border)); + le32_to_cpu(border)); } /* @@ -685,9 +684,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, while (path[depth].p_ext <= EXT_MAX_EXTENT(path[depth].p_hdr)) { ext_debug("move %d:%llu:%d in new leaf %llu\n", - le32_to_cpu(path[depth].p_ext->ee_block), - ext_pblock(path[depth].p_ext), - le16_to_cpu(path[depth].p_ext->ee_len), + le32_to_cpu(path[depth].p_ext->ee_block), + ext_pblock(path[depth].p_ext), + le16_to_cpu(path[depth].p_ext->ee_len), newblock); /*memmove(ex++, path[depth].p_ext++, sizeof(struct ext4_extent)); @@ -766,9 +765,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, EXT_LAST_INDEX(path[i].p_hdr)); while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { ext_debug("%d: move %d:%d in new index %llu\n", i, - le32_to_cpu(path[i].p_idx->ei_block), - idx_pblock(path[i].p_idx), - newblock); + le32_to_cpu(path[i].p_idx->ei_block), + idx_pblock(path[i].p_idx), + newblock); /*memmove(++fidx, path[i].p_idx++, sizeof(struct ext4_extent_idx)); neh->eh_entries++; @@ -1129,6 +1128,55 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, } /* + * check if a portion of the "newext" extent overlaps with an + * existing extent. + * + * If there is an overlap discovered, it updates the length of the newext + * such that there will be no overlap, and then returns 1. + * If there is no overlap found, it returns 0. + */ +unsigned int ext4_ext_check_overlap(struct inode *inode, + struct ext4_extent *newext, + struct ext4_ext_path *path) +{ + unsigned long b1, b2; + unsigned int depth, len1; + unsigned int ret = 0; + + b1 = le32_to_cpu(newext->ee_block); + len1 = le16_to_cpu(newext->ee_len); + depth = ext_depth(inode); + if (!path[depth].p_ext) + goto out; + b2 = le32_to_cpu(path[depth].p_ext->ee_block); + + /* + * get the next allocated block if the extent in the path + * is before the requested block(s) + */ + if (b2 < b1) { + b2 = ext4_ext_next_allocated_block(path); + if (b2 == EXT_MAX_BLOCK) + goto out; + } + + /* check for wrap through zero */ + if (b1 + len1 < b1) { + len1 = EXT_MAX_BLOCK - b1; + newext->ee_len = cpu_to_le16(len1); + ret = 1; + } + + /* check for overlap */ + if (b1 + len1 > b2) { + newext->ee_len = cpu_to_le16(b2 - b1); + ret = 1; + } +out: + return ret; +} + +/* * ext4_ext_insert_extent: * tries to merge requsted extent into the existing extent or * inserts requested extent as new one into the tree, @@ -1213,12 +1261,12 @@ has_space: if (!nearex) { /* there is no extent in this leaf, create first one */ ext_debug("first extent in the leaf: %d:%llu:%d\n", - le32_to_cpu(newext->ee_block), - ext_pblock(newext), - le16_to_cpu(newext->ee_len)); + le32_to_cpu(newext->ee_block), + ext_pblock(newext), + le16_to_cpu(newext->ee_len)); path[depth].p_ext = EXT_FIRST_EXTENT(eh); } else if (le32_to_cpu(newext->ee_block) - > le32_to_cpu(nearex->ee_block)) { + > le32_to_cpu(nearex->ee_block)) { /* BUG_ON(newext->ee_block == nearex->ee_block); */ if (nearex != EXT_LAST_EXTENT(eh)) { len = EXT_MAX_EXTENT(eh) - nearex; @@ -1226,9 +1274,9 @@ has_space: len = len < 0 ? 0 : len; ext_debug("insert %d:%llu:%d after: nearest 0x%p, " "move %d from 0x%p to 0x%p\n", - le32_to_cpu(newext->ee_block), - ext_pblock(newext), - le16_to_cpu(newext->ee_len), + le32_to_cpu(newext->ee_block), + ext_pblock(newext), + le16_to_cpu(newext->ee_len), nearex, len, nearex + 1, nearex + 2); memmove(nearex + 2, nearex + 1, len); } @@ -1359,9 +1407,9 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block, cbex.ec_start = 0; cbex.ec_type = EXT4_EXT_CACHE_GAP; } else { - cbex.ec_block = le32_to_cpu(ex->ee_block); - cbex.ec_len = le16_to_cpu(ex->ee_len); - cbex.ec_start = ext_pblock(ex); + cbex.ec_block = le32_to_cpu(ex->ee_block); + cbex.ec_len = le16_to_cpu(ex->ee_len); + cbex.ec_start = ext_pblock(ex); cbex.ec_type = EXT4_EXT_CACHE_EXTENT; } @@ -1432,16 +1480,16 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, len = le32_to_cpu(ex->ee_block) - block; ext_debug("cache gap(before): %lu [%lu:%lu]", (unsigned long) block, - (unsigned long) le32_to_cpu(ex->ee_block), - (unsigned long) le16_to_cpu(ex->ee_len)); + (unsigned long) le32_to_cpu(ex->ee_block), + (unsigned long) le16_to_cpu(ex->ee_len)); } else if (block >= le32_to_cpu(ex->ee_block) - + le16_to_cpu(ex->ee_len)) { - lblock = le32_to_cpu(ex->ee_block) - + le16_to_cpu(ex->ee_len); + + le16_to_cpu(ex->ee_len)) { + lblock = le32_to_cpu(ex->ee_block) + + le16_to_cpu(ex->ee_len); len = ext4_ext_next_allocated_block(path); ext_debug("cache gap(after): [%lu:%lu] %lu", - (unsigned long) le32_to_cpu(ex->ee_block), - (unsigned long) le16_to_cpu(ex->ee_len), + (unsigned long) le32_to_cpu(ex->ee_block), + (unsigned long) le16_to_cpu(ex->ee_len), (unsigned long) block); BUG_ON(len == lblock); len = len - lblock; @@ -1469,9 +1517,9 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block, BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && cex->ec_type != EXT4_EXT_CACHE_EXTENT); if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { - ex->ee_block = cpu_to_le32(cex->ec_block); + ex->ee_block = cpu_to_le32(cex->ec_block); ext4_ext_store_pblock(ex, cex->ec_start); - ex->ee_len = cpu_to_le16(cex->ec_len); + ex->ee_len = cpu_to_le16(cex->ec_len); ext_debug("%lu cached by %lu:%lu:%llu\n", (unsigned long) block, (unsigned long) cex->ec_block, @@ -1957,9 +2005,9 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, /* we should allocate requested block */ } else if (goal == EXT4_EXT_CACHE_EXTENT) { /* block is already allocated */ - newblock = iblock - - le32_to_cpu(newex.ee_block) - + ext_pblock(&newex); + newblock = iblock + - le32_to_cpu(newex.ee_block) + + ext_pblock(&newex); /* number of remaining blocks in the extent */ allocated = le16_to_cpu(newex.ee_len) - (iblock - le32_to_cpu(newex.ee_block)); @@ -1988,7 +2036,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, ex = path[depth].p_ext; if (ex) { - unsigned long ee_block = le32_to_cpu(ex->ee_block); + unsigned long ee_block = le32_to_cpu(ex->ee_block); ext4_fsblk_t ee_start = ext_pblock(ex); unsigned short ee_len = le16_to_cpu(ex->ee_len); @@ -2001,7 +2049,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, if (ee_len > EXT_MAX_LEN) goto out2; /* if found extent covers block, simply return it */ - if (iblock >= ee_block && iblock < ee_block + ee_len) { + if (iblock >= ee_block && iblock < ee_block + ee_len) { newblock = iblock - ee_block + ee_start; /* number of remaining blocks in the extent */ allocated = ee_len - (iblock - ee_block); @@ -2032,7 +2080,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, /* allocate new block */ goal = ext4_ext_find_goal(inode, path, iblock); - allocated = max_blocks; + + /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */ + newex.ee_block = cpu_to_le32(iblock); + newex.ee_len = cpu_to_le16(max_blocks); + err = ext4_ext_check_overlap(inode, &newex, path); + if (err) + allocated = le16_to_cpu(newex.ee_len); + else + allocated = max_blocks; newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); if (!newblock) goto out2; @@ -2040,12 +2096,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, goal, newblock, allocated); /* try to insert new extent into found leaf and return */ - newex.ee_block = cpu_to_le32(iblock); ext4_ext_store_pblock(&newex, newblock); newex.ee_len = cpu_to_le16(allocated); err = ext4_ext_insert_extent(handle, inode, path, &newex); - if (err) + if (err) { + /* free data blocks we just allocated */ + ext4_free_blocks(handle, inode, ext_pblock(&newex), + le16_to_cpu(newex.ee_len)); goto out2; + } if (extend_disksize && inode->i_size > EXT4_I(inode)->i_disksize) EXT4_I(inode)->i_disksize = inode->i_size; @@ -2158,11 +2217,3 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num) return needed; } - -EXPORT_SYMBOL(ext4_mark_inode_dirty); -EXPORT_SYMBOL(ext4_ext_invalidate_cache); -EXPORT_SYMBOL(ext4_ext_insert_extent); -EXPORT_SYMBOL(ext4_ext_walk_space); -EXPORT_SYMBOL(ext4_ext_find_goal); -EXPORT_SYMBOL(ext4_ext_calc_credits_for_insert); - diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 810b6d6474bf..8416fa28c422 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -27,7 +27,6 @@ #include <linux/time.h> #include <linux/ext4_jbd2.h> #include <linux/jbd2.h> -#include <linux/smp_lock.h> #include <linux/highuid.h> #include <linux/pagemap.h> #include <linux/quotaops.h> @@ -256,8 +255,8 @@ static int verify_chain(Indirect *from, Indirect *to) * @inode: inode in question (we are only interested in its superblock) * @i_block: block number to be parsed * @offsets: array to store the offsets in - * @boundary: set this non-zero if the referred-to block is likely to be - * followed (on disk) by an indirect block. + * @boundary: set this non-zero if the referred-to block is likely to be + * followed (on disk) by an indirect block. * * To store the locations of file's data ext4 uses a data structure common * for UNIX filesystems - tree of pointers anchored in the inode, with @@ -2611,9 +2610,9 @@ void ext4_read_inode(struct inode * inode) } inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); inode->i_size = le32_to_cpu(raw_inode->i_size); - inode->i_atime.tv_sec = le32_to_cpu(raw_inode->i_atime); - inode->i_ctime.tv_sec = le32_to_cpu(raw_inode->i_ctime); - inode->i_mtime.tv_sec = le32_to_cpu(raw_inode->i_mtime); + inode->i_atime.tv_sec = (signed)le32_to_cpu(raw_inode->i_atime); + inode->i_ctime.tv_sec = (signed)le32_to_cpu(raw_inode->i_ctime); + inode->i_mtime.tv_sec = (signed)le32_to_cpu(raw_inode->i_mtime); inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; ei->i_state = 0; @@ -2674,8 +2673,10 @@ void ext4_read_inode(struct inode * inode) */ ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > - EXT4_INODE_SIZE(inode->i_sb)) + EXT4_INODE_SIZE(inode->i_sb)) { + brelse (bh); goto bad_inode; + } if (ei->i_extra_isize == 0) { /* The extra space is currently unused. Use it. */ ei->i_extra_isize = sizeof(struct ext4_inode) - diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index e7e1d79a7d75..2811e5720ad0 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -36,7 +36,6 @@ #include <linux/quotaops.h> #include <linux/buffer_head.h> #include <linux/bio.h> -#include <linux/smp_lock.h> #include "namei.h" #include "xattr.h" @@ -47,7 +46,7 @@ */ #define NAMEI_RA_CHUNKS 2 #define NAMEI_RA_BLOCKS 4 -#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) +#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) static struct buffer_head *ext4_append(handle_t *handle, @@ -242,7 +241,7 @@ static inline unsigned dx_node_limit (struct inode *dir) static void dx_show_index (char * label, struct dx_entry *entries) { int i, n = dx_get_count (entries); - printk("%s index ", label); + printk("%s index ", label); for (i = 0; i < n; i++) { printk("%x->%u ", i? dx_get_hash(entries + i) : 0, dx_get_block(entries + i)); @@ -967,6 +966,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry, (block<<EXT4_BLOCK_SIZE_BITS(sb)) +((char *)de - bh->b_data))) { brelse (bh); + *err = ERR_BAD_DX_DIR; goto errout; } *res_dir = de; @@ -1132,9 +1132,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, char *data1 = (*bh)->b_data, *data2; unsigned split; struct ext4_dir_entry_2 *de = NULL, *de2; - int err; + int err = 0; - bh2 = ext4_append (handle, dir, &newblock, error); + bh2 = ext4_append (handle, dir, &newblock, &err); if (!(bh2)) { brelse(*bh); *bh = NULL; @@ -1143,14 +1143,9 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, BUFFER_TRACE(*bh, "get_write_access"); err = ext4_journal_get_write_access(handle, *bh); - if (err) { - journal_error: - brelse(*bh); - brelse(bh2); - *bh = NULL; - ext4_std_error(dir->i_sb, err); - goto errout; - } + if (err) + goto journal_error; + BUFFER_TRACE(frame->bh, "get_write_access"); err = ext4_journal_get_write_access(handle, frame->bh); if (err) @@ -1193,8 +1188,16 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, goto journal_error; brelse (bh2); dxtrace(dx_show_index ("frame", frame->entries)); -errout: return de; + +journal_error: + brelse(*bh); + brelse(bh2); + *bh = NULL; + ext4_std_error(dir->i_sb, err); +errout: + *error = err; + return NULL; } #endif diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index ea99f6c97f56..aa11d7dbe970 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -11,7 +11,6 @@ #define EXT4FS_DEBUG -#include <linux/smp_lock.h> #include <linux/ext4_jbd2.h> #include <linux/errno.h> diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 719126932354..175b68c60968 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -517,14 +517,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_orphan); + INIT_LIST_HEAD(&ei->i_orphan); #ifdef CONFIG_EXT4DEV_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - mutex_init(&ei->truncate_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->truncate_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) @@ -1987,7 +1985,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb, if (bd_claim(bdev, sb)) { printk(KERN_ERR - "EXT4: failed to claim external journal device.\n"); + "EXT4: failed to claim external journal device.\n"); blkdev_put(bdev); return NULL; } diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c index b6a6861951f9..f17eaf2321b9 100644 --- a/fs/ext4/xattr_security.c +++ b/fs/ext4/xattr_security.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/fs.h> -#include <linux/smp_lock.h> #include <linux/ext4_jbd2.h> #include <linux/ext4_fs.h> #include <linux/security.h> diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c index b76f2dbc82da..e0f05acdafec 100644 --- a/fs/ext4/xattr_trusted.c +++ b/fs/ext4/xattr_trusted.c @@ -9,7 +9,6 @@ #include <linux/string.h> #include <linux/capability.h> #include <linux/fs.h> -#include <linux/smp_lock.h> #include <linux/ext4_jbd2.h> #include <linux/ext4_fs.h> #include "xattr.h" diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c index c53cded0761a..7ed3d8ebf096 100644 --- a/fs/ext4/xattr_user.c +++ b/fs/ext4/xattr_user.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/fs.h> -#include <linux/smp_lock.h> #include <linux/ext4_jbd2.h> #include <linux/ext4_fs.h> #include "xattr.h" |