rpms/kernel/devel build-with-fno-dwarf2-cfi-asm.patch, NONE, 1.3.2.2 linux-2.6-ext4-extent-header-check-fix.patch, NONE, 1.2.2.2 linux-2.6-ext4-print-warning-once.patch, NONE, 1.2.2.2 linux-2.6-hdpvr.patch, NONE, 1.7.2.2 linux-2.6-net-tulip-interrupt.patch, NONE, 1.3.2.2 linux-2.6-net-velocity-dma.patch, NONE, 1.2.2.2 linux-2.6.28.tar.bz2.sign, NONE, 1.2.2.2 patch-2.6.29-rc8-git2.bz2.sign, NONE, 1.2.2.2 patch-2.6.29-rc8.bz2.sign, NONE, 1.2.2.2 config-powerpc-generic, 1.36, 1.36.6.1 kernel.spec, 1.1438, 1.1438.2.1 linux-2.6-btrfs-experimental-branch.patch, 1.1, 1.1.8.1

Kyle McMartin kyle at fedoraproject.org
Tue Mar 24 17:57:35 UTC 2009


Author: kyle

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv14701

Modified Files:
      Tag: private-F-11-beta-snap
	config-powerpc-generic kernel.spec 
	linux-2.6-btrfs-experimental-branch.patch 
Added Files:
      Tag: private-F-11-beta-snap
	build-with-fno-dwarf2-cfi-asm.patch 
	linux-2.6-ext4-extent-header-check-fix.patch 
	linux-2.6-ext4-print-warning-once.patch linux-2.6-hdpvr.patch 
	linux-2.6-net-tulip-interrupt.patch 
	linux-2.6-net-velocity-dma.patch linux-2.6.28.tar.bz2.sign 
	patch-2.6.29-rc8-git2.bz2.sign patch-2.6.29-rc8.bz2.sign 
Log Message:
* Tue Mar 24 2009 Kyle McMartin <kyle at redhat.com>
- F-11 beta branch
- btrfs fixes + ide disk ppc fix.
- add back in dropped stuff due to cvs flubbage.


build-with-fno-dwarf2-cfi-asm.patch:

--- NEW FILE build-with-fno-dwarf2-cfi-asm.patch ---
From: Kyle McMartin <kyle at redhat.com>

On ppc64 (at least) gcc-4.4 is defaulting to generating .eh_frame
sections, which are, for the kernel, fairly pointless. Additionally, on
ppc64 this generates a relocation format which the kernel module loader
does not currently support (R_PPC64_REL32.)

Alexandre Oliva verifies that -fno-dwarf2-cfi-asm prevents this
.eh_frame section from being generated.

These seem to be used for unwinding, but it doesn't look like we
currently use them anywhere. (In fact, we explicitly dump them in the
x86_64 linker script.)

If these .eh_frame sections are eventually used, adding a per-arch
CONFIG_WANT_UNWIND check would be trivial.

(This was reported against Fedora, which appears to be the only distro
doing any building against gcc-4.4 at present: RH bz#486545.)

Signed-off-by: Kyle McMartin <kyle at redhat.com>
Cc: roland at redhat.com
Cc: aoliva at redhat.com

---
diff --git a/Makefile b/Makefile
index df6ce3e..d66a512 100644
--- a/Makefile
+++ b/Makefile
@@ -566,6 +566,11 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 # disable pointer signed / unsigned warnings in gcc 4.0
 KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 
+# gcc-4.4 defaults to generating .eh_frame sections, but we aren't
+# interested in those currently. additionally, it causes issues on some
+# architectures.
+KBUILD_CFLAGS += $(call cc-option,-fno-dwarf2-cfi-asm)
+
 # Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments
 # But warn user when we do so
 warn-assign = \

linux-2.6-ext4-extent-header-check-fix.patch:

--- NEW FILE linux-2.6-ext4-extent-header-check-fix.patch ---
This should resolve kernel.org bugzilla 12821

I've not actually crafted a workload to exercise this code; 
this is from inspection...

The ext4_ext_search_right() function is confusing; it uses a
"depth" variable which is 0 at the root and maximum at the leaves, 
but the on-disk metadata uses a "depth" (actually eh_depth) which
is opposite: maximum at the root, and 0 at the leaves.

The ext4_ext_check_header() function is given a depth and checks
the header agaisnt that depth; it expects the on-disk semantics,
but we are giving it the opposite in the while loop in this 
function.  We should be giving it the on-disk notion of "depth"
which we can get from (p_depth - depth) - and if you look, the last
(more commonly hit) call to ext4_ext_check_header() does just this.

Sending in the wrong depth results in (incorrect) messages
about corruption:

EXT4-fs error (device sdb1): ext4_ext_search_right: bad header
in inode #2621457: unexpected eh_depth - magic f30a, entries 340,
max 340(0), depth 1(2)

Reported-by: David Dindorp <ddi at dubex.dk>
Signed-off-by: Eric Sandeen <sandeen at redhat.com>
--

Index: linux-2.6/fs/ext4/extents.c
===================================================================
--- linux-2.6.orig/fs/ext4/extents.c
+++ linux-2.6/fs/ext4/extents.c
@@ -1122,7 +1122,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 @@ got_index:
 		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;
 		}

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


linux-2.6-ext4-print-warning-once.patch:

--- NEW FILE linux-2.6-ext4-print-warning-once.patch ---
From: Theodore Ts'o <tytso at mit.edu>
Date: Thu, 12 Mar 2009 16:20:01 +0000 (-0400)
Subject: ext4: Print the find_group_flex() warning only once
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftytso%2Fext4.git;a=commitdiff_plain;h=e8eb6f8319eb2536d292fc18fe14e745c970049a

ext4: Print the find_group_flex() warning only once

This is a short-term warning, and even printk_ratelimit() can result
in too much noise in system logs.  So only print it once as a warning.

Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
---

diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 627f8c3..2d2b358 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -698,6 +698,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
 	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 */
@@ -719,7 +720,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, int mode)
 		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);

linux-2.6-hdpvr.patch:

--- NEW FILE linux-2.6-hdpvr.patch ---
Video capture driver for the Hauppauge HD PVR

upstream: http://hg.jannau.net/hdpvr/
product info: http://hauppauge.com/site/products/data_hdpvr.html

Signed-off-by: Jarod Wilson <jarod at redhat.com>

---
 drivers/media/video/Kconfig               |    2 +
 drivers/media/video/Makefile              |    2 +
 drivers/media/video/hdpvr/Kconfig         |   10 +
 drivers/media/video/hdpvr/Makefile        |    7 +
 drivers/media/video/hdpvr/hdpvr-control.c |  212 +++++
 drivers/media/video/hdpvr/hdpvr-core.c    |  461 +++++++++++
 drivers/media/video/hdpvr/hdpvr-i2c.c     |  145 ++++
 drivers/media/video/hdpvr/hdpvr-video.c   | 1258 +++++++++++++++++++++++++++++
 drivers/media/video/hdpvr/hdpvr.h         |  326 ++++++++
 drivers/media/video/v4l2-common.c         |    3 +
 include/linux/i2c-id.h                    |    1 +
 11 files changed, 2427 insertions(+), 0 deletions(-)

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 19cf3b8..4f29e1a 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -817,6 +817,8 @@ source "drivers/media/video/gspca/Kconfig"
 
 source "drivers/media/video/pvrusb2/Kconfig"
 
