From 75ff1cadfd6549bb07126ad2b55989e461485fd9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Pali=20Roh=C3=A1r?= Date: Mon, 22 Aug 2011 14:45:25 +0200 Subject: [PATCH] Released version v48 --- kernel-power-2.6.28/.gitignore | 96 -- kernel-power-2.6.28/debian/changelog | 2 + kernel-power-2.6.28/debian/control | 2 +- .../debian/kernel-power-flasher.preinst | 1 + kernel-power-2.6.28/debian/madde.patch | 14 +- .../debian/patches/ext4-data-corruption.diff | 1216 ++++++++++---------- kernel-power-2.6.28/debian/rules | 26 +- 7 files changed, 628 insertions(+), 729 deletions(-) delete mode 100644 kernel-power-2.6.28/.gitignore diff --git a/kernel-power-2.6.28/.gitignore b/kernel-power-2.6.28/.gitignore deleted file mode 100644 index 01e9800..0000000 --- a/kernel-power-2.6.28/.gitignore +++ /dev/null @@ -1,96 +0,0 @@ -# -# NOTE! Don't add files that are generated in specific -# subdirectories here. Add them in the ".gitignore" file -# in that subdirectory instead. -# -# NOTE! Please use 'git-ls-files -i --exclude-standard' -# command after changing this file, to see if there are -# any tracked files which get ignored after the change. -# -# Normal rules -# -.* -*.o -*.o.* -*.a -*.s -*.ko -*.so -*.so.dbg -*.mod.c -*.i -*.lst -*.symtypes -*.order -*.elf -*.bin -*.gz - -# -# Top-level generic files -# -tags -TAGS -vmlinux -System.map -Module.markers -Module.symvers -!.gitignore -!.mailmap - -# -# Generated include files -# -include/asm -include/asm-*/asm-offsets.h -include/config -include/linux/autoconf.h -include/linux/compile.h -include/linux/version.h -include/linux/utsrelease.h -include/linux/bounds.h - -# stgit generated dirs -patches-* - -# quilt's files -#patches -#series - -# cscope files -cscope.* -ncscope.* - -*.orig -*~ -\#*# - -# kernel-power tree -.mailmap -COPYING -CREDITS -Documentation -Kbuild -MAINTAINERS -Makefile -README -REPORTING-BUGS -arch -block -crypto -drivers -firmware -fs -include -init -ipc -kernel -lib -mm -net -samples -scripts -security -sound -usr -virt diff --git a/kernel-power-2.6.28/debian/changelog b/kernel-power-2.6.28/debian/changelog index c3d1d95..f3d5501 100644 --- a/kernel-power-2.6.28/debian/changelog +++ b/kernel-power-2.6.28/debian/changelog @@ -14,6 +14,8 @@ kernel-power (1:2.6.28-10power48) fremantle; urgency=low * enabled nilfs2 kernel module * enabled xts kernel module * fixed class 10 microSD card + * disabled patch i2c-battery.diff + * disabled board-rx51-peripherals.diff (disabled autoloading bq27x00_battery module) -- Pali Rohár Sat, 09 Jul 2011 16:03:55 +0200 diff --git a/kernel-power-2.6.28/debian/control b/kernel-power-2.6.28/debian/control index ac43331..99c601c 100644 --- a/kernel-power-2.6.28/debian/control +++ b/kernel-power-2.6.28/debian/control @@ -236,7 +236,7 @@ Description: Linux kernel modules for debugging (kernel power 2.6.28.10) Package: kernel-power-debug Architecture: armel -Description: Linux kernel debug symblos for kernel power 2.6.28.10 +Description: Linux kernel debug symblos (kernel power 2.6.28.10) This packages provides vmlinux file for the kernel and kernel modules related to debugging. diff --git a/kernel-power-2.6.28/debian/kernel-power-flasher.preinst b/kernel-power-2.6.28/debian/kernel-power-flasher.preinst index 21f5256..e6d53cf 100644 --- a/kernel-power-2.6.28/debian/kernel-power-flasher.preinst +++ b/kernel-power-2.6.28/debian/kernel-power-flasher.preinst @@ -1,6 +1,7 @@ #!/bin/sh test "$1" = install || exit 0 # upgrades are fine +echo "Confirm information text on screen" f=/tmp/kernel-power-msg cat > $f < 3) -+ if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || -+ (*retries)++ > 3 || -+ !EXT4_SB(sb)->s_journal) - return 0; - - jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); -diff -uprN linux-2.6.28.orig/fs/ext4/ext4.h linux-2.6.28/fs/ext4/ext4.h ---- linux-2.6.28.orig/fs/ext4/ext4.h 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/ext4.h 2009-05-23 16:05:41.000000000 +0200 -@@ -248,6 +248,30 @@ struct flex_groups { - #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ - #define EXT4_FL_USER_MODIFIABLE 0x000B80FF /* User modifiable flags */ - -+/* Flags that should be inherited by new inodes from their parent. */ -+#define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\ -+ EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\ -+ EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ -+ EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ -+ EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL) -+ -+/* Flags that are appropriate for regular files (all but dir-specific ones). */ -+#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL)) -+ -+/* Flags that are appropriate for non-directories/regular files. */ -+#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL) -+ -+/* Mask out flags that are inappropriate for the given type of inode. */ -+static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags) -+{ -+ if (S_ISDIR(mode)) -+ return flags; -+ else if (S_ISREG(mode)) -+ return flags & EXT4_REG_FLMASK; -+ else -+ return flags & EXT4_OTHER_FLMASK; -+} -+ - /* - * Inode dynamic state flags - */ -@@ -529,7 +556,7 @@ do { \ - #define EXT4_MOUNT_NO_UID32 0x02000 /* Disable 32-bit UIDs */ - #define EXT4_MOUNT_XATTR_USER 0x04000 /* Extended user attributes */ - #define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ --#define EXT4_MOUNT_RESERVATION 0x10000 /* Preallocation */ -+#define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */ - #define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */ - #define EXT4_MOUNT_NOBH 0x40000 /* No bufferheads */ - #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ -diff -uprN linux-2.6.28.orig/fs/ext4/extents.c linux-2.6.28/fs/ext4/extents.c ---- linux-2.6.28.orig/fs/ext4/extents.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/extents.c 2009-05-23 16:05:41.000000000 +0200 -@@ -1120,7 +1120,8 @@ ext4_ext_search_right(struct inode *inod - struct ext4_extent_idx *ix; - struct ext4_extent *ex; - ext4_fsblk_t block; -- int depth, ee_len; -+ int depth; /* Note, NOT eh_depth; depth from top of tree */ -+ int ee_len; - - BUG_ON(path == NULL); - depth = path->p_depth; -@@ -1179,7 +1180,8 @@ ext4_ext_search_right(struct inode *inod - if (bh == NULL) - return -EIO; - eh = ext_block_hdr(bh); -- if (ext4_ext_check_header(inode, eh, depth)) { -+ /* subtract from p_depth to get proper eh_depth */ -+ if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) { - put_bh(bh); - return -EIO; - } -@@ -1740,11 +1742,13 @@ ext4_ext_put_in_cache(struct inode *inod - { - struct ext4_ext_cache *cex; - BUG_ON(len == 0); -+ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); - cex = &EXT4_I(inode)->i_cached_extent; - cex->ec_type = type; - cex->ec_block = block; - cex->ec_len = len; - cex->ec_start = start; -+ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); - } - - /* -@@ -1801,12 +1805,17 @@ ext4_ext_in_cache(struct inode *inode, e - struct ext4_extent *ex) - { - struct ext4_ext_cache *cex; -+ int ret = EXT4_EXT_CACHE_NO; - -+ /* -+ * We borrow i_block_reservation_lock to protect i_cached_extent -+ */ -+ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); - cex = &EXT4_I(inode)->i_cached_extent; - - /* has cache valid data? */ - if (cex->ec_type == EXT4_EXT_CACHE_NO) -- return EXT4_EXT_CACHE_NO; -+ goto errout; - - BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && - cex->ec_type != EXT4_EXT_CACHE_EXTENT); -@@ -1817,11 +1826,11 @@ ext4_ext_in_cache(struct inode *inode, e - ext_debug("%u cached by %u:%u:%llu\n", - block, - cex->ec_block, cex->ec_len, cex->ec_start); -- return cex->ec_type; -+ ret = cex->ec_type; - } -- -- /* not in cache */ -- return EXT4_EXT_CACHE_NO; -+errout: -+ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); -+ return ret; - } - - /* -@@ -2777,6 +2786,8 @@ int ext4_ext_get_blocks(handle_t *handle - if (allocated > max_blocks) - allocated = max_blocks; - set_buffer_unwritten(bh_result); -+ bh_result->b_bdev = inode->i_sb->s_bdev; -+ bh_result->b_blocknr = newblock; - goto out2; - } - -diff -uprN linux-2.6.28.orig/fs/ext4/ialloc.c linux-2.6.28/fs/ext4/ialloc.c ---- linux-2.6.28.orig/fs/ext4/ialloc.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/ialloc.c 2009-05-23 16:05:41.000000000 +0200 -@@ -188,7 +188,7 @@ void ext4_free_inode(handle_t *handle, s - struct ext4_group_desc *gdp; - struct ext4_super_block *es; - struct ext4_sb_info *sbi; -- int fatal = 0, err; -+ int fatal = 0, err, cleared; - ext4_group_t flex_group; - - if (atomic_read(&inode->i_count) > 1) { -@@ -243,8 +243,10 @@ void ext4_free_inode(handle_t *handle, s - goto error_return; - - /* Ok, now we can actually update the inode bitmaps.. */ -- if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group), -- bit, bitmap_bh->b_data)) -+ spin_lock(sb_bgl_lock(sbi, block_group)); -+ cleared = ext4_clear_bit(bit, bitmap_bh->b_data); -+ spin_unlock(sb_bgl_lock(sbi, block_group)); -+ if (!cleared) - ext4_error(sb, "ext4_free_inode", - "bit already cleared for inode %lu", ino); - else { -@@ -686,6 +688,7 @@ struct inode *ext4_new_inode(handle_t *h - struct inode *ret; - ext4_group_t i; - int free = 0; -+ static int once = 1; - ext4_group_t flex_group; - - /* Cannot create files in a deleted directory */ -@@ -705,10 +708,12 @@ struct inode *ext4_new_inode(handle_t *h - ret2 = find_group_flex(sb, dir, &group); - if (ret2 == -1) { - ret2 = find_group_other(sb, dir, &group); -- if (ret2 == 0 && printk_ratelimit()) -+ if (ret2 == 0 && once) { -+ once = 0; - printk(KERN_NOTICE "ext4: find_group_flex " - "failed, fallback succeeded dir %lu\n", - dir->i_ino); -+ } - } - goto got_group; - } -@@ -862,16 +867,12 @@ got: - ei->i_disksize = 0; - - /* -- * Don't inherit extent flag from directory. We set extent flag on -- * newly created directory and file only if -o extent mount option is -- * specified -+ * Don't inherit extent flag from directory, amongst others. We set -+ * extent flag on newly created directory and file only if -o extent -+ * mount option is specified - */ -- ei->i_flags = EXT4_I(dir)->i_flags & ~(EXT4_INDEX_FL|EXT4_EXTENTS_FL); -- if (S_ISLNK(mode)) -- ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL); -- /* dirsync only applies to directories */ -- if (!S_ISDIR(mode)) -- ei->i_flags &= ~EXT4_DIRSYNC_FL; -+ ei->i_flags = -+ ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED); - ei->i_file_acl = 0; - ei->i_dtime = 0; - ei->i_block_group = group; -diff -uprN linux-2.6.28.orig/fs/ext4/inode.c linux-2.6.28/fs/ext4/inode.c ---- linux-2.6.28.orig/fs/ext4/inode.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/inode.c 2009-05-23 16:05:41.000000000 +0200 -@@ -1052,6 +1059,7 @@ int ext4_get_blocks_wrap(handle_t *handl - int retval; - - clear_buffer_mapped(bh); -+ clear_buffer_unwritten(bh); - - /* - * Try to see if we can get the block without requesting -@@ -1082,6 +1090,18 @@ int ext4_get_blocks_wrap(handle_t *handl - return retval; - - /* -+ * When we call get_blocks without the create flag, the -+ * BH_Unwritten flag could have gotten set if the blocks -+ * requested were part of a uninitialized extent. We need to -+ * clear this flag now that we are committed to convert all or -+ * part of the uninitialized extent to be an initialized -+ * extent. This is because we need to avoid the combination -+ * of BH_Unwritten and BH_Mapped flags being simultaneously -+ * set on the buffer_head. -+ */ -+ clear_buffer_unwritten(bh); -+ -+ /* - * New blocks allocate and/or writing to uninitialized extent - * will possibly result in updating i_data, so we take - * the write lock of i_data_sem, and call get_blocks() -@@ -2180,6 +2200,10 @@ static int ext4_da_get_block_prep(struct - struct buffer_head *bh_result, int create) - { - int ret = 0; -+ sector_t invalid_block = ~((sector_t) 0xffff); -+ -+ if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es)) -+ invalid_block = ~0; - - BUG_ON(create == 0); - BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); -@@ -2201,11 +2225,18 @@ static int ext4_da_get_block_prep(struct - /* not enough space to reserve */ - return ret; - -- map_bh(bh_result, inode->i_sb, 0); -+ map_bh(bh_result, inode->i_sb, invalid_block); - set_buffer_new(bh_result); - set_buffer_delay(bh_result); - } else if (ret > 0) { - bh_result->b_size = (ret << inode->i_blkbits); -+ /* -+ * With sub-block writes into unwritten extents -+ * we also need to mark the buffer as new so that -+ * the unwritten parts of the buffer gets correctly zeroed. -+ */ -+ if (buffer_unwritten(bh_result)) -+ set_buffer_new(bh_result); - ret = 0; - } - -@@ -2493,7 +2524,7 @@ retry: - - ext4_journal_stop(handle); - -- if (mpd.retval == -ENOSPC) { -+ if ((mpd.retval == -ENOSPC) && sbi->s_journal) { - /* commit the transaction which would - * free blocks released in the transaction - * and try again -@@ -4167,11 +4243,9 @@ struct inode *ext4_iget(struct super_blo - ei->i_flags = le32_to_cpu(raw_inode->i_flags); - inode->i_blocks = ext4_inode_blocks(raw_inode, ei); - ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); -- if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != -- cpu_to_le32(EXT4_OS_HURD)) { -+ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) - ei->i_file_acl |= - ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; -- } - inode->i_size = ext4_isize(raw_inode); - ei->i_disksize = inode->i_size; - inode->i_generation = le32_to_cpu(raw_inode->i_generation); -@@ -4218,6 +4292,18 @@ struct inode *ext4_iget(struct super_blo - (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; - } - -+ if (ei->i_file_acl && -+ ((ei->i_file_acl < -+ (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + -+ EXT4_SB(sb)->s_gdb_count)) || -+ (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) { -+ ext4_error(sb, __func__, -+ "bad extended attribute block %llu in inode #%lu", -+ ei->i_file_acl, inode->i_ino); -+ ret = -EIO; -+ goto bad_inode; -+ } -+ - if (S_ISREG(inode->i_mode)) { - inode->i_op = &ext4_file_inode_operations; - inode->i_fop = &ext4_file_operations; -@@ -4232,7 +4318,8 @@ struct inode *ext4_iget(struct super_blo - inode->i_op = &ext4_symlink_inode_operations; - ext4_set_aops(inode); - } -- } else { -+ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || -+ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { - inode->i_op = &ext4_special_inode_operations; - if (raw_inode->i_block[0]) - init_special_inode(inode, inode->i_mode, -@@ -4240,6 +4327,13 @@ struct inode *ext4_iget(struct super_blo - else - init_special_inode(inode, inode->i_mode, - new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); -+ } else { -+ brelse(bh); -+ ret = -EIO; -+ ext4_error(inode->i_sb, __func__, -+ "bogus i_mode (%o) for inode=%lu", -+ inode->i_mode, inode->i_ino); -+ goto bad_inode; - } - brelse(iloc.bh); - ext4_set_inode_flags(inode); -diff -uprN linux-2.6.28.orig/fs/ext4/ioctl.c linux-2.6.28/fs/ext4/ioctl.c ---- linux-2.6.28.orig/fs/ext4/ioctl.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/ioctl.c 2009-05-23 16:05:41.000000000 +0200 -@@ -48,8 +48,7 @@ long ext4_ioctl(struct file *filp, unsig - if (err) - return err; - -- if (!S_ISDIR(inode->i_mode)) -- flags &= ~EXT4_DIRSYNC_FL; -+ flags = ext4_mask_flags(inode->i_mode, flags); - - err = -EPERM; - mutex_lock(&inode->i_mutex); -diff -uprN linux-2.6.28.orig/fs/ext4/mballoc.c linux-2.6.28/fs/ext4/mballoc.c ---- linux-2.6.28.orig/fs/ext4/mballoc.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/mballoc.c 2009-05-23 16:05:41.000000000 +0200 -@@ -1448,7 +1448,7 @@ static void ext4_mb_measure_extent(struc - struct ext4_free_extent *gex = &ac->ac_g_ex; - - BUG_ON(ex->fe_len <= 0); -- BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); -+ BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); - BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); - BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); - -@@ -2692,7 +2692,7 @@ int ext4_mb_init(struct super_block *sb, - i = (sb->s_blocksize_bits + 2) * sizeof(unsigned int); - sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL); - if (sbi->s_mb_maxs == NULL) { -- kfree(sbi->s_mb_maxs); -+ kfree(sbi->s_mb_offsets); - return -ENOMEM; - } - -@@ -3289,7 +3289,7 @@ ext4_mb_normalize_request(struct ext4_al - } - BUG_ON(start + size <= ac->ac_o_ex.fe_logical && - start > ac->ac_o_ex.fe_logical); -- BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); -+ BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); - - /* now prepare goal request */ - -@@ -3586,6 +3586,7 @@ static void ext4_mb_put_pa(struct ext4_a - struct super_block *sb, struct ext4_prealloc_space *pa) - { - unsigned long grp; -+ ext4_fsblk_t grp_blk; - - if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) - return; -@@ -3600,8 +3601,12 @@ static void ext4_mb_put_pa(struct ext4_a - pa->pa_deleted = 1; - spin_unlock(&pa->pa_lock); - -- /* -1 is to protect from crossing allocation group */ -- ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL); -+ grp_blk = pa->pa_pstart; -+ /* If linear, pa_pstart may be in the next group when pa is used up */ -+ if (pa->pa_linear) -+ grp_blk--; -+ -+ ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL); - - /* - * possible race: -@@ -4414,7 +4419,7 @@ static void ext4_mb_add_n_trim(struct ex - pa_inode_list) { - spin_lock(&tmp_pa->pa_lock); - if (tmp_pa->pa_deleted) { -- spin_unlock(&pa->pa_lock); -+ spin_unlock(&tmp_pa->pa_lock); - continue; - } - if (!added && pa->pa_free < tmp_pa->pa_free) { -diff -uprN linux-2.6.28.orig/fs/ext4/namei.c linux-2.6.28/fs/ext4/namei.c ---- linux-2.6.28.orig/fs/ext4/namei.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/namei.c 2009-05-23 16:05:41.000000000 +0200 -@@ -1056,8 +1056,16 @@ static struct dentry *ext4_lookup(struct - return ERR_PTR(-EIO); - } - inode = ext4_iget(dir->i_sb, ino); -- if (IS_ERR(inode)) -- return ERR_CAST(inode); -+ if (unlikely(IS_ERR(inode))) { -+ if (PTR_ERR(inode) == -ESTALE) { -+ ext4_error(dir->i_sb, __func__, -+ "deleted inode referenced: %u", -+ ino); -+ return ERR_PTR(-EIO); -+ } else { -+ return ERR_CAST(inode); -+ } -+ } - } - return d_splice_alias(inode, dentry); - } -@@ -2436,7 +2444,8 @@ static int ext4_rename(struct inode *old - ext4_mark_inode_dirty(handle, new_inode); - if (!new_inode->i_nlink) - ext4_orphan_add(handle, new_inode); -- force_da_alloc = 1; -+ if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC)) -+ force_da_alloc = 1; - } - retval = 0; - -diff -uprN linux-2.6.28.orig/fs/ext4/super.c linux-2.6.28/fs/ext4/super.c ---- linux-2.6.28.orig/fs/ext4/super.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ext4/super.c 2009-05-23 16:05:41.000000000 +0200 -@@ -679,8 +679,6 @@ static int ext4_show_options(struct seq_ - if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) - seq_puts(seq, ",noacl"); - #endif -- if (!test_opt(sb, RESERVATION)) -- seq_puts(seq, ",noreservation"); - if (sbi->s_commit_interval) { - seq_printf(seq, ",commit=%u", - (unsigned) (sbi->s_commit_interval / HZ)); -@@ -724,6 +722,9 @@ static int ext4_show_options(struct seq_ - if (test_opt(sb, DATA_ERR_ABORT)) - seq_puts(seq, ",data_err=abort"); - -+ if (test_opt(sb, NO_AUTO_DA_ALLOC)) -+ seq_puts(seq, ",auto_da_alloc=0"); -+ - ext4_show_quota_options(seq, sb); - return 0; - } -@@ -849,7 +850,7 @@ enum { - Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, - Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov, - Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, -- Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, -+ Opt_auto_da_alloc, Opt_noload, Opt_nobh, Opt_bh, - Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, - Opt_journal_checksum, Opt_journal_async_commit, - Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, -@@ -883,8 +884,6 @@ static const match_table_t tokens = { - {Opt_nouser_xattr, "nouser_xattr"}, - {Opt_acl, "acl"}, - {Opt_noacl, "noacl"}, -- {Opt_reservation, "reservation"}, -- {Opt_noreservation, "noreservation"}, - {Opt_noload, "noload"}, - {Opt_nobh, "nobh"}, - {Opt_bh, "bh"}, -@@ -919,6 +918,7 @@ static const match_table_t tokens = { - {Opt_delalloc, "delalloc"}, - {Opt_nodelalloc, "nodelalloc"}, - {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, -+ {Opt_auto_da_alloc, "auto_da_alloc=%u"}, - {Opt_err, NULL}, - }; - -@@ -1049,12 +1049,6 @@ static int parse_options(char *options, - "not supported\n"); - break; - #endif -- case Opt_reservation: -- set_opt(sbi->s_mount_opt, RESERVATION); -- break; -- case Opt_noreservation: -- clear_opt(sbi->s_mount_opt, RESERVATION); -- break; - case Opt_journal_update: - /* @@@ FIXME */ - /* Eventually we will want to be able to create -@@ -1331,6 +1325,14 @@ set_qf_format: - return 0; - sbi->s_inode_readahead_blks = option; - break; -+ case Opt_auto_da_alloc: -+ if (match_int(&args[0], &option)) -+ return 0; -+ if (option) -+ clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC); -+ else -+ set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); -+ break; - default: - printk(KERN_ERR - "EXT4-fs: Unrecognized mount option \"%s\" " -@@ -1956,7 +1958,6 @@ static int ext4_fill_super(struct super_ - sbi->s_resuid = le16_to_cpu(es->s_def_resuid); - sbi->s_resgid = le16_to_cpu(es->s_def_resgid); - -- set_opt(sbi->s_mount_opt, RESERVATION); - set_opt(sbi->s_mount_opt, BARRIER); - - /* -diff -uprN linux-2.6.28.orig/fs/jbd2/revoke.c linux-2.6.28/fs/jbd2/revoke.c ---- linux-2.6.28.orig/fs/jbd2/revoke.c 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/jbd2/revoke.c 2009-05-23 16:05:41.000000000 +0200 -@@ -55,6 +55,25 @@ - * need do nothing. - * RevokeValid set, Revoked set: - * buffer has been revoked. -+ * -+ * Locking rules: -+ * We keep two hash tables of revoke records. One hashtable belongs to the -+ * running transaction (is pointed to by journal->j_revoke), the other one -+ * belongs to the committing transaction. Accesses to the second hash table -+ * happen only from the kjournald and no other thread touches this table. Also -+ * journal_switch_revoke_table() which switches which hashtable belongs to the -+ * running and which to the committing transaction is called only from -+ * kjournald. Therefore we need no locks when accessing the hashtable belonging -+ * to the committing transaction. -+ * -+ * All users operating on the hash table belonging to the running transaction -+ * have a handle to the transaction. Therefore they are safe from kjournald -+ * switching hash tables under them. For operations on the lists of entries in -+ * the hash table j_revoke_lock is used. -+ * -+ * Finally, also replay code uses the hash tables but at this moment noone else -+ * can touch them (filesystem isn't mounted yet) and hence no locking is -+ * needed. - */ - - #ifndef __KERNEL__ -@@ -401,8 +420,6 @@ int jbd2_journal_revoke(handle_t *handle - * the second time we would still have a pending revoke to cancel. So, - * do not trust the Revoked bit on buffers unless RevokeValid is also - * set. -- * -- * The caller must have the journal locked. - */ - int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh) - { -@@ -480,10 +497,7 @@ void jbd2_journal_switch_revoke_table(jo - /* - * Write revoke records to the journal for all entries in the current - * revoke hash, deleting the entries as we go. -- * -- * Called with the journal lock held. - */ -- - void jbd2_journal_write_revoke_records(journal_t *journal, - transaction_t *transaction) - { -diff -uprN linux-2.6.28.orig/fs/ocfs2/ocfs2_jbd_compat.h linux-2.6.28/fs/ocfs2/ocfs2_jbd_compat.h ---- linux-2.6.28.orig/fs/ocfs2/ocfs2_jbd_compat.h 2009-05-02 20:54:43.000000000 +0200 -+++ linux-2.6.28/fs/ocfs2/ocfs2_jbd_compat.h 2009-05-23 16:05:41.000000000 +0200 -@@ -60,7 +60,8 @@ static inline int jbd2_journal_file_inod - return 0; - } - --static inline int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, -+static inline int jbd2_journal_begin_ordered_truncate(journal_t *journal, -+ struct jbd2_inode *inode, - loff_t new_size) - { - return 0; +diff -uprN linux-2.6.28.orig/Documentation/filesystems/ext4.txt linux-2.6.28/Documentation/filesystems/ext4.txt +--- linux-2.6.28.orig/Documentation/filesystems/ext4.txt 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/Documentation/filesystems/ext4.txt 2009-05-23 16:05:41.000000000 +0200 +@@ -76,7 +76,7 @@ Note: More extensive information for get + * extent format more robust in face of on-disk corruption due to magics, + * internal redunancy in tree + * improved file allocation (multi-block alloc) +-* fix 32000 subdirectory limit ++* lift 32000 subdirectory limit imposed by i_links_count[1] + * nsec timestamps for mtime, atime, ctime, create time + * inode version field on disk (NFSv4, Lustre) + * reduced e2fsck time via uninit_bg feature +@@ -91,6 +91,9 @@ Note: More extensive information for get + * efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force + the ordering) + ++[1] Filesystems with a block size of 1k may see a limit imposed by the ++directory hash tree having a maximum depth of two. ++ + 2.2 Candidate features for future inclusion + + * Online defrag (patches available but not well tested) +diff -uprN linux-2.6.28.orig/fs/ext4/balloc.c linux-2.6.28/fs/ext4/balloc.c +--- linux-2.6.28.orig/fs/ext4/balloc.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/balloc.c 2009-05-23 16:05:41.000000000 +0200 +@@ -608,7 +608,9 @@ int ext4_claim_free_blocks(struct ext4_s + */ + int ext4_should_retry_alloc(struct super_block *sb, int *retries) + { +- if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || (*retries)++ > 3) ++ if (!ext4_has_free_blocks(EXT4_SB(sb), 1) || ++ (*retries)++ > 3 || ++ !EXT4_SB(sb)->s_journal) + return 0; + + jbd_debug(1, "%s: retrying operation after ENOSPC\n", sb->s_id); +diff -uprN linux-2.6.28.orig/fs/ext4/ext4.h linux-2.6.28/fs/ext4/ext4.h +--- linux-2.6.28.orig/fs/ext4/ext4.h 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/ext4.h 2009-05-23 16:05:41.000000000 +0200 +@@ -248,6 +248,30 @@ struct flex_groups { + #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ + #define EXT4_FL_USER_MODIFIABLE 0x000B80FF /* User modifiable flags */ + ++/* Flags that should be inherited by new inodes from their parent. */ ++#define EXT4_FL_INHERITED (EXT4_SECRM_FL | EXT4_UNRM_FL | EXT4_COMPR_FL |\ ++ EXT4_SYNC_FL | EXT4_IMMUTABLE_FL | EXT4_APPEND_FL |\ ++ EXT4_NODUMP_FL | EXT4_NOATIME_FL |\ ++ EXT4_NOCOMPR_FL | EXT4_JOURNAL_DATA_FL |\ ++ EXT4_NOTAIL_FL | EXT4_DIRSYNC_FL) ++ ++/* Flags that are appropriate for regular files (all but dir-specific ones). */ ++#define EXT4_REG_FLMASK (~(EXT4_DIRSYNC_FL | EXT4_TOPDIR_FL)) ++ ++/* Flags that are appropriate for non-directories/regular files. */ ++#define EXT4_OTHER_FLMASK (EXT4_NODUMP_FL | EXT4_NOATIME_FL) ++ ++/* Mask out flags that are inappropriate for the given type of inode. */ ++static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags) ++{ ++ if (S_ISDIR(mode)) ++ return flags; ++ else if (S_ISREG(mode)) ++ return flags & EXT4_REG_FLMASK; ++ else ++ return flags & EXT4_OTHER_FLMASK; ++} ++ + /* + * Inode dynamic state flags + */ +@@ -529,7 +556,7 @@ do { \ + #define EXT4_MOUNT_NO_UID32 0x02000 /* Disable 32-bit UIDs */ + #define EXT4_MOUNT_XATTR_USER 0x04000 /* Extended user attributes */ + #define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ +-#define EXT4_MOUNT_RESERVATION 0x10000 /* Preallocation */ ++#define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */ + #define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */ + #define EXT4_MOUNT_NOBH 0x40000 /* No bufferheads */ + #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ +diff -uprN linux-2.6.28.orig/fs/ext4/extents.c linux-2.6.28/fs/ext4/extents.c +--- linux-2.6.28.orig/fs/ext4/extents.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/extents.c 2009-05-23 16:05:41.000000000 +0200 +@@ -1120,7 +1120,8 @@ ext4_ext_search_right(struct inode *inod + struct ext4_extent_idx *ix; + struct ext4_extent *ex; + ext4_fsblk_t block; +- int depth, ee_len; ++ int depth; /* Note, NOT eh_depth; depth from top of tree */ ++ int ee_len; + + BUG_ON(path == NULL); + depth = path->p_depth; +@@ -1179,7 +1180,8 @@ ext4_ext_search_right(struct inode *inod + if (bh == NULL) + return -EIO; + eh = ext_block_hdr(bh); +- if (ext4_ext_check_header(inode, eh, depth)) { ++ /* subtract from p_depth to get proper eh_depth */ ++ if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) { + put_bh(bh); + return -EIO; + } +@@ -1740,11 +1742,13 @@ ext4_ext_put_in_cache(struct inode *inod + { + struct ext4_ext_cache *cex; + BUG_ON(len == 0); ++ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); + cex = &EXT4_I(inode)->i_cached_extent; + cex->ec_type = type; + cex->ec_block = block; + cex->ec_len = len; + cex->ec_start = start; ++ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); + } + + /* +@@ -1801,12 +1805,17 @@ ext4_ext_in_cache(struct inode *inode, e + struct ext4_extent *ex) + { + struct ext4_ext_cache *cex; ++ int ret = EXT4_EXT_CACHE_NO; + ++ /* ++ * We borrow i_block_reservation_lock to protect i_cached_extent ++ */ ++ spin_lock(&EXT4_I(inode)->i_block_reservation_lock); + cex = &EXT4_I(inode)->i_cached_extent; + + /* has cache valid data? */ + if (cex->ec_type == EXT4_EXT_CACHE_NO) +- return EXT4_EXT_CACHE_NO; ++ goto errout; + + BUG_ON(cex->ec_type != EXT4_EXT_CACHE_GAP && + cex->ec_type != EXT4_EXT_CACHE_EXTENT); +@@ -1817,11 +1826,11 @@ ext4_ext_in_cache(struct inode *inode, e + ext_debug("%u cached by %u:%u:%llu\n", + block, + cex->ec_block, cex->ec_len, cex->ec_start); +- return cex->ec_type; ++ ret = cex->ec_type; + } +- +- /* not in cache */ +- return EXT4_EXT_CACHE_NO; ++errout: ++ spin_unlock(&EXT4_I(inode)->i_block_reservation_lock); ++ return ret; + } + + /* +@@ -2777,6 +2786,8 @@ int ext4_ext_get_blocks(handle_t *handle + if (allocated > max_blocks) + allocated = max_blocks; + set_buffer_unwritten(bh_result); ++ bh_result->b_bdev = inode->i_sb->s_bdev; ++ bh_result->b_blocknr = newblock; + goto out2; + } + +diff -uprN linux-2.6.28.orig/fs/ext4/ialloc.c linux-2.6.28/fs/ext4/ialloc.c +--- linux-2.6.28.orig/fs/ext4/ialloc.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/ialloc.c 2009-05-23 16:05:41.000000000 +0200 +@@ -188,7 +188,7 @@ void ext4_free_inode(handle_t *handle, s + struct ext4_group_desc *gdp; + struct ext4_super_block *es; + struct ext4_sb_info *sbi; +- int fatal = 0, err; ++ int fatal = 0, err, cleared; + ext4_group_t flex_group; + + if (atomic_read(&inode->i_count) > 1) { +@@ -243,8 +243,10 @@ void ext4_free_inode(handle_t *handle, s + goto error_return; + + /* Ok, now we can actually update the inode bitmaps.. */ +- if (!ext4_clear_bit_atomic(sb_bgl_lock(sbi, block_group), +- bit, bitmap_bh->b_data)) ++ spin_lock(sb_bgl_lock(sbi, block_group)); ++ cleared = ext4_clear_bit(bit, bitmap_bh->b_data); ++ spin_unlock(sb_bgl_lock(sbi, block_group)); ++ if (!cleared) + ext4_error(sb, "ext4_free_inode", + "bit already cleared for inode %lu", ino); + else { +@@ -686,6 +688,7 @@ struct inode *ext4_new_inode(handle_t *h + struct inode *ret; + ext4_group_t i; + int free = 0; ++ static int once = 1; + ext4_group_t flex_group; + + /* Cannot create files in a deleted directory */ +@@ -705,10 +708,12 @@ struct inode *ext4_new_inode(handle_t *h + ret2 = find_group_flex(sb, dir, &group); + if (ret2 == -1) { + ret2 = find_group_other(sb, dir, &group); +- if (ret2 == 0 && printk_ratelimit()) ++ if (ret2 == 0 && once) { ++ once = 0; + printk(KERN_NOTICE "ext4: find_group_flex " + "failed, fallback succeeded dir %lu\n", + dir->i_ino); ++ } + } + goto got_group; + } +@@ -862,16 +867,12 @@ got: + ei->i_disksize = 0; + + /* +- * Don't inherit extent flag from directory. We set extent flag on +- * newly created directory and file only if -o extent mount option is +- * specified ++ * Don't inherit extent flag from directory, amongst others. We set ++ * extent flag on newly created directory and file only if -o extent ++ * mount option is specified + */ +- ei->i_flags = EXT4_I(dir)->i_flags & ~(EXT4_INDEX_FL|EXT4_EXTENTS_FL); +- if (S_ISLNK(mode)) +- ei->i_flags &= ~(EXT4_IMMUTABLE_FL|EXT4_APPEND_FL); +- /* dirsync only applies to directories */ +- if (!S_ISDIR(mode)) +- ei->i_flags &= ~EXT4_DIRSYNC_FL; ++ ei->i_flags = ++ ext4_mask_flags(mode, EXT4_I(dir)->i_flags & EXT4_FL_INHERITED); + ei->i_file_acl = 0; + ei->i_dtime = 0; + ei->i_block_group = group; +diff -uprN linux-2.6.28.orig/fs/ext4/inode.c linux-2.6.28/fs/ext4/inode.c +--- linux-2.6.28.orig/fs/ext4/inode.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/inode.c 2009-05-23 16:05:41.000000000 +0200 +@@ -1052,6 +1059,7 @@ int ext4_get_blocks_wrap(handle_t *handl + int retval; + + clear_buffer_mapped(bh); ++ clear_buffer_unwritten(bh); + + /* + * Try to see if we can get the block without requesting +@@ -1082,6 +1090,18 @@ int ext4_get_blocks_wrap(handle_t *handl + return retval; + + /* ++ * When we call get_blocks without the create flag, the ++ * BH_Unwritten flag could have gotten set if the blocks ++ * requested were part of a uninitialized extent. We need to ++ * clear this flag now that we are committed to convert all or ++ * part of the uninitialized extent to be an initialized ++ * extent. This is because we need to avoid the combination ++ * of BH_Unwritten and BH_Mapped flags being simultaneously ++ * set on the buffer_head. ++ */ ++ clear_buffer_unwritten(bh); ++ ++ /* + * New blocks allocate and/or writing to uninitialized extent + * will possibly result in updating i_data, so we take + * the write lock of i_data_sem, and call get_blocks() +@@ -2180,6 +2200,10 @@ static int ext4_da_get_block_prep(struct + struct buffer_head *bh_result, int create) + { + int ret = 0; ++ sector_t invalid_block = ~((sector_t) 0xffff); ++ ++ if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es)) ++ invalid_block = ~0; + + BUG_ON(create == 0); + BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); +@@ -2201,11 +2225,18 @@ static int ext4_da_get_block_prep(struct + /* not enough space to reserve */ + return ret; + +- map_bh(bh_result, inode->i_sb, 0); ++ map_bh(bh_result, inode->i_sb, invalid_block); + set_buffer_new(bh_result); + set_buffer_delay(bh_result); + } else if (ret > 0) { + bh_result->b_size = (ret << inode->i_blkbits); ++ /* ++ * With sub-block writes into unwritten extents ++ * we also need to mark the buffer as new so that ++ * the unwritten parts of the buffer gets correctly zeroed. ++ */ ++ if (buffer_unwritten(bh_result)) ++ set_buffer_new(bh_result); + ret = 0; + } + +@@ -2493,7 +2524,7 @@ retry: + + ext4_journal_stop(handle); + +- if (mpd.retval == -ENOSPC) { ++ if ((mpd.retval == -ENOSPC) && sbi->s_journal) { + /* commit the transaction which would + * free blocks released in the transaction + * and try again +@@ -4167,11 +4243,9 @@ struct inode *ext4_iget(struct super_blo + ei->i_flags = le32_to_cpu(raw_inode->i_flags); + inode->i_blocks = ext4_inode_blocks(raw_inode, ei); + ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); +- if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != +- cpu_to_le32(EXT4_OS_HURD)) { ++ if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_64BIT)) + ei->i_file_acl |= + ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; +- } + inode->i_size = ext4_isize(raw_inode); + ei->i_disksize = inode->i_size; + inode->i_generation = le32_to_cpu(raw_inode->i_generation); +@@ -4218,6 +4292,18 @@ struct inode *ext4_iget(struct super_blo + (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; + } + ++ if (ei->i_file_acl && ++ ((ei->i_file_acl < ++ (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + ++ EXT4_SB(sb)->s_gdb_count)) || ++ (ei->i_file_acl >= ext4_blocks_count(EXT4_SB(sb)->s_es)))) { ++ ext4_error(sb, __func__, ++ "bad extended attribute block %llu in inode #%lu", ++ ei->i_file_acl, inode->i_ino); ++ ret = -EIO; ++ goto bad_inode; ++ } ++ + if (S_ISREG(inode->i_mode)) { + inode->i_op = &ext4_file_inode_operations; + inode->i_fop = &ext4_file_operations; +@@ -4232,7 +4318,8 @@ struct inode *ext4_iget(struct super_blo + inode->i_op = &ext4_symlink_inode_operations; + ext4_set_aops(inode); + } +- } else { ++ } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || ++ S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + inode->i_op = &ext4_special_inode_operations; + if (raw_inode->i_block[0]) + init_special_inode(inode, inode->i_mode, +@@ -4240,6 +4327,13 @@ struct inode *ext4_iget(struct super_blo + else + init_special_inode(inode, inode->i_mode, + new_decode_dev(le32_to_cpu(raw_inode->i_block[1]))); ++ } else { ++ brelse(bh); ++ ret = -EIO; ++ ext4_error(inode->i_sb, __func__, ++ "bogus i_mode (%o) for inode=%lu", ++ inode->i_mode, inode->i_ino); ++ goto bad_inode; + } + brelse(iloc.bh); + ext4_set_inode_flags(inode); +diff -uprN linux-2.6.28.orig/fs/ext4/ioctl.c linux-2.6.28/fs/ext4/ioctl.c +--- linux-2.6.28.orig/fs/ext4/ioctl.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/ioctl.c 2009-05-23 16:05:41.000000000 +0200 +@@ -48,8 +48,7 @@ long ext4_ioctl(struct file *filp, unsig + if (err) + return err; + +- if (!S_ISDIR(inode->i_mode)) +- flags &= ~EXT4_DIRSYNC_FL; ++ flags = ext4_mask_flags(inode->i_mode, flags); + + err = -EPERM; + mutex_lock(&inode->i_mutex); +diff -uprN linux-2.6.28.orig/fs/ext4/mballoc.c linux-2.6.28/fs/ext4/mballoc.c +--- linux-2.6.28.orig/fs/ext4/mballoc.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/mballoc.c 2009-05-23 16:05:41.000000000 +0200 +@@ -1448,7 +1448,7 @@ static void ext4_mb_measure_extent(struc + struct ext4_free_extent *gex = &ac->ac_g_ex; + + BUG_ON(ex->fe_len <= 0); +- BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); ++ BUG_ON(ex->fe_len > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); + BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); + BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); + +@@ -2692,7 +2692,7 @@ int ext4_mb_init(struct super_block *sb, + i = (sb->s_blocksize_bits + 2) * sizeof(unsigned int); + sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL); + if (sbi->s_mb_maxs == NULL) { +- kfree(sbi->s_mb_maxs); ++ kfree(sbi->s_mb_offsets); + return -ENOMEM; + } + +@@ -3289,7 +3289,7 @@ ext4_mb_normalize_request(struct ext4_al + } + BUG_ON(start + size <= ac->ac_o_ex.fe_logical && + start > ac->ac_o_ex.fe_logical); +- BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); ++ BUG_ON(size <= 0 || size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); + + /* now prepare goal request */ + +@@ -3586,6 +3586,7 @@ static void ext4_mb_put_pa(struct ext4_a + struct super_block *sb, struct ext4_prealloc_space *pa) + { + unsigned long grp; ++ ext4_fsblk_t grp_blk; + + if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) + return; +@@ -3600,8 +3601,12 @@ static void ext4_mb_put_pa(struct ext4_a + pa->pa_deleted = 1; + spin_unlock(&pa->pa_lock); + +- /* -1 is to protect from crossing allocation group */ +- ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL); ++ grp_blk = pa->pa_pstart; ++ /* If linear, pa_pstart may be in the next group when pa is used up */ ++ if (pa->pa_linear) ++ grp_blk--; ++ ++ ext4_get_group_no_and_offset(sb, grp_blk, &grp, NULL); + + /* + * possible race: +@@ -4414,7 +4419,7 @@ static void ext4_mb_add_n_trim(struct ex + pa_inode_list) { + spin_lock(&tmp_pa->pa_lock); + if (tmp_pa->pa_deleted) { +- spin_unlock(&pa->pa_lock); ++ spin_unlock(&tmp_pa->pa_lock); + continue; + } + if (!added && pa->pa_free < tmp_pa->pa_free) { +diff -uprN linux-2.6.28.orig/fs/ext4/namei.c linux-2.6.28/fs/ext4/namei.c +--- linux-2.6.28.orig/fs/ext4/namei.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/namei.c 2009-05-23 16:05:41.000000000 +0200 +@@ -1056,8 +1056,16 @@ static struct dentry *ext4_lookup(struct + return ERR_PTR(-EIO); + } + inode = ext4_iget(dir->i_sb, ino); +- if (IS_ERR(inode)) +- return ERR_CAST(inode); ++ if (unlikely(IS_ERR(inode))) { ++ if (PTR_ERR(inode) == -ESTALE) { ++ ext4_error(dir->i_sb, __func__, ++ "deleted inode referenced: %u", ++ ino); ++ return ERR_PTR(-EIO); ++ } else { ++ return ERR_CAST(inode); ++ } ++ } + } + return d_splice_alias(inode, dentry); + } +@@ -2436,7 +2444,8 @@ static int ext4_rename(struct inode *old + ext4_mark_inode_dirty(handle, new_inode); + if (!new_inode->i_nlink) + ext4_orphan_add(handle, new_inode); +- force_da_alloc = 1; ++ if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC)) ++ force_da_alloc = 1; + } + retval = 0; + +diff -uprN linux-2.6.28.orig/fs/ext4/super.c linux-2.6.28/fs/ext4/super.c +--- linux-2.6.28.orig/fs/ext4/super.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ext4/super.c 2009-05-23 16:05:41.000000000 +0200 +@@ -679,8 +679,6 @@ static int ext4_show_options(struct seq_ + if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) + seq_puts(seq, ",noacl"); + #endif +- if (!test_opt(sb, RESERVATION)) +- seq_puts(seq, ",noreservation"); + if (sbi->s_commit_interval) { + seq_printf(seq, ",commit=%u", + (unsigned) (sbi->s_commit_interval / HZ)); +@@ -724,6 +722,9 @@ static int ext4_show_options(struct seq_ + if (test_opt(sb, DATA_ERR_ABORT)) + seq_puts(seq, ",data_err=abort"); + ++ if (test_opt(sb, NO_AUTO_DA_ALLOC)) ++ seq_puts(seq, ",auto_da_alloc=0"); ++ + ext4_show_quota_options(seq, sb); + return 0; + } +@@ -849,7 +850,7 @@ enum { + Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, + Opt_nouid32, Opt_debug, Opt_oldalloc, Opt_orlov, + Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, +- Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, ++ Opt_auto_da_alloc, Opt_noload, Opt_nobh, Opt_bh, + Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, + Opt_journal_checksum, Opt_journal_async_commit, + Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, +@@ -883,8 +884,6 @@ static const match_table_t tokens = { + {Opt_nouser_xattr, "nouser_xattr"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, +- {Opt_reservation, "reservation"}, +- {Opt_noreservation, "noreservation"}, + {Opt_noload, "noload"}, + {Opt_nobh, "nobh"}, + {Opt_bh, "bh"}, +@@ -919,6 +918,7 @@ static const match_table_t tokens = { + {Opt_delalloc, "delalloc"}, + {Opt_nodelalloc, "nodelalloc"}, + {Opt_inode_readahead_blks, "inode_readahead_blks=%u"}, ++ {Opt_auto_da_alloc, "auto_da_alloc=%u"}, + {Opt_err, NULL}, + }; + +@@ -1049,12 +1049,6 @@ static int parse_options(char *options, + "not supported\n"); + break; + #endif +- case Opt_reservation: +- set_opt(sbi->s_mount_opt, RESERVATION); +- break; +- case Opt_noreservation: +- clear_opt(sbi->s_mount_opt, RESERVATION); +- break; + case Opt_journal_update: + /* @@@ FIXME */ + /* Eventually we will want to be able to create +@@ -1331,6 +1325,14 @@ set_qf_format: + return 0; + sbi->s_inode_readahead_blks = option; + break; ++ case Opt_auto_da_alloc: ++ if (match_int(&args[0], &option)) ++ return 0; ++ if (option) ++ clear_opt(sbi->s_mount_opt, NO_AUTO_DA_ALLOC); ++ else ++ set_opt(sbi->s_mount_opt,NO_AUTO_DA_ALLOC); ++ break; + default: + printk(KERN_ERR + "EXT4-fs: Unrecognized mount option \"%s\" " +@@ -1956,7 +1958,6 @@ static int ext4_fill_super(struct super_ + sbi->s_resuid = le16_to_cpu(es->s_def_resuid); + sbi->s_resgid = le16_to_cpu(es->s_def_resgid); + +- set_opt(sbi->s_mount_opt, RESERVATION); + set_opt(sbi->s_mount_opt, BARRIER); + + /* +diff -uprN linux-2.6.28.orig/fs/jbd2/revoke.c linux-2.6.28/fs/jbd2/revoke.c +--- linux-2.6.28.orig/fs/jbd2/revoke.c 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/jbd2/revoke.c 2009-05-23 16:05:41.000000000 +0200 +@@ -55,6 +55,25 @@ + * need do nothing. + * RevokeValid set, Revoked set: + * buffer has been revoked. ++ * ++ * Locking rules: ++ * We keep two hash tables of revoke records. One hashtable belongs to the ++ * running transaction (is pointed to by journal->j_revoke), the other one ++ * belongs to the committing transaction. Accesses to the second hash table ++ * happen only from the kjournald and no other thread touches this table. Also ++ * journal_switch_revoke_table() which switches which hashtable belongs to the ++ * running and which to the committing transaction is called only from ++ * kjournald. Therefore we need no locks when accessing the hashtable belonging ++ * to the committing transaction. ++ * ++ * All users operating on the hash table belonging to the running transaction ++ * have a handle to the transaction. Therefore they are safe from kjournald ++ * switching hash tables under them. For operations on the lists of entries in ++ * the hash table j_revoke_lock is used. ++ * ++ * Finally, also replay code uses the hash tables but at this moment noone else ++ * can touch them (filesystem isn't mounted yet) and hence no locking is ++ * needed. + */ + + #ifndef __KERNEL__ +@@ -401,8 +420,6 @@ int jbd2_journal_revoke(handle_t *handle + * the second time we would still have a pending revoke to cancel. So, + * do not trust the Revoked bit on buffers unless RevokeValid is also + * set. +- * +- * The caller must have the journal locked. + */ + int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh) + { +@@ -480,10 +497,7 @@ void jbd2_journal_switch_revoke_table(jo + /* + * Write revoke records to the journal for all entries in the current + * revoke hash, deleting the entries as we go. +- * +- * Called with the journal lock held. + */ +- + void jbd2_journal_write_revoke_records(journal_t *journal, + transaction_t *transaction) + { +diff -uprN linux-2.6.28.orig/fs/ocfs2/ocfs2_jbd_compat.h linux-2.6.28/fs/ocfs2/ocfs2_jbd_compat.h +--- linux-2.6.28.orig/fs/ocfs2/ocfs2_jbd_compat.h 2009-05-02 20:54:43.000000000 +0200 ++++ linux-2.6.28/fs/ocfs2/ocfs2_jbd_compat.h 2009-05-23 16:05:41.000000000 +0200 +@@ -60,7 +60,8 @@ static inline int jbd2_journal_file_inod + return 0; + } + +-static inline int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, ++static inline int jbd2_journal_begin_ordered_truncate(journal_t *journal, ++ struct jbd2_inode *inode, + loff_t new_size) + { + return 0; diff --git a/kernel-power-2.6.28/debian/rules b/kernel-power-2.6.28/debian/rules index ae15ee3..ab5831f 100755 --- a/kernel-power-2.6.28/debian/rules +++ b/kernel-power-2.6.28/debian/rules @@ -42,18 +42,14 @@ ifneq (,$(findstring parallel,$(DEB_BUILD_OPTIONS))) endif get-orig-source: - wget ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.28.tar.gz + wget http://repository.maemo.org/pool/maemo5.0/free/k/kernel/kernel_2.6.28.orig.tar.gz -O kernel-power_2.6.28.orig.tar.gz -source-copy-stamp: +source-stamp: dh_testdir - mkdir -p $(BUILDTMP)/$(SOURCE_PACKAGE) - $(MAKE) clean - tar cf - `echo * | sed -e 's/ debian//g;s/\.deb//g;s/\.gz//g;s/fiasco//g'` 2>/dev/null | ( cd $(BUILDTMP)/$(SOURCE_PACKAGE); umask 000; tar xspf - ) - cd $(BUILDTMP)/$(SOURCE_PACKAGE) && ( QUILT_PATCHES=$(CURDIR)/debian/patches quilt push -a -q || test $$? = 2 ) - touch $@ - -source-stamp: source-copy-stamp - cd $(BUILDTMP) && cp -a $(SOURCE_PACKAGE) $(KSRC) + mkdir -p $(KSRC) + tar cf - `echo * | sed -e 's/ debian//g;s/\.deb//g;s/\.gz//g;s/fiasco//g'` 2>/dev/null | ( cd $(KSRC); umask 000; tar xspf - ) + cd $(KSRC) && ( QUILT_PATCHES=$(CURDIR)/debian/patches quilt push -a -q || test $$? = 2 ) + cd $(BUILDTMP) && tar --exclude=".pc" --bzip2 -cf $(SOURCE_PACKAGE)-$(RELEASE).tar.bz2 $(PACKAGE) touch $@ configure-stamp: source-stamp @@ -68,10 +64,6 @@ modules-stamp: configure-stamp $(MAKE) -C $(KSRC) $(NJOBS) $(EXTRAVERSION) modules touch $@ -kernel-source-stamp: source-copy-stamp - cd $(BUILDTMP) && tar --bzip2 -cf $(SOURCE_PACKAGE)-$(RELEASE).tar.bz2 $(SOURCE_PACKAGE) - touch $@ - headers: kernel-stamp modules-stamp clean: @@ -79,7 +71,7 @@ clean: dh_testroot rm -rf $(BUILDTMP) rm -f debian/files debian/$(FLASHER_PACKAGE).postinst debian/$(MODULES_PACKAGE).postinst debian/$(MODULES_PACKAGE).postrm - rm -f source-copy-stamp source-stamp configure-stamp kernel-stamp modules-stamp kernel-source-stamp + rm -f source-stamp configure-stamp kernel-stamp modules-stamp dh_clean install-kernel: @@ -170,7 +162,7 @@ install-headers: cp -a $(KSRC)/scripts $(CURDIR)/debian/$(HEADERS_PACKAGE)/usr/src/$(KBUILD_PACKAGE) #kbuild fixes cd $(CURDIR)/debian/$(HEADERS_PACKAGE)/usr/src/$(KBUILD_PACKAGE)/scripts && rm -f $(RM_SCRIPTS) && chmod a-x mkcompile_h - find $(CURDIR)/debian/$(HEADERS_PACKAGE) -name ".gitignore" -delete + #find $(CURDIR)/debian/$(HEADERS_PACKAGE) -name ".gitignore" -delete install-libc-headers: source-stamp dh_testdir @@ -192,7 +184,7 @@ else build-arch: endif -build-indep: kernel-source-stamp +build-indep: source-stamp build: build-arch build-indep -- 1.7.9.5