summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJody McIntyre <scjody@modernduck.com>2005-02-09 08:19:10 -0500
committerJody McIntyre <scjody@modernduck.com>2005-02-09 08:19:10 -0500
commit23750010bfa81de0867ddd4bd4bd7c9b2d27fe05 (patch)
tree0b0b2ff8aab00bf3dcb5753a2e7a1217194c1312
parentc5ff533d2618c3c26242551e2a9957763f126e2c (diff)
parent245f9eba891010ed627fec5b83d0f7b575e3d5ce (diff)
Merge modernduck.com:/usr/src/bk/linux-2.5
into modernduck.com:/usr/src/bk/1394-2.6
-rw-r--r--Documentation/nommu-mmap.txt141
-rw-r--r--arch/arm/mm/tlb-v4.S2
-rw-r--r--arch/arm/mm/tlb-v4wb.S2
-rw-r--r--arch/mips/lib-32/dump_tlb.c2
-rw-r--r--arch/mips/lib-64/dump_tlb.c2
-rw-r--r--arch/sparc64/defconfig16
-rw-r--r--arch/sparc64/lib/user_fixup.c9
-rw-r--r--arch/um/kernel/skas/Makefile2
-rw-r--r--drivers/char/agp/intel-agp.c4
-rw-r--r--drivers/char/drm/drm_drv.c2
-rw-r--r--drivers/char/drm/drm_os_linux.h3
-rw-r--r--drivers/char/drm/radeon_drv.h28
-rw-r--r--drivers/char/drm/radeon_state.c155
-rw-r--r--drivers/md/md.c23
-rw-r--r--drivers/md/raid5.c123
-rw-r--r--drivers/md/raid6main.c112
-rw-r--r--drivers/net/tg3.c32
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/serial/8250.c7
-rw-r--r--fs/hostfs/hostfs.h21
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rw-r--r--fs/nfsd/nfsproc.c2
-rw-r--r--fs/nfsd/vfs.c9
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c1
-rw-r--r--include/asm-ia64/page.h3
-rw-r--r--include/asm-sparc64/compat.h2
-rw-r--r--include/asm-x86_64/system.h2
-rw-r--r--include/linux/highmem.h4
-rw-r--r--include/linux/mm.h4
-rw-r--r--include/linux/raid/raid5.h2
-rw-r--r--init/do_mounts_md.c10
-rw-r--r--kernel/sched.c8
-rw-r--r--mm/filemap.c10
-rw-r--r--mm/nommu.c16
-rw-r--r--net/atm/addr.c2
-rw-r--r--net/atm/addr.h2
-rw-r--r--net/core/dev.c4
-rw-r--r--net/ipv4/ipconfig.c11
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c14
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/sched/cls_u32.c5
-rw-r--r--net/xfrm/Makefile3
-rw-r--r--net/xfrm/xfrm_algo.c12
-rw-r--r--net/xfrm/xfrm_export.c62
-rw-r--r--net/xfrm/xfrm_input.c4
-rw-r--r--net/xfrm/xfrm_policy.c20
-rw-r--r--net/xfrm/xfrm_state.c29
48 files changed, 604 insertions, 340 deletions
diff --git a/Documentation/nommu-mmap.txt b/Documentation/nommu-mmap.txt
new file mode 100644
index 000000000000..fcf1c086f0ba
--- /dev/null
+++ b/Documentation/nommu-mmap.txt
@@ -0,0 +1,141 @@
+ =============================
+ NO-MMU MEMORY MAPPING SUPPORT
+ =============================
+
+The kernel has limited support for memory mapping under no-MMU conditions, such
+as are used in uClinux environments. From the userspace point of view, memory
+mapping is made use of in conjunction with the mmap() system call, the shmat()
+call and the execve() system call. From the kernel's point of view, execve()
+mapping is actually performed by the binfmt drivers, which call back into the
+mmap() routines to do the actual work.
+
+Memory mapping behaviour also involves the way fork(), vfork(), clone() and
+ptrace() work. Under uClinux there is no fork(), and clone() must be supplied
+the CLONE_VM flag.
+
+The behaviour is similar between the MMU and no-MMU cases, but not identical;
+and it's also much more restricted in the latter case:
+
+ (*) Anonymous mapping, MAP_PRIVATE
+
+ In the MMU case: VM regions backed by arbitrary pages; copy-on-write
+ across fork.
+
+ In the no-MMU case: VM regions backed by arbitrary contiguous runs of
+ pages.
+
+ (*) Anonymous mapping, MAP_SHARED
+
+ These behave very much like private mappings, except that they're
+ shared across fork() or clone() without CLONE_VM in the MMU case. Since
+ the no-MMU case doesn't support these, behaviour is identical to
+ MAP_PRIVATE there.
+
+ (*) File, MAP_PRIVATE, PROT_READ / PROT_EXEC, !PROT_WRITE
+
+ In the MMU case: VM regions backed by pages read from file; changes to
+ the underlying file are reflected in the mapping; copied across fork.
+
+ In the no-MMU case: VM regions backed by arbitrary contiguous runs of
+ pages into which the appropriate bit of the file is read; any remaining
+ bit of the mapping is cleared; such mappings are shared if possible;
+ writes to the file do not affect the mapping; writes to the mapping are
+ visible in other processes (no MMU protection), but should not happen.
+
+ (*) File, MAP_PRIVATE, PROT_READ / PROT_EXEC, PROT_WRITE
+
+ In the MMU case: like the non-PROT_WRITE case, except that the pages in
+ question get copied before the write actually happens. From that point
+ on writes to that page in the file no longer get reflected into the
+ mapping's backing pages.
+
+ In the no-MMU case: works exactly as for the non-PROT_WRITE case.
+
+ (*) Regular file / blockdev, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE
+
+ In the MMU case: VM regions backed by pages read from file; changes to
+ pages written back to file; writes to file reflected into pages backing
+ mapping; shared across fork.
+
+ In the no-MMU case: not supported.
+
+ (*) Memory backed regular file, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE
+
+ In the MMU case: As for ordinary regular files.
+
+ In the no-MMU case: The filesystem providing the memory-backed file
+ (such as ramfs or tmpfs) may choose to honour an open, truncate, mmap
+ sequence by providing a contiguous sequence of pages to map. In that
+ case, a shared-writable memory mapping will be possible. It will work
+ as for the MMU case. If the filesystem does not provide any such
+ support, then the mapping request will be denied.
+
+ (*) Memory backed chardev, MAP_SHARED, PROT_READ / PROT_EXEC / PROT_WRITE
+
+ In the MMU case: As for ordinary regular files.
+
+ In the no-MMU case: The character device driver may choose to honour
+ the mmap() by providing direct access to the underlying device if it
+ provides memory or quasi-memory that can be accessed directly. Examples
+ of such are frame buffers and flash devices. If the driver does not
+ provide any such support, then the mapping request will be denied.
+
+
+============================
+FURTHER NOTES ON NO-MMU MMAP
+============================
+
+ (*) A request for a private mapping of less than a page in size may not return
+ a page-aligned buffer. This is because the kernel calls kmalloc() to
+ allocate the buffer, not get_free_page().
+
+ (*) A list of all the mappings on the system is visible through /proc/maps in
+ no-MMU mode.
+
+ (*) Supplying MAP_FIXED or a requesting a particular mapping address will
+ result in an error.
+
+ (*) Files mapped privately must have a read method provided by the driver or
+ filesystem so that the contents can be read into the memory allocated. An
+ error will result if they don't. This is most likely to be encountered
+ with character device files, pipes, fifos and sockets.
+
+
+============================================
+PROVIDING SHAREABLE CHARACTER DEVICE SUPPORT
+============================================
+
+To provide shareable character device support, a driver must provide a
+file->f_op->get_unmapped_area() operation. The mmap() routines will call this
+to get a proposed address for the mapping. This may return an error if it
+doesn't wish to honour the mapping because it's too long, at a weird offset,
+under some unsupported combination of flags or whatever.
+
+The vm_ops->close() routine will be invoked when the last mapping on a chardev
+is removed. An existing mapping will be shared, partially or not, if possible
+without notifying the driver.
+
+It is permitted also for the file->f_op->get_unmapped_area() operation to
+return -ENOSYS. This will be taken to mean that this operation just doesn't
+want to handle it, despite the fact it's got an operation. For instance, it
+might try directing the call to a secondary driver which turns out not to
+implement it. Such is the case for the framebuffer driver which attempts to
+direct the call to the device-specific driver.
+
+
+==============================================
+PROVIDING SHAREABLE MEMORY-BACKED FILE SUPPORT
+==============================================
+
+Provision of shared mappings on memory backed files is similar to the provision
+of support for shared mapped character devices. The main difference is that the
+filesystem providing the service will probably allocate a contiguous collection
+of pages and permit mappings to be made on that.
+
+It is recommended that a truncate operation applied to such a file that
+increases the file size, if that file is empty, be taken as a request to gather
+enough pages to honour a mapping. This is required to support POSIX shared
+memory.
+
+Memory backed devices are indicated by the mapping's backing device info having
+the memory_backed flag set.
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index 0c7329f9c38a..db82ee468248 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -44,7 +44,7 @@ ENTRY(v4_flush_user_tlb_range)
mov pc, lr
/*
- * v4_flush_kerm_tlb_range(start, end)
+ * v4_flush_kern_tlb_range(start, end)
*
* Invalidate a range of TLB entries in the specified kernel
* address range.
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index 15dc83d10397..7908d5f1f130 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -47,7 +47,7 @@ ENTRY(v4wb_flush_user_tlb_range)
mov pc, lr
/*
- * v4_flush_kerm_tlb_range(start, end)
+ * v4_flush_kern_tlb_range(start, end)
*
* Invalidate a range of TLB entries in the specified kernel
* address range.
diff --git a/arch/mips/lib-32/dump_tlb.c b/arch/mips/lib-32/dump_tlb.c
index b92fea6927ea..019ac8f005d7 100644
--- a/arch/mips/lib-32/dump_tlb.c
+++ b/arch/mips/lib-32/dump_tlb.c
@@ -32,6 +32,8 @@ static inline const char *msk2str(unsigned int mask)
case PM_256M: return "256Mb";
#endif
}
+
+ return "unknown";
}
#define BARRIER() \
diff --git a/arch/mips/lib-64/dump_tlb.c b/arch/mips/lib-64/dump_tlb.c
index 2a422948c7dc..42f88e055b4c 100644
--- a/arch/mips/lib-64/dump_tlb.c
+++ b/arch/mips/lib-64/dump_tlb.c
@@ -32,6 +32,8 @@ static inline const char *msk2str(unsigned int mask)
case PM_256M: return "256Mb";
#endif
}
+
+ return "unknown";
}
#define BARRIER() \
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 79917803c92d..5fe6aaabd05f 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1
-# Fri Jan 21 20:03:21 2005
+# Linux kernel version: 2.6.11-rc3
+# Mon Feb 7 15:29:00 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -845,6 +845,7 @@ CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_BCSP_TXCRC=y
CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
CONFIG_BT_HCIBFUSB=m
CONFIG_BT_HCIVHCI=m
CONFIG_NETDEVICES=y
@@ -1245,7 +1246,12 @@ CONFIG_JFS_SECURITY=y
# CONFIG_JFS_DEBUG is not set
# CONFIG_JFS_STATISTICS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
CONFIG_XFS_QUOTA=y
CONFIG_XFS_SECURITY=y
@@ -1520,6 +1526,11 @@ CONFIG_DVB_ATMEL_AT76C651=m
CONFIG_DVB_VES1820=m
CONFIG_DVB_TDA10021=m
CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terresterial DTV) frontends
+#
+CONFIG_DVB_NXT2002=m
CONFIG_VIDEO_SAA7146=m
CONFIG_VIDEO_SAA7146_VV=m
CONFIG_VIDEO_VIDEOBUF=m
@@ -1527,6 +1538,7 @@ CONFIG_VIDEO_TUNER=m
CONFIG_VIDEO_BUF=m
CONFIG_VIDEO_BTCX=m
CONFIG_VIDEO_IR=m
+CONFIG_VIDEO_TVEEPROM=m
#
# Sound
diff --git a/arch/sparc64/lib/user_fixup.c b/arch/sparc64/lib/user_fixup.c
index 58ec56050b9e..0278e34125db 100644
--- a/arch/sparc64/lib/user_fixup.c
+++ b/arch/sparc64/lib/user_fixup.c
@@ -20,11 +20,12 @@ unsigned long copy_from_user_fixup(void *to, const void __user *from, unsigned l
char *dst = to;
const char __user *src = from;
- while (size--) {
+ while (size) {
if (__get_user(*dst, src))
break;
dst++;
src++;
+ size--;
}
if (size)
@@ -38,11 +39,12 @@ unsigned long copy_to_user_fixup(void __user *to, const void *from, unsigned lon
char __user *dst = to;
const char *src = from;
- while (size--) {
+ while (size) {
if (__put_user(*src, dst))
break;
dst++;
src++;
+ size--;
}
return size;
@@ -53,7 +55,7 @@ unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned lo
char __user *dst = to;
char __user *src = from;
- while (size--) {
+ while (size) {
char tmp;
if (__get_user(tmp, src))
@@ -62,6 +64,7 @@ unsigned long copy_in_user_fixup(void __user *to, void __user *from, unsigned lo
break;
dst++;
src++;
+ size--;
}
return size;
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index c340c9cbf19b..867dff072934 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -11,3 +11,5 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+subdir- := util
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index a3abfb89d7cb..06e791f3b65d 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -1748,12 +1748,16 @@ static int agp_intel_resume(struct pci_dev *pdev)
if (bridge->driver == &intel_generic_driver)
intel_configure();
+ else if (bridge->driver == &intel_850_driver)
+ intel_850_configure();
else if (bridge->driver == &intel_845_driver)
intel_845_configure();
else if (bridge->driver == &intel_830mp_driver)
intel_830mp_configure();
else if (bridge->driver == &intel_915_driver)
intel_i915_configure();
+ else if (bridge->driver == &intel_830_driver)
+ intel_i830_configure();
return 0;
}
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index d216c28fb669..5845d986e6ec 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -516,7 +516,7 @@ int drm_ioctl( struct inode *inode, struct file *filp,
if (nr < DRIVER_IOCTL_COUNT)
ioctl = &drm_ioctls[nr];
- else if ((nr >= DRM_COMMAND_BASE) || (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+ else if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
else
goto err_i1;
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
index 9870cc3283b1..3247e14b564f 100644
--- a/drivers/char/drm/drm_os_linux.h
+++ b/drivers/char/drm/drm_os_linux.h
@@ -96,9 +96,6 @@ static __inline__ int mtrr_del (int reg, unsigned long base,
__copy_to_user(arg1, arg2, arg3)
#define DRM_GET_USER_UNCHECKED(val, uaddr) \
__get_user(val, uaddr)
-#define DRM_PUT_USER_UNCHECKED(uaddr, val) \
- __put_user(val, uaddr)
-
#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 4fdcc2836f69..ce4ea6969ea5 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -1027,25 +1027,27 @@ do { \
} while (0)
-#define OUT_RING_USER_TABLE( tab, sz ) do { \
+#define OUT_RING_TABLE( tab, sz ) do { \
int _size = (sz); \
- int __user *_tab = (tab); \
+ int *_tab = (int *)(tab); \
\
if (write + _size > mask) { \
- int i = (mask+1) - write; \
- if (DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \
- _tab, i*4 )) \
- return DRM_ERR(EFAULT); \
+ int _i = (mask+1) - write; \
+ _size -= _i; \
+ while (_i > 0 ) { \
+ *(int *)(ring + write) = *_tab++; \
+ write++; \
+ _i--; \
+ } \
write = 0; \
- _size -= i; \
- _tab += i; \
+ _tab += _i; \
} \
\
- if (_size && DRM_COPY_FROM_USER_UNCHECKED( (int *)(ring+write), \
- _tab, _size*4 )) \
- return DRM_ERR(EFAULT); \
- \
- write += _size; \
+ while (_size > 0) { \
+ *(ring + write) = *_tab++; \
+ write++; \
+ _size--; \
+ } \
write &= mask; \
} while (0)
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 6a0f129f7bc9..b8d38e106708 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -93,21 +93,6 @@ static __inline__ int radeon_check_and_fixup_offset( drm_radeon_private_t *dev_p
return 0;
}
-static __inline__ int radeon_check_and_fixup_offset_user( drm_radeon_private_t *dev_priv,
- drm_file_t *filp_priv,
- u32 __user *offset ) {
- u32 off;
-
- DRM_GET_USER_UNCHECKED( off, offset );
-
- if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &off ) )
- return DRM_ERR( EINVAL );
-
- DRM_PUT_USER_UNCHECKED( offset, off );
-
- return 0;
-}
-
static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_priv,
drm_file_t *filp_priv,
int id,
@@ -115,18 +100,18 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
switch ( id ) {
case RADEON_EMIT_PP_MISC:
- if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
- &data[( RADEON_RB3D_DEPTHOFFSET
- - RADEON_PP_MISC ) / 4] ) ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_DEPTHOFFSET
+ - RADEON_PP_MISC ) / 4] ) ) {
DRM_ERROR( "Invalid depth buffer offset\n" );
return DRM_ERR( EINVAL );
}
break;
case RADEON_EMIT_PP_CNTL:
- if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
- &data[( RADEON_RB3D_COLOROFFSET
- - RADEON_PP_CNTL ) / 4] ) ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &data[( RADEON_RB3D_COLOROFFSET
+ - RADEON_PP_CNTL ) / 4] ) ) {
DRM_ERROR( "Invalid colour buffer offset\n" );
return DRM_ERR( EINVAL );
}
@@ -138,8 +123,8 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case R200_EMIT_PP_TXOFFSET_3:
case R200_EMIT_PP_TXOFFSET_4:
case R200_EMIT_PP_TXOFFSET_5:
- if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
- &data[0] ) ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &data[0] ) ) {
DRM_ERROR( "Invalid R200 texture offset\n" );
return DRM_ERR( EINVAL );
}
@@ -148,9 +133,9 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case RADEON_EMIT_PP_TXFILTER_0:
case RADEON_EMIT_PP_TXFILTER_1:
case RADEON_EMIT_PP_TXFILTER_2:
- if ( radeon_check_and_fixup_offset_user( dev_priv, filp_priv,
- &data[( RADEON_PP_TXOFFSET_0
- - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &data[( RADEON_PP_TXOFFSET_0
+ - RADEON_PP_TXFILTER_0 ) / 4] ) ) {
DRM_ERROR( "Invalid R100 texture offset\n" );
return DRM_ERR( EINVAL );
}
@@ -164,9 +149,8 @@ static __inline__ int radeon_check_and_fixup_packets( drm_radeon_private_t *dev_
case R200_EMIT_PP_CUBIC_OFFSETS_5: {
int i;
for ( i = 0; i < 5; i++ ) {
- if ( radeon_check_and_fixup_offset_user( dev_priv,
- filp_priv,
- &data[i] ) ) {
+ if ( radeon_check_and_fixup_offset( dev_priv, filp_priv,
+ &data[i] ) ) {
DRM_ERROR( "Invalid R200 cubic texture offset\n" );
return DRM_ERR( EINVAL );
}
@@ -250,17 +234,11 @@ static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_
drm_file_t *filp_priv,
drm_radeon_cmd_buffer_t *cmdbuf,
unsigned int *cmdsz ) {
- u32 tmp[4];
- u32 __user *cmd = (u32 __user *)cmdbuf->buf;
-
- if ( DRM_COPY_FROM_USER_UNCHECKED( tmp, cmd, sizeof( tmp ) ) ) {
- DRM_ERROR( "Failed to copy data from user space\n" );
- return DRM_ERR( EFAULT );
- }
+ u32 *cmd = (u32 *) cmdbuf->buf;
- *cmdsz = 2 + ( ( tmp[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
+ *cmdsz = 2 + ( ( cmd[0] & RADEON_CP_PACKET_COUNT_MASK ) >> 16 );
- if ( ( tmp[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
+ if ( ( cmd[0] & 0xc0000000 ) != RADEON_CP_PACKET3 ) {
DRM_ERROR( "Not a type 3 packet\n" );
return DRM_ERR( EINVAL );
}
@@ -271,32 +249,27 @@ static __inline__ int radeon_check_and_fixup_packet3( drm_radeon_private_t *dev_
}
/* Check client state and fix it up if necessary */
- if ( tmp[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
+ if ( cmd[0] & 0x8000 ) { /* MSB of opcode: next DWORD GUI_CNTL */
u32 offset;
- if ( tmp[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
+ if ( cmd[1] & ( RADEON_GMC_SRC_PITCH_OFFSET_CNTL
| RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
- offset = tmp[2] << 10;
+ offset = cmd[2] << 10;
if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
DRM_ERROR( "Invalid first packet offset\n" );
return DRM_ERR( EINVAL );
}
- tmp[2] = ( tmp[2] & 0xffc00000 ) | offset >> 10;
+ cmd[2] = ( cmd[2] & 0xffc00000 ) | offset >> 10;
}
- if ( ( tmp[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
- ( tmp[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
- offset = tmp[3] << 10;
+ if ( ( cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL ) &&
+ ( cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL ) ) {
+ offset = cmd[3] << 10;
if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &offset ) ) {
DRM_ERROR( "Invalid second packet offset\n" );
return DRM_ERR( EINVAL );
}
- tmp[3] = ( tmp[3] & 0xffc00000 ) | offset >> 10;
- }
-
- if ( DRM_COPY_TO_USER_UNCHECKED( cmd, tmp, sizeof( tmp ) ) ) {
- DRM_ERROR( "Failed to copy data to user space\n" );
- return DRM_ERR( EFAULT );
+ cmd[3] = ( cmd[3] & 0xffc00000 ) | offset >> 10;
}
}
@@ -2473,7 +2446,7 @@ static int radeon_emit_packets(
{
int id = (int)header.packet.packet_id;
int sz, reg;
- int __user *data = (int __user *)cmdbuf->buf;
+ int *data = (int *)cmdbuf->buf;
RING_LOCALS;
if (id >= RADEON_MAX_STATE_PACKETS)
@@ -2494,7 +2467,7 @@ static int radeon_emit_packets(
BEGIN_RING(sz+1);
OUT_RING( CP_PACKET0( reg, (sz-1) ) );
- OUT_RING_USER_TABLE( data, sz );
+ OUT_RING_TABLE( data, sz );
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
@@ -2508,7 +2481,6 @@ static __inline__ int radeon_emit_scalars(
drm_radeon_cmd_buffer_t *cmdbuf )
{
int sz = header.scalars.count;
- int __user *data = (int __user *)cmdbuf->buf;
int start = header.scalars.offset;
int stride = header.scalars.stride;
RING_LOCALS;
@@ -2517,7 +2489,7 @@ static __inline__ int radeon_emit_scalars(
OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
- OUT_RING_USER_TABLE( data, sz );
+ OUT_RING_TABLE( cmdbuf->buf, sz );
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
@@ -2532,7 +2504,6 @@ static __inline__ int radeon_emit_scalars2(
drm_radeon_cmd_buffer_t *cmdbuf )
{
int sz = header.scalars.count;
- int __user *data = (int __user *)cmdbuf->buf;
int start = ((unsigned int)header.scalars.offset) + 0x100;
int stride = header.scalars.stride;
RING_LOCALS;
@@ -2541,7 +2512,7 @@ static __inline__ int radeon_emit_scalars2(
OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
OUT_RING( start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT));
OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_SCALAR_DATA_REG, sz-1 ) );
- OUT_RING_USER_TABLE( data, sz );
+ OUT_RING_TABLE( cmdbuf->buf, sz );
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
@@ -2554,7 +2525,6 @@ static __inline__ int radeon_emit_vectors(
drm_radeon_cmd_buffer_t *cmdbuf )
{
int sz = header.vectors.count;
- int __user *data = (int __user *)cmdbuf->buf;
int start = header.vectors.offset;
int stride = header.vectors.stride;
RING_LOCALS;
@@ -2563,7 +2533,7 @@ static __inline__ int radeon_emit_vectors(
OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
- OUT_RING_USER_TABLE( data, sz );
+ OUT_RING_TABLE( cmdbuf->buf, sz );
ADVANCE_RING();
cmdbuf->buf += sz * sizeof(int);
@@ -2578,7 +2548,6 @@ static int radeon_emit_packet3( drm_device_t *dev,
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int cmdsz;
- int __user *cmd = (int __user *)cmdbuf->buf;
int ret;
RING_LOCALS;
@@ -2591,7 +2560,7 @@ static int radeon_emit_packet3( drm_device_t *dev,
}
BEGIN_RING( cmdsz );
- OUT_RING_USER_TABLE( cmd, cmdsz );
+ OUT_RING_TABLE( cmdbuf->buf, cmdsz );
ADVANCE_RING();
cmdbuf->buf += cmdsz * 4;
@@ -2608,7 +2577,6 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_clip_rect_t box;
unsigned int cmdsz;
- int __user *cmd = (int __user *)cmdbuf->buf;
int ret;
drm_clip_rect_t __user *boxes = cmdbuf->boxes;
int i = 0;
@@ -2627,7 +2595,7 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
do {
if ( i < cmdbuf->nbox ) {
- if (DRM_COPY_FROM_USER_UNCHECKED( &box, &boxes[i], sizeof(box) ))
+ if (DRM_COPY_FROM_USER( &box, &boxes[i], sizeof(box) ))
return DRM_ERR(EFAULT);
/* FIXME The second and subsequent times round
* this loop, send a WAIT_UNTIL_3D_IDLE before
@@ -2650,7 +2618,7 @@ static int radeon_emit_packet3_cliprect( drm_device_t *dev,
}
BEGIN_RING( cmdsz );
- OUT_RING_USER_TABLE( cmd, cmdsz );
+ OUT_RING_TABLE( cmdbuf->buf, cmdsz );
ADVANCE_RING();
} while ( ++i < cmdbuf->nbox );
@@ -2703,7 +2671,8 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
int idx;
drm_radeon_cmd_buffer_t cmdbuf;
drm_radeon_cmd_header_t header;
- int orig_nbox;
+ int orig_nbox, orig_bufsz;
+ char *kbuf=NULL;
LOCK_TEST_WITH_RETURN( dev, filp );
@@ -2720,24 +2689,29 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
RING_SPACE_TEST_WITH_RETURN( dev_priv );
VB_AGE_TEST_WITH_RETURN( dev_priv );
+ if (cmdbuf.bufsz > 64*1024 || cmdbuf.bufsz<0) {
+ return DRM_ERR(EINVAL);
+ }
- if (DRM_VERIFYAREA_READ( cmdbuf.buf, cmdbuf.bufsz ))
- return DRM_ERR(EFAULT);
-
- if (cmdbuf.nbox &&
- DRM_VERIFYAREA_READ(cmdbuf.boxes,
- cmdbuf.nbox * sizeof(drm_clip_rect_t)))
- return DRM_ERR(EFAULT);
+ /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid
+ * races between checking values and using those values in other code,
+ * and simply to avoid a lot of function calls to copy in data.
+ */
+ orig_bufsz = cmdbuf.bufsz;
+ if (orig_bufsz != 0) {
+ kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER);
+ if (kbuf == NULL)
+ return DRM_ERR(ENOMEM);
+ if (DRM_COPY_FROM_USER(kbuf, cmdbuf.buf, cmdbuf.bufsz))
+ return DRM_ERR(EFAULT);
+ cmdbuf.buf = kbuf;
+ }
orig_nbox = cmdbuf.nbox;
while ( cmdbuf.bufsz >= sizeof(header) ) {
-
- if (DRM_GET_USER_UNCHECKED( header.i, (int __user *)cmdbuf.buf )) {
- DRM_ERROR("__get_user %p\n", cmdbuf.buf);
- return DRM_ERR(EFAULT);
- }
+ header.i = *(int *)cmdbuf.buf;
cmdbuf.buf += sizeof(header);
cmdbuf.bufsz -= sizeof(header);
@@ -2746,7 +2720,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_PACKET\n");
if (radeon_emit_packets( dev_priv, filp_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_packets failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2754,7 +2728,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_SCALARS\n");
if (radeon_emit_scalars( dev_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_scalars failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2762,7 +2736,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_VECTORS\n");
if (radeon_emit_vectors( dev_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_vectors failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2772,14 +2746,14 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
if ( idx < 0 || idx >= dma->buf_count ) {
DRM_ERROR( "buffer index %d (of %d max)\n",
idx, dma->buf_count - 1 );
- return DRM_ERR(EINVAL);
+ goto err;
}
buf = dma->buflist[idx];
if ( buf->filp != filp || buf->pending ) {
DRM_ERROR( "bad buffer %p %p %d\n",
buf->filp, filp, buf->pending);
- return DRM_ERR(EINVAL);
+ goto err;
}
radeon_cp_discard_buffer( dev, buf );
@@ -2789,7 +2763,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_PACKET3\n");
if (radeon_emit_packet3( dev, filp_priv, &cmdbuf )) {
DRM_ERROR("radeon_emit_packet3 failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2797,7 +2771,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n");
if (radeon_emit_packet3_cliprect( dev, filp_priv, &cmdbuf, orig_nbox )) {
DRM_ERROR("radeon_emit_packet3_clip failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2805,7 +2779,7 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_SCALARS2\n");
if (radeon_emit_scalars2( dev_priv, header, &cmdbuf )) {
DRM_ERROR("radeon_emit_scalars2 failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
@@ -2813,21 +2787,28 @@ int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
DRM_DEBUG("RADEON_CMD_WAIT\n");
if (radeon_emit_wait( dev, header.wait.flags )) {
DRM_ERROR("radeon_emit_wait failed\n");
- return DRM_ERR(EINVAL);
+ goto err;
}
break;
default:
DRM_ERROR("bad cmd_type %d at %p\n",
header.header.cmd_type,
cmdbuf.buf - sizeof(header));
- return DRM_ERR(EINVAL);
+ goto err;
}
}
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
DRM_DEBUG("DONE\n");
COMMIT_RING();
return 0;
+
+err:
+ if (orig_bufsz != 0)
+ drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER);
+ return DRM_ERR(EINVAL);
}
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 071b347b282b..68669ce10268 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -935,8 +935,8 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
max_dev = 0;
ITERATE_RDEV(mddev,rdev2,tmp)
- if (rdev2->desc_nr > max_dev)
- max_dev = rdev2->desc_nr;
+ if (rdev2->desc_nr+1 > max_dev)
+ max_dev = rdev2->desc_nr+1;
sb->max_dev = cpu_to_le32(max_dev);
for (i=0; i<max_dev;i++)
@@ -953,6 +953,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
}
sb->recovery_offset = cpu_to_le64(0); /* not supported yet */
+ sb->sb_csum = calc_sb_1_csum(sb);
}
@@ -1472,10 +1473,13 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data)
}
disk->major = MAJOR(dev);
disk->first_minor = unit << shift;
- if (partitioned)
+ if (partitioned) {
sprintf(disk->disk_name, "md_d%d", unit);
- else
+ sprintf(disk->devfs_name, "md/d%d", unit);
+ } else {
sprintf(disk->disk_name, "md%d", unit);
+ sprintf(disk->devfs_name, "md/%d", unit);
+ }
disk->fops = &md_fops;
disk->private_data = mddev;
disk->queue = mddev->queue;
@@ -2440,6 +2444,9 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev)
{
mdk_rdev_t *rdev;
+ if (mddev->pers == NULL)
+ return -ENODEV;
+
rdev = find_rdev(mddev, dev);
if (!rdev)
return -ENODEV;
@@ -3362,10 +3369,12 @@ static void md_do_sync(mddev_t *mddev)
init_waitqueue_head(&mddev->recovery_wait);
last_check = 0;
- if (j)
+ if (j>2) {
printk(KERN_INFO
"md: resuming recovery of %s from checkpoint.\n",
mdname(mddev));
+ mddev->curr_resync = j;
+ }
while (j < max_sectors) {
int sectors;
@@ -3447,7 +3456,7 @@ static void md_do_sync(mddev_t *mddev)
if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
mddev->curr_resync > 2 &&
- mddev->curr_resync > mddev->recovery_cp) {
+ mddev->curr_resync >= mddev->recovery_cp) {
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
printk(KERN_INFO
"md: checkpointing recovery of %s.\n",
@@ -3655,7 +3664,7 @@ int __init md_init(void)
for (minor=0; minor < MAX_MD_DEVS; ++minor)
devfs_mk_bdev(MKDEV(mdp_major, minor<<MdpMinorShift),
S_IFBLK|S_IRUSR|S_IWUSR,
- "md/d%d", minor);
+ "md/mdp%d", minor);
register_reboot_notifier(&md_notifier);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 783ae7a5b218..5ee4c2b553e9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -49,7 +49,7 @@
* This macro is used to determine the 'next' bio in the list, given the sector
* of the current stripe+device
*/
-#define r5_next_bio(bio, sect) ( ( bio->bi_sector + (bio->bi_size>>9) < sect + STRIPE_SECTORS) ? bio->bi_next : NULL)
+#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
/*
* The following can be used to debug the driver
*/
@@ -232,6 +232,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
}
static void unplug_slaves(mddev_t *mddev);
+static void raid5_unplug_device(request_queue_t *q);
static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector,
int pd_idx, int noblock)
@@ -612,11 +613,10 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i)
/*
- * Copy data between a page in the stripe cache, and one or more bion
- * The page could align with the middle of the bio, or there could be
- * several bion, each with several bio_vecs, which cover part of the page
- * Multiple bion are linked together on bi_next. There may be extras
- * at the end of this list. We ignore them.
+ * Copy data between a page in the stripe cache, and a bio.
+ * There are no alignment or size guarantees between the page or the
+ * bio except that there is some overlap.
+ * All iovecs in the bio must be considered.
*/
static void copy_data(int frombio, struct bio *bio,
struct page *page,
@@ -625,41 +625,38 @@ static void copy_data(int frombio, struct bio *bio,
char *pa = page_address(page);
struct bio_vec *bvl;
int i;
+ int page_offset;
- for (;bio && bio->bi_sector < sector+STRIPE_SECTORS;
- bio = r5_next_bio(bio, sector) ) {
- int page_offset;
- if (bio->bi_sector >= sector)
- page_offset = (signed)(bio->bi_sector - sector) * 512;
- else
- page_offset = (signed)(sector - bio->bi_sector) * -512;
- bio_for_each_segment(bvl, bio, i) {
- int len = bio_iovec_idx(bio,i)->bv_len;
- int clen;
- int b_offset = 0;
-
- if (page_offset < 0) {
- b_offset = -page_offset;
- page_offset += b_offset;
- len -= b_offset;
- }
+ if (bio->bi_sector >= sector)
+ page_offset = (signed)(bio->bi_sector - sector) * 512;
+ else
+ page_offset = (signed)(sector - bio->bi_sector) * -512;
+ bio_for_each_segment(bvl, bio, i) {
+ int len = bio_iovec_idx(bio,i)->bv_len;
+ int clen;
+ int b_offset = 0;
+
+ if (page_offset < 0) {
+ b_offset = -page_offset;
+ page_offset += b_offset;
+ len -= b_offset;
+ }
- if (len > 0 && page_offset + len > STRIPE_SIZE)
- clen = STRIPE_SIZE - page_offset;
- else clen = len;
+ if (len > 0 && page_offset + len > STRIPE_SIZE)
+ clen = STRIPE_SIZE - page_offset;
+ else clen = len;
- if (clen > 0) {
- char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
- if (frombio)
- memcpy(pa+page_offset, ba+b_offset, clen);
- else
- memcpy(ba+b_offset, pa+page_offset, clen);
- __bio_kunmap_atomic(ba, KM_USER0);
- }
- if (clen < len) /* hit end of page */
- break;
- page_offset += len;
+ if (clen > 0) {
+ char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
+ if (frombio)
+ memcpy(pa+page_offset, ba+b_offset, clen);
+ else
+ memcpy(ba+b_offset, pa+page_offset, clen);
+ __bio_kunmap_atomic(ba, KM_USER0);
}
+ if (clen < len) /* hit end of page */
+ break;
+ page_offset += len;
}
}
@@ -725,6 +722,10 @@ static void compute_parity(struct stripe_head *sh, int method)
ptr[count++] = page_address(sh->dev[i].page);
chosen = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
+
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
if (sh->dev[i].written) BUG();
sh->dev[i].written = chosen;
check_xor();
@@ -737,6 +738,10 @@ static void compute_parity(struct stripe_head *sh, int method)
if (i!=pd_idx && sh->dev[i].towrite) {
chosen = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
+
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
if (sh->dev[i].written) BUG();
sh->dev[i].written = chosen;
}
@@ -793,7 +798,7 @@ static void compute_parity(struct stripe_head *sh, int method)
* toread/towrite point to the first in a chain.
* The bi_next chain must be in order.
*/
-static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
+static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
{
struct bio **bip;
raid5_conf_t *conf = sh->raid_conf;
@@ -810,10 +815,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
- BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector);
+ if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+ goto overlap;
bip = & (*bip)->bi_next;
}
-/* FIXME do I need to worry about overlapping bion */
+ if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
+ goto overlap;
+
if (*bip && bi->bi_next && (*bip) != bi->bi_next)
BUG();
if (*bip)
@@ -828,7 +836,7 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
(unsigned long long)sh->sector, dd_idx);
if (forwrite) {
- /* check if page is coverred */
+ /* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
for (bi=sh->dev[dd_idx].towrite;
sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
@@ -840,6 +848,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
}
+ return 1;
+
+ overlap:
+ set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
+ spin_unlock_irq(&conf->device_lock);
+ spin_unlock(&sh->lock);
+ return 0;
}
@@ -900,6 +915,8 @@ static void handle_stripe(struct stripe_head *sh)
spin_lock_irq(&conf->device_lock);
rbi = dev->toread;
dev->toread = NULL;
+ if (test_and_clear_bit(R5_Overlap, &dev->flags))
+ wake_up(&conf->wait_for_overlap);
spin_unlock_irq(&conf->device_lock);
while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
copy_data(0, rbi, dev->page, dev->sector);
@@ -947,6 +964,9 @@ static void handle_stripe(struct stripe_head *sh)
sh->dev[i].towrite = NULL;
if (bi) to_write--;
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -975,6 +995,8 @@ static void handle_stripe(struct stripe_head *sh)
if (!test_bit(R5_Insync, &sh->dev[i].flags)) {
bi = sh->dev[i].toread;
sh->dev[i].toread = NULL;
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
if (bi) to_read--;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
@@ -1402,6 +1424,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
if ( bio_data_dir(bi) == WRITE )
md_write_start(mddev);
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+ DEFINE_WAIT(w);
new_sector = raid5_compute_sector(logical_sector,
raid_disks, data_disks, &dd_idx, &pd_idx, conf);
@@ -1410,17 +1433,28 @@ static int make_request (request_queue_t *q, struct bio * bi)
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
+ retry:
+ prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
if (sh) {
-
- add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
-
+ if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+ /* Add failed due to overlap. Flush everything
+ * and wait a while
+ */
+ raid5_unplug_device(mddev->queue);
+ release_stripe(sh);
+ schedule();
+ goto retry;
+ }
+ finish_wait(&conf->wait_for_overlap, &w);
raid5_plug_device(conf);
handle_stripe(sh);
release_stripe(sh);
+
} else {
/* cannot get stripe for read-ahead, just give-up */
clear_bit(BIO_UPTODATE, &bi->bi_flags);
+ finish_wait(&conf->wait_for_overlap, &w);
break;
}
@@ -1568,6 +1602,7 @@ static int run (mddev_t *mddev)
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
+ init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
INIT_LIST_HEAD(&conf->inactive_list);
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 8c52254c262f..0f82d85939e7 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -54,7 +54,7 @@
* This macro is used to determine the 'next' bio in the list, given the sector
* of the current stripe+device
*/
-#define r5_next_bio(bio, sect) ( ( bio->bi_sector + (bio->bi_size>>9) < sect + STRIPE_SECTORS) ? bio->bi_next : NULL)
+#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
/*
* The following can be used to debug the driver
*/
@@ -670,41 +670,38 @@ static void copy_data(int frombio, struct bio *bio,
char *pa = page_address(page);
struct bio_vec *bvl;
int i;
+ int page_offset;
- for (;bio && bio->bi_sector < sector+STRIPE_SECTORS;
- bio = r5_next_bio(bio, sector) ) {
- int page_offset;
- if (bio->bi_sector >= sector)
- page_offset = (signed)(bio->bi_sector - sector) * 512;
- else
- page_offset = (signed)(sector - bio->bi_sector) * -512;
- bio_for_each_segment(bvl, bio, i) {
- int len = bio_iovec_idx(bio,i)->bv_len;
- int clen;
- int b_offset = 0;
-
- if (page_offset < 0) {
- b_offset = -page_offset;
- page_offset += b_offset;
- len -= b_offset;
- }
+ if (bio->bi_sector >= sector)
+ page_offset = (signed)(bio->bi_sector - sector) * 512;
+ else
+ page_offset = (signed)(sector - bio->bi_sector) * -512;
+ bio_for_each_segment(bvl, bio, i) {
+ int len = bio_iovec_idx(bio,i)->bv_len;
+ int clen;
+ int b_offset = 0;
+
+ if (page_offset < 0) {
+ b_offset = -page_offset;
+ page_offset += b_offset;
+ len -= b_offset;
+ }
- if (len > 0 && page_offset + len > STRIPE_SIZE)
- clen = STRIPE_SIZE - page_offset;
- else clen = len;
-
- if (clen > 0) {
- char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
- if (frombio)
- memcpy(pa+page_offset, ba+b_offset, clen);
- else
- memcpy(ba+b_offset, pa+page_offset, clen);
- __bio_kunmap_atomic(ba, KM_USER0);
- }
- if (clen < len) /* hit end of page */
- break;
- page_offset += len;
+ if (len > 0 && page_offset + len > STRIPE_SIZE)
+ clen = STRIPE_SIZE - page_offset;
+ else clen = len;
+
+ if (clen > 0) {
+ char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
+ if (frombio)
+ memcpy(pa+page_offset, ba+b_offset, clen);
+ else
+ memcpy(ba+b_offset, pa+page_offset, clen);
+ __bio_kunmap_atomic(ba, KM_USER0);
}
+ if (clen < len) /* hit end of page */
+ break;
+ page_offset += len;
}
}
@@ -738,6 +735,10 @@ static void compute_parity(struct stripe_head *sh, int method)
if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
chosen = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
+
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
if (sh->dev[i].written) BUG();
sh->dev[i].written = chosen;
}
@@ -900,7 +901,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
* toread/towrite point to the first in a chain.
* The bi_next chain must be in order.
*/
-static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
+static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
{
struct bio **bip;
raid6_conf_t *conf = sh->raid_conf;
@@ -917,10 +918,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
- BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector);
- bip = & (*bip)->bi_next;
+ if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
+ goto overlap;
+ bip = &(*bip)->bi_next;
}
-/* FIXME do I need to worry about overlapping bion */
+ if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
+ goto overlap;
+
if (*bip && bi->bi_next && (*bip) != bi->bi_next)
BUG();
if (*bip)
@@ -935,7 +939,7 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
(unsigned long long)sh->sector, dd_idx);
if (forwrite) {
- /* check if page is coverred */
+ /* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
for (bi=sh->dev[dd_idx].towrite;
sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
@@ -947,6 +951,13 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx,
if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
}
+ return 1;
+
+ overlap:
+ set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
+ spin_unlock_irq(&conf->device_lock);
+ spin_unlock(&sh->lock);
+ return 0;
}
@@ -1010,6 +1021,8 @@ static void handle_stripe(struct stripe_head *sh)
spin_lock_irq(&conf->device_lock);
rbi = dev->toread;
dev->toread = NULL;
+ if (test_and_clear_bit(R5_Overlap, &dev->flags))
+ wake_up(&conf->wait_for_overlap);
spin_unlock_irq(&conf->device_lock);
while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
copy_data(0, rbi, dev->page, dev->sector);
@@ -1059,6 +1072,9 @@ static void handle_stripe(struct stripe_head *sh)
sh->dev[i].towrite = NULL;
if (bi) to_write--;
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
+
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1087,6 +1103,8 @@ static void handle_stripe(struct stripe_head *sh)
if (!test_bit(R5_Insync, &sh->dev[i].flags)) {
bi = sh->dev[i].toread;
sh->dev[i].toread = NULL;
+ if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+ wake_up(&conf->wait_for_overlap);
if (bi) to_read--;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
@@ -1566,6 +1584,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
if ( bio_data_dir(bi) == WRITE )
md_write_start(mddev);
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
+ DEFINE_WAIT(w);
new_sector = raid6_compute_sector(logical_sector,
raid_disks, data_disks, &dd_idx, &pd_idx, conf);
@@ -1574,17 +1593,27 @@ static int make_request (request_queue_t *q, struct bio * bi)
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
+ retry:
+ prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
if (sh) {
-
- add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK));
-
+ if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+ /* Add failed due to overlap. Flush everything
+ * and wait a while
+ */
+ raid6_unplug_device(mddev->queue);
+ release_stripe(sh);
+ schedule();
+ goto retry;
+ }
+ finish_wait(&conf->wait_for_overlap, &w);
raid6_plug_device(conf);
handle_stripe(sh);
release_stripe(sh);
} else {
/* cannot get stripe for read-ahead, just give-up */
clear_bit(BIO_UPTODATE, &bi->bi_flags);
+ finish_wait(&conf->wait_for_overlap, &w);
break;
}
@@ -1732,6 +1761,7 @@ static int run (mddev_t *mddev)
spin_lock_init(&conf->device_lock);
init_waitqueue_head(&conf->wait_for_stripe);
+ init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
INIT_LIST_HEAD(&conf->inactive_list);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 0a09d933a770..789b9086b717 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -60,8 +60,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.20"
-#define DRV_MODULE_RELDATE "February 2, 2005"
+#define DRV_MODULE_VERSION "3.21"
+#define DRV_MODULE_RELDATE "February 8, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -893,7 +893,7 @@ static void tg3_frob_aux_power(struct tg3 *tp)
GRC_LCLCTRL_GPIO_OUTPUT1));
udelay(100);
} else {
- int no_gpio2;
+ u32 no_gpio2;
u32 grc_local_ctrl;
if (tp_peer != tp &&
@@ -901,8 +901,8 @@ static void tg3_frob_aux_power(struct tg3 *tp)
return;
/* On 5753 and variants, GPIO2 cannot be used. */
- no_gpio2 = (tp->nic_sram_data_cfg &
- NIC_SRAM_DATA_CFG_NO_GPIO2) != 0;
+ no_gpio2 = tp->nic_sram_data_cfg &
+ NIC_SRAM_DATA_CFG_NO_GPIO2;
grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
GRC_LCLCTRL_GPIO_OE1 |
@@ -914,29 +914,17 @@ static void tg3_frob_aux_power(struct tg3 *tp)
GRC_LCLCTRL_GPIO_OUTPUT2);
}
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl);
+ grc_local_ctrl);
udelay(100);
- grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1 |
- GRC_LCLCTRL_GPIO_OUTPUT2;
- if (no_gpio2) {
- grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT2);
- }
+ grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
+
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
- grc_local_ctrl);
+ grc_local_ctrl);
udelay(100);
- grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
- GRC_LCLCTRL_GPIO_OE1 |
- GRC_LCLCTRL_GPIO_OE2 |
- GRC_LCLCTRL_GPIO_OUTPUT0 |
- GRC_LCLCTRL_GPIO_OUTPUT1;
if (!no_gpio2) {
+ grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
grc_local_ctrl);
udelay(100);
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 3b20d4be6835..e709bad434f4 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -224,7 +224,7 @@ static int get_children_props(struct device_node *dn, int **drc_indexes,
if (!indexes || !names || !types || !domains) {
/* Slot does not have dynamically-removable children */
- return 1;
+ return -EINVAL;
}
if (drc_indexes)
*drc_indexes = indexes;
@@ -260,7 +260,7 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
}
rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
- if (rc) {
+ if (rc < 0) {
return 1;
}
@@ -307,7 +307,7 @@ static int is_php_dn(struct device_node *dn, int **indexes, int **names,
int rc;
rc = get_children_props(dn, indexes, names, &drc_types, power_domains);
- if (rc) {
+ if (rc >= 0) {
if (is_php_type((char *) &drc_types[1])) {
*types = drc_types;
return 1;
@@ -331,7 +331,7 @@ static int is_dr_dn(struct device_node *dn, int **indexes, int **names,
rc = get_children_props(dn->parent, indexes, names, types,
power_domains);
- return (rc == 0);
+ return (rc >= 0);
}
static inline int is_vdevice_root(struct device_node *dn)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 540879308d32..22bdb841c8e4 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -859,7 +859,7 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*fn)(struct scsi_cmnd *))
* In all other cases we'll let an irq pick up our IO and submit it
* to the controller to improve affinity.
*/
- if (smp_processor_id() == ha->last_irq_cpu || was_empty)
+ if (_smp_processor_id() == ha->last_irq_cpu || was_empty)
qla2x00_next(ha);
spin_lock_irq(ha->host->host_lock);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index d4e7733dbeb8..ec620e33fcf6 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -987,8 +987,11 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
/* The following is not allowed by the tty layer and
unsafe. It should be fixed ASAP */
if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
- if(tty->low_latency)
+ if (tty->low_latency) {
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
+ }
/* If this failed then we will throw away the
bytes but must do so to clear interrupts */
}
@@ -1059,7 +1062,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
ignore_char:
lsr = serial_inp(up, UART_LSR);
} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+ spin_unlock(&up->port.lock);
tty_flip_buffer_push(tty);
+ spin_lock(&up->port.lock);
*status = lsr;
}
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h
index 416761fce324..c1516d013bf6 100644
--- a/fs/hostfs/hostfs.h
+++ b/fs/hostfs/hostfs.h
@@ -16,9 +16,30 @@
#define HOSTFS_ATTR_CTIME 64
#define HOSTFS_ATTR_ATIME_SET 128
#define HOSTFS_ATTR_MTIME_SET 256
+
+/* These two are unused by hostfs. */
#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */
#define HOSTFS_ATTR_ATTR_FLAG 1024
+/* If you are very careful, you'll notice that these two are missing:
+ *
+ * #define ATTR_KILL_SUID 2048
+ * #define ATTR_KILL_SGID 4096
+ *
+ * and this is because they were added in 2.5 development in this patch:
+ *
+ * http://linux.bkbits.net:8080/linux-2.5/
+ * cset@3caf4a12k4XgDzK7wyK-TGpSZ9u2Ww?nav=index.html
+ * |src/.|src/include|src/include/linux|related/include/linux/fs.h
+ *
+ * Actually, they are not needed by most ->setattr() methods - they are set by
+ * callers of notify_change() to notify that the setuid/setgid bits must be
+ * dropped.
+ * notify_change() will delete those flags, make sure attr->ia_valid & ATTR_MODE
+ * is on, and remove the appropriate bits from attr->ia_mode (attr is a
+ * "struct iattr *"). -BlaisorBlade
+ */
+
struct hostfs_iattr {
unsigned int ia_valid;
mode_t ia_mode;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index f9759e012416..144ff70fbd55 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -823,6 +823,10 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
char *name;
int err;
+ err = inode_change_ok(dentry->d_inode, attr);
+ if (err)
+ return err;
+
if(append)
attr->ia_valid &= ~ATTR_SIZE;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 70b32eac873c..f3bf5368551c 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -540,7 +540,7 @@ static struct svc_procedure nfsd_procedures2[18] = {
PROC(symlink, symlinkargs, void, none, RC_REPLSTAT, ST),
PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF, ST+FH+AT),
PROC(rmdir, diropargs, void, none, RC_REPLSTAT, ST),
- PROC(readdir, readdirargs, readdirres, none, RC_REPLBUFF, 0),
+ PROC(readdir, readdirargs, readdirres, none, RC_NOCACHE, 0),
PROC(statfs, fhandle, statfsres, none, RC_NOCACHE, ST+5),
};
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index f7ad9f759f83..a5a58a1dba0a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -656,12 +656,15 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dentry = fhp->fh_dentry;
inode = dentry->d_inode;
- /* Disallow access to files with the append-only bit set or
- * with mandatory locking enabled
+ /* Disallow write access to files with the append-only bit set
+ * or any access when mandatory locking enabled
*/
err = nfserr_perm;
- if (IS_APPEND(inode) || IS_ISMNDLK(inode))
+ if (IS_APPEND(inode) && (access & MAY_WRITE))
goto out;
+ if (IS_ISMNDLK(inode))
+ goto out;
+
if (!inode->i_fop)
goto out;
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 0e930601a821..7321db1c2fb4 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -531,6 +531,7 @@ struct file_operations linvfs_dir_operations = {
static struct vm_operations_struct linvfs_file_vm_ops = {
.nopage = filemap_nopage,
+ .populate = filemap_populate,
#ifdef HAVE_VMOP_MPROTECT
.mprotect = linvfs_mprotect,
#endif
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 1991944ddfd9..24770c011fd8 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -79,7 +79,8 @@ do { \
#define alloc_zeroed_user_highpage(vma, vaddr) \
({ \
struct page *page = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vma, vaddr); \
- flush_dcache_page(page); \
+ if (page) \
+ flush_dcache_page(page); \
page; \
})
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index e26d7d85c55a..da9c81a6af5a 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -133,6 +133,8 @@ static __inline__ void __user *compat_alloc_user_space(long len)
if (!(test_thread_flag(TIF_32BIT)))
usp += STACK_BIAS;
+ else
+ usp &= 0xffffffffUL;
return (void __user *) (usp - len);
}
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 05acc62c2b61..c1710933828f 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -35,7 +35,7 @@
"thread_return:\n\t" \
"movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \
"movq %P[thread_info](%%rsi),%%r8\n\t" \
- "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
+ LOCK "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
"movq %%rax,%%rdi\n\t" \
"jc ret_from_fork\n\t" \
RESTORE_CONTEXT \
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 11d84c93af71..2a7e6c65c882 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -48,7 +48,9 @@ alloc_zeroed_user_highpage(struct vm_area_struct *vma, unsigned long vaddr)
{
struct page *page = alloc_page_vma(GFP_HIGHUSER, vma, vaddr);
- clear_user_highpage(page, vaddr);
+ if (page)
+ clear_user_highpage(page, vaddr);
+
return page;
}
#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 10d011f464d6..3a8c47c5dc9c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -756,7 +756,9 @@ extern unsigned long page_unuse(struct page *);
extern void truncate_inode_pages(struct address_space *, loff_t);
/* generic vm_area_ops exported for stackable file systems */
-struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
+extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *);
+extern int filemap_populate(struct vm_area_struct *, unsigned long,
+ unsigned long, pgprot_t, unsigned long, int);
/* mm/page-writeback.c */
int write_one_page(struct page *page, int wait);
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index baf88d2ad986..d63ddcb4afad 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -152,6 +152,7 @@ struct stripe_head {
#define R5_Wantread 4 /* want to schedule a read */
#define R5_Wantwrite 5
#define R5_Syncio 6 /* this io need to be accounted as resync io */
+#define R5_Overlap 7 /* There is a pending overlapping request on this block */
/*
* Write method
@@ -219,6 +220,7 @@ struct raid5_private_data {
atomic_t active_stripes;
struct list_head inactive_list;
wait_queue_head_t wait_for_stripe;
+ wait_queue_head_t wait_for_overlap;
int inactive_blocked; /* release of inactive stripes blocked,
* waiting for 25% to be free
*/
diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
index 1b960c88cb58..3fbc3555ce96 100644
--- a/init/do_mounts_md.c
+++ b/init/do_mounts_md.c
@@ -232,6 +232,16 @@ static void __init md_setup_drive(void)
err = sys_ioctl(fd, RUN_ARRAY, 0);
if (err)
printk(KERN_WARNING "md: starting md%d failed\n", minor);
+ else {
+ /* reread the partition table.
+ * I (neilb) and not sure why this is needed, but I cannot
+ * boot a kernel with devfs compiled in from partitioned md
+ * array without it
+ */
+ sys_close(fd);
+ fd = sys_open(name, 0, 0);
+ sys_ioctl(fd, BLKRRPART, 0);
+ }
sys_close(fd);
}
}
diff --git a/kernel/sched.c b/kernel/sched.c
index f708d10e7750..95042b27d30c 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -867,7 +867,7 @@ void wait_task_inactive(task_t * p)
repeat:
rq = task_rq_lock(p, &flags);
/* Must be off runqueue entirely, not preempted. */
- if (unlikely(p->array)) {
+ if (unlikely(p->array || task_running(rq, p))) {
/* If it's preempted, we yield. It could be a while. */
preempted = !task_running(rq, p);
task_rq_unlock(rq, &flags);
@@ -885,6 +885,12 @@ repeat:
*
* Cause a process which is running on another CPU to enter
* kernel-mode, without any delay. (to get signals handled.)
+ *
+ * NOTE: this function doesnt have to take the runqueue lock,
+ * because all it wants to ensure is that the remote task enters
+ * the kernel. If the IPI races and the task has been migrated
+ * to another CPU then no harm is done and the purpose has been
+ * achieved as well.
*/
void kick_process(task_t *p)
{
diff --git a/mm/filemap.c b/mm/filemap.c
index e82fc19ee094..6d04b97fea14 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1458,12 +1458,9 @@ err:
return NULL;
}
-static int filemap_populate(struct vm_area_struct *vma,
- unsigned long addr,
- unsigned long len,
- pgprot_t prot,
- unsigned long pgoff,
- int nonblock)
+int filemap_populate(struct vm_area_struct *vma, unsigned long addr,
+ unsigned long len, pgprot_t prot, unsigned long pgoff,
+ int nonblock)
{
struct file *file = vma->vm_file;
struct address_space *mapping = file->f_mapping;
@@ -1523,6 +1520,7 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
vma->vm_ops = &generic_file_vm_ops;
return 0;
}
+EXPORT_SYMBOL(filemap_populate);
/*
* This is for filesystems which do not implement ->writepage.
diff --git a/mm/nommu.c b/mm/nommu.c
index fcca232e4b9e..8e70b95a8d9f 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -4,7 +4,9 @@
* Replacement code for mm functions to support CPU's that don't
* have any form of memory management unit (thus no virtual memory).
*
- * Copyright (c) 2004 David Howells <dhowells@redhat.com>
+ * See Documentation/nommu-mmap.txt
+ *
+ * Copyright (c) 2004-2005 David Howells <dhowells@redhat.com>
* Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
* Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
* Copyright (c) 2002 Greg Ungerer <gerg@snapgear.com>
@@ -567,12 +569,14 @@ unsigned long do_mmap_pgoff(struct file *file,
* that it represents a valid section of the address space
* - this is the hook for quasi-memory character devices
*/
- if (file && file->f_op->get_unmapped_area)
+ if (file && file->f_op->get_unmapped_area) {
addr = file->f_op->get_unmapped_area(file, addr, len, pgoff, flags);
-
- if (IS_ERR((void *) addr)) {
- ret = addr;
- goto error;
+ if (IS_ERR((void *) addr)) {
+ ret = addr;
+ if (ret == (unsigned long) -ENOSYS)
+ ret = (unsigned long) -ENODEV;
+ goto error;
+ }
}
/* we're going to need a VMA struct as well */
diff --git a/net/atm/addr.c b/net/atm/addr.c
index 225f6843c32f..1c8867f7f54a 100644
--- a/net/atm/addr.c
+++ b/net/atm/addr.c
@@ -108,7 +108,7 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
}
int atm_get_addr(struct atm_dev *dev, struct sockaddr_atmsvc __user * buf,
- int size)
+ size_t size)
{
unsigned long flags;
struct atm_dev_addr *this;
diff --git a/net/atm/addr.h b/net/atm/addr.h
index 2affa3a128ca..3099d21feeaa 100644
--- a/net/atm/addr.h
+++ b/net/atm/addr.h
@@ -13,6 +13,6 @@
void atm_reset_addr(struct atm_dev *dev);
int atm_add_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr);
int atm_del_addr(struct atm_dev *dev,struct sockaddr_atmsvc *addr);
-int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,int size);
+int atm_get_addr(struct atm_dev *dev,struct sockaddr_atmsvc __user *buf,size_t size);
#endif
diff --git a/net/core/dev.c b/net/core/dev.c
index 4dc01e26f158..5d4abaa85351 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -108,6 +108,7 @@
#include <linux/kallsyms.h>
#include <linux/netpoll.h>
#include <linux/rcupdate.h>
+#include <linux/delay.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
#include <net/iw_handler.h>
@@ -2899,8 +2900,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
rebroadcast_time = jiffies;
}
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 4);
+ msleep(250);
if (time_after(jiffies, warning_time + 10 * HZ)) {
printk(KERN_EMERG "unregister_netdevice: "
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index c542f2dab253..f2509034ce72 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -53,6 +53,7 @@
#include <linux/seq_file.h>
#include <linux/major.h>
#include <linux/root_dev.h>
+#include <linux/delay.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/ipconfig.h>
@@ -84,8 +85,8 @@
#endif
/* Define the friendly delay before and after opening net devices */
-#define CONF_PRE_OPEN (HZ/2) /* Before opening: 1/2 second */
-#define CONF_POST_OPEN (1*HZ) /* After opening: 1 second */
+#define CONF_PRE_OPEN 500 /* Before opening: 1/2 second */
+#define CONF_POST_OPEN 1 /* After opening: 1 second */
/* Define the timeout for waiting for a DHCP/BOOTP/RARP reply */
#define CONF_OPEN_RETRIES 2 /* (Re)open devices twice */
@@ -1259,16 +1260,14 @@ static int __init ip_auto_config(void)
try_try_again:
#endif
/* Give hardware a chance to settle */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(CONF_PRE_OPEN);
+ msleep(CONF_PRE_OPEN);
/* Setup all network devices */
if (ic_open_devs() < 0)
return -1;
/* Give drivers a chance to settle */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(CONF_POST_OPEN);
+ ssleep(CONF_POST_OPEN);
/*
* If the config information is insufficient (e.g., our IP address or
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index da30bebbddc8..25c479550a32 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/net.h>
#include <linux/completion.h>
-
+#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/igmp.h> /* for ip_mc_join_group */
@@ -647,8 +647,7 @@ static void sync_master_loop(void)
if (stop_master_sync)
break;
- __set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
+ ssleep(1);
}
/* clean up the sync_buff queue */
@@ -705,8 +704,7 @@ static void sync_backup_loop(void)
if (stop_backup_sync)
break;
- __set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ);
+ ssleep(1);
}
/* release the sending multicast socket */
@@ -818,8 +816,7 @@ static int fork_sync_thread(void *startup)
if ((pid = kernel_thread(sync_thread, startup, 0)) < 0) {
IP_VS_ERR("could not create sync_thread due to %d... "
"retrying.\n", pid);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
+ ssleep(1);
goto repeat;
}
@@ -853,8 +850,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
IP_VS_ERR("could not create fork_sync_thread due to %d... "
"retrying.\n", pid);
- current->state = TASK_UNINTERRUPTIBLE;
- schedule_timeout(HZ);
+ ssleep(1);
goto repeat;
}
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bfcd43832cb0..9865091954f3 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3760,8 +3760,7 @@ tcp_collapse(struct sock *sk, struct sk_buff *head,
while (before(start, end)) {
struct sk_buff *nskb;
int header = skb_headroom(skb);
- int copy = (PAGE_SIZE - sizeof(struct sk_buff) -
- sizeof(struct skb_shared_info) - header - 31)&~15;
+ int copy = SKB_MAX_ORDER(header, 0);
/* Too big header? This can happen with IPv6. */
if (copy < 0)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 8b870402bc96..821d3b9c5c55 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -91,6 +91,7 @@ struct tc_u_hnode
{
struct tc_u_hnode *next;
u32 handle;
+ u32 prio;
struct tc_u_common *tp_c;
int refcnt;
unsigned divisor;
@@ -323,6 +324,7 @@ static int u32_init(struct tcf_proto *tp)
root_ht->divisor = 0;
root_ht->refcnt++;
root_ht->handle = tp_c ? gen_new_htid(tp_c) : 0x80000000;
+ root_ht->prio = tp->prio;
if (tp_c == NULL) {
tp_c = kmalloc(sizeof(*tp_c), GFP_KERNEL);
@@ -587,6 +589,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
ht->refcnt = 0;
ht->divisor = divisor;
ht->handle = handle;
+ ht->prio = tp->prio;
ht->next = tp_c->hlist;
tp_c->hlist = ht;
*arg = (unsigned long)ht;
@@ -703,6 +706,8 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
return;
for (ht = tp_c->hlist; ht; ht = ht->next) {
+ if (ht->prio != tp->prio)
+ continue;
if (arg->count >= arg->skip) {
if (arg->fn(tp, (unsigned long)ht, arg) < 0) {
arg->stop = 1;
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index 12bf0f88616c..693aac1aa833 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -2,7 +2,6 @@
# Makefile for the XFRM subsystem.
#
-obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o \
- xfrm_export.o
+obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o
obj-$(CONFIG_XFRM_USER) += xfrm_user.o
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 74e995aed022..080aae243ce0 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -316,6 +316,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
}
return NULL;
}
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
{
@@ -331,6 +332,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
}
return NULL;
}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
{
@@ -346,6 +348,7 @@ struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
}
return NULL;
}
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
int entries, char *name,
@@ -380,16 +383,19 @@ struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
{
return xfrm_get_byname(aalg_list, aalg_entries(), name, probe);
}
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
{
return xfrm_get_byname(ealg_list, ealg_entries(), name, probe);
}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
{
return xfrm_get_byname(calg_list, calg_entries(), name, probe);
}
+EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
{
@@ -398,6 +404,7 @@ struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
return &aalg_list[idx];
}
+EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
{
@@ -406,6 +413,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
return &ealg_list[idx];
}
+EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
/*
* Probe for the availability of crypto algorithms, and set the available
@@ -438,6 +446,7 @@ void xfrm_probe_algs(void)
}
#endif
}
+EXPORT_SYMBOL_GPL(xfrm_probe_algs);
int xfrm_count_auth_supported(void)
{
@@ -448,6 +457,7 @@ int xfrm_count_auth_supported(void)
n++;
return n;
}
+EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
int xfrm_count_enc_supported(void)
{
@@ -458,6 +468,7 @@ int xfrm_count_enc_supported(void)
n++;
return n;
}
+EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
/* Move to common area: it is shared with AH. */
@@ -532,6 +543,7 @@ void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm,
if (len)
BUG();
}
+EXPORT_SYMBOL_GPL(skb_icv_walk);
#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE)
diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
deleted file mode 100644
index 7ca0e889e54a..000000000000
--- a/net/xfrm/xfrm_export.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include <linux/module.h>
-#include <net/xfrm.h>
-
-EXPORT_SYMBOL(xfrm_user_policy);
-EXPORT_SYMBOL(km_waitq);
-EXPORT_SYMBOL(km_new_mapping);
-EXPORT_SYMBOL(xfrm_cfg_sem);
-EXPORT_SYMBOL(xfrm_policy_alloc);
-EXPORT_SYMBOL(__xfrm_policy_destroy);
-EXPORT_SYMBOL(xfrm_lookup);
-EXPORT_SYMBOL(__xfrm_policy_check);
-EXPORT_SYMBOL(__xfrm_route_forward);
-EXPORT_SYMBOL(xfrm_state_alloc);
-EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm_state_insert);
-EXPORT_SYMBOL(xfrm_state_add);
-EXPORT_SYMBOL(xfrm_state_update);
-EXPORT_SYMBOL(xfrm_state_check_expire);
-EXPORT_SYMBOL(xfrm_state_check);
-EXPORT_SYMBOL(xfrm_state_lookup);
-EXPORT_SYMBOL(xfrm_state_register_afinfo);
-EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
-EXPORT_SYMBOL(xfrm_state_delete_tunnel);
-EXPORT_SYMBOL(xfrm_replay_check);
-EXPORT_SYMBOL(xfrm_replay_advance);
-EXPORT_SYMBOL(__secpath_destroy);
-EXPORT_SYMBOL(secpath_dup);
-EXPORT_SYMBOL(xfrm_get_acqseq);
-EXPORT_SYMBOL(xfrm_parse_spi);
-EXPORT_SYMBOL(xfrm_register_type);
-EXPORT_SYMBOL(xfrm_unregister_type);
-EXPORT_SYMBOL(xfrm_get_type);
-EXPORT_SYMBOL(xfrm_register_km);
-EXPORT_SYMBOL(xfrm_unregister_km);
-EXPORT_SYMBOL(xfrm_state_delete);
-EXPORT_SYMBOL(xfrm_state_walk);
-EXPORT_SYMBOL(xfrm_find_acq_byseq);
-EXPORT_SYMBOL(xfrm_find_acq);
-EXPORT_SYMBOL(xfrm_alloc_spi);
-EXPORT_SYMBOL(xfrm_state_flush);
-EXPORT_SYMBOL(xfrm_policy_bysel);
-EXPORT_SYMBOL(xfrm_policy_insert);
-EXPORT_SYMBOL(xfrm_policy_walk);
-EXPORT_SYMBOL(xfrm_policy_flush);
-EXPORT_SYMBOL(xfrm_policy_byid);
-EXPORT_SYMBOL(xfrm_policy_list);
-EXPORT_SYMBOL(xfrm_dst_lookup);
-EXPORT_SYMBOL(xfrm_policy_register_afinfo);
-EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
-
-EXPORT_SYMBOL_GPL(xfrm_probe_algs);
-EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
-EXPORT_SYMBOL_GPL(xfrm_count_enc_supported);
-EXPORT_SYMBOL_GPL(xfrm_aalg_get_byidx);
-EXPORT_SYMBOL_GPL(xfrm_ealg_get_byidx);
-EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
-EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
-EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
-EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
-EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
-EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
-EXPORT_SYMBOL_GPL(skb_icv_walk);
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index abe2e674cabd..c58a6f05a0b6 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -8,6 +8,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include <net/ip.h>
#include <net/xfrm.h>
@@ -20,6 +21,7 @@ void __secpath_destroy(struct sec_path *sp)
xfrm_state_put(sp->x[i].xvec);
kmem_cache_free(secpath_cachep, sp);
}
+EXPORT_SYMBOL(__secpath_destroy);
struct sec_path *secpath_dup(struct sec_path *src)
{
@@ -40,6 +42,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
atomic_set(&sp->refcnt, 1);
return sp;
}
+EXPORT_SYMBOL(secpath_dup);
/* Fetch spi and seq from ipsec header */
@@ -73,6 +76,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
*seq = *(u32*)(skb->h.raw + offset_seq);
return 0;
}
+EXPORT_SYMBOL(xfrm_parse_spi);
void __init xfrm_input_init(void)
{
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 3ec936879f38..8d34ed106443 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -21,14 +21,17 @@
#include <linux/workqueue.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
+#include <linux/module.h>
#include <net/xfrm.h>
#include <net/ip.h>
DECLARE_MUTEX(xfrm_cfg_sem);
+EXPORT_SYMBOL(xfrm_cfg_sem);
static DEFINE_RWLOCK(xfrm_policy_lock);
struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2];
+EXPORT_SYMBOL(xfrm_policy_list);
static DEFINE_RWLOCK(xfrm_policy_afinfo_lock);
static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO];
@@ -62,6 +65,7 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family)
xfrm_policy_put_afinfo(afinfo);
return err;
}
+EXPORT_SYMBOL(xfrm_register_type);
int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
{
@@ -82,6 +86,7 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
xfrm_policy_put_afinfo(afinfo);
return err;
}
+EXPORT_SYMBOL(xfrm_unregister_type);
struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
{
@@ -112,6 +117,7 @@ retry:
xfrm_policy_put_afinfo(afinfo);
return type;
}
+EXPORT_SYMBOL(xfrm_get_type);
int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
unsigned short family)
@@ -129,6 +135,7 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
xfrm_policy_put_afinfo(afinfo);
return err;
}
+EXPORT_SYMBOL(xfrm_dst_lookup);
void xfrm_put_type(struct xfrm_type *type)
{
@@ -234,6 +241,7 @@ struct xfrm_policy *xfrm_policy_alloc(int gfp)
}
return policy;
}
+EXPORT_SYMBOL(xfrm_policy_alloc);
/* Destroy xfrm_policy: descendant resources must be released to this moment. */
@@ -250,6 +258,7 @@ void __xfrm_policy_destroy(struct xfrm_policy *policy)
kfree(policy);
}
+EXPORT_SYMBOL(__xfrm_policy_destroy);
static void xfrm_policy_gc_kill(struct xfrm_policy *policy)
{
@@ -373,6 +382,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
}
return 0;
}
+EXPORT_SYMBOL(xfrm_policy_insert);
struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
int delete)
@@ -396,6 +406,7 @@ struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel,
}
return pol;
}
+EXPORT_SYMBOL(xfrm_policy_bysel);
struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
{
@@ -418,6 +429,7 @@ struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete)
}
return pol;
}
+EXPORT_SYMBOL(xfrm_policy_byid);
void xfrm_policy_flush(void)
{
@@ -438,6 +450,7 @@ void xfrm_policy_flush(void)
atomic_inc(&flow_cache_genid);
write_unlock_bh(&xfrm_policy_lock);
}
+EXPORT_SYMBOL(xfrm_policy_flush);
int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*),
void *data)
@@ -470,7 +483,7 @@ out:
read_unlock_bh(&xfrm_policy_lock);
return error;
}
-
+EXPORT_SYMBOL(xfrm_policy_walk);
/* Find policy to apply to this flow. */
@@ -845,6 +858,7 @@ error:
*dst_p = NULL;
return err;
}
+EXPORT_SYMBOL(xfrm_lookup);
/* When skb is transformed back to its "native" form, we have to
* check policy restrictions. At the moment we make this in maximally
@@ -981,6 +995,7 @@ reject:
xfrm_pol_put(pol);
return 0;
}
+EXPORT_SYMBOL(__xfrm_policy_check);
int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
{
@@ -991,6 +1006,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;
}
+EXPORT_SYMBOL(__xfrm_route_forward);
/* Optimize later using cookies and generation ids. */
@@ -1163,6 +1179,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
write_unlock(&xfrm_policy_afinfo_lock);
return err;
}
+EXPORT_SYMBOL(xfrm_policy_register_afinfo);
int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
{
@@ -1190,6 +1207,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
write_unlock(&xfrm_policy_afinfo_lock);
return err;
}
+EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
{
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 5c9a57d6c09a..e43aa8c27483 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -17,6 +17,7 @@
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
/* Each xfrm_state may be linked to two tables:
@@ -38,6 +39,7 @@ static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
DECLARE_WAIT_QUEUE_HEAD(km_waitq);
+EXPORT_SYMBOL(km_waitq);
static DEFINE_RWLOCK(xfrm_state_afinfo_lock);
static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO];
@@ -193,6 +195,7 @@ struct xfrm_state *xfrm_state_alloc(void)
}
return x;
}
+EXPORT_SYMBOL(xfrm_state_alloc);
void __xfrm_state_destroy(struct xfrm_state *x)
{
@@ -203,6 +206,7 @@ void __xfrm_state_destroy(struct xfrm_state *x)
spin_unlock_bh(&xfrm_state_gc_lock);
schedule_work(&xfrm_state_gc_work);
}
+EXPORT_SYMBOL(__xfrm_state_destroy);
static void __xfrm_state_delete(struct xfrm_state *x)
{
@@ -241,6 +245,7 @@ void xfrm_state_delete(struct xfrm_state *x)
__xfrm_state_delete(x);
spin_unlock_bh(&x->lock);
}
+EXPORT_SYMBOL(xfrm_state_delete);
void xfrm_state_flush(u8 proto)
{
@@ -267,6 +272,7 @@ restart:
spin_unlock_bh(&xfrm_state_lock);
wake_up(&km_waitq);
}
+EXPORT_SYMBOL(xfrm_state_flush);
static int
xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl,
@@ -392,6 +398,7 @@ void xfrm_state_insert(struct xfrm_state *x)
__xfrm_state_insert(x);
spin_unlock_bh(&xfrm_state_lock);
}
+EXPORT_SYMBOL(xfrm_state_insert);
static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq);
@@ -444,6 +451,7 @@ out:
return err;
}
+EXPORT_SYMBOL(xfrm_state_add);
int xfrm_state_update(struct xfrm_state *x)
{
@@ -508,6 +516,7 @@ out:
return err;
}
+EXPORT_SYMBOL(xfrm_state_update);
int xfrm_state_check_expire(struct xfrm_state *x)
{
@@ -531,6 +540,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
km_state_expired(x, 0);
return 0;
}
+EXPORT_SYMBOL(xfrm_state_check_expire);
static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
{
@@ -553,6 +563,7 @@ int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
err:
return err;
}
+EXPORT_SYMBOL(xfrm_state_check);
struct xfrm_state *
xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
@@ -569,6 +580,7 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
xfrm_state_put_afinfo(afinfo);
return x;
}
+EXPORT_SYMBOL(xfrm_state_lookup);
struct xfrm_state *
xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
@@ -586,6 +598,7 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
xfrm_state_put_afinfo(afinfo);
return x;
}
+EXPORT_SYMBOL(xfrm_find_acq);
/* Silly enough, but I'm lazy to build resolution list */
@@ -614,7 +627,8 @@ struct xfrm_state *xfrm_find_acq_byseq(u32 seq)
spin_unlock_bh(&xfrm_state_lock);
return x;
}
-
+EXPORT_SYMBOL(xfrm_find_acq_byseq);
+
u32 xfrm_get_acqseq(void)
{
u32 res;
@@ -626,6 +640,7 @@ u32 xfrm_get_acqseq(void)
spin_unlock_bh(&acqseq_lock);
return res;
}
+EXPORT_SYMBOL(xfrm_get_acqseq);
void
xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
@@ -666,6 +681,7 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
wake_up(&km_waitq);
}
}
+EXPORT_SYMBOL(xfrm_alloc_spi);
int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*),
void *data)
@@ -700,7 +716,7 @@ out:
spin_unlock_bh(&xfrm_state_lock);
return err;
}
-
+EXPORT_SYMBOL(xfrm_state_walk);
int xfrm_replay_check(struct xfrm_state *x, u32 seq)
{
@@ -726,6 +742,7 @@ int xfrm_replay_check(struct xfrm_state *x, u32 seq)
}
return 0;
}
+EXPORT_SYMBOL(xfrm_replay_check);
void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
{
@@ -745,6 +762,7 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
x->replay.bitmap |= (1U << diff);
}
}
+EXPORT_SYMBOL(xfrm_replay_advance);
static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
static DEFINE_RWLOCK(xfrm_km_lock);
@@ -797,6 +815,7 @@ int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport)
read_unlock(&xfrm_km_lock);
return err;
}
+EXPORT_SYMBOL(km_new_mapping);
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
{
@@ -850,6 +869,7 @@ out:
kfree(data);
return err;
}
+EXPORT_SYMBOL(xfrm_user_policy);
int xfrm_register_km(struct xfrm_mgr *km)
{
@@ -858,6 +878,7 @@ int xfrm_register_km(struct xfrm_mgr *km)
write_unlock_bh(&xfrm_km_lock);
return 0;
}
+EXPORT_SYMBOL(xfrm_register_km);
int xfrm_unregister_km(struct xfrm_mgr *km)
{
@@ -866,6 +887,7 @@ int xfrm_unregister_km(struct xfrm_mgr *km)
write_unlock_bh(&xfrm_km_lock);
return 0;
}
+EXPORT_SYMBOL(xfrm_unregister_km);
int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
{
@@ -885,6 +907,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo)
write_unlock(&xfrm_state_afinfo_lock);
return err;
}
+EXPORT_SYMBOL(xfrm_state_register_afinfo);
int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
{
@@ -906,6 +929,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
write_unlock(&xfrm_state_afinfo_lock);
return err;
}
+EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
{
@@ -940,6 +964,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
x->tunnel = NULL;
}
}
+EXPORT_SYMBOL(xfrm_state_delete_tunnel);
void __init xfrm_state_init(void)
{