+source "drivers/media/video/hdpvr/Kconfig"
+
 source "drivers/media/video/em28xx/Kconfig"
 
 source "drivers/media/video/usbvision/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 72f6d03..e7e4508 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -128,6 +128,8 @@ obj-$(CONFIG_USB_VICAM)         += usbvideo/
 obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= usbvideo/
 obj-$(CONFIG_USB_S2255)		+= s2255drv.o
 
+obj-$(CONFIG_VIDEO_HDPVR)       += hdpvr/
+
 obj-$(CONFIG_VIDEO_IVTV) += ivtv/
 obj-$(CONFIG_VIDEO_CX18) += cx18/
 
diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/video/hdpvr/Kconfig
new file mode 100644
index 0000000..de247f3
--- /dev/null
+++ b/drivers/media/video/hdpvr/Kconfig
@@ -0,0 +1,10 @@
+
+config VIDEO_HDPVR
+	tristate "Hauppauge HD PVR support"
+	depends on VIDEO_DEV
+	---help---
+	  This is a video4linux driver for Hauppauge's HD PVR USB device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hdpvr
+
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
new file mode 100644
index 0000000..79ad2e1
--- /dev/null
+++ b/drivers/media/video/hdpvr/Makefile
@@ -0,0 +1,7 @@
+hdpvr-objs	:= hdpvr-control.o hdpvr-core.o hdpvr-i2c.o hdpvr-video.o
+
+obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
+
+EXTRA_CFLAGS += -Idrivers/media/video
+
+EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c
new file mode 100644
index 0000000..eee0cc6
--- /dev/null
+++ b/drivers/media/video/hdpvr/hdpvr-control.c
@@ -0,0 +1,212 @@
+/*
+ * Hauppage HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j at jannau.net)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+#include <linux/videodev2.h>
+
+#include "hdpvr.h"
+
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
+{
+	int ret;
+	char request_type = 0x38, snd_request = 0x01;
+	char *buf = kmalloc(1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	msleep(10);
+
+	*buf = valbuf;
+	ret = usb_control_msg(dev->udev,
+			      usb_sndctrlpipe(dev->udev, 0),
+			      snd_request, 0x00 | request_type,
+			      value, CTRL_DEFAULT_INDEX,
+			      buf, 1, 10000);
+
+	hdpvr_info("config call request returned %d", ret);
+
+	kfree(buf);
+
+	return ret < 0 ? ret : 0;
+}
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
+{
+	u8 *buffer;
+	struct hdpvr_video_info *vidinf = NULL;
+#ifdef HDPVR_DEBUG
+	char print_buf[15];
+#endif
+	int ret;
+
+	buffer = kzalloc(5, GFP_KERNEL);
+	if (!buffer) {
+		err("out of memory");
+		goto err;
+	}
+	vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
+	if (!vidinf) {
+		err("out of memory");
+		goto err;
+	}
+
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1400, 0x0003,
+			      buffer, 5,
+			      1000);
+	if (ret == 5) {
+		vidinf->width	= buffer[1] << 8 | buffer[0];
+		vidinf->height	= buffer[3] << 8 | buffer[2];
+		vidinf->fps	= buffer[4];
+	}
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO) {
+		print_bytes(print_buf, buffer, 5);
+		hdpvr_info("get video info returned: %d, %s", ret, print_buf);
+	}
+#endif
+
+	if (!vidinf->width || !vidinf->height || !vidinf->fps) {
+		kfree(vidinf);
+		vidinf = NULL;
+	}
+err:
+	kfree(buffer);
+	return vidinf;
+}
+
+int get_input_lines_info(struct hdpvr_device *dev)
+{
+	u8 buffer[3];
+#ifdef HDPVR_DEBUG
+	char print_buf[9];
+#endif
+	int ret;
+
+	ret = usb_control_msg(dev->udev,
+			      usb_rcvctrlpipe(dev->udev, 0),
+			      0x81, 0x80 | 0x38,
+			      0x1800, 0x0003,
+			      buffer, 3,
+			      1000);
+
+#ifdef HDPVR_DEBUG
+	if (hdpvr_debug & MSG_INFO) {
+		print_bytes(print_buf, buffer, 3);
+		hdpvr_info("get input lines info returned: %d, %s", ret,
[...2142 lines suppressed...]
+	STATUS_STREAMING,
+	STATUS_ERROR,
+};
+
+enum {
+	HDPVR_FLAG_AC3_CAP = 1,
+};
+
+enum {
+	BUFSTAT_UNINITIALIZED = 0,
+	BUFSTAT_AVAILABLE,
+	BUFSTAT_INPROGRESS,
+	BUFSTAT_READY,
+};
+
+#define CTRL_START_STREAMING_VALUE	0x0700
+#define CTRL_STOP_STREAMING_VALUE	0x0800
+#define CTRL_BITRATE_VALUE		0x1000
+#define CTRL_BITRATE_MODE_VALUE		0x1200
+#define CTRL_GOP_MODE_VALUE		0x1300
+#define CTRL_VIDEO_INPUT_VALUE		0x1500
+#define CTRL_VIDEO_STD_TYPE		0x1700
+#define CTRL_AUDIO_INPUT_VALUE		0x2500
+#define CTRL_BRIGHTNESS			0x2900
+#define CTRL_CONTRAST			0x2a00
+#define CTRL_HUE			0x2b00
+#define CTRL_SATURATION			0x2c00
+#define CTRL_SHARPNESS			0x2d00
+#define CTRL_LOW_PASS_FILTER_VALUE	0x3100
+
+#define CTRL_DEFAULT_INDEX		0x0003
+
+
+	/* :0 s 38 01 1000 0003 0004 4 = 0a00ca00
+	 * BITRATE SETTING
+	 *   1st and 2nd byte (little endian): average bitrate in 100 000 bit/s
+	 *                                     min: 1 mbit/s, max: 13.5 mbit/s
+	 *   3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s
+	 *                                     min: average + 100kbit/s,
+	 *                                      max: 20.2 mbit/s
+	 */
+
+	/* :0 s 38 01 1200 0003 0001 1 = 02
+	 * BIT RATE MODE
+	 *  constant = 1, variable (peak) = 2, variable (average) = 3
+	 */
+
+	/* :0 s 38 01 1300 0003 0001 1 = 03
+	 * GOP MODE (2 bit)
+	 *    low bit 0/1: advanced/simple GOP
+	 *   high bit 0/1: IDR(4/32/128) / no IDR (4/32/0)
+	 */
+
+	/* :0 s 38 01 1700 0003 0001 1 = 00
+	 * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz
+	 */
+
+	/* :0 s 38 01 3100 0003 0004 4 = 03030000
+	 * FILTER CONTROL
+	 *   1st byte luma low pass filter strength,
+	 *   2nd byte chroma low pass filter strength,
+	 *   3rd byte MF enable chroma, min=0, max=1
+	 *   4th byte n
+	 */
+
+
+	/* :0 s 38 b9 0001 0000 0000 0 */
+
+
+
+/* :0 s 38 d3 0000 0000 0001 1 = 00 */
+/* 		ret = usb_control_msg(dev->udev, */
+/* 				      usb_sndctrlpipe(dev->udev, 0), */
+/* 				      0xd3, 0x38, */
+/* 				      0, 0, */
+/* 				      "\0", 1, */
+/* 				      1000); */
+
+/* 		info("control request returned %d", ret); */
+/* 		msleep(5000); */
+
+
+	/* :0 s b8 81 1400 0003 0005 5 <
+	 * :0 0 5 = d0024002 19
+	 * QUERY FRAME SIZE AND RATE
+	 *   1st and 2nd byte (little endian): horizontal resolution
+	 *   3rd and 4th byte (little endian): vertical resolution
+	 *   5th byte: frame rate
+	 */
+
+	/* :0 s b8 81 1800 0003 0003 3 <
+	 * :0 0 3 = 030104
+	 * QUERY SIGNAL AND DETECTED LINES, maybe INPUT
+	 */
+
+enum hdpvr_video_std {
+	HDPVR_60HZ = 0,
+	HDPVR_50HZ,
+};
+
+enum hdpvr_video_input {
+	HDPVR_COMPONENT = 0,
+	HDPVR_SVIDEO,
+	HDPVR_COMPOSITE,
+	HDPVR_VIDEO_INPUTS
+};
+
+enum hdpvr_audio_inputs {
+	HDPVR_RCA_BACK = 0,
+	HDPVR_RCA_FRONT,
+	HDPVR_SPDIF,
+	HDPVR_AUDIO_INPUTS
+};
+
+enum hdpvr_bitrate_mode {
+	HDPVR_CONSTANT = 1,
+	HDPVR_VARIABLE_PEAK,
+	HDPVR_VARIABLE_AVERAGE,
+};
+
+enum hdpvr_gop_mode {
+	HDPVR_ADVANCED_IDR_GOP = 0,
+	HDPVR_SIMPLE_IDR_GOP,
+	HDPVR_ADVANCED_NOIDR_GOP,
+	HDPVR_SIMPLE_NOIDR_GOP,
+};
+
+void hdpvr_delete(struct kref *kref);
+
+/*========================================================================*/
+/* hardware control functions */
+int hdpvr_set_options(struct hdpvr_device *dev);
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev);
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+		    enum v4l2_mpeg_audio_encoding codec);
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value,
+		      unsigned char valbuf);
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev);
+
+/* :0 s b8 81 1800 0003 0003 3 < */
+/* :0 0 3 = 0301ff */
+int get_input_lines_info(struct hdpvr_device *dev);
+
+
+/*========================================================================*/
+/* v4l2 registration */
+int hdpvr_register_videodev(struct hdpvr_device *dev, int devnumber);
+
+
+/*========================================================================*/
+/* i2c adapter registration */
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* buffer management */
+int hdpvr_free_buffers(struct hdpvr_device *dev);
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count);
+
+
+
+#ifdef HDPVR_DEBUG
+void print_bytes(char *string, unsigned char *buf, size_t len);
+#endif
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index b8f2be8..0e8bd98 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -547,6 +547,7 @@ int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 ste
 	case V4L2_CID_CONTRAST:
 	case V4L2_CID_SATURATION:
 	case V4L2_CID_HUE:
