diff options
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> |
