summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCecil Hugh Watson <knoppmyth@gmail.com>2009-08-17 06:31:43 (GMT)
committerCecil Hugh Watson <knoppmyth@gmail.com>2009-08-17 06:31:43 (GMT)
commit6361f26251ab679de77f9db79b16632df05a8235 (patch)
tree7e54548ca41245bf413cfd3c6db47d1d448b3968
parent3df8e145831128ee1de658a48057cd2afefea94f (diff)
downloadlinhes_pkgbuild-6361f26251ab679de77f9db79b16632df05a8235.zip
linhes_pkgbuild-6361f26251ab679de77f9db79b16632df05a8235.tar.gz
linhes_pkgbuild-6361f26251ab679de77f9db79b16632df05a8235.tar.bz2
Kernel26:Patch for EXT4 data loss.
-rw-r--r--abs/core-testing/kernel26/PKGBUILD6
-rw-r--r--abs/core-testing/kernel26/ext4.patch152
2 files changed, 156 insertions, 2 deletions
diff --git a/abs/core-testing/kernel26/PKGBUILD b/abs/core-testing/kernel26/PKGBUILD
index 2f238fd..8248fc5 100644
--- a/abs/core-testing/kernel26/PKGBUILD
+++ b/abs/core-testing/kernel26/PKGBUILD
@@ -5,7 +5,7 @@
pkgname=kernel26
_basekernel=2.6.28
pkgver=2.6.28.5
-pkgrel=3
+pkgrel=4
_pkgrel=1
_patchname="patch-${pkgver}-${_pkgrel}-ARCH"
_fbpatchname="fbcondecor-0.9.5-2.6.28.patch"
@@ -34,7 +34,8 @@ source=(ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-$_basekernel.tar.bz2
# standard config files for mkinitcpio ramdisk
kernel26.preset
logo_linux_clut224.ppm
- serial.diff)
+ serial.diff
+ ext4.patch)
optdepends=('crda: to set the correct wireless channels of your country')
md5sums=('d351e44709c9810b85e29b877f50968a'
'6e63a5f54c142f42de7e59fc5f75eab2'
@@ -53,6 +54,7 @@ build() {
# See http://projects.archlinux.org/git/?p=linux-2.6-ARCH.git;a=summary
patch -Np1 -i ${srcdir}/${_patchname} || return 1
patch -Np1 -i ${srcdir}/${_fbpatchname} || return 1
+ patch -Np1 -i ${srcdir}/ext4.patch || return 1
# patch -p0 < ../../serial.diff
if [ "$CARCH" = "x86_64" ]; then
diff --git a/abs/core-testing/kernel26/ext4.patch b/abs/core-testing/kernel26/ext4.patch
new file mode 100644
index 0000000..40ecfde
--- /dev/null
+++ b/abs/core-testing/kernel26/ext4.patch
@@ -0,0 +1,152 @@
+diff -ruaN 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 2008-12-24 23:26:37.000000000 +0000
++++ linux-2.6.28/fs/ext4/ext4.h 2009-08-17 04:22:43.000000000 +0000
+@@ -254,6 +254,7 @@
+ #define EXT4_STATE_NEW 0x00000002 /* inode is newly created */
+ #define EXT4_STATE_XATTR 0x00000004 /* has in-inode xattrs */
+ #define EXT4_STATE_NO_EXPAND 0x00000008 /* No space for expansion */
++#define EXT4_STATE_DA_ALLOC_CLOSE 0x00000010 /* Alloc DA blks on close */
+
+ /* Used to pass group descriptor data when online resize is done */
+ struct ext4_new_group_input {
+@@ -301,7 +302,9 @@
+ #define EXT4_IOC_GROUP_EXTEND _IOW('f', 7, unsigned long)
+ #define EXT4_IOC_GROUP_ADD _IOW('f', 8, struct ext4_new_group_input)
+ #define EXT4_IOC_MIGRATE _IO('f', 9)
++ /* note ioctl 10 reserved for an early version of the FIEMAP ioctl */
+ /* note ioctl 11 reserved for filesystem-independent FIEMAP ioctl */
++#define EXT4_IOC_ALLOC_DA_BLKS _IO('f', 12)
+
+ /*
+ * ioctl commands in 32 bit emulation
+@@ -1088,6 +1091,7 @@
+ extern void ext4_truncate(struct inode *);
+ extern void ext4_set_inode_flags(struct inode *);
+ extern void ext4_get_inode_flags(struct ext4_inode_info *);
++extern int ext4_alloc_da_blocks(struct inode *inode);
+ extern void ext4_set_aops(struct inode *inode);
+ extern int ext4_writepage_trans_blocks(struct inode *);
+ extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks);
+diff -ruaN linux-2.6.28.orig/fs/ext4/file.c linux-2.6.28/fs/ext4/file.c
+--- linux-2.6.28.orig/fs/ext4/file.c 2008-12-24 23:26:37.000000000 +0000
++++ linux-2.6.28/fs/ext4/file.c 2009-08-17 04:15:17.000000000 +0000
+@@ -33,6 +33,10 @@
+ */
+ static int ext4_release_file(struct inode *inode, struct file *filp)
+ {
++ if (EXT4_I(inode)->i_state & EXT4_STATE_DA_ALLOC_CLOSE) {
++ ext4_alloc_da_blocks(inode);
++ EXT4_I(inode)->i_state &= ~EXT4_STATE_DA_ALLOC_CLOSE;
++ }
+ /* if we are the last writer on the inode, drop the block reservation */
+ if ((filp->f_mode & FMODE_WRITE) &&
+ (atomic_read(&inode->i_writecount) == 1))
+diff -ruaN 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 2008-12-24 23:26:37.000000000 +0000
++++ linux-2.6.28/fs/ext4/inode.c 2009-08-17 04:34:48.000000000 +0000
+@@ -2686,6 +2686,42 @@
+ return;
+ }
+
++/*
++ * Force all delayed allocation blocks to be allocated for a given inode.
++ */
++int ext4_alloc_da_blocks(struct inode *inode)
++{
++ if (!EXT4_I(inode)->i_reserved_data_blocks &&
++ !EXT4_I(inode)->i_reserved_meta_blocks)
++ return 0;
++ /*
++ * We do something simple for now. The filemap_flush() will
++ * also start triggering a write of the data blocks, which is
++ * not strictly speaking necessary (and for users of
++ * laptop_mode, not even desirable). However, to do otherwise
++ * would require replicating code paths in:
++ *
++ * ext4_da_writepages() ->
++ * write_cache_pages() ---> (via passed in callback function)
++ * __mpage_da_writepage() -->
++ * mpage_ad_bh_to_extent()
++ * mpage_da_map_blocks()
++ *
++ * The problem is that write_cache_pages(), and then redirty all of
++ * the pages calling redirty_page_for_writeback() but that
++ * would be ugly in the extreme. So instead we would need to
++ * replicate parts of the code in teh above functions,
++ * simplifying them because we wouldn't actually intend to
++ * write out the pages, but rather only collect contiguous
++ * logical block extents, call the multi-block allocator, and
++ * then update the buffer heads with the block allocations.
++ *
++ * For now, though we'll cheat by calling filemap_flush(),
++ * which will map the blocks, and start the I/O, but not
++ * actually wait for the I/O to complte.
++ */
++ return filemap_flush(inode->i_mapping);
++}
+
+ /*
+ * bmap() is special. It gets used by applications such as lilo and by
+@@ -3695,6 +3731,9 @@
+ if (!ext4_can_truncate(inode))
+ return;
+
++ if (inode->i_size == 0)
++ ei->i_state |= EXT4_STATE_DA_ALLOC_CLOSE;
++
+ if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) {
+ ext4_ext_truncate(inode);
+ return;
+diff -ruaN 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 2008-12-24 23:26:37.000000000 +0000
++++ linux-2.6.28/fs/ext4/ioctl.c 2009-08-17 04:38:43.000000000 +0000
+@@ -263,6 +263,20 @@
+ return err;
+ }
+
++ case EXT4_IOC_ALLOC_DA_BLKS:
++ {
++ int err;
++ if (!is_owner_or_cap(inode))
++ return -EACCES;
++
++ err = mnt_want_write(filp->f_path.mnt);
++ if (err)
++ return err;
++ err = ext4_alloc_da_blocks(inode);
++ mnt_drop_write(filp->f_path.mnt);
++ return err;
++ }
++
+ default:
+ return -ENOTTY;
+ }
+diff -ruaN 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 2008-12-24 23:26:37.000000000 +0000
++++ linux-2.6.28/fs/ext4/namei.c 2009-08-17 04:11:01.000000000 +0000
+@@ -2283,7 +2283,7 @@
+ struct inode *old_inode, *new_inode;
+ struct buffer_head *old_bh, *new_bh, *dir_bh;
+ struct ext4_dir_entry_2 *old_de, *new_de;
+- int retval;
++ int retval, force_da_alloc = 0;
+
+ old_bh = new_bh = dir_bh = NULL;
+
+@@ -2421,6 +2421,7 @@
+ ext4_mark_inode_dirty(handle, new_inode);
+ if (!new_inode->i_nlink)
+ ext4_orphan_add(handle, new_inode);
++ force_da_alloc = 1;
+ }
+ retval = 0;
+
+@@ -2429,6 +2430,8 @@
+ brelse(old_bh);
+ brelse(new_bh);
+ ext4_journal_stop(handle);
++ if (retval == 0 && force_da_alloc)
++ ext4_alloc_da_blocks(old_inode);
+ return retval;
+ }
+