+	case V4L2_CID_SHARPNESS:
 		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
 		break;
 	}
@@ -585,6 +586,8 @@ int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
 		return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64);
 	case V4L2_CID_HUE:
 		return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0);
+	case V4L2_CID_SHARPNESS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
 
 	/* MPEG controls */
 	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 1ffc23b..e77f81b 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -87,6 +87,7 @@
 #define I2C_HW_B_CX2341X	0x010020 /* Conexant CX2341X MPEG encoder cards */
 #define I2C_HW_B_CX23885	0x010022 /* conexant 23885 based tv cards (bus1) */
 #define I2C_HW_B_AU0828		0x010023 /* auvitek au0828 usb bridge */
+#define I2C_HW_B_HDPVR		0x010024 /* Hauppauge HD PVR */
 
 /* --- SGI adapters							*/
 #define I2C_HW_SGI_VINO		0x160000

linux-2.6-net-tulip-interrupt.patch:

--- NEW FILE linux-2.6-net-tulip-interrupt.patch ---
https://bugzilla.redhat.com/show_bug.cgi?id=454575

Signed-off-by: Dave Jones <davej at redhat.com>

diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index cafa89e..daa83a7 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -502,11 +502,11 @@ tulip_open(struct net_device *dev)
 {
 	int retval;
 
+	tulip_init_ring(dev);
+
 	if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev)))
 		return retval;
 
-	tulip_init_ring (dev);
-
 	tulip_up (dev);
 
 	netif_start_queue (dev);

linux-2.6-net-velocity-dma.patch:

--- NEW FILE linux-2.6-net-velocity-dma.patch ---
The DMA debug patches caught this..

via-velocity 0000:00:0e.0: DMA-API: device driver frees DMA memory with different size [device address=0x000000001a4c8ca2] [map size=60 bytes] [unmap size=54 bytes]

Signed-off-by: Dave Jones <davej at redhat.com>

diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index c5691fd..cd34dda 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -1838,6 +1838,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_
 {
 	struct sk_buff *skb = tdinfo->skb;
 	int i;
+	int pktlen;
 
 	/*
 	 *	Don't unmap the pre-allocated tx_bufs
@@ -1845,10 +1846,12 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_
 	if (tdinfo->skb_dma) {
 
 		for (i = 0; i < tdinfo->nskb_dma; i++) {
+			pktlen = max_t(unsigned, skb->len, ETH_ZLEN);
+
 #ifdef VELOCITY_ZERO_COPY_SUPPORT
 			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE);
 #else
-			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE);
+			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE);
 #endif
 			tdinfo->skb_dma[i] = 0;
 		}
@@ -2080,17 +2083,14 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct tx_desc *td_ptr;
 	struct velocity_td_info *tdinfo;
 	unsigned long flags;
-	int pktlen = skb->len;
+	int pktlen;
 	__le16 len;
 	int index;
 
 
-
-	if (skb->len < ETH_ZLEN) {
-		if (skb_padto(skb, ETH_ZLEN))
-			goto out;
-		pktlen = ETH_ZLEN;
-	}
+	if (skb_padto(skb, ETH_ZLEN))
+		goto out;
+	pktlen = max_t(unsigned, skb->len, ETH_ZLEN);
 
 	len = cpu_to_le16(pktlen);
 


--- NEW FILE linux-2.6.28.tar.bz2.sign ---
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: See http://www.kernel.org/signature.html for info

iD8DBQBJUsmzyGugalF9Dw4RAmYWAKCUJGMWXRrUNC/XDQl8lXXOv5zMvACfUvU5
Tq+2snGYOGwTki85iNpds/o=
=Ha/W
-----END PGP SIGNATURE-----


--- NEW FILE patch-2.6.29-rc8-git2.bz2.sign ---
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: See http://www.kernel.org/signature.html for info

iD8DBQBJvZc3yGugalF9Dw4RAnitAJ4giK8VMVgmN6jhwp6e9mWJuFeGdwCfddkj
Lv6B1wHur1mgk2HzkrWPsPI=
=kj/v
-----END PGP SIGNATURE-----


--- NEW FILE patch-2.6.29-rc8.bz2.sign ---
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: See http://www.kernel.org/signature.html for info

iD8DBQBJud6vyGugalF9Dw4RAi59AJ46IxrRi8gfTikGOfe4LBW7ukwcgQCeMSQz
mB+94unFITUPKld3rfo0gXA=
=ShaR
-----END PGP SIGNATURE-----


Index: config-powerpc-generic
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/config-powerpc-generic,v
retrieving revision 1.36
retrieving revision 1.36.6.1
diff -u -r1.36 -r1.36.6.1
--- config-powerpc-generic	4 Mar 2009 00:09:55 -0000	1.36
+++ config-powerpc-generic	24 Mar 2009 17:57:34 -0000	1.36.6.1
@@ -262,7 +262,7 @@
 CONFIG_QE_GPIO=y
 CONFIG_MPC8xxx_GPIO=y
 
-CONFIG_IDE_GD=m
+CONFIG_IDE_GD=y
 CONFIG_IDE_GD_ATA=y
 CONFIG_IDE_GD_ATAPI=y
 


Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.1438
retrieving revision 1.1438.2.1
diff -u -r1.1438 -r1.1438.2.1
--- kernel.spec	17 Mar 2009 00:43:17 -0000	1.1438
+++ kernel.spec	24 Mar 2009 17:57:34 -0000	1.1438.2.1
@@ -1815,6 +1815,17 @@
 # and build.
 
 %changelog
+* Tue Mar 24 2009 Kyle McMartin <kyle at redhat.com>
+- F-11 beta branch
+- btrfs fixes + ide disk ppc fix.
+- add back in dropped stuff due to cvs flubbage.
+
+* Tue Mar 24 2009 Josef Bacik <josef at toxicpanda.com>
+- fsync replay fixes for btrfs
+
+* Mon Mar 23 2009 Bill Nottingham <notting at redhat.com>
+- build ide-gd_mod in on PPC (#491380)
+
 * Mon Mar 16 2009 Josef Bacik <josef at toxicpanda.com> 2.6.29-0.258.rc8.git2
 - update btrfs code so it doesn't pop the stack on x86
 

linux-2.6-btrfs-experimental-branch.patch:

Index: linux-2.6-btrfs-experimental-branch.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-btrfs-experimental-branch.patch,v
retrieving revision 1.1
retrieving revision 1.1.8.1
diff -u -r1.1 -r1.1.8.1
--- linux-2.6-btrfs-experimental-branch.patch	16 Mar 2009 17:30:23 -0000	1.1
+++ linux-2.6-btrfs-experimental-branch.patch	24 Mar 2009 17:57:34 -0000	1.1.8.1
@@ -5205,3 +5205,946 @@
  out:
  	if (path)
  		btrfs_free_path(path);
+diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
+index 72677ce..3af4cfb 100644
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -86,12 +86,6 @@ struct btrfs_inode {
+ 	 */
+ 	u64 logged_trans;
+ 
+-	/*
+-	 * trans that last made a change that should be fully fsync'd.  This
+-	 * gets reset to zero each time the inode is logged
+-	 */
+-	u64 log_dirty_trans;
+-
+ 	/* total number of bytes pending delalloc, used by stat to calc the
+ 	 * real block usage of the file
+ 	 */
+@@ -121,6 +115,13 @@ struct btrfs_inode {
+ 	/* the start of block group preferred for allocations. */
+ 	u64 block_group;
+ 
++	/* the fsync log has some corner cases that mean we have to check
++	 * directories to see if any unlinks have been done before
++	 * the directory was logged.  See tree-log.c for all the
++	 * details
++	 */
++	u64 last_unlink_trans;
++
+ 	struct inode vfs_inode;
+ };
+ 
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index 4ddce91..2737fac 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -695,7 +695,12 @@ struct btrfs_fs_info {
+ 
+ 	u64 generation;
+ 	u64 last_trans_committed;
+-	u64 last_trans_new_blockgroup;
++
++	/*
++	 * this is updated to the current trans every time a full commit
++	 * is required instead of the faster short fsync log commits
++	 */
++	u64 last_trans_log_full_commit;
+ 	u64 open_ioctl_trans;
+ 	unsigned long mount_opt;
+ 	u64 max_extent;
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 8933d15..0c482e0 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -5897,7 +5897,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
+ 
+ 	extent_root = root->fs_info->extent_root;
+ 
+-	root->fs_info->last_trans_new_blockgroup = trans->transid;
++	root->fs_info->last_trans_log_full_commit = trans->transid;
+ 
+ 	cache = kzalloc(sizeof(*cache), GFP_NOFS);
+ 	if (!cache)
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index f06c275..32d10a6 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1173,8 +1173,11 @@ out_nolock:
+ 			ret = btrfs_log_dentry_safe(trans, root,
+ 						    file->f_dentry);
+ 			if (ret == 0) {
+-				btrfs_sync_log(trans, root);
+-				btrfs_end_transaction(trans, root);
++				ret = btrfs_sync_log(trans, root);
++				if (ret == 0)
++					btrfs_end_transaction(trans, root);
++				else
++					btrfs_commit_transaction(trans, root);
+ 			} else {
+ 				btrfs_commit_transaction(trans, root);
+ 			}
+@@ -1266,8 +1269,11 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+ 	if (ret > 0) {
+ 		ret = btrfs_commit_transaction(trans, root);
+ 	} else {
+-		btrfs_sync_log(trans, root);
+-		ret = btrfs_end_transaction(trans, root);
++		ret = btrfs_sync_log(trans, root);
++		if (ret == 0)
++			ret = btrfs_end_transaction(trans, root);
++		else
++			ret = btrfs_commit_transaction(trans, root);
+ 	}
+ 	mutex_lock(&dentry->d_inode->i_mutex);
+ out:
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 9b4faac..bffd79f 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -2246,8 +2246,6 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
+ 	ret = btrfs_del_inode_ref_in_log(trans, root, name, name_len,
+ 					 inode, dir->i_ino);
+ 	BUG_ON(ret != 0 && ret != -ENOENT);
+-	if (ret != -ENOENT)
+-		BTRFS_I(dir)->log_dirty_trans = trans->transid;
+ 
+ 	ret = btrfs_del_dir_entries_in_log(trans, root, name, name_len,
+ 					   dir, index);
+@@ -2280,6 +2278,9 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
+ 	trans = btrfs_start_transaction(root, 1);
+ 
+ 	btrfs_set_trans_block_group(trans, dir);
++
++	btrfs_record_unlink_dir(trans, dir, dentry->d_inode, 0);
++
+ 	ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
+ 				 dentry->d_name.name, dentry->d_name.len);
+ 
+@@ -3042,7 +3043,7 @@ static noinline void init_btrfs_i(struct inode *inode)
+ 	bi->disk_i_size = 0;
+ 	bi->flags = 0;
+ 	bi->index_cnt = (u64)-1;
+-	bi->log_dirty_trans = 0;
++	bi->last_unlink_trans = 0;
+ 	extent_map_tree_init(&BTRFS_I(inode)->extent_tree, GFP_NOFS);
+ 	extent_io_tree_init(&BTRFS_I(inode)->io_tree,
+ 			     inode->i_mapping, GFP_NOFS);
+@@ -3786,6 +3787,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
+ 		drop_inode = 1;
+ 
+ 	nr = trans->blocks_used;
++
++	btrfs_log_new_name(trans, inode, NULL, dentry->d_parent);
+ 	btrfs_end_transaction_throttle(trans, root);
+ fail:
+ 	if (drop_inode) {
+@@ -4666,6 +4669,15 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 
+ 	trans = btrfs_start_transaction(root, 1);
+ 
++	/*
++	 * this is an ugly little race, but the rename is required to make
++	 * sure that if we crash, the inode is either at the old name
++	 * or the new one.  pinning the log transaction lets us make sure
++	 * we don't allow a log commit to come in after we unlink the
++	 * name but before we add the new name back in.
++	 */
++	btrfs_pin_log_trans(root);
++
+ 	btrfs_set_trans_block_group(trans, new_dir);
+ 
+ 	btrfs_inc_nlink(old_dentry->d_inode);
+@@ -4673,6 +4685,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	new_dir->i_ctime = new_dir->i_mtime = ctime;
+ 	old_inode->i_ctime = ctime;
+ 
++	if (old_dentry->d_parent != new_dentry->d_parent)
++		btrfs_record_unlink_dir(trans, old_dir, old_inode, 1);
++
+ 	ret = btrfs_unlink_inode(trans, root, old_dir, old_dentry->d_inode,
+ 				 old_dentry->d_name.name,
+ 				 old_dentry->d_name.len);
+@@ -4704,7 +4719,14 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ 	if (ret)
+ 		goto out_fail;
+ 
++	btrfs_log_new_name(trans, old_inode, old_dir,
++				       new_dentry->d_parent);
+ out_fail:
++
++	/* this btrfs_end_log_trans just allows the current
++	 * log-sub transaction to complete
++	 */
++	btrfs_end_log_trans(root);
+ 	btrfs_end_transaction_throttle(trans, root);
+ out_unlock:
+ 	return ret;
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index 9c462fb..fc9b87a 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -35,6 +35,49 @@
+ #define LOG_INODE_EXISTS 1
+ 
+ /*
++ * directory trouble cases
++ *
++ * 1) on rename or unlink, if the inode being unlinked isn't in the fsync
++ * log, we must force a full commit before doing an fsync of the directory
++ * where the unlink was done.
++ * ---> record transid of last unlink/rename per directory
++ *
++ * mkdir foo/some_dir
++ * normal commit
++ * rename foo/some_dir foo2/some_dir
++ * mkdir foo/some_dir
++ * fsync foo/some_dir/some_file
++ *
++ * The fsync above will unlink the original some_dir without recording
++ * it in its new location (foo2).  After a crash, some_dir will be gone
++ * unless the fsync of some_file forces a full commit
++ *
++ * 2) we must log any new names for any file or dir that is in the fsync
++ * log. ---> check inode while renaming/linking.
++ *
++ * 2a) we must log any new names for any file or dir during rename
++ * when the directory they are being removed from was logged.
++ * ---> check inode and old parent dir during rename
++ *
++ *  2a is actually the more important variant.  With the extra logging
++ *  a crash might unlink the old name without recreating the new one
++ *
++ * 3) after a crash, we must go through any directories with a link count
++ * of zero and redo the rm -rf
++ *
++ * mkdir f1/foo
++ * normal commit
++ * rm -rf f1/foo
++ * fsync(f1)
++ *
++ * The directory f1 was fully removed from the FS, but fsync was never
++ * called on f1, only its parent dir.  After a crash the rm -rf must
++ * be replayed.  This must be able to recurse down the entire
++ * directory tree.  The inode link count fixup code takes care of the
++ * ugly details.
++ */
++
++/*
+  * stages for the tree walking.  The first
+  * stage (0) is to only pin down the blocks we find
+  * the second stage (1) is to make sure that all the inodes
+@@ -47,12 +90,17 @@
+ #define LOG_WALK_REPLAY_INODES 1
+ #define LOG_WALK_REPLAY_ALL 2
+ 
+-static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
++static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ 			     struct btrfs_root *root, struct inode *inode,
+ 			     int inode_only);
+ static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
+ 			     struct btrfs_root *root,
+ 			     struct btrfs_path *path, u64 objectid);
++static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
++				       struct btrfs_root *root,
++				       struct btrfs_root *log,
++				       struct btrfs_path *path,
++				       u64 dirid, int del_all);
+ 
+ /*
+  * tree logging is a special write ahead log used to make sure that
+@@ -133,10 +181,25 @@ static int join_running_log_trans(struct btrfs_root *root)
+ }
+ 
+ /*
++ * This either makes the current running log transaction wait
++ * until you call btrfs_end_log_trans() or it makes any future
++ * log transactions wait until you call btrfs_end_log_trans()
++ */
++int btrfs_pin_log_trans(struct btrfs_root *root)
++{
++	int ret = -ENOENT;
++
++	mutex_lock(&root->log_mutex);
++	atomic_inc(&root->log_writers);
++	mutex_unlock(&root->log_mutex);
++	return ret;
++}
++
++/*
+  * indicate we're done making changes to the log tree
+  * and wake up anyone waiting to do a sync
+  */
+-static int end_log_trans(struct btrfs_root *root)
++int btrfs_end_log_trans(struct btrfs_root *root)
+ {
+ 	if (atomic_dec_and_test(&root->log_writers)) {
+ 		smp_mb();
+@@ -203,7 +266,6 @@ static int process_one_buffer(struct btrfs_root *log,
+ 		mutex_lock(&log->fs_info->pinned_mutex);
+ 		btrfs_update_pinned_extents(log->fs_info->extent_root,
+ 					    eb->start, eb->len, 1);
+-		mutex_unlock(&log->fs_info->pinned_mutex);
+ 	}
+ 
+ 	if (btrfs_buffer_uptodate(eb, gen)) {
+@@ -603,6 +665,7 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans,
+ 
+ 	ret = link_to_fixup_dir(trans, root, path, location.objectid);
+ 	BUG_ON(ret);
++
+ 	ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len);
+ 	BUG_ON(ret);
+ 	kfree(name);
+@@ -804,6 +867,7 @@ conflict_again:
+ 					    victim_name_len)) {
+ 				btrfs_inc_nlink(inode);
+ 				btrfs_release_path(root, path);
++
+ 				ret = btrfs_unlink_inode(trans, root, dir,
+ 							 inode, victim_name,
+ 							 victim_name_len);
+@@ -922,13 +986,20 @@ static noinline int fixup_inode_link_count(struct btrfs_trans_handle *trans,
+ 		key.offset--;
+ 		btrfs_release_path(root, path);
+ 	}
+-	btrfs_free_path(path);
++	btrfs_release_path(root, path);
+ 	if (nlink != inode->i_nlink) {
+ 		inode->i_nlink = nlink;
+ 		btrfs_update_inode(trans, root, inode);
+ 	}
+ 	BTRFS_I(inode)->index_cnt = (u64)-1;
+ 
++	if (inode->i_nlink == 0 && S_ISDIR(inode->i_mode)) {
++		ret = replay_dir_deletes(trans, root, NULL, path,
++					 inode->i_ino, 1);
++		BUG_ON(ret);
++	}
++	btrfs_free_path(path);
++
+ 	return 0;
+ }
+ 
+@@ -971,9 +1042,12 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans,
+ 
+ 		iput(inode);
+ 
+-		if (key.offset == 0)
+-			break;
+-		key.offset--;
++		/*
++		 * fixup on a directory may create new entries,
++		 * make sure we always look for the highset possible
++		 * offset
++		 */
++		key.offset = (u64)-1;
+ 	}
+ 	btrfs_release_path(root, path);
+ 	return 0;
+@@ -1313,11 +1387,11 @@ again:
+ 		read_extent_buffer(eb, name, (unsigned long)(di + 1),
+ 				  name_len);
+ 		log_di = NULL;
+-		if (dir_key->type == BTRFS_DIR_ITEM_KEY) {
++		if (log && dir_key->type == BTRFS_DIR_ITEM_KEY) {
+ 			log_di = btrfs_lookup_dir_item(trans, log, log_path,
+ 						       dir_key->objectid,
+ 						       name, name_len, 0);
+-		} else if (dir_key->type == BTRFS_DIR_INDEX_KEY) {
++		} else if (log && dir_key->type == BTRFS_DIR_INDEX_KEY) {
+ 			log_di = btrfs_lookup_dir_index_item(trans, log,
+ 						     log_path,
+ 						     dir_key->objectid,
+@@ -1378,7 +1452,7 @@ static noinline int replay_dir_deletes(struct btrfs_trans_handle *trans,
+ 				       struct btrfs_root *root,
+ 				       struct btrfs_root *log,
+ 				       struct btrfs_path *path,
+-				       u64 dirid)
++				       u64 dirid, int del_all)
+ {
+ 	u64 range_start;
+ 	u64 range_end;
+@@ -1408,10 +1482,14 @@ again:
+ 	range_start = 0;
+ 	range_end = 0;
+ 	while (1) {
+-		ret = find_dir_range(log, path, dirid, key_type,
+-				     &range_start, &range_end);
+-		if (ret != 0)
+-			break;
++		if (del_all)
++			range_end = (u64)-1;
++		else {
++			ret = find_dir_range(log, path, dirid, key_type,
++					     &range_start, &range_end);
++			if (ret != 0)
++				break;
++		}
+ 
+ 		dir_key.offset = range_start;
+ 		while (1) {
+@@ -1437,7 +1515,8 @@ again:
+ 				break;
+ 
+ 			ret = check_item_in_log(trans, root, log, path,
+-						log_path, dir, &found_key);
++						log_path, dir,
++						&found_key);
+ 			BUG_ON(ret);
+ 			if (found_key.offset == (u64)-1)
+ 				break;
+@@ -1514,7 +1593,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
+ 			mode = btrfs_inode_mode(eb, inode_item);
+ 			if (S_ISDIR(mode)) {
+ 				ret = replay_dir_deletes(wc->trans,
+-					 root, log, path, key.objectid);
++					 root, log, path, key.objectid, 0);
+ 				BUG_ON(ret);
+ 			}
+ 			ret = overwrite_item(wc->trans, root, path,
+@@ -1533,6 +1612,17 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
+ 					root, inode, inode->i_size,
+ 					BTRFS_EXTENT_DATA_KEY);
+ 				BUG_ON(ret);
++
++				/* if the nlink count is zero here, the iput
++				 * will free the inode.  We bump it to make
++				 * sure it doesn't get freed until the link
++				 * count fixup is done
++				 */
++				if (inode->i_nlink == 0) {
++					btrfs_inc_nlink(inode);
++					btrfs_update_inode(wc->trans,
++							   root, inode);
++				}
+ 				iput(inode);
+ 			}
+ 			ret = link_to_fixup_dir(wc->trans, root,
+@@ -1840,7 +1930,8 @@ static int update_log_root(struct btrfs_trans_handle *trans,
+ 	return ret;
+ }
+ 
+-static int wait_log_commit(struct btrfs_root *root, unsigned long transid)
++static int wait_log_commit(struct btrfs_trans_handle *trans,
++			   struct btrfs_root *root, unsigned long transid)
+ {
+ 	DEFINE_WAIT(wait);
+ 	int index = transid % 2;
+@@ -1854,9 +1945,12 @@ static int wait_log_commit(struct btrfs_root *root, unsigned long transid)
+ 		prepare_to_wait(&root->log_commit_wait[index],
+ 				&wait, TASK_UNINTERRUPTIBLE);
+ 		mutex_unlock(&root->log_mutex);
+-		if (root->log_transid < transid + 2 &&
++
++		if (root->fs_info->last_trans_log_full_commit !=
++		    trans->transid && root->log_transid < transid + 2 &&
+ 		    atomic_read(&root->log_commit[index]))
+ 			schedule();
++
+ 		finish_wait(&root->log_commit_wait[index], &wait);
+ 		mutex_lock(&root->log_mutex);
+ 	} while (root->log_transid < transid + 2 &&
+@@ -1864,14 +1958,16 @@ static int wait_log_commit(struct btrfs_root *root, unsigned long transid)
+ 	return 0;
+ }
+ 
+-static int wait_for_writer(struct btrfs_root *root)
++static int wait_for_writer(struct btrfs_trans_handle *trans,
++			   struct btrfs_root *root)
+ {
+ 	DEFINE_WAIT(wait);
+ 	while (atomic_read(&root->log_writers)) {
+ 		prepare_to_wait(&root->log_writer_wait,
+ 				&wait, TASK_UNINTERRUPTIBLE);
+ 		mutex_unlock(&root->log_mutex);
+-		if (atomic_read(&root->log_writers))
++		if (root->fs_info->last_trans_log_full_commit !=
++		    trans->transid && atomic_read(&root->log_writers))
+ 			schedule();
+ 		mutex_lock(&root->log_mutex);
+ 		finish_wait(&root->log_writer_wait, &wait);
+@@ -1882,7 +1978,14 @@ static int wait_for_writer(struct btrfs_root *root)
+ /*
+  * btrfs_sync_log does sends a given tree log down to the disk and
+  * updates the super blocks to record it.  When this call is done,
+- * you know that any inodes previously logged are safely on disk
++ * you know that any inodes previously logged are safely on disk only
++ * if it returns 0.
++ *
++ * Any other return value means you need to call btrfs_commit_transaction.
++ * Some of the edge cases for fsyncing directories that have had unlinks
++ * or renames done in the past mean that sometimes the only safe
++ * fsync is to commit the whole FS.  When btrfs_sync_log returns -EAGAIN,
++ * that has happened.
+  */
+ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 		   struct btrfs_root *root)
+@@ -1896,7 +1999,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 	mutex_lock(&root->log_mutex);
+ 	index1 = root->log_transid % 2;
+ 	if (atomic_read(&root->log_commit[index1])) {
+-		wait_log_commit(root, root->log_transid);
++		wait_log_commit(trans, root, root->log_transid);
+ 		mutex_unlock(&root->log_mutex);
+ 		return 0;
+ 	}
+@@ -1904,18 +2007,26 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 
+ 	/* wait for previous tree log sync to complete */
+ 	if (atomic_read(&root->log_commit[(index1 + 1) % 2]))
+-		wait_log_commit(root, root->log_transid - 1);
++		wait_log_commit(trans, root, root->log_transid - 1);
+ 
+ 	while (1) {
+ 		unsigned long batch = root->log_batch;
+ 		mutex_unlock(&root->log_mutex);
+ 		schedule_timeout_uninterruptible(1);
+ 		mutex_lock(&root->log_mutex);
+-		wait_for_writer(root);
++
++		wait_for_writer(trans, root);
+ 		if (batch == root->log_batch)
+ 			break;
+ 	}
+ 
++	/* bail out if we need to do a full commit */
++	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
++		ret = -EAGAIN;
++		mutex_unlock(&root->log_mutex);
++		goto out;
++	}
++
+ 	ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages);
+ 	BUG_ON(ret);
+ 
+@@ -1951,16 +2062,29 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 
+ 	index2 = log_root_tree->log_transid % 2;
+ 	if (atomic_read(&log_root_tree->log_commit[index2])) {
+-		wait_log_commit(log_root_tree, log_root_tree->log_transid);
++		wait_log_commit(trans, log_root_tree,
++				log_root_tree->log_transid);
+ 		mutex_unlock(&log_root_tree->log_mutex);
+ 		goto out;
+ 	}
+ 	atomic_set(&log_root_tree->log_commit[index2], 1);
+ 
+-	if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2]))
+-		wait_log_commit(log_root_tree, log_root_tree->log_transid - 1);
++	if (atomic_read(&log_root_tree->log_commit[(index2 + 1) % 2])) {
++		wait_log_commit(trans, log_root_tree,
++				log_root_tree->log_transid - 1);
++	}
++
++	wait_for_writer(trans, log_root_tree);
+ 
+-	wait_for_writer(log_root_tree);
++	/*
++	 * now that we've moved on to the tree of log tree roots,
++	 * check the full commit flag again
++	 */
++	if (root->fs_info->last_trans_log_full_commit == trans->transid) {
++		mutex_unlock(&log_root_tree->log_mutex);
++		ret = -EAGAIN;
++		goto out_wake_log_root;
++	}
+ 
+ 	ret = btrfs_write_and_wait_marked_extents(log_root_tree,
+ 				&log_root_tree->dirty_log_pages);
+@@ -1985,7 +2109,9 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 	 * in and cause problems either.
+ 	 */
+ 	write_ctree_super(trans, root->fs_info->tree_root, 2);
++	ret = 0;
+ 
++out_wake_log_root:
+ 	atomic_set(&log_root_tree->log_commit[index2], 0);
+ 	smp_mb();
+ 	if (waitqueue_active(&log_root_tree->log_commit_wait[index2]))
+@@ -1998,7 +2124,8 @@ out:
+ 	return 0;
+ }
+ 
+-/* * free all the extents used by the tree log.  This should be called
++/*
++ * free all the extents used by the tree log.  This should be called
+  * at commit time of the full transaction
+  */
+ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root)
+@@ -2132,7 +2259,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
+ 
+ 	btrfs_free_path(path);
+ 	mutex_unlock(&BTRFS_I(dir)->log_mutex);
+-	end_log_trans(root);
++	btrfs_end_log_trans(root);
+ 
+ 	return 0;
+ }
+@@ -2159,7 +2286,7 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
+ 	ret = btrfs_del_inode_ref(trans, log, name, name_len, inode->i_ino,
+ 				  dirid, &index);
+ 	mutex_unlock(&BTRFS_I(inode)->log_mutex);
+-	end_log_trans(root);
++	btrfs_end_log_trans(root);
+ 
+ 	return ret;
+ }
+@@ -2559,7 +2686,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
+  *
+  * This handles both files and directories.
+  */
+-static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
++static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ 			     struct btrfs_root *root, struct inode *inode,
+ 			     int inode_only)
+ {
+@@ -2585,28 +2712,17 @@ static int __btrfs_log_inode(struct btrfs_trans_handle *trans,
+ 	min_key.offset = 0;
+ 
+ 	max_key.objectid = inode->i_ino;
++
++	/* today the code can only do partial logging of directories */
++	if (!S_ISDIR(inode->i_mode))
++	    inode_only = LOG_INODE_ALL;
++
+ 	if (inode_only == LOG_INODE_EXISTS || S_ISDIR(inode->i_mode))
+ 		max_key.type = BTRFS_XATTR_ITEM_KEY;
+ 	else
+ 		max_key.type = (u8)-1;
+ 	max_key.offset = (u64)-1;
+ 
+-	/*
+-	 * if this inode has already been logged and we're in inode_only
+-	 * mode, we don't want to delete the things that have already
+-	 * been written to the log.
+-	 *
+-	 * But, if the inode has been through an inode_only log,
+-	 * the logged_trans field is not set.  This allows us to catch
+-	 * any new names for this inode in the backrefs by logging it
+-	 * again
+-	 */
+-	if (inode_only == LOG_INODE_EXISTS &&
+-	    BTRFS_I(inode)->logged_trans == trans->transid) {
+-		btrfs_free_path(path);
+-		btrfs_free_path(dst_path);
+-		goto out;
+-	}
+ 	mutex_lock(&BTRFS_I(inode)->log_mutex);
+ 
+ 	/*
+@@ -2693,7 +2809,6 @@ next_slot:
+ 	if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
+ 		btrfs_release_path(root, path);
+ 		btrfs_release_path(log, dst_path);
+-		BTRFS_I(inode)->log_dirty_trans = 0;
+ 		ret = log_directory_changes(trans, root, inode, path, dst_path);
+ 		BUG_ON(ret);
+ 	}
+@@ -2702,19 +2817,69 @@ next_slot:
+ 
+ 	btrfs_free_path(path);
+ 	btrfs_free_path(dst_path);
+-out:
+ 	return 0;
+ }
+ 
+-int btrfs_log_inode(struct btrfs_trans_handle *trans,
+-		    struct btrfs_root *root, struct inode *inode,
+-		    int inode_only)
++/*
++ * follow the dentry parent pointers up the chain and see if any
++ * of the directories in it require a full commit before they can
++ * be logged.  Returns zero if nothing special needs to be done or 1 if
++ * a full commit is required.
++ */
++static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans,
++					       struct inode *inode,
++					       struct dentry *parent,
++					       struct super_block *sb,
++					       u64 last_committed)
+ {
+-	int ret;
++	int ret = 0;
++	struct btrfs_root *root;
+ 
+-	start_log_trans(trans, root);
+-	ret = __btrfs_log_inode(trans, root, inode, inode_only);
+-	end_log_trans(root);
++	/*
++	 * for regular files, if its inode is already on disk, we don't
++	 * have to worry about the parents at all.  This is because
++	 * we can use the last_unlink_trans field to record renames
++	 * and other fun in this file.
++	 */
++	if (S_ISREG(inode->i_mode) &&
++	    BTRFS_I(inode)->generation <= last_committed &&
++	    BTRFS_I(inode)->last_unlink_trans <= last_committed)
++			goto out;
++
++	if (!S_ISDIR(inode->i_mode)) {
++		if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
++			goto out;
++		inode = parent->d_inode;
++	}
++
++	while (1) {
++		BTRFS_I(inode)->logged_trans = trans->transid;
++		smp_mb();
++
++		if (BTRFS_I(inode)->last_unlink_trans > last_committed) {
++			root = BTRFS_I(inode)->root;
++
++			/*
++			 * make sure any commits to the log are forced
++			 * to be full commits
++			 */
++			root->fs_info->last_trans_log_full_commit =
++				trans->transid;
++			ret = 1;
++			break;
++		}
++
++		if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
++			break;
++
++		if (parent == sb->s_root)
++			break;
++
++		parent = parent->d_parent;
++		inode = parent->d_inode;
++
++	}
++out:
+ 	return ret;
+ }
+ 
+@@ -2724,31 +2889,65 @@ int btrfs_log_inode(struct btrfs_trans_handle *trans,
+  * only logging is done of any parent directories that are older than
+  * the last committed transaction
+  */
+-int btrfs_log_dentry(struct btrfs_trans_handle *trans,
+-		    struct btrfs_root *root, struct dentry *dentry)
++int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
++		    struct btrfs_root *root, struct inode *inode,
++		    struct dentry *parent, int exists_only)
+ {
+-	int inode_only = LOG_INODE_ALL;
++	int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL;
+ 	struct super_block *sb;
+-	int ret;
++	int ret = 0;
++	u64 last_committed = root->fs_info->last_trans_committed;
++
++	sb = inode->i_sb;
++
++	if (root->fs_info->last_trans_log_full_commit >
++	    root->fs_info->last_trans_committed) {
++		ret = 1;
++		goto end_no_trans;
++	}
++
++	ret = check_parent_dirs_for_sync(trans, inode, parent,
++					 sb, last_committed);
++	if (ret)
++		goto end_no_trans;
+ 
+ 	start_log_trans(trans, root);
+-	sb = dentry->d_inode->i_sb;
+-	while (1) {
+-		ret = __btrfs_log_inode(trans, root, dentry->d_inode,
+-					inode_only);
+-		BUG_ON(ret);
+-		inode_only = LOG_INODE_EXISTS;
+ 
+-		dentry = dentry->d_parent;
+-		if (!dentry || !dentry->d_inode || sb != dentry->d_inode->i_sb)
++	ret = btrfs_log_inode(trans, root, inode, inode_only);
++	BUG_ON(ret);
++
++	/*
++	 * for regular files, if its inode is already on disk, we don't
++	 * have to worry about the parents at all.  This is because
++	 * we can use the last_unlink_trans field to record renames
++	 * and other fun in this file.
++	 */
++	if (S_ISREG(inode->i_mode) &&
++	    BTRFS_I(inode)->generation <= last_committed &&
++	    BTRFS_I(inode)->last_unlink_trans <= last_committed)
++			goto no_parent;
++
++	inode_only = LOG_INODE_EXISTS;
++	while (1) {
++		if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb)
+ 			break;
+ 
+-		if (BTRFS_I(dentry->d_inode)->generation <=
+-		    root->fs_info->last_trans_committed)
++		inode = parent->d_inode;
++		if (BTRFS_I(inode)->generation >
++		    root->fs_info->last_trans_committed) {
++			ret = btrfs_log_inode(trans, root, inode, inode_only);
++			BUG_ON(ret);
++		}
++		if (parent == sb->s_root)
+ 			break;
++
++		parent = parent->d_parent;
+ 	}
+-	end_log_trans(root);
+-	return 0;
++no_parent:
++	ret = 0;
++	btrfs_end_log_trans(root);
++end_no_trans:
++	return ret;
+ }
+ 
+ /*
+@@ -2760,12 +2959,8 @@ int btrfs_log_dentry(struct btrfs_trans_handle *trans,
+ int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
+ 			  struct btrfs_root *root, struct dentry *dentry)
+ {
+-	u64 gen;
+-	gen = root->fs_info->last_trans_new_blockgroup;
+-	if (gen > root->fs_info->last_trans_committed)
+-		return 1;
+-	else
+-		return btrfs_log_dentry(trans, root, dentry);
++	return btrfs_log_inode_parent(trans, root, dentry->d_inode,
++				      dentry->d_parent, 0);
+ }
+ 
+ /*
+@@ -2884,3 +3079,94 @@ again:
+ 	kfree(log_root_tree);
+ 	return 0;
+ }
++
++/*
++ * there are some corner cases where we want to force a full
++ * commit instead of allowing a directory to be logged.
++ *
++ * They revolve around files there were unlinked from the directory, and
++ * this function updates the parent directory so that a full commit is
++ * properly done if it is fsync'd later after the unlinks are done.
++ */
++void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
++			     struct inode *dir, struct inode *inode,
++			     int for_rename)
++{
++	/*
++	 * when we're logging a file, if it hasn't been renamed
++	 * or unlinked, and its inode is fully committed on disk,
++	 * we don't have to worry about walking up the directory chain
++	 * to log its parents.
++	 *
++	 * So, we use the last_unlink_trans field to put this transid
++	 * into the file.  When the file is logged we check it and
++	 * don't log the parents if the file is fully on disk.
++	 */
++	if (S_ISREG(inode->i_mode))
++		BTRFS_I(inode)->last_unlink_trans = trans->transid;
++
++	/*
++	 * if this directory was already logged any new
++	 * names for this file/dir will get recorded
++	 */
++	smp_mb();
++	if (BTRFS_I(dir)->logged_trans == trans->transid)
++		return;
++
++	/*
++	 * if the inode we're about to unlink was logged,
++	 * the log will be properly updated for any new names
++	 */
++	if (BTRFS_I(inode)->logged_trans == trans->transid)
++		return;
++
++	/*
++	 * when renaming files across directories, if the directory
++	 * there we're unlinking from gets fsync'd later on, there's
++	 * no way to find the destination directory later and fsync it
++	 * properly.  So, we have to be conservative and force commits
++	 * so the new name gets discovered.
++	 */
++	if (for_rename)
++		goto record;
++
++	/* we can safely do the unlink without any special recording */
++	return;
++
++record:
++	BTRFS_I(dir)->last_unlink_trans = trans->transid;
++}
++
++/*
++ * Call this after adding a new name for a file and it will properly
++ * update the log to reflect the new name.
++ *
++ * It will return zero if all goes well, and it will return 1 if a
++ * full transaction commit is required.
++ */
++int btrfs_log_new_name(struct btrfs_trans_handle *trans,
++			struct inode *inode, struct inode *old_dir,
++			struct dentry *parent)
++{
++	struct btrfs_root * root = BTRFS_I(inode)->root;
++
++	/*
++	 * this will force the logging code to walk the dentry chain
++	 * up for the file
++	 */
++	if (S_ISREG(inode->i_mode))
++		BTRFS_I(inode)->last_unlink_trans = trans->transid;
++
++	/*
++	 * if this inode hasn't been logged and directory we're renaming it
++	 * from hasn't been logged, we don't need to log it
++	 */
++	if (BTRFS_I(inode)->logged_trans <=
++	    root->fs_info->last_trans_committed &&
++	    (!old_dir || BTRFS_I(old_dir)->logged_trans <=
++		    root->fs_info->last_trans_committed))
++		return 0;
++
++	return btrfs_log_inode_parent(trans, root, inode, parent, 1);
++}
++
+diff --git a/fs/btrfs/tree-log.h b/fs/btrfs/tree-log.h
+index b9409b3..d09c760 100644
+--- a/fs/btrfs/tree-log.h
++++ b/fs/btrfs/tree-log.h
+@@ -22,14 +22,9 @@
+ int btrfs_sync_log(struct btrfs_trans_handle *trans,
+ 		   struct btrfs_root *root);
+ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root);
+-int btrfs_log_dentry(struct btrfs_trans_handle *trans,
+-		    struct btrfs_root *root, struct dentry *dentry);
+ int btrfs_recover_log_trees(struct btrfs_root *tree_root);
+ int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
+ 			  struct btrfs_root *root, struct dentry *dentry);
+-int btrfs_log_inode(struct btrfs_trans_handle *trans,
+-		    struct btrfs_root *root, struct inode *inode,
+-		    int inode_only);
+ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
+ 				 struct btrfs_root *root,
+ 				 const char *name, int name_len,
+@@ -38,4 +33,16 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
+ 			       struct btrfs_root *root,
+ 			       const char *name, int name_len,
+ 			       struct inode *inode, u64 dirid);
++int btrfs_join_running_log_trans(struct btrfs_root *root);
++int btrfs_end_log_trans(struct btrfs_root *root);
++int btrfs_pin_log_trans(struct btrfs_root *root);
++int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
++		    struct btrfs_root *root, struct inode *inode,
++		    struct dentry *parent, int exists_only);
++void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
++			     struct inode *dir, struct inode *inode,
++			     int for_rename);
++int btrfs_log_new_name(struct btrfs_trans_handle *trans,
++			struct inode *inode, struct inode *old_dir,
++			struct dentry *parent);
+ #endif




More information about the fedora-extras-commits mailing list