summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-02-19 01:06:44 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-02-19 01:06:44 -0800
commitb76a852bfb51ffe25505bab3dfd87ddbc821c2aa (patch)
tree25e4f88a1d60f92c7f00f19e835a23d1502c5c82
parent612cbdcf44289e81a4327d8f67fcc41e07ad33c3 (diff)
parent6ab007bf3fd8db711771db1e93880213a63ecd38 (diff)
Merge bk://are.twiddle.net/axp-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--MAINTAINERS9
-rw-r--r--arch/sparc/Kconfig44
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c3
-rw-r--r--arch/sparc/kernel/time.c1
-rw-r--r--arch/sparc64/kernel/systbls.S2
-rw-r--r--arch/sparc64/oprofile/timer_int.c1
-rw-r--r--drivers/serial/sunsu.c1
-rw-r--r--drivers/serial/sunzilog.c1
-rw-r--r--fs/buffer.c3
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/cifsproto.h38
-rw-r--r--fs/cifs/cifssmb.c156
-rw-r--r--fs/cifs/connect.c30
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/misc.c2
-rw-r--r--fs/cifs/transport.c28
-rw-r--r--fs/xfs/linux/xfs_aops.c242
-rw-r--r--fs/xfs/linux/xfs_iomap.c8
-rw-r--r--fs/xfs/linux/xfs_super.c6
-rw-r--r--fs/xfs/pagebuf/page_buf.c78
-rw-r--r--fs/xfs/pagebuf/page_buf.h3
-rw-r--r--fs/xfs/support/debug.c2
-rw-r--r--fs/xfs/support/spin.h1
-rw-r--r--fs/xfs/xfs_dir_leaf.c2
-rw-r--r--fs/xfs/xfs_error.h2
-rw-r--r--fs/xfs/xfs_log.c21
-rw-r--r--fs/xfs/xfs_log.h2
-rw-r--r--fs/xfs/xfs_log_recover.c9
-rw-r--r--fs/xfs/xfs_mount.c20
-rw-r--r--fs/xfs/xfs_trans.c43
-rw-r--r--include/asm-sparc/ide.h109
-rw-r--r--include/asm-sparc/posix_types.h2
-rw-r--r--include/asm-sparc64/ide.h145
-rw-r--r--include/asm-sparc64/posix_types.h2
-rw-r--r--include/linux/skbuff.h2
-rw-r--r--include/net/dn_route.h2
-rw-r--r--net/decnet/dn_nsp_out.c2
-rw-r--r--net/decnet/dn_route.c2
-rw-r--r--net/ipv4/igmp.c10
-rw-r--r--net/ipv4/ip_fragment.c58
-rw-r--r--net/ipv4/ip_input.c2
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/route.c220
-rw-r--r--net/ipv4/xfrm_policy.c44
-rw-r--r--net/ipv4/xfrm_user.c97
-rw-r--r--net/ipv6/Makefile2
-rw-r--r--net/ipv6/exthdrs.c4
-rw-r--r--net/ipv6/ip6_input.c4
-rw-r--r--net/ipv6/ip6_output.c4
-rw-r--r--net/ipv6/ipv6_syms.c4
-rw-r--r--net/ipv6/reassembly.c56
-rw-r--r--net/ipv6/xfrm_policy.c43
-rw-r--r--net/key/af_key.c1
-rw-r--r--net/netsyms.c3
-rw-r--r--sound/pci/ac97/ac97_codec.c1
55 files changed, 954 insertions, 637 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index b3a40388f2..e9249865ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -316,6 +316,15 @@ M: marcel@holtmann.org
W: http://www.holtmann.org/linux/bluetooth/
S: Maintained
+BONDING DRIVER
+P: Chad Tindel
+M: ctindel@users.sourceforge.net
+P: Jay Vosburgh
+M: fubar@us.ibm.com
+L: bonding-devel@lists.sourceforge.net
+W: http://sourceforge.net/projects/bonding/
+S: Supported
+
BTTV VIDEO4LINUX DRIVER
P: Gerd Knorr
M: kraxel@bytesex.org
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index e242e2f0a2..14d58b9357 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -136,34 +136,20 @@ config SPARC32
config ISA
bool
help
- Find out whether you have ISA slots on your motherboard. ISA is the
- name of a bus system, i.e. the way the CPU talks to the other stuff
- inside your box. Other bus systems are PCI, EISA, MicroChannel
- (MCA) or VESA. ISA is an older system, now being displaced by PCI;
- newer boards don't support it. If you have ISA, say Y, otherwise N.
+ ISA is found on Espresso only and is not supported currently.
+ Say N
config EISA
bool
- ---help---
- The Extended Industry Standard Architecture (EISA) bus was
- developed as an open alternative to the IBM MicroChannel bus.
-
- The EISA bus provided some of the features of the IBM MicroChannel
- bus while maintaining backward compatibility with cards made for
- the older ISA bus. The EISA bus saw limited use between 1988 and
- 1995 when it was made obsolete by the PCI bus.
-
- Say Y here if you are building a kernel for an EISA-based machine.
-
- Otherwise, say N.
+ help
+ EISA is not supported.
+ Say N
config MCA
bool
help
- MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- <file:Documentation/mca.txt> (and especially the web page given
- there) before attempting to build an MCA bus kernel.
+ EISA is not supported.
+ Say N
config PCMCIA
tristate
@@ -242,8 +228,8 @@ config SUN_PM
config SUN4
bool "Support for SUN4 machines (disables SUN4[CDM] support)"
help
- Say Y here if, and only if, your machine is a Sun4. Note that
- a kernel compiled with this option will run only on Sun4.
+ Say Y here if, and only if, your machine is a sun4. Note that
+ a kernel compiled with this option will run only on sun4.
(And the current version will probably work only on sun4/330.)
if !SUN4
@@ -251,15 +237,9 @@ if !SUN4
config PCI
bool "Support for PCI and PS/2 keyboard/mouse"
help
- Find out whether you have a PCI motherboard. PCI is the name of a
- bus system, i.e. the way the CPU talks to the other stuff inside
- your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
- VESA. If you have PCI, say Y, otherwise N.
-
- The PCI-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>, contains valuable
- information about which PCI hardware does work under Linux and which
- doesn't.
+ CONFIG_PCI is needed for all JavaStation's (including MrCoffee),
+ CP-1200, JavaEngine-1, Corona, Red October, and Serengeti SGSC.
+ All of these platforms are extremely obscure, so say N if unsure.
source "drivers/pci/Kconfig"
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index e198ca77e8..f31a846379 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -55,6 +55,8 @@
#include <asm/a.out.h>
#include <asm/io-unit.h>
+extern spinlock_t rtc_lock;
+
struct poll {
int fd;
short events;
@@ -152,6 +154,7 @@ EXPORT_SYMBOL(__cpu_logical_map);
EXPORT_SYMBOL(udelay);
EXPORT_SYMBOL(ndelay);
+EXPORT_SYMBOL(rtc_lock);
EXPORT_SYMBOL(mostek_lock);
EXPORT_SYMBOL(mstk48t02_regs);
#if CONFIG_SUN_AUXIO
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 43130a381c..0254734f17 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -47,6 +47,7 @@ extern unsigned long wall_jiffies;
u64 jiffies_64;
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
enum sparc_clock_type sp_clock_typ;
spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
unsigned long mstk48t02_regs = 0UL;
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 7624a7c671..49f144e792 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -47,7 +47,7 @@ sys_call_table32:
.word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64
-/*140*/ .word sys32_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys32_getrlimit
+/*140*/ .word sys32_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, sys32_getrlimit
.word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64
.word sys32_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount
diff --git a/arch/sparc64/oprofile/timer_int.c b/arch/sparc64/oprofile/timer_int.c
index 8e6253e9c8..833b685d45 100644
--- a/arch/sparc64/oprofile/timer_int.c
+++ b/arch/sparc64/oprofile/timer_int.c
@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <linux/irq.h>
#include <linux/oprofile.h>
+#include <linux/profile.h>
#include <asm/ptrace.h>
static int timer_notify(struct notifier_block * self, unsigned long val, void * data)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index bf249dc55e..f2dc14483c 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -525,7 +525,6 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, struct pt_regs *reg
up->kbd_id = 0;
return;
}
- kbd_pt_regs = regs;
#ifdef CONFIG_SERIO
serio_interrupt(&up->serio, ch, 0, regs);
#endif
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 33483ff03f..875a7ac6f8 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -301,7 +301,6 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up,
up->kbd_id = 0;
return;
}
- kbd_pt_regs = regs;
#ifdef CONFIG_SERIO
serio_interrupt(&up->serio, ch, 0, regs);
#endif
diff --git a/fs/buffer.c b/fs/buffer.c
index c1379af3f9..db30b30596 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -659,8 +659,7 @@ void buffer_insert_list(spinlock_t *lock,
struct buffer_head *bh, struct list_head *list)
{
spin_lock(lock);
- list_del(&bh->b_assoc_buffers);
- list_add(&bh->b_assoc_buffers, list);
+ list_move_tail(&bh->b_assoc_buffers, list);
spin_unlock(lock);
}
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 7d851b2af1..d8f7370cca 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -105,7 +105,7 @@ struct TCP_Server_Info {
char versionMinor;
int svlocal:1; /* local server or remote */
atomic_t socketUseCount; /* indicates if the server has any open cifs sessions */
- enum statusEnum tcpStatus; /* what we think the status is */
+ enum statusEnum tcpStatus; /* what we think the status is */
struct semaphore tcpSem;
struct task_struct *tsk;
char server_GUID[16];
@@ -170,7 +170,7 @@ struct cifsTconInfo {
struct list_head openFileList;
struct semaphore tconSem;
struct cifsSesInfo *ses; /* pointer to session associated with */
- char treeName[MAX_TREE_SIZE + 1]; /* The ascii or unicode name of this resource depending on the ses->capabilities *//* BB fill in this field */
+ char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
char *nativeFileSystem;
__u16 tid; /* The 2 byte transaction id */
__u16 Flags; /* optional support bits */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 66b3c3cb9d..b6b8965f9e 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -93,26 +93,26 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const char *tree, struct cifsTconInfo *tcon,
const struct nls_table *);
-extern int CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName,
FILE_DIRECTORY_INFO * findData,
T2_FFIRST_RSP_PARMS * findParms,
const struct nls_table *nls_codepage,
int *pUnicodeFlag,
int *pUnixFlag /* if Unix extensions used */ );
-extern int CIFSFindNext(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
FILE_DIRECTORY_INFO * findData,
T2_FNEXT_RSP_PARMS * findParms,
const __u16 searchHandle, const __u32 resumeKey,
int *UnicodeFlag, int *pUnixFlag);
-extern int CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_ALL_INFO * findData,
const struct nls_table *nls_codepage);
extern int CIFSSMBUnixQPathInfo(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_UNIX_BASIC_INFO * pFindData,
const struct nls_table *nls_codepage);
@@ -127,7 +127,7 @@ extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path,
const struct nls_table *nls_codepage);
-extern int CIFSSMBQFSInfo(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct statfs *FSData,
const struct nls_table *nls_codepage);
extern int CIFSSMBQFSAttributeInfo(const int xid,
@@ -150,57 +150,57 @@ extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon,
char *full_path, __u64 mode, __u64 uid,
__u64 gid, const struct nls_table *nls_codepage);
-extern int CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
const char *newName,
const struct nls_table *nls_codepage);
-extern int CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
const char *name, const struct nls_table *nls_codepage);
-extern int CIFSSMBDelFile(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
const char *name,
const struct nls_table *nls_codepage);
-extern int CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage);
extern int CIFSCreateHardLink(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage);
extern int CIFSUnixCreateHardLink(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage);
extern int CIFSUnixCreateSymLink(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage);
extern int CIFSSMBUnixQuerySymLink(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *syminfo, const int buflen,
const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
- const struct cifsTconInfo *tcon,
+ struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *symlinkinfo, const int buflen, __u16 fid,
const struct nls_table *nls_codepage);
-extern int CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int disposition,
const int access_flags, const int omode,
__u16 * netfid, int *pOplock,
const struct nls_table *nls_codepage);
-extern int CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
const int smb_file_id);
-extern int CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
const int netfid, unsigned int count,
const __u64 lseek, unsigned int *nbytes, char **buf);
-extern int CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes,
const char *buf, const int long_op);
-extern int CIFSSMBLock(const int xid, const struct cifsTconInfo *tcon,
+extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 netfid, const __u64 len,
const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 98221be0e6..e434f781d5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -43,16 +43,27 @@ static struct {
};
int
-smb_init(int smb_command, int wct, const struct cifsTconInfo *tcon,
+smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
void **request_buf /* returned */ ,
void **response_buf /* returned */ )
{
int rc = 0;
- if(tcon)
- if(tcon->ses)
+ if(tcon && (tcon->tidStatus == CifsNeedReconnect)) {
+ rc = -EIO;
+ if(tcon->ses) {
+ struct nls_table *nls_codepage = load_nls_default();
if(tcon->ses->status == CifsNeedReconnect)
- setup_session(0, tcon->ses, load_nls_default());
+ rc = setup_session(0, tcon->ses, nls_codepage);
+ if(!rc) {
+ rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
+ nls_codepage);
+ cFYI(1, ("reconnect tcon rc = %d", rc));
+ }
+ }
+ }
+ if(rc)
+ return rc;
*request_buf = buf_get();
if (request_buf == 0) {
@@ -143,7 +154,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMBr->u.extended_response.
GUID, 16) != 0) {
cFYI(1,
- ("UID of server does not match that of previous connection to same ip address"));
+ ("UID of server does not match previous connection to same ip address"));
memcpy(server->
server_GUID,
pSMBr->u.
@@ -166,7 +177,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
server->capabilities &= ~CAP_EXTENDED_SECURITY;
if(sign_CIFS_PDUs == FALSE) {
if(server->secMode & SECMODE_SIGN_REQUIRED)
- cERROR(1,("Server required CIFS packet signing - enable /proc/fs/cifs/PacketSigningEnabled"));
+ cERROR(1,
+ ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
}
}
@@ -188,8 +200,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
* If last user of the connection and
* connection alive - disconnect it
* If this is the last connection on the server session disconnect it
- * (and inside session disconnect we should check if tcp socket needs to
- * be freed and kernel thread woken up).
+ * (and inside session disconnect we should check if tcp socket needs
+ * to be freed and kernel thread woken up).
*/
if (tcon)
down(&tcon->tconSem);
@@ -237,7 +249,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
cFYI(1, ("In SMBLogoff for session disconnect"));
if (ses)
- down(&ses->sesSem); /* need to add more places where this sem is checked */
+ down(&ses->sesSem); /* check this sem more places */
else
return -EIO;
@@ -246,10 +258,10 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
up(&ses->sesSem);
return -EBUSY;
}
- if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */ ,
- (void **) &pSMB, (void **) &smb_buffer_response);
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+ rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
+ (void **) &pSMB, (void **) &smb_buffer_response);
if (rc) {
up(&ses->sesSem);
return rc;
@@ -272,7 +284,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
}
int
-CIFSSMBDelFile(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const struct nls_table *nls_codepage)
{
DELETE_FILE_REQ *pSMB = NULL;
@@ -315,7 +327,7 @@ CIFSSMBDelFile(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
const char *dirName, const struct nls_table *nls_codepage)
{
DELETE_DIRECTORY_REQ *pSMB = NULL;
@@ -358,7 +370,7 @@ CIFSSMBRmDir(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
const char *name, const struct nls_table *nls_codepage)
{
int rc = 0;
@@ -402,7 +414,7 @@ CIFSSMBMkDir(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int openDisposition,
const int access_flags, const int create_options, __u16 * netfid,
int *pOplock, const struct nls_table *nls_codepage)
@@ -446,14 +458,15 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
pSMB->AllocationSize = 0;
pSMB->FileAttributes = ATTR_NORMAL; /* XP does not handle ATTR_POSIX_SEMANTICS */
/*if ((omode & S_IWUGO) == 0)
- pSMB->FileAttributes |= ATTR_READONLY;*/
- /* Above line causes problems due to problem with vfs splitting create into
- two pieces - need to set mode after file created not while it is being created */
+ pSMB->FileAttributes |= ATTR_READONLY;*/
+ /* Above line causes problems due to vfs splitting create into two
+ pieces - need to set mode after file created not while it is
+ being created */
pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
pSMB->CreateDisposition = cpu_to_le32(openDisposition);
pSMB->CreateOptions = cpu_to_le32(create_options);
- pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ?? BB */
+ pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
pSMB->SecurityFlags =
cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
@@ -470,7 +483,7 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
*netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Do we care about the CreateAction in any cases? */
- /* BB add code to update inode with file sizes from create response */
+ /* BB add code to update inode file sizes from create response */
}
if (pSMB)
buf_release(pSMB);
@@ -483,7 +496,7 @@ CIFSSMBOpen(const int xid, const struct cifsTconInfo *tcon,
freed by the caller */
int
-CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 lseek, unsigned int *nbytes, char **buf)
{
@@ -504,9 +517,8 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
pSMB->Remaining = 0;
- pSMB->MaxCount = cpu_to_le16(min(count,
- (tcon->ses->server->maxBuf -
- MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
+ pSMB->MaxCount = cpu_to_le16(min_t(const unsigned int, count,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00));
pSMB->MaxCountHigh = 0;
pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
@@ -545,7 +557,7 @@ CIFSSMBRead(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
const int netfid, const unsigned int count,
const __u64 offset, unsigned int *nbytes, const char *buf,
const int long_op)
@@ -596,7 +608,7 @@ CIFSSMBWrite(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBLock(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
const __u16 smb_file_id, const __u64 len,
const __u64 offset, const __u32 numUnlock,
const __u32 numLock, const __u8 lockType, const int waitFlag)
@@ -639,7 +651,7 @@ CIFSSMBLock(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon, int smb_file_id)
+CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
{
int rc = 0;
CLOSE_REQ *pSMB = NULL;
@@ -667,7 +679,7 @@ CIFSSMBClose(const int xid, const struct cifsTconInfo *tcon, int smb_file_id)
}
int
-CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage)
{
@@ -697,7 +709,8 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0; /* pad */
- pSMB->OldFileName[name_len + 1] = 0x04; /* strange that protocol requires an ASCII signature byte on Unicode string */
+ /* protocol requires ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x04;
name_len2 =
cifs_strtoUCS((wchar_t *) & pSMB->
OldFileName[name_len + 2], toName, 530,
@@ -710,13 +723,13 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
strncpy(pSMB->OldFileName, fromName, name_len);
name_len2 = strnlen(toName, 530);
name_len2++; /* trailing null */
- pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
+ pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
name_len2++; /* trailing null */
name_len2++; /* signature byte */
}
- pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
+ pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
/* we could also set search attributes but not needed */
pSMB->hdr.smb_buf_length += pSMB->ByteCount;
pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
@@ -733,7 +746,7 @@ CIFSSMBRename(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSUnixCreateSymLink(const int xid, const struct cifsTconInfo *tcon,
+CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage)
{
@@ -791,7 +804,8 @@ CIFSUnixCreateSymLink(const int xid, const struct cifsTconInfo *tcon,
pSMB->DataCount = name_len_target;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /*BB find exact max SMB from sess */
+ /* BB find exact max on data count below from sess */
+ pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
@@ -820,7 +834,7 @@ CIFSUnixCreateSymLink(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSUnixCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
+CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage)
{
@@ -877,7 +891,8 @@ CIFSUnixCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
pSMB->DataCount = name_len_target;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB from sess*/
+ /* BB find exact max on data count below from sess*/
+ pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
@@ -904,7 +919,7 @@ CIFSUnixCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
+CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
const char *fromName, const char *toName,
const struct nls_table *nls_codepage)
{
@@ -937,7 +952,7 @@ CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0; /* pad */
- pSMB->OldFileName[name_len + 1] = 0x04; /* strange that protocol requires an ASCII signature byte on Unicode string */
+ pSMB->OldFileName[name_len + 1] = 0x04;
name_len2 =
cifs_strtoUCS((wchar_t *) & pSMB->
OldFileName[name_len + 2], toName, 530,
@@ -972,7 +987,7 @@ CIFSCreateHardLink(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *symlinkinfo, const int buflen,
const struct nls_table *nls_codepage)
@@ -1007,7 +1022,8 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ /* BB find exact max data count below from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
@@ -1041,27 +1057,17 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
else {
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = UniStrnlen((wchar_t *) ((char *)
- &pSMBr->hdr.
- Protocol +
- pSMBr->
- DataOffset),
- min(buflen,
- (int) pSMBr->
- DataCount) / 2);
+ &pSMBr->hdr.Protocol +pSMBr->DataOffset),
+ min_t(const int, buflen,pSMBr->DataCount) / 2);
cifs_strfromUCS_le(symlinkinfo,
- (wchar_t *) ((char *)
- &pSMBr->
- hdr.
- Protocol +
- pSMBr->
- DataOffset),
- name_len, nls_codepage);
+ (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
+ pSMBr->DataOffset),
+ name_len, nls_codepage);
} else {
strncpy(symlinkinfo,
- (char *) &pSMBr->hdr.Protocol +
- pSMBr->DataOffset, min(buflen, (int)
- pSMBr->
- DataCount));
+ (char *) &pSMBr->hdr.Protocol +
+ pSMBr->DataOffset,
+ min_t(const int, buflen, pSMBr->DataCount));
}
symlinkinfo[buflen] = 0;
/* just in case so calling code does not go off the end of buffer */
@@ -1075,7 +1081,7 @@ CIFSSMBUnixQuerySymLink(const int xid, const struct cifsTconInfo *tcon,
int
-CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *symlinkinfo, const int buflen,__u16 fid,
const struct nls_table *nls_codepage)
@@ -1086,7 +1092,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
struct smb_com_transaction_ioctl_req * pSMB;
struct smb_com_transaction_ioctl_rsp * pSMBr;
- cFYI(1, ("In Windows reparse style QueryLink info for path %s", searchName));
+ cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
(void **) &pSMBr);
if (rc)
@@ -1095,7 +1101,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
pSMB->TotalParameterCount = 0 ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ /* BB find exact data count max from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 4;
pSMB->Reserved = 0;
pSMB->ParameterOffset = 0;
@@ -1122,7 +1129,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
rc = -EIO; /* bad smb */
else {
if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
- /* could also validata reparse tag && better check name length */
+ /* could also validate reparse tag && better check name length */
struct reparse_data * reparse_buf = (struct reparse_data *)
((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
@@ -1137,7 +1144,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
} else { /* ASCII names */
strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
reparse_buf->TargetNameOffset,
- min(buflen, (int)reparse_buf->TargetNameLen));
+ min_t(const int, buflen, reparse_buf->TargetNameLen));
}
} else {
rc = -EIO;
@@ -1154,7 +1161,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_ALL_INFO * pFindData,
const struct nls_table *nls_codepage)
@@ -1216,7 +1223,8 @@ CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
cFYI(1, ("Send error in QPathInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
+ /* BB also check enough total bytes returned */
+ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */
else {
memcpy((char *) pFindData,
@@ -1230,7 +1238,7 @@ CIFSSMBQPathInfo(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_UNIX_BASIC_INFO * pFindData,
const struct nls_table *nls_codepage)
@@ -1265,7 +1273,8 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
name_len /* includes null */ ;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
- pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
+ /* BB find exact max SMB PDU from sess structure BB */
+ pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
@@ -1292,7 +1301,8 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
cFYI(1, ("Send error in QPathInfo = %d", rc));
} else { /* decode response */
pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
- if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
+ /* BB also check if enough total bytes returned */
+ if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
rc = -EIO; /* bad smb */
else {
memcpy((char *) pFindData,
@@ -1307,7 +1317,7 @@ CIFSSMBUnixQPathInfo(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSFindSingle(const int xid, const struct cifsTconInfo *tcon,
+CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
const char *searchName, FILE_ALL_INFO * findData,
const struct nls_table *nls_codepage)
{
@@ -1381,7 +1391,7 @@ CIFSFindSingle(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
const char *searchName, FILE_DIRECTORY_INFO * findData,
T2_FFIRST_RSP_PARMS * findParms,
const struct nls_table *nls_codepage, int *pUnicodeFlag,
@@ -1484,7 +1494,7 @@ CIFSFindFirst(const int xid, const struct cifsTconInfo *tcon,
}
int
-CIFSFindNext(const int xid, const struct cifsTconInfo *tcon,
+CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
FILE_DIRECTORY_INFO * findData,
T2_FNEXT_RSP_PARMS * findParms, const __u16 searchHandle,
__u32 resumeKey, int *pUnicodeFlag, int *pUnixFlag)
@@ -1661,7 +1671,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
}
int
-CIFSSMBQFSInfo(const int xid, const struct cifsTconInfo *tcon,
+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
struct statfs *FSData, const struct nls_table *nls_codepage)
{
/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 40e8ea8124..dd28f46185 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -76,22 +76,32 @@ cifs_reconnect(struct TCP_Server_Info *server)
int rc = 0;
struct list_head *tmp;
struct cifsSesInfo *ses;
+ struct cifsTconInfo *tcon;
server->tcpStatus = CifsNeedReconnect;
server->maxBuf = 0;
cFYI(1, ("Reconnecting tcp session "));
+ /* before reconnecting the tcp session, mark the smb session (uid)
+ and the tid bad so they are not used until reconnected */
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &GlobalSMBSessionList) {
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if (ses->server) {
if (ses->server == server) {
ses->status = CifsNeedReconnect;
+ ses->ipc_tid = 0;
}
}
/* else tcp and smb sessions need reconnection */
}
+ list_for_each(tmp, &GlobalTreeConnectionList) {
+ tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
+ if(tcon->ses->server == server) {
+ tcon->tidStatus = CifsNeedReconnect;
+ }
+ }
read_unlock(&GlobalSMBSeslock);
if(server->ssocket) {
@@ -112,6 +122,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
schedule_timeout(3 * HZ);
} else {
server->tcpStatus = CifsGood;
+ wake_up(&server->response_q);
}
}
@@ -174,15 +185,12 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
csocket = server->ssocket;
continue;
} else { /* find define for the -512 returned at unmount time */
- cFYI(1,
- ("Received error on sock_recvmsg( peek) with length = %d",
+ cFYI(1,("Error on sock_recvmsg(peek) length = %d",
length));
}
break;
- }
- if (length == 0) {
- cFYI(1,
- ("Zero length peek received - dead session?"));
+ } else if (length == 0) {
+ cFYI(1,("Zero length peek received - dead session?"));
cifs_reconnect(server);
csocket = server->ssocket;
continue;
@@ -507,8 +515,7 @@ find_unc(__u32 new_target_ip_addr, char *uncName, char *userName)
/* BB lock tcon and server and tcp session and increment use count here? */
/* found a match on the TCP session */
/* BB check if reconnection needed */
- cFYI(1,
- ("Matched ip, old UNC: %s == new: %s ?",
+ cFYI(1,("Matched ip, old UNC: %s == new: %s ?",
tcon->treeName, uncName));
if (strncmp
(tcon->treeName, uncName,
@@ -855,9 +862,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
FreeXid(xid);
return -ENODEV;
} else {
- rc = CIFSTCon(xid, pSesInfo,
- volume_info.UNC,
- tcon, cifs_sb->local_nls);
+ rc = CIFSTCon(xid, pSesInfo,
+ volume_info.UNC,
+ tcon, cifs_sb->local_nls);
cFYI(1, ("CIFS Tcon rc = %d", rc));
}
if (!rc)
@@ -2196,6 +2203,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
/* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
+ tcon->tidStatus = CifsGood;
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 0510f81840..03aa43894f 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -423,6 +423,7 @@ cifs_partialpagewrite(struct page *page,unsigned from, unsigned to)
return rc;
}
+#if 0
static int
cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
{
@@ -434,6 +435,7 @@ cifs_writepages(struct address_space *mapping, struct writeback_control *wbc)
FreeXid(xid);
return rc;
}
+#endif
static int
cifs_writepage(struct page* page, struct writeback_control *wbc)
@@ -635,7 +637,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
}
page_cache_get(page);
- target = kmap(page);
+ target = kmap_atomic(page,KM_USER0);
if(PAGE_CACHE_SIZE > bytes_read) {
memcpy(target,data,bytes_read);
@@ -649,7 +651,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
__pagevec_lru_add(plru_pvec);
flush_dcache_page(page);
SetPageUptodate(page);
- kunmap(page);
+ kunmap_atomic(page,KM_USER0);
unlock_page(page);
page_cache_release(page);
data += PAGE_CACHE_SIZE;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 400bca121f..02a235ee94 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -70,6 +70,7 @@ sesInfoAlloc(void)
memset(ret_buf, 0, sizeof (struct cifsSesInfo));
write_lock(&GlobalSMBSeslock);
atomic_inc(&sesInfoAllocCount);
+ ret_buf->status = CifsNew;
list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList);
init_MUTEX(&ret_buf->sesSem);
write_unlock(&GlobalSMBSeslock);
@@ -111,6 +112,7 @@ tconInfoAlloc(void)
atomic_inc(&tconInfoAllocCount);
list_add(&ret_buf->cifsConnectionList,
&GlobalTreeConnectionList);
+ ret_buf->tidStatus = CifsNew;
INIT_LIST_HEAD(&ret_buf->openFileList);
init_MUTEX(&ret_buf->tconSem);
write_unlock(&GlobalSMBSeslock);
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 56936ef0e0..aad3a7b4aa 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -37,6 +37,7 @@ struct mid_q_entry *
AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
{
struct mid_q_entry *temp;
+ int timeout = 10 * HZ;
/* BB add spinlock to protect midq for each session BB */
if (ses == NULL) {
@@ -57,13 +58,22 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
temp->ses = ses;
temp->tsk = current;
}
+
+ while ((ses->server->tcpStatus != CifsGood) && (timeout > 0)){
+ /* Give the tcp thread up to 10 seconds to reconnect */
+ /* Should we wake up tcp thread first? BB */
+ timeout = wait_event_interruptible_timeout(ses->server->response_q,
+ (ses->server->tcpStatus == CifsGood), timeout);
+ cFYI(1,("timeout (after reconnection wait) %d",timeout));
+ }
+
if (ses->server->tcpStatus == CifsGood) {
write_lock(&GlobalMid_Lock);
list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
atomic_inc(&midCount);
temp->midState = MID_REQUEST_ALLOCATED;
write_unlock(&GlobalMid_Lock);
- } else { /* could add more reconnect code here BB */
+ } else {
cERROR(1,("Need to reconnect after session died to server"));
if (temp)
kmem_cache_free(cifs_mid_cachep, temp);
@@ -106,16 +116,16 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
smb_msg.msg_iovlen = 1;
smb_msg.msg_control = NULL;
smb_msg.msg_controllen = 0;
- smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags? */
+ smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
- /* smb header is converted in header_assemble. bcc and rest of SMB word area,
- and byte area if necessary, is converted to littleendian in cifssmb.c and RFC1001
- len is converted to bigendian in smb_send */
+ /* smb header is converted in header_assemble. bcc and rest of SMB word
+ area, and byte area if necessary, is converted to littleendian in
+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send */
if (smb_buf_length > 12)
smb_buffer->Flags2 = cpu_to_le16(smb_buffer->Flags2);
- /* if(smb_buffer->Flags2 & SMBFLG2_SECURITY_SIGNATURE)
- sign_smb(smb_buffer); */ /* BB enable when signing tested more */
+ /* if(smb_buffer->Flags2 & SMBFLG2_SECURITY_SIGNATURE)
+ sign_smb(smb_buffer); */ /* BB enable when signing tested more */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d ", smb_buf_length));
@@ -148,7 +158,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
midQ = AllocMidQEntry(in_buf, ses);
if (midQ == NULL)
- return -EIO; /* reconnect should be done, if possible, in AllocMidQEntry */
+ return -EIO;
if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) {
cERROR(1,
("Illegal length, greater than maximum frame, %d ",
@@ -219,7 +229,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
*pbytes_returned = out_buf->smb_buf_length;
/* BB special case reconnect tid and reconnect uid here? */
- rc = map_smb_to_linux_error(out_buf); /* BB watch endianness here BB */
+ rc = map_smb_to_linux_error(out_buf);
/* convert ByteCount if necessary */
if (receive_len >=
diff --git a/fs/xfs/linux/xfs_aops.c b/fs/xfs/linux/xfs_aops.c
index 5505483ca8..0b9c47c436 100644
--- a/fs/xfs/linux/xfs_aops.c
+++ b/fs/xfs/linux/xfs_aops.c
@@ -53,12 +53,15 @@ map_blocks(
count = max_t(ssize_t, count, XFS_WRITE_IO_LOG);
retry:
VOP_BMAP(vp, offset, count, flags, pbmapp, &nmaps, error);
- if (flags & PBF_WRITE) {
- if (unlikely((flags & PBF_DIRECT) && nmaps &&
- (pbmapp->pbm_flags & PBMF_DELAY))) {
- flags = PBF_FILE_ALLOCATE;
- goto retry;
- }
+ if (error == EAGAIN)
+ return -error;
+ if (unlikely((flags & (PBF_WRITE|PBF_DIRECT)) ==
+ (PBF_WRITE|PBF_DIRECT) && nmaps &&
+ (pbmapp->pbm_flags & PBMF_DELAY))) {
+ flags = PBF_FILE_ALLOCATE;
+ goto retry;
+ }
+ if (flags & (PBF_WRITE|PBF_FILE_ALLOCATE)) {
VMODIFY(vp);
}
return -error;
@@ -309,6 +312,7 @@ convert_page(
if (startio && (offset < end)) {
bh_arr[index++] = bh;
} else {
+ set_buffer_dirty(bh);
unlock_buffer(bh);
}
} while (i++, (bh = bh->b_this_page) != head);
@@ -365,9 +369,9 @@ cluster_write(
STATIC int
delalloc_convert(
- struct page *page,
- int startio,
- int allocate_space)
+ struct page *page,
+ int startio,
+ int unmapped) /* also implies page uptodate */
{
struct inode *inode = page->mapping->host;
struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head;
@@ -375,6 +379,9 @@ delalloc_convert(
unsigned long p_offset = 0, end_index;
loff_t offset, end_offset;
int len, err, i, cnt = 0, uptodate = 1;
+ int flags = startio ? 0 : PBF_TRYLOCK;
+ int page_dirty = 1;
+
/* Are we off the end of the file ? */
end_index = inode->i_size >> PAGE_CACHE_SHIFT;
@@ -390,9 +397,6 @@ delalloc_convert(
if (end_offset > inode->i_size)
end_offset = inode->i_size;
- if (startio && !page_has_buffers(page))
- create_empty_buffers(page, 1 << inode->i_blkbits, 0);
-
bh = head = page_buffers(page);
mp = NULL;
@@ -406,10 +410,14 @@ delalloc_convert(
mp = match_offset_to_mapping(page, &map, p_offset);
}
+ /*
+ * First case, allocate space for delalloc buffer head
+ * we can return EAGAIN here in the release page case.
+ */
if (buffer_delay(bh)) {
if (!mp) {
err = map_blocks(inode, offset, len, &map,
- PBF_FILE_ALLOCATE);
+ PBF_FILE_ALLOCATE | flags);
if (err) {
goto error;
}
@@ -422,14 +430,17 @@ delalloc_convert(
if (startio) {
bh_arr[cnt++] = bh;
} else {
+ set_buffer_dirty(bh);
unlock_buffer(bh);
}
+ page_dirty = 0;
}
} else if ((buffer_uptodate(bh) || PageUptodate(page)) &&
- (allocate_space || startio)) {
+ (unmapped || startio)) {
+
if (!buffer_mapped(bh)) {
int size;
-
+
/*
* Getting here implies an unmapped buffer
* was found, and we are in a path where we
@@ -454,13 +465,16 @@ delalloc_convert(
if (startio) {
bh_arr[cnt++] = bh;
} else {
+ set_buffer_dirty(bh);
unlock_buffer(bh);
}
+ page_dirty = 0;
}
- } else if (startio && buffer_mapped(bh)) {
- if (buffer_uptodate(bh) && allocate_space) {
+ } else if (startio) {
+ if (buffer_uptodate(bh)) {
lock_buffer(bh);
bh_arr[cnt++] = bh;
+ page_dirty = 0;
}
}
}
@@ -482,10 +496,10 @@ next_bh:
if (mp) {
cluster_write(inode, page->index + 1, mp,
- startio, allocate_space);
+ startio, unmapped);
}
- return 0;
+ return page_dirty;
error:
for (i = 0; i < cnt; i++) {
@@ -494,12 +508,15 @@ error:
/*
* If it's delalloc and we have nowhere to put it,
- * throw it away.
+ * throw it away, unless the lower layers told
+ * us to try again.
*/
- if (!allocate_space) {
- block_invalidatepage(page, 0);
+ if (err != -EAGAIN) {
+ if (!unmapped) {
+ block_invalidatepage(page, 0);
+ }
+ ClearPageUptodate(page);
}
- ClearPageUptodate(page);
return err;
}
@@ -679,109 +696,172 @@ linvfs_readpages(
}
-STATIC int
+STATIC void
count_page_state(
struct page *page,
- int *nr_delalloc,
- int *nr_unmapped)
+ int *delalloc,
+ int *unmapped)
{
- *nr_delalloc = *nr_unmapped = 0;
-
- if (page_has_buffers(page)) {
- struct buffer_head *bh, *head;
+ struct buffer_head *bh, *head;
- bh = head = page_buffers(page);
- do {
- if (buffer_uptodate(bh) && !buffer_mapped(bh))
- (*nr_unmapped)++;
- else if (buffer_delay(bh))
- (*nr_delalloc)++;
- } while ((bh = bh->b_this_page) != head);
+ *delalloc = *unmapped = 0;
- return 1;
- }
-
- return 0;
+ bh = head = page_buffers(page);
+ do {
+ if (buffer_uptodate(bh) && !buffer_mapped(bh))
+ (*unmapped) = 1;
+ else if (buffer_delay(bh))
+ (*delalloc) = 1;
+ } while ((bh = bh->b_this_page) != head);
}
+
+/*
+ * writepage: Called from one of two places:
+ *
+ * 1. we are flushing a delalloc buffer head.
+ *
+ * 2. we are writing out a dirty page. Typically the page dirty
+ * state is cleared before we get here. In this case is it
+ * conceivable we have no buffer heads.
+ *
+ * For delalloc space on the page we need to allocate space and
+ * flush it. For unmapped buffer heads on the page we should
+ * allocate space if the page is uptodate. For any other dirty
+ * buffer heads on the page we should flush them.
+ *
+ * If we detect that a transaction would be required to flush
+ * the page, we have to check the process flags first, if we
+ * are already in a transaction or disk I/O during allocations
+ * is off, we need to fail the writepage and redirty the page.
+ * We also need to set PF_NOIO ourselves.
+ */
STATIC int
linvfs_writepage(
struct page *page,
struct writeback_control *wbc)
{
int error;
- int need_trans = 1;
- int nr_delalloc, nr_unmapped;
+ int need_trans;
+ int delalloc, unmapped;
+ struct inode *inode = page->mapping->host;
- if (count_page_state(page, &nr_delalloc, &nr_unmapped))
- need_trans = nr_delalloc + nr_unmapped;
+ /*
+ * We need a transaction if:
+ * 1. There are delalloc buffers on the page
+ * 2. The page is upto date and we have unmapped buffers
+ * 3. The page is upto date and we have no buffers
+ */
+ if (!page_has_buffers(page)) {
+ unmapped = 1;
+ need_trans = 1;
+ } else {
+ count_page_state(page, &delalloc, &unmapped);
+ if (!PageUptodate(page))
+ unmapped = 0;
+ need_trans = delalloc + unmapped;
+ }
+ /*
+ * If we need a transaction and the process flags say
+ * we are already in a transaction, or no IO is allowed
+ * then mark the page dirty again and leave the page
+ * as is.
+ */
if ((current->flags & (PF_FSTRANS)) && need_trans)
goto out_fail;
/*
+ * Delay hooking up buffer heads until we have
+ * made our go/no-go decision.
+ */
+ if (!page_has_buffers(page)) {
+ create_empty_buffers(page, 1 << inode->i_blkbits, 0);
+ }
+
+ /*
* Convert delalloc or unmapped space to real space and flush out
* to disk.
*/
- error = delalloc_convert(page, 1, nr_delalloc == 0);
- if (unlikely(error))
- unlock_page(page);
- return error;
+ error = delalloc_convert(page, 1, unmapped);
+ if (error == -EAGAIN)
+ goto out_fail;
+ if (unlikely(error < 0))
+ goto out_unlock;
+
+ return 0;
out_fail:
set_page_dirty(page);
unlock_page(page);
return 0;
-}
-
-STATIC int
-linvfs_prepare_write(
- struct file *file,
- struct page *page,
- unsigned int from,
- unsigned int to)
-{
- if (file && (file->f_flags & O_SYNC)) {
- return block_prepare_write(page, from, to,
- linvfs_get_block_sync);
- } else {
- return block_prepare_write(page, from, to,
- linvfs_get_block);
- }
+out_unlock:
+ unlock_page(page);
+ return error;
}
/*
- * This gets a page into cleanable state - page locked on entry
- * kept locked on exit. If the page is marked dirty we should
- * not come this way.
+ * Called to move a page into cleanable state - and from there
+ * to be released. Possibly the page is already clean. We always
+ * have buffer heads in this call.
+ *
+ * Returns 0 if the page is ok to release, 1 otherwise.
+ *
+ * Possible scenarios are:
+ *
+ * 1. We are being called to release a page which has been written
+ * to via regular I/O. buffer heads will be dirty and possibly
+ * delalloc. If no delalloc buffer heads in this case then we
+ * can just return zero.
+ *
+ * 2. We are called to release a page which has been written via
+ * mmap, all we need to do is ensure there is no delalloc
+ * state in the buffer heads, if not we can let the caller
+ * free them and we should come back later via writepage.
*/
STATIC int
linvfs_release_page(
struct page *page,
int gfp_mask)
{
- int nr_delalloc, nr_unmapped;
+ int delalloc, unmapped;
- if (count_page_state(page, &nr_delalloc, &nr_unmapped)) {
- if (!nr_delalloc)
- goto free_buffers;
- }
+ count_page_state(page, &delalloc, &unmapped);
+ if (!delalloc)
+ goto free_buffers;
- if (gfp_mask & __GFP_FS) {
- /*
- * Convert delalloc space to real space, do not flush the
- * data out to disk, that will be done by the caller.
- */
- if (delalloc_convert(page, 0, 0) == 0)
- goto free_buffers;
- }
+ if (!(gfp_mask & __GFP_FS))
+ return 0;
+ /*
+ * Convert delalloc space to real space, do not flush the
+ * data out to disk, that will be done by the caller.
+ * Never need to allocate space here - we will always
+ * come back to writepage in that case.
+ */
+ if (delalloc_convert(page, 0, 0) == 0)
+ goto free_buffers;
return 0;
free_buffers:
return try_to_free_buffers(page);
}
+STATIC int
+linvfs_prepare_write(
+ struct file *file,
+ struct page *page,
+ unsigned int from,
+ unsigned int to)
+{
+ if (file && (file->f_flags & O_SYNC)) {
+ return block_prepare_write(page, from, to,
+ linvfs_get_block_sync);
+ } else {
+ return block_prepare_write(page, from, to,
+ linvfs_get_block);
+ }
+}
struct address_space_operations linvfs_aops = {
.readpage = linvfs_readpage,
diff --git a/fs/xfs/linux/xfs_iomap.c b/fs/xfs/linux/xfs_iomap.c
index 322a8d3836..9769d225fb 100644
--- a/fs/xfs/linux/xfs_iomap.c
+++ b/fs/xfs/linux/xfs_iomap.c
@@ -120,7 +120,13 @@ xfs_iomap(
case PBF_FILE_ALLOCATE:
lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD;
bmap_flags = XFS_BMAPI_ENTIRE;
- XFS_ILOCK(mp, io, lockmode);
+ /* Attempt non-blocking lock */
+ if (flags & PBF_TRYLOCK) {
+ if (!XFS_ILOCK_NOWAIT(mp, io, lockmode))
+ return XFS_ERROR(EAGAIN);
+ } else {
+ XFS_ILOCK(mp, io, lockmode);
+ }
break;
case PBF_FILE_UNWRITTEN:
lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR;
diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c
index fc9235db86..89a401fdd6 100644
--- a/fs/xfs/linux/xfs_super.c
+++ b/fs/xfs/linux/xfs_super.c
@@ -1009,13 +1009,13 @@ init_xfs_fs( void )
if (error < 0)
return error;
+ si_meminfo(&si);
+ xfs_physmem = si.totalram;
+
error = pagebuf_init();
if (error < 0)
goto out;
- si_meminfo(&si);
- xfs_physmem = si.totalram;
-
vn_init();
xfs_init();
dmapi_init();
diff --git a/fs/xfs/pagebuf/page_buf.c b/fs/xfs/pagebuf/page_buf.c
index 5663f6d4b4..05e086ad25 100644
--- a/fs/xfs/pagebuf/page_buf.c
+++ b/fs/xfs/pagebuf/page_buf.c
@@ -119,9 +119,9 @@ pb_trace_func(
STATIC kmem_cache_t *pagebuf_cache;
STATIC void pagebuf_daemon_wakeup(int);
+STATIC void pagebuf_delwri_queue(page_buf_t *, int);
STATIC struct workqueue_struct *pagebuf_workqueue;
-
/*
* Pagebuf module configuration parameters, exported via
* /proc/sys/vm/pagebuf
@@ -155,35 +155,37 @@ struct pbstats pbstats;
* Pagebuf hashing
*/
-#define NBITS 5
-#define NHASH (1<<NBITS)
-
+/* This structure must be a power of 2 long for the hash to work */
typedef struct {
struct list_head pb_hash;
int pb_count;
spinlock_t pb_hash_lock;
} pb_hash_t;
-STATIC pb_hash_t pbhash[NHASH];
+static pb_hash_t *pbhash;
+static unsigned int pb_hash_mask;
+static unsigned int pb_hash_shift;
+static unsigned int pb_order;
#define pb_hash(pb) &pbhash[pb->pb_hash_index]
-STATIC int
+/*
+ * This hash is the same one as used on the Linux buffer cache,
+ * see fs/buffer.c
+ */
+
+#define _hashfn(dev,block) \
+ ((((dev)<<(pb_hash_shift - 6)) ^ ((dev)<<(pb_hash_shift - 9))) ^ \
+ (((block)<<(pb_hash_shift - 6)) ^ ((block) >> 13) ^ \
+ ((block) << (pb_hash_shift - 12))))
+
+static inline int
_bhash(
dev_t dev,
loff_t base)
{
- int bit, hval;
-
base >>= 9;
- /*
- * dev_t is 16 bits, loff_t is always 64 bits
- */
- base ^= dev;
- for (bit = hval = 0; base != 0 && bit < sizeof(base) * 8; bit += NBITS) {
- hval ^= (int)base & (NHASH-1);
- base >>= NBITS;
- }
- return hval;
+
+ return (_hashfn(dev, base) & pb_hash_mask);
}
/*
@@ -1516,7 +1518,7 @@ STATIC int pbd_active = 1;
STATIC LIST_HEAD(pbd_delwrite_queue);
STATIC spinlock_t pbd_delwrite_lock = SPIN_LOCK_UNLOCKED;
-void
+STATIC void
pagebuf_delwri_queue(
page_buf_t *pb,
int unlock)
@@ -1862,7 +1864,39 @@ pagebuf_shaker(void)
int __init
pagebuf_init(void)
{
- int i;
+ int order, mempages, i;
+ unsigned int nr_hash;
+ extern int xfs_physmem;
+
+ mempages = xfs_physmem >>= 16;
+ mempages *= sizeof(pb_hash_t);
+ for (order = 0; (1 << order) < mempages; order++)
+ ;
+
+ if (order > 3) order = 3; /* cap us at 2K buckets */
+
+ do {
+ unsigned long tmp;
+
+ nr_hash = (PAGE_SIZE << order) / sizeof(pb_hash_t);
+ nr_hash = 1 << (ffs(nr_hash) - 1);
+ pb_hash_mask = (nr_hash - 1);
+ tmp = nr_hash;
+ pb_hash_shift = 0;
+ while((tmp >>= 1UL) != 0UL)
+ pb_hash_shift++;
+
+ pbhash = (pb_hash_t *)
+ __get_free_pages(GFP_KERNEL, order);
+ pb_order = order;
+ } while (pbhash == NULL && --order > 0);
+ printk("pagebuf cache hash table entries: %d (order: %d, %ld bytes)\n",
+ nr_hash, order, (PAGE_SIZE << order));
+
+ for(i = 0; i < nr_hash; i++) {
+ spin_lock_init(&pbhash[i].pb_hash_lock);
+ INIT_LIST_HEAD(&pbhash[i].pb_hash);
+ }
pagebuf_table_header = register_sysctl_table(pagebuf_root_table, 1);
@@ -1880,11 +1914,6 @@ pagebuf_init(void)
return -ENOMEM;
}
- for (i = 0; i < NHASH; i++) {
- spin_lock_init(&pbhash[i].pb_hash_lock);
- INIT_LIST_HEAD(&pbhash[i].pb_hash);
- }
-
#ifdef PAGEBUF_TRACE
pb_trace.buf = (pagebuf_trace_t *)kmalloc(
PB_TRACE_BUFSIZE * sizeof(pagebuf_trace_t), GFP_KERNEL);
@@ -1911,6 +1940,7 @@ pagebuf_terminate(void)
kmem_cache_destroy(pagebuf_cache);
kmem_shake_deregister(pagebuf_shaker);
+ free_pages((unsigned long)pbhash, pb_order);
unregister_sysctl_table(pagebuf_table_header);
#ifdef CONFIG_PROC_FS
diff --git a/fs/xfs/pagebuf/page_buf.h b/fs/xfs/pagebuf/page_buf.h
index 65fb68dccc..52bde568a6 100644
--- a/fs/xfs/pagebuf/page_buf.h
+++ b/fs/xfs/pagebuf/page_buf.h
@@ -215,8 +215,8 @@ typedef struct page_buf_s {
unsigned short pb_error; /* error code on I/O */
unsigned short pb_page_count; /* size of page array */
unsigned short pb_offset; /* page offset in first page */
+ unsigned short pb_hash_index; /* hash table index */
unsigned char pb_locked; /* page array is locked */
- unsigned char pb_hash_index; /* hash table index */
struct page **pb_pages; /* array of page pointers */
struct page *pb_page_array[PB_PAGES]; /* inline pages */
#ifdef PAGEBUF_LOCK_TRACKING
@@ -350,7 +350,6 @@ extern int pagebuf_ispin( page_buf_t *); /* check if pagebuf is pinned */
/* Reading and writing pages */
-extern void pagebuf_delwri_queue(page_buf_t *, int);
extern void pagebuf_delwri_dequeue(page_buf_t *);
#define PBDF_WAIT 0x01
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index cbedf29d75..524238f6f9 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -86,7 +86,7 @@ cmn_err(register int level, char *fmt, ...)
{
char *fp = fmt;
int len;
- int flags;
+ unsigned long flags;
va_list ap;
level &= XFS_ERR_MASK;
diff --git a/fs/xfs/support/spin.h b/fs/xfs/support/spin.h
index f28f251ce8..4a876797f8 100644
--- a/fs/xfs/support/spin.h
+++ b/fs/xfs/support/spin.h
@@ -46,7 +46,6 @@
typedef spinlock_t lock_t;
#define spinlock_init(lock, name) spin_lock_init(lock)
-#define init_spinlock(lock, name, ll) spin_lock_init(lock)
#define spinlock_destroy(lock)
static inline unsigned long mutex_spinlock(lock_t *lock)
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index d689c169f6..8dfb1ab6ff 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -648,7 +648,7 @@ xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp,
XFS_DATA_FORK);
if (retval)
- return(retval);
+ goto out;
ASSERT(bp != NULL);
memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
leaf = (xfs_dir_leafblock_t *)tmpbuffer;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index f6c313627e..b59b84fa6b 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -33,7 +33,7 @@
#define __XFS_ERROR_H__
#define prdev(fmt,dev,args...) \
- printk("XFS: device 0x%x- " fmt "\n", dev, ## args)
+ printk("XFS: device 0x%x- " fmt "\n", (unsigned)dev, ## args)
#define XFS_ERECOVER 1 /* Failure to recover log */
#define XFS_ELOGSTAT 2 /* Failure to stat log in user space */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index a30359bcbb..b044f4f800 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -378,17 +378,26 @@ xfs_log_notify(xfs_mount_t *mp, /* mount of partition */
iclog->ic_callback_tail = &(cb->cb_next);
}
LOG_UNLOCK(log, spl);
- if (!abortflg) {
- if (xlog_state_release_iclog(log, iclog)) {
- xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
- return EIO;
- }
- } else {
+ if (abortflg) {
cb->cb_func(cb->cb_arg, abortflg);
}
return 0;
} /* xfs_log_notify */
+int
+xfs_log_release_iclog(xfs_mount_t *mp,
+ void *iclog_hndl)
+{
+ xlog_t *log = mp->m_log;
+ xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
+
+ if (xlog_state_release_iclog(log, iclog)) {
+ xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+ return(EIO);
+ }
+
+ return 0;
+}
/*
* Initialize log manager data. This routine is intended to be called when
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 68a3ea4fe7..02955f0c0b 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -164,6 +164,8 @@ void xfs_log_move_tail(struct xfs_mount *mp,
int xfs_log_notify(struct xfs_mount *mp,
void *iclog,
xfs_log_callback_t *callback_entry);
+int xfs_log_release_iclog(struct xfs_mount *mp,
+ void *iclog_hndl);
int xfs_log_reserve(struct xfs_mount *mp,
int length,
int count,
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 617eead8f1..6eddf1a0d5 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1287,10 +1287,6 @@ xlog_recover_add_to_trans(xlog_recover_t *trans,
if (!len)
return 0;
- ptr = kmem_zalloc(len, 0);
- memcpy(ptr, dp, len);
-
- in_f = (xfs_inode_log_format_t *)ptr;
item = trans->r_itemq;
if (item == 0) {
ASSERT(*(uint *)dp == XFS_TRANS_HEADER_MAGIC);
@@ -1299,6 +1295,11 @@ xlog_recover_add_to_trans(xlog_recover_t *trans,
memcpy(&trans->r_theader, dp, len); /* d, s, l */
return 0;
}
+
+ ptr = kmem_alloc(len, 0);
+ memcpy(ptr, dp, len);
+ in_f = (xfs_inode_log_format_t *)ptr;
+
if (item->ri_prev->ri_total != 0 &&
item->ri_prev->ri_total == item->ri_prev->ri_cnt) {
xlog_recover_add_item(&trans->r_itemq);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index df578881cb..6fa2f67a74 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -272,7 +272,7 @@ xfs_mount_validate_sb(
cmn_err(CE_WARN,
"XFS: Only page-sized (%d) or less blocksizes currently work.",
PAGE_SIZE);
- return XFS_ERROR(EWRONGFS);
+ return XFS_ERROR(ENOSYS);
}
return 0;
@@ -459,10 +459,22 @@ xfs_readsb(xfs_mount_t *mp)
}
/*
- * Re-read the superblock so that our buffer is correctly sized.
- * We only need to do this if sector size on-disk is different.
+ * We must be able to do sector-sized and sector-aligned IO.
+ */
+ if (sector_size > mp->m_sb.sb_sectsize) {
+ cmn_err(CE_WARN,
+ "XFS: device supports only %u byte sectors (not %u)",
+ sector_size, mp->m_sb.sb_sectsize);
+ XFS_BUF_UNMANAGE(bp);
+ xfs_buf_relse(bp);
+ return XFS_ERROR(ENOSYS);
+ }
+
+ /*
+ * If device sector size is smaller than the superblock size,
+ * re-read the superblock so the buffer is correctly sized.
*/
- if (sector_size != mp->m_sb.sb_sectsize) {
+ if (sector_size < mp->m_sb.sb_sectsize) {
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
sector_size = mp->m_sb.sb_sectsize;
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 355e283f8a..599ec46ec7 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -809,19 +809,6 @@ shut_us_down:
}
/*
- * Once all the items of the transaction have been copied
- * to the in core log we can release them. Do that here.
- * This will free descriptors pointing to items which were
- * not logged since there is nothing more to do with them.
- * For items which were logged, we will keep pointers to them
- * so they can be unpinned after the transaction commits to disk.
- * This will also stamp each modified meta-data item with
- * the commit lsn of this transaction for dependency tracking
- * purposes.
- */
- xfs_trans_unlock_items(tp, commit_lsn);
-
- /*
* Once the transaction has committed, unused
* reservations need to be released and changes to
* the superblock need to be reflected in the in-core
@@ -856,12 +843,36 @@ shut_us_down:
tp->t_logcb.cb_arg = tp;
/* We need to pass the iclog buffer which was used for the
- * transaction commit record into this function, attach
- * the callback to it, and then release it. This will guarantee
- * that we do callbacks on the transaction in the correct order.
+ * transaction commit record into this function, and attach
+ * the callback to it. The callback must be attached before
+ * the items are unlocked to avoid racing with other threads
+ * waiting for an item to unlock.
*/
error = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
#endif
+
+ /*
+ * Once all the items of the transaction have been copied
+ * to the in core log and the callback is attached, the
+ * items can be unlocked.
+ *
+ * This will free descriptors pointing to items which were
+ * not logged since there is nothing more to do with them.
+ * For items which were logged, we will keep pointers to them
+ * so they can be unpinned after the transaction commits to disk.
+ * This will also stamp each modified meta-data item with
+ * the commit lsn of this transaction for dependency tracking
+ * purposes.
+ */
+ xfs_trans_unlock_items(tp, commit_lsn);
+
+ /*
+ * Now that the xfs_trans_committed callback has been attached,
+ * and the items are released we can finally allow the iclog to
+ * go to disk.
+ */
+ error = xfs_log_release_iclog(mp, commit_iclog);
+
/*
* If the transaction needs to be synchronous, then force the
* log out now and wait for it.
diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
index e1e6dfd512..b8acc156b9 100644
--- a/include/asm-sparc/ide.h
+++ b/include/asm-sparc/ide.h
@@ -20,12 +20,12 @@
#undef MAX_HWIFS
#define MAX_HWIFS 2
-static __inline__ int ide_default_irq(ide_ioreg_t base)
+static __inline__ int ide_default_irq(unsigned long base)
{
return 0;
}
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
+static __inline__ unsigned long ide_default_io_base(int index)
{
return 0;
}
@@ -34,9 +34,9 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index)
* Doing any sort of ioremap() here does not work
* because this function may be called with null aguments.
*/
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
{
- ide_ioreg_t reg = data_port;
+ unsigned long reg = data_port;
int i;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
@@ -46,7 +46,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
if (ctrl_port) {
hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
} else {
- hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
}
if (irq != NULL)
*irq = 0;
@@ -64,6 +64,7 @@ static __inline__ void ide_init_default_hwifs(void)
int index;
for (index = 0; index < MAX_HWIFS; index++) {
+ memset(&hw, 0, sizeof hw);
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw, NULL);
@@ -71,38 +72,78 @@ static __inline__ void ide_init_default_hwifs(void)
#endif
}
-#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
-#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
-#define ide_check_region(from,extent) check_region((from), (extent))
-#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
-#define ide_release_region(from,extent) release_region((from), (extent))
+#define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+#define __ide_outsl(data_reg, buffer, wcount) \
+ __ide_outsw(data_reg, buffer, (wcount)<<1)
-/*
- * The following is not needed for the non-m68k ports
- */
-#define ide_ack_intr(hwif) (1)
+/* On sparc, I/O ports and MMIO registers are accessed identically. */
+#define __ide_mm_insw __ide_insw
+#define __ide_mm_insl __ide_insl
+#define __ide_mm_outsw __ide_outsw
+#define __ide_mm_outsl __ide_outsl
-/* XXX Known to be broken. Axboe will fix the problems this
- * XXX has by making separate IN/OUT macros for IDE_DATA
- * XXX register and rest of IDE regs and also using
- * XXX ide_ioreg_t instead of u32 for ports. -DaveM
- */
+static __inline__ void __ide_insw(unsigned long port,
+ void *dst,
+ unsigned long count)
+{
+ volatile unsigned short *data_port;
+ /* unsigned long end = (unsigned long)dst + (count << 1); */ /* P3 */
+ u16 *ps = dst;
+ u32 *pi;
+
+ data_port = (volatile unsigned short *)port;
-#define HAVE_ARCH_IN_BYTE
-#define IN_BYTE(p) (*((volatile u8 *)(p)))
-#define IN_WORD(p) (*((volatile u16 *)(p)))
-#define IN_LONG(p) (*((volatile u32 *)(p)))
-#define IN_BYTE_P IN_BYTE
-#define IN_WORD_P IN_WORD
-#define IN_LONG_P IN_LONG
-
-#define HAVE_ARCH_OUT_BYTE
-#define OUT_BYTE(b,p) ((*((volatile u8 *)(p))) = (b))
-#define OUT_WORD(w,p) ((*((volatile u16 *)(p))) = (w))
-#define OUT_LONG(l,p) ((*((volatile u32 *)(p))) = (l))
-#define OUT_BYTE_P OUT_BYTE
-#define OUT_WORD_P OUT_WORD
-#define OUT_LONG_P OUT_LONG
+ if(((unsigned long)ps) & 0x2) {
+ *ps++ = *data_port;
+ count--;
+ }
+ pi = (u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = (*data_port) << 16;
+ w |= (*data_port);
+ *pi++ = w;
+ count -= 2;
+ }
+ ps = (u16 *)pi;
+ if(count)
+ *ps++ = *data_port;
+
+ /* __flush_dcache_range((unsigned long)dst, end); */ /* P3 see hme */
+}
+
+static __inline__ void __ide_outsw(unsigned long port,
+ const void *src,
+ unsigned long count)
+{
+ volatile unsigned short *data_port;
+ /* unsigned long end = (unsigned long)src + (count << 1); */
+ const u16 *ps = src;
+ const u32 *pi;
+
+ data_port = (volatile unsigned short *)port;
+
+ if(((unsigned long)src) & 0x2) {
+ *data_port = *ps++;
+ count--;
+ }
+ pi = (const u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = *pi++;
+ *data_port = (w >> 16);
+ *data_port = w;
+ count -= 2;
+ }
+ ps = (const u16 *)pi;
+ if(count)
+ *data_port = *ps;
+
+ /* __flush_dcache_range((unsigned long)src, end); */ /* P3 see hme */
+}
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc/posix_types.h b/include/asm-sparc/posix_types.h
index 72991ca023..7efd7c0fae 100644
--- a/include/asm-sparc/posix_types.h
+++ b/include/asm-sparc/posix_types.h
@@ -31,6 +31,8 @@ typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index b27e040068..111826ebb5 100644
--- a/include/asm-sparc64/ide.h
+++ b/include/asm-sparc64/ide.h
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.22 2002/01/16 20:58:40 davem Exp $
+/* $Id: ide.h,v 1.21 2001/09/25 20:21:48 kanoj Exp $
* ide.h: Ultra/PCI specific IDE glue.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -20,19 +20,19 @@
#undef MAX_HWIFS
#define MAX_HWIFS 2
-static __inline__ int ide_default_irq(ide_ioreg_t base)
+static __inline__ int ide_default_irq(unsigned long base)
{
return 0;
}
-static __inline__ ide_ioreg_t ide_default_io_base(int index)
+static __inline__ unsigned long ide_default_io_base(int index)
{
return 0;
}
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, unsigned long ctrl_port, int *irq)
{
- ide_ioreg_t reg = data_port;
+ unsigned long reg = data_port;
int i;
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
@@ -42,7 +42,7 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
if (ctrl_port) {
hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
} else {
- hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+ hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
}
if (irq != NULL)
*irq = 0;
@@ -55,84 +55,111 @@ static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
*/
static __inline__ void ide_init_default_hwifs(void)
{
-#ifndef CONFIG_PCI
+#ifndef CONFIG_BLK_DEV_IDEPCI
hw_regs_t hw;
int index;
for (index = 0; index < MAX_HWIFS; index++) {
+ memset(&hw, 0, sizeof hw);
ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
hw.irq = ide_default_irq(ide_default_io_base(index));
ide_register_hw(&hw, NULL);
}
-#endif
+#endif /* CONFIG_BLK_DEV_IDEPCI */
}
+#define __ide_insl(data_reg, buffer, wcount) \
+ __ide_insw(data_reg, buffer, (wcount)<<1)
+#define __ide_outsl(data_reg, buffer, wcount) \
+ __ide_outsw(data_reg, buffer, (wcount)<<1)
-#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id))
-#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id))
-#define ide_check_region(from,extent) check_region((from), (extent))
-#define ide_request_region(from,extent,name) request_region((from), (extent), (name))
-#define ide_release_region(from,extent) release_region((from), (extent))
-
-/*
- * The following is not needed for the non-m68k ports
- */
-#define ide_ack_intr(hwif) (1)
+/* On sparc64, I/O ports and MMIO registers are accessed identically. */
+#define __ide_mm_insw __ide_insw
+#define __ide_mm_insl __ide_insl
+#define __ide_mm_outsw __ide_outsw
+#define __ide_mm_outsl __ide_outsl
-/* XXX Known to be broken. Axboe will fix the problems this
- * XXX has by making separate IN/OUT macros for IDE_DATA
- * XXX register and rest of IDE regs and also using
- * XXX ide_ioreg_t instead of u32 for ports. -DaveM
- */
+static __inline__ unsigned int inw_be(unsigned long addr)
+{
+ unsigned int ret;
-#define HAVE_ARCH_IN_BYTE
-static __inline__ u8 IN_BYTE(ide_ioreg_t addr)
-{ u8 ret;
- __asm__ __volatile__("lduba [%1] %2, %0\t/* ide_in_byte */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
- return ret;
-}
-static __inline__ u16 IN_WORD(ide_ioreg_t addr)
-{ u16 ret;
- __asm__ __volatile__("lduha [%1] %2, %0\t/* ide_in_word */"
- : "=r" (ret)
- : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
- return ret;
-}
-static __inline__ u16 IN_LONG(ide_ioreg_t addr)
-{ u32 ret;
- __asm__ __volatile__("lduwa [%1] %2, %0\t/* ide_in_long */"
+ __asm__ __volatile__("lduha [%1] %2, %0"
: "=r" (ret)
: "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+
return ret;
}
-#define IN_BYTE_P IN_BYTE
-#define IN_WORD_P IN_WORD
-#define IN_LONG_P IN_LONG
-#define HAVE_ARCH_OUT_BYTE
-static __inline__ void OUT_BYTE(u8 byte, ide_ioreg_t addr)
+static __inline__ void __ide_insw(unsigned long port,
+ void *dst,
+ u32 count)
{
- __asm__ __volatile__("stba %r0, [%1] %2\t/* ide_out_byte */"
- : /* no outputs */
- : "Jr" (byte), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+#if (L1DCACHE_SIZE > PAGE_SIZE) /* is there D$ aliasing problem */
+ unsigned long end = (unsigned long)dst + (count << 1);
+#endif
+ u16 *ps = dst;
+ u32 *pi;
+
+ if(((u64)ps) & 0x2) {
+ *ps++ = inw_be(port);
+ count--;
+ }
+ pi = (u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = inw_be(port) << 16;
+ w |= inw_be(port);
+ *pi++ = w;
+ count -= 2;
+ }
+ ps = (u16 *)pi;
+ if(count)
+ *ps++ = inw_be(port);
+
+#if (L1DCACHE_SIZE > PAGE_SIZE) /* is there D$ aliasing problem */
+ __flush_dcache_range((unsigned long)dst, end);
+#endif
}
-static __inline__ void OUT_WORD(u16 word, ide_ioreg_t addr)
+
+static __inline__ void outw_be(unsigned short w, unsigned long addr)
{
- __asm__ __volatile__("stha %r0, [%1] %2\t/* ide_out_word */"
+ __asm__ __volatile__("stha %0, [%1] %2"
: /* no outputs */
- : "Jr" (word), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+ : "r" (w), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
}
-static __inline__ void OUT_LONG(u32 _long, ide_ioreg_t addr)
+
+static __inline__ void __ide_outsw(unsigned long port,
+ void *src,
+ u32 count)
{
- __asm__ __volatile__("stwa %r0, [%1] %2\t/* ide_out_long */"
- : /* no outputs */
- : "Jr" (_long), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E));
+#if (L1DCACHE_SIZE > PAGE_SIZE) /* is there D$ aliasing problem */
+ unsigned long end = (unsigned long)src + (count << 1);
+#endif
+ const u16 *ps = src;
+ const u32 *pi;
+
+ if(((u64)src) & 0x2) {
+ outw_be(*ps++, port);
+ count--;
+ }
+ pi = (const u32 *)ps;
+ while(count >= 2) {
+ u32 w;
+
+ w = *pi++;
+ outw_be((w >> 16), port);
+ outw_be(w, port);
+ count -= 2;
+ }
+ ps = (const u16 *)pi;
+ if(count)
+ outw_be(*ps, port);
+
+#if (L1DCACHE_SIZE > PAGE_SIZE) /* is there D$ aliasing problem */
+ __flush_dcache_range((unsigned long)src, end);
+#endif
}
-#define OUT_BYTE_P OUT_BYTE
-#define OUT_WORD_P OUT_WORD
-#define OUT_LONG_P OUT_LONG
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc64/posix_types.h b/include/asm-sparc64/posix_types.h
index b39c8781fb..5bcd2a1b6e 100644
--- a/include/asm-sparc64/posix_types.h
+++ b/include/asm-sparc64/posix_types.h
@@ -26,6 +26,8 @@ typedef long __kernel_off_t;
typedef char * __kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_timer_t;
typedef __kernel_uid_t __kernel_old_uid_t;
typedef __kernel_gid_t __kernel_old_gid_t;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e364ce6c00..8c6c375d56 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1102,7 +1102,7 @@ static inline int skb_cow(struct sk_buff *skb, unsigned int headroom)
static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
{
- unsigned int size = skb->len + skb->data_len;
+ unsigned int size = skb->len;
if (likely(size >= len))
return skb;
return skb_pad(skb, len-size);
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 5ad620b362..97b75f6a56 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -122,7 +122,7 @@ static inline void dn_nsp_send(struct sk_buff *skb)
if ((dst = sk->dst_cache) && !dst->obsolete) {
try_again:
skb->dst = dst_clone(dst);
- dst->output(skb);
+ dst_output(skb);
return;
}
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index d77ba3c65f..ead417ca70 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -593,7 +593,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
* associations.
*/
skb->dst = dst_clone(dst);
- skb->dst->output(skb);
+ dst_output(skb);
}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index d8520fd9f0..21c6f5934e 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -389,7 +389,7 @@ static int dn_route_rx_packet(struct sk_buff *skb)
int err;
if ((err = dn_route_input(skb)) == 0)
- return skb->dst->input(skb);
+ return dst_input(skb);
if (decnet_debug_level & 4) {
char *devname = skb->dev ? skb->dev->name : "???";
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index ba52c37b39..dbf2ac519e 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -184,14 +184,6 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
#define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
-/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook
- changes route */
-static inline int
-output_maybe_reroute(struct sk_buff *skb)
-{
- return skb->dst->output(skb);
-}
-
static int igmp_send_report(struct net_device *dev, u32 group, int type)
{
struct sk_buff *skb;
@@ -255,7 +247,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
- output_maybe_reroute);
+ dst_output);
}
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 1a0d3cf287..4799d1e074 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -19,6 +19,7 @@
* Bill Hawes : Frag accounting and evictor fixes.
* John McDonald : 0 length frag bug.
* Alexey Kuznetsov: SMP races, threading, cleanup.
+ * Patrick McHardy : LRU queue of frag heads for evictor.
*/
#include <linux/config.h>
@@ -26,6 +27,7 @@
#include <linux/mm.h>
#include <linux/jiffies.h>
#include <linux/skbuff.h>
+#include <linux/list.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <linux/netdevice.h>
@@ -67,6 +69,7 @@ struct ipfrag_skb_cb
/* Describe an entry in the "incomplete datagrams" queue. */
struct ipq {
struct ipq *next; /* linked list pointers */
+ struct list_head lru_list; /* lru list member */
u32 saddr;
u32 daddr;
u16 id;
@@ -94,6 +97,7 @@ struct ipq {
/* Per-bucket lock is easy to add now. */
static struct ipq *ipq_hash[IPQ_HASHSZ];
static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(ipq_lru_list);
int ip_frag_nqueues = 0;
static __inline__ void __ipq_unlink(struct ipq *qp)
@@ -101,6 +105,7 @@ static __inline__ void __ipq_unlink(struct ipq *qp)
if(qp->next)
qp->next->pprev = qp->pprev;
*qp->pprev = qp->next;
+ list_del(&qp->lru_list);
ip_frag_nqueues--;
}
@@ -202,39 +207,30 @@ static void ipq_kill(struct ipq *ipq)
*/
static void ip_evictor(void)
{
- int i, progress;
+ struct ipq *qp;
+ struct list_head *tmp;
- do {
+ for(;;) {
if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
return;
- progress = 0;
- /* FIXME: Make LRU queue of frag heads. -DaveM */
- for (i = 0; i < IPQ_HASHSZ; i++) {
- struct ipq *qp;
- if (ipq_hash[i] == NULL)
- continue;
-
- read_lock(&ipfrag_lock);
- if ((qp = ipq_hash[i]) != NULL) {
- /* find the oldest queue for this hash bucket */
- while (qp->next)
- qp = qp->next;
- atomic_inc(&qp->refcnt);
- read_unlock(&ipfrag_lock);
-
- spin_lock(&qp->lock);
- if (!(qp->last_in&COMPLETE))
- ipq_kill(qp);
- spin_unlock(&qp->lock);
-
- ipq_put(qp);
- IP_INC_STATS_BH(IpReasmFails);
- progress = 1;
- continue;
- }
+ read_lock(&ipfrag_lock);
+ if (list_empty(&ipq_lru_list)) {
read_unlock(&ipfrag_lock);
+ return;
}
- } while (progress);
+ tmp = ipq_lru_list.next;
+ qp = list_entry(tmp, struct ipq, lru_list);
+ atomic_inc(&qp->refcnt);
+ read_unlock(&ipfrag_lock);
+
+ spin_lock(&qp->lock);
+ if (!(qp->last_in&COMPLETE))
+ ipq_kill(qp);
+ spin_unlock(&qp->lock);
+
+ ipq_put(qp);
+ IP_INC_STATS_BH(IpReasmFails);
+ }
}
/*
@@ -302,6 +298,8 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
qp->next->pprev = &qp->next;
ipq_hash[hash] = qp;
qp->pprev = &ipq_hash[hash];
+ INIT_LIST_HEAD(&qp->lru_list);
+ list_add_tail(&qp->lru_list, &ipq_lru_list);
ip_frag_nqueues++;
write_unlock(&ipfrag_lock);
return qp;
@@ -496,6 +494,10 @@ static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
if (offset == 0)
qp->last_in |= FIRST_IN;
+ write_lock(&ipfrag_lock);
+ list_move_tail(&qp->lru_list, &ipq_lru_list);
+ write_unlock(&ipfrag_lock);
+
return;
err:
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 092f0a2e52..d1079ca007 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -344,7 +344,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
}
}
- return skb->dst->input(skb);
+ return dst_input(skb);
inhdr_error:
IP_INC_STATS_BH(IpInHdrErrors);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index ac2b00d8b4..174697063d 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1112,9 +1112,9 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
struct dst_entry *dst = skb->dst;
if (skb->len <= dst_pmtu(dst))
- return dst->output(skb);
+ return dst_output(skb);
else
- return ip_fragment(skb, dst->output);
+ return ip_fragment(skb, dst_output);
}
/*
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 74422ccb7b..c4fe2f58d6 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2409,149 +2409,149 @@ static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name,
ctl_table ipv4_route_table[] = {
{
- .ctl_name = NET_IPV4_ROUTE_FLUSH,
- .procname = "flush",
- .data = &flush_delay,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&ipv4_sysctl_rtcache_flush,
- .strategy = &ipv4_sysctl_rtcache_flush_strategy,
+ .ctl_name = NET_IPV4_ROUTE_FLUSH,
+ .procname = "flush",
+ .data = &flush_delay,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &ipv4_sysctl_rtcache_flush,
+ .strategy = &ipv4_sysctl_rtcache_flush_strategy,
},
{
- .ctl_name = NET_IPV4_ROUTE_MIN_DELAY,
- .procname = "min_delay",
- .data = &ip_rt_min_delay,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_MIN_DELAY,
+ .procname = "min_delay",
+ .data = &ip_rt_min_delay,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_MAX_DELAY,
- .procname = "max_delay",
- .data = &ip_rt_max_delay,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_MAX_DELAY,
+ .procname = "max_delay",
+ .data = &ip_rt_max_delay,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
- .procname = "gc_thresh",
- .data = &ipv4_dst_ops.gc_thresh,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_GC_THRESH,
+ .procname = "gc_thresh",
+ .data = &ipv4_dst_ops.gc_thresh,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_MAX_SIZE,
- .procname = "max_size",
- .data = &ip_rt_max_size,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_MAX_SIZE,
+ .procname = "max_size",
+ .data = &ip_rt_max_size,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL,
- .procname = "gc_min_interval",
- .data = &ip_rt_gc_min_interval,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_GC_MIN_INTERVAL,
+ .procname = "gc_min_interval",
+ .data = &ip_rt_gc_min_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
- .procname = "gc_timeout",
- .data = &ip_rt_gc_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_GC_TIMEOUT,
+ .procname = "gc_timeout",
+ .data = &ip_rt_gc_timeout,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_GC_INTERVAL,
- .procname = "gc_interval",
- .data = &ip_rt_gc_interval,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_GC_INTERVAL,
+ .procname = "gc_interval",
+ .data = &ip_rt_gc_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_REDIRECT_LOAD,
- .procname = "redirect_load",
- .data = &ip_rt_redirect_load,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_REDIRECT_LOAD,
+ .procname = "redirect_load",
+ .data = &ip_rt_redirect_load,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_REDIRECT_NUMBER,
- .procname = "redirect_number",
- .data = &ip_rt_redirect_number,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_REDIRECT_NUMBER,
+ .procname = "redirect_number",
+ .data = &ip_rt_redirect_number,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_REDIRECT_SILENCE,
- .procname = "redirect_silence",
- .data = &ip_rt_redirect_silence,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_REDIRECT_SILENCE,
+ .procname = "redirect_silence",
+ .data = &ip_rt_redirect_silence,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_ERROR_COST,
- .procname = "error_cost",
- .data = &ip_rt_error_cost,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_ERROR_COST,
+ .procname = "error_cost",
+ .data = &ip_rt_error_cost,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_ERROR_BURST,
- .procname = "error_burst",
- .data = &ip_rt_error_burst,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_ERROR_BURST,
+ .procname = "error_burst",
+ .data = &ip_rt_error_burst,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_GC_ELASTICITY,
- .procname = "gc_elasticity",
- .data = &ip_rt_gc_elasticity,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_GC_ELASTICITY,
+ .procname = "gc_elasticity",
+ .data = &ip_rt_gc_elasticity,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_MTU_EXPIRES,
- .procname = "mtu_expires",
- .data = &ip_rt_mtu_expires,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec_jiffies,
- .strategy = &sysctl_jiffies,
+ .ctl_name = NET_IPV4_ROUTE_MTU_EXPIRES,
+ .procname = "mtu_expires",
+ .data = &ip_rt_mtu_expires,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
},
{
- .ctl_name = NET_IPV4_ROUTE_MIN_PMTU,
- .procname = "min_pmtu",
- .data = &ip_rt_min_pmtu,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_MIN_PMTU,
+ .procname = "min_pmtu",
+ .data = &ip_rt_min_pmtu,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_IPV4_ROUTE_MIN_ADVMSS,
- .procname = "min_adv_mss",
- .data = &ip_rt_min_advmss,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler =&proc_dointvec,
+ .ctl_name = NET_IPV4_ROUTE_MIN_ADVMSS,
+ .procname = "min_adv_mss",
+ .data = &ip_rt_min_advmss,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
},
- { 0 }
+ { .ctl_name = 0 }
};
#endif
diff --git a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
index 9d015cbbab..02d7ce7797 100644
--- a/net/ipv4/xfrm_policy.c
+++ b/net/ipv4/xfrm_policy.c
@@ -1,3 +1,4 @@
+#include <linux/config.h>
#include <net/xfrm.h>
#include <net/ip.h>
@@ -198,6 +199,49 @@ struct xfrm_type *xfrm_get_type(u8 proto)
return type;
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static struct xfrm_type *xfrm6_type_map[256];
+static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
+
+int xfrm6_register_type(struct xfrm_type *type)
+{
+ int err = 0;
+
+ write_lock(&xfrm6_type_lock);
+ if (xfrm6_type_map[type->proto] == NULL)
+ xfrm6_type_map[type->proto] = type;
+ else
+ err = -EEXIST;
+ write_unlock(&xfrm6_type_lock);
+ return err;
+}
+
+int xfrm6_unregister_type(struct xfrm_type *type)
+{
+ int err = 0;
+
+ write_lock(&xfrm6_type_lock);
+ if (xfrm6_type_map[type->proto] != type)
+ err = -ENOENT;
+ else
+ xfrm6_type_map[type->proto] = NULL;
+ write_unlock(&xfrm6_type_lock);
+ return err;
+}
+
+struct xfrm_type *xfrm6_get_type(u8 proto)
+{
+ struct xfrm_type *type;
+
+ read_lock(&xfrm6_type_lock);
+ type = xfrm6_type_map[proto];
+ if (type && !try_module_get(type->owner))
+ type = NULL;
+ read_unlock(&xfrm6_type_lock);
+ return type;
+}
+#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
+
void xfrm_put_type(struct xfrm_type *type)
{
module_put(type->owner);
diff --git a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c
index 05738783a1..736060f9ff 100644
--- a/net/ipv4/xfrm_user.c
+++ b/net/ipv4/xfrm_user.c
@@ -1,6 +1,13 @@
/* xfrm_user.c: User interface to configure xfrm engine.
*
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
+ *
+ * Changes
+ *
+ * Mitsuru KANDA @USAGI : IPv6 Support
+ * Kazunori MIYAZAWA @USAGI :
+ * Kunihiro Ishiguro :
+ *
*/
#include <linux/module.h>
@@ -17,6 +24,9 @@
#include <linux/ipsec.h>
#include <linux/init.h>
#include <linux/security.h>
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#include <linux/in6.h>
+#endif
#include <net/sock.h>
#include <net/xfrm.h>
@@ -63,10 +73,14 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
case AF_INET:
break;
- case AF_INET6: /* XXX */
+ case AF_INET6:
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ break;
+#else
err = -EAFNOSUPPORT;
+ goto out;
+#endif
- /* fallthru */
default:
goto out;
};
@@ -171,7 +185,19 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
goto error;
err = -ENOENT;
- x->type = xfrm_get_type(x->id.proto);
+ switch (x->props.family) {
+ case AF_INET:
+ x->type = xfrm_get_type(x->id.proto);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ x->type = xfrm6_get_type(x->id.proto);
+ break;
+#endif
+ default:
+ x->type = NULL;
+ break;
+ }
if (x->type == NULL)
goto error;
@@ -206,8 +232,21 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (!x)
return err;
- x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
- x->id.spi, x->id.proto);
+ switch (x->props.family) {
+ case AF_INET:
+ x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr,
+ x->id.spi, x->id.proto);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ x1 = xfrm6_state_lookup((struct in6_addr*)x->props.saddr.a6,
+ x->id.spi, x->id.proto);
+ break;
+#endif
+ default:
+ x1 = NULL;
+ break;
+ }
if (x1) {
xfrm_state_put(x);
xfrm_state_put(x1);
@@ -224,7 +263,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
struct xfrm_state *x;
struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
- x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+ switch (p->family) {
+ case AF_INET:
+ x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
+ break;
+#endif
+ default:
+ x = NULL;
+ break;
+ }
if (x == NULL)
return -ESRCH;
@@ -342,7 +393,19 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
struct sk_buff *resp_skb;
int err;
- x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+ switch (p->family) {
+ case AF_INET:
+ x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ x = xfrm6_state_lookup((struct in6_addr*)p->saddr.a6, p->spi, p->proto);
+ break;
+#endif
+ default:
+ x = NULL;
+ break;
+ }
err = -ESRCH;
if (x == NULL)
goto out_noput;
@@ -393,9 +456,23 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, void **
err = verify_userspi_info(p);
if (err)
goto out_noput;
- x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
- p->info.sel.daddr.xfrm4_addr,
- p->info.sel.saddr.xfrm4_addr, 1);
+ switch (p->info.family) {
+ case AF_INET:
+ x = xfrm_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
+ p->info.sel.daddr.xfrm4_addr,
+ p->info.sel.saddr.xfrm4_addr, 1);
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ x = xfrm6_find_acq(p->info.mode, p->info.reqid, p->info.id.proto,
+ (struct in6_addr*)p->info.sel.daddr.a6,
+ (struct in6_addr*)p->info.sel.saddr.a6, 1);
+ break;
+#endif
+ default:
+ x = NULL;
+ break;
+ }
err = -ENOENT;
if (x == NULL)
goto out_noput;
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 373dbcef9d..db0614ef81 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -11,5 +11,3 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \
ip6_flowlabel.o ipv6_syms.o
obj-$(CONFIG_NETFILTER) += netfilter/
-
-obj-y += xfrm_policy.o
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2b20154fe0..79232f6901 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -288,7 +288,7 @@ looped_back:
dst_release(xchg(&skb->dst, NULL));
ip6_route_input(skb);
if (skb->dst->error) {
- skb->dst->input(skb);
+ dst_input(skb);
return -1;
}
if (skb->dst->dev->flags&IFF_LOOPBACK) {
@@ -302,7 +302,7 @@ looped_back:
goto looped_back;
}
- skb->dst->input(skb);
+ dst_input(skb);
return -1;
}
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 1c4d561033..84ca549a74 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -47,7 +47,7 @@ static inline int ip6_rcv_finish( struct sk_buff *skb)
if (skb->dst == NULL)
ip6_route_input(skb);
- return skb->dst->input(skb);
+ return dst_input(skb);
}
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
@@ -235,7 +235,7 @@ int ip6_mc_input(struct sk_buff *skb)
skb2 = skb;
}
- dst->output(skb2);
+ dst_output(skb2);
}
}
#endif
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 162c3487d2..8cb79dd31f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -174,7 +174,7 @@ static inline int ip6_maybe_reroute(struct sk_buff *skb)
}
}
#endif /* CONFIG_NETFILTER */
- return skb->dst->output(skb);
+ return dst_output(skb);
}
/*
@@ -722,7 +722,7 @@ int ip6_call_ra_chain(struct sk_buff *skb, int sel)
static inline int ip6_forward_finish(struct sk_buff *skb)
{
- return skb->dst->output(skb);
+ return dst_output(skb);
}
int ip6_forward(struct sk_buff *skb)
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 9e2af9ed54..ddb235fa1e 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -4,7 +4,6 @@
#include <net/ipv6.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
-#include <net/xfrm.h>
EXPORT_SYMBOL(ipv6_addr_type);
EXPORT_SYMBOL(icmpv6_send);
@@ -26,6 +25,3 @@ EXPORT_SYMBOL(inet6_getname);
EXPORT_SYMBOL(inet6_ioctl);
EXPORT_SYMBOL(ipv6_get_saddr);
EXPORT_SYMBOL(ipv6_chk_addr);
-EXPORT_SYMBOL(xfrm6_register_type);
-EXPORT_SYMBOL(xfrm6_unregister_type);
-EXPORT_SYMBOL(xfrm6_get_type);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index bb66e1789b..33e5193bf9 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -22,6 +22,7 @@
*
* Horst von Brand Add missing #include <linux/string.h>
* Alexey Kuznetsov SMP races, threading, cleanup.
+ * Patrick McHardy LRU queue of frag heads for evictor.
*/
#include <linux/config.h>
#include <linux/errno.h>
@@ -31,6 +32,7 @@
#include <linux/sockios.h>
#include <linux/jiffies.h>
#include <linux/net.h>
+#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/in6.h>
#include <linux/ipv6.h>
@@ -67,6 +69,7 @@ struct ip6frag_skb_cb
struct frag_queue
{
struct frag_queue *next;
+ struct list_head lru_list; /* lru list member */
__u32 id; /* fragment id */
struct in6_addr saddr;
@@ -95,6 +98,7 @@ struct frag_queue
static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
+static LIST_HEAD(ip6_frag_lru_list);
int ip6_frag_nqueues = 0;
static __inline__ void __fq_unlink(struct frag_queue *fq)
@@ -102,6 +106,7 @@ static __inline__ void __fq_unlink(struct frag_queue *fq)
if(fq->next)
fq->next->pprev = fq->pprev;
*fq->pprev = fq->next;
+ list_del(&fq->lru_list);
ip6_frag_nqueues--;
}
@@ -193,38 +198,30 @@ static __inline__ void fq_kill(struct frag_queue *fq)
static void ip6_evictor(void)
{
- int i, progress;
+ struct frag_queue *fq;
+ struct list_head *tmp;
- do {
+ for(;;) {
if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
return;
- progress = 0;
- for (i = 0; i < IP6Q_HASHSZ; i++) {
- struct frag_queue *fq;
- if (ip6_frag_hash[i] == NULL)
- continue;
-
- read_lock(&ip6_frag_lock);
- if ((fq = ip6_frag_hash[i]) != NULL) {
- /* find the oldest queue for this hash bucket */
- while (fq->next)
- fq = fq->next;
- atomic_inc(&fq->refcnt);
- read_unlock(&ip6_frag_lock);
-
- spin_lock(&fq->lock);
- if (!(fq->last_in&COMPLETE))
- fq_kill(fq);
- spin_unlock(&fq->lock);
-
- fq_put(fq);
- IP6_INC_STATS_BH(Ip6ReasmFails);
- progress = 1;
- continue;
- }
+ read_lock(&ip6_frag_lock);
+ if (list_empty(&ip6_frag_lru_list)) {
read_unlock(&ip6_frag_lock);
+ return;
}
- } while (progress);
+ tmp = ip6_frag_lru_list.next;
+ fq = list_entry(tmp, struct frag_queue, lru_list);
+ atomic_inc(&fq->refcnt);
+ read_unlock(&ip6_frag_lock);
+
+ spin_lock(&fq->lock);
+ if (!(fq->last_in&COMPLETE))
+ fq_kill(fq);
+ spin_unlock(&fq->lock);
+
+ fq_put(fq);
+ IP6_INC_STATS_BH(Ip6ReasmFails);
+ }
}
static void ip6_frag_expire(unsigned long data)
@@ -294,6 +291,8 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash,
fq->next->pprev = &fq->next;
ip6_frag_hash[hash] = fq;
fq->pprev = &ip6_frag_hash[hash];
+ INIT_LIST_HEAD(&fq->lru_list);
+ list_add_tail(&fq->lru_list, &ip6_frag_lru_list);
ip6_frag_nqueues++;
write_unlock(&ip6_frag_lock);
return fq;
@@ -501,6 +500,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
fq->nhoffset = nhoff;
fq->last_in |= FIRST_IN;
}
+ write_lock(&ip6_frag_lock);
+ list_move_tail(&fq->lru_list, &ip6_frag_lru_list);
+ write_unlock(&ip6_frag_lock);
return;
err:
diff --git a/net/ipv6/xfrm_policy.c b/net/ipv6/xfrm_policy.c
deleted file mode 100644
index 208f6aac59..0000000000
--- a/net/ipv6/xfrm_policy.c
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <net/xfrm.h>
-#include <net/ip.h>
-
-static struct xfrm_type *xfrm6_type_map[256];
-static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED;
-
-int xfrm6_register_type(struct xfrm_type *type)
-{
- int err = 0;
-
- write_lock(&xfrm6_type_lock);
- if (xfrm6_type_map[type->proto] == NULL)
- xfrm6_type_map[type->proto] = type;
- else
- err = -EEXIST;
- write_unlock(&xfrm6_type_lock);
- return err;
-}
-
-int xfrm6_unregister_type(struct xfrm_type *type)
-{
- int err = 0;
-
- write_lock(&xfrm6_type_lock);
- if (xfrm6_type_map[type->proto] != type)
- err = -ENOENT;
- else
- xfrm6_type_map[type->proto] = NULL;
- write_unlock(&xfrm6_type_lock);
- return err;
-}
-
-struct xfrm_type *xfrm6_get_type(u8 proto)
-{
- struct xfrm_type *type;
-
- read_lock(&xfrm6_type_lock);
- type = xfrm6_type_map[proto];
- if (type && !try_module_get(type->owner))
- type = NULL;
- read_unlock(&xfrm6_type_lock);
- return type;
-}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index cb33ca931c..f0b2bd607d 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -10,6 +10,7 @@
* David S. Miller <davem@redhat.com>
* Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
* Kunihiro Ishiguro <kunihiro@ipinfusion.com>
+ * Kazunori MIYAZAWA / USAGI Project <miyazawa@linux-ipv6.org>
*/
#include <linux/config.h>
diff --git a/net/netsyms.c b/net/netsyms.c
index e9e6408db4..76c32e9baf 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -328,6 +328,9 @@ EXPORT_SYMBOL(xfrm_policy_list);
EXPORT_SYMBOL(xfrm6_state_lookup);
EXPORT_SYMBOL(xfrm6_find_acq);
EXPORT_SYMBOL(xfrm6_alloc_spi);
+EXPORT_SYMBOL(xfrm6_register_type);
+EXPORT_SYMBOL(xfrm6_unregister_type);
+EXPORT_SYMBOL(xfrm6_get_type);
#endif
EXPORT_SYMBOL_GPL(xfrm_probe_algs);
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 5224b539cc..1aeca5f4fc 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/pci.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>