From a0d3bea3cf6c7c1b53a46432bd490b5dc784ca42 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 11 Aug 2005 16:05:50 -0700 Subject: [PATCH 01/22] [NET]: Make skb->protocol __be16 There are many instances of skb->protocol = htons(ETH_P_*); skb->protocol = __constant_htons(ETH_P_*); and skb->protocol = *_type_trans(...); Most of *_type_trans() are already endian-annotated, so, let's shift attention on other warnings. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0061c9470482..948527e42a60 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -255,7 +255,7 @@ struct sk_buff { nohdr:1; /* 3 bits spare */ __u8 pkt_type; - __u16 protocol; + __be16 protocol; void (*destructor)(struct sk_buff *skb); #ifdef CONFIG_NETFILTER From 11513128bb66b0b09d5d0df069b58afdb01752a2 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 11 Aug 2005 19:23:04 -0700 Subject: [PATCH 02/22] [NETPOLL]: rx_flags bugfix Initialize npinfo->rx_flags. The way it stands now, this will have random garbage, and so will incur a locking penalty even when an rx_hook isn't registered and we are not active in the netpoll polling code. Signed-off-by: Jeff Moyer Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c327c9edadc5..895f3efc65aa 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -639,6 +639,7 @@ int netpoll_setup(struct netpoll *np) if (!npinfo) goto release; + npinfo->rx_flags = 0; npinfo->rx_np = NULL; npinfo->poll_lock = SPIN_LOCK_UNLOCKED; npinfo->poll_owner = -1; From a636e1357911afdea7c8344ee65f78d36caf3c16 Mon Sep 17 00:00:00 2001 From: Jeff Moyer Date: Thu, 11 Aug 2005 19:23:50 -0700 Subject: [PATCH 03/22] [NETPOLL]: deadlock bugfix This fixes an obvious deadlock in the netpoll code. netpoll_rx takes the npinfo->rx_lock. netpoll_rx is also the only caller of arp_reply (through __netpoll_rx). As such, it is not necessary to take this lock. Signed-off-by: Jeff Moyer Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 895f3efc65aa..b9d9da082af2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -353,11 +353,8 @@ static void arp_reply(struct sk_buff *skb) struct sk_buff *send_skb; struct netpoll *np = NULL; - spin_lock_irqsave(&npinfo->rx_lock, flags); if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) np = npinfo->rx_np; - spin_unlock_irqrestore(&npinfo->rx_lock, flags); - if (!np) return; From 6b0b31572985c2e64f7216c798766302fb782281 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:24:33 -0700 Subject: [PATCH 04/22] [NETPOLL]: e1000 netpoll tweak Suggested by Steven Rostedt, matches his patch included in e100. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5e5d2c3c7ce4..b82fd15d0891 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3789,6 +3789,7 @@ e1000_netpoll(struct net_device *netdev) struct e1000_adapter *adapter = netdev_priv(netdev); disable_irq(adapter->pdev->irq); e1000_intr(adapter->pdev->irq, netdev, NULL); + e1000_clean_tx_irq(adapter); enable_irq(adapter->pdev->irq); } #endif From f0d3459d0722782c7d9d0e35a1ed0815e75fcde5 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:25:11 -0700 Subject: [PATCH 05/22] [NETPOLL]: netpoll_send_skb simplify Minor netpoll_send_skb restructuring Restructure to avoid confusing goto and move some bits out of the retry loop. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b9d9da082af2..59ed186e4f46 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -248,14 +248,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) int status; struct netpoll_info *npinfo; -repeat: - if(!np || !np->dev || !netif_running(np->dev)) { + if (!np || !np->dev || !netif_running(np->dev)) { __kfree_skb(skb); return; } - /* avoid recursion */ npinfo = np->dev->npinfo; + + /* avoid recursion */ if (npinfo->poll_owner == smp_processor_id() || np->dev->xmit_lock_owner == smp_processor_id()) { if (np->drop) @@ -265,29 +265,31 @@ repeat: return; } - spin_lock(&np->dev->xmit_lock); - np->dev->xmit_lock_owner = smp_processor_id(); + while (1) { + spin_lock(&np->dev->xmit_lock); + np->dev->xmit_lock_owner = smp_processor_id(); - /* - * network drivers do not expect to be called if the queue is - * stopped. - */ - if (netif_queue_stopped(np->dev)) { + /* + * network drivers do not expect to be called if the queue is + * stopped. + */ + if (netif_queue_stopped(np->dev)) { + np->dev->xmit_lock_owner = -1; + spin_unlock(&np->dev->xmit_lock); + netpoll_poll(np); + continue; + } + + status = np->dev->hard_start_xmit(skb, np->dev); np->dev->xmit_lock_owner = -1; spin_unlock(&np->dev->xmit_lock); - netpoll_poll(np); - goto repeat; - } + /* success */ + if(!status) + return; - status = np->dev->hard_start_xmit(skb, np->dev); - np->dev->xmit_lock_owner = -1; - spin_unlock(&np->dev->xmit_lock); - - /* transmit busy */ - if(status) { + /* transmit busy */ netpoll_poll(np); - goto repeat; } } From 0db1d6fc1ea051af49ebe03c503d23996a7c5bbb Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:25:54 -0700 Subject: [PATCH 06/22] [NETPOLL]: add retry timeout Add limited retry logic to netpoll_send_skb Each time we attempt to send, decrement our per-device retry counter. On every successful send, we reset the counter. We delay 50us between attempts with up to 20000 retries for a total of 1 second. After we've exhausted our retries, subsequent failed attempts will try only once until reset by success. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- include/linux/netpoll.h | 1 + net/core/netpoll.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index bcd0ac33f592..be68d94b03d5 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -26,6 +26,7 @@ struct netpoll { struct netpoll_info { spinlock_t poll_lock; int poll_owner; + int tries; int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 59ed186e4f46..d09affdbad3c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -33,6 +33,7 @@ #define MAX_UDP_CHUNK 1460 #define MAX_SKBS 32 #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) +#define MAX_RETRIES 20000 static DEFINE_SPINLOCK(skb_list_lock); static int nr_skbs; @@ -265,7 +266,8 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) return; } - while (1) { + do { + npinfo->tries--; spin_lock(&np->dev->xmit_lock); np->dev->xmit_lock_owner = smp_processor_id(); @@ -277,6 +279,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) np->dev->xmit_lock_owner = -1; spin_unlock(&np->dev->xmit_lock); netpoll_poll(np); + udelay(50); continue; } @@ -285,12 +288,15 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) spin_unlock(&np->dev->xmit_lock); /* success */ - if(!status) + if(!status) { + npinfo->tries = MAX_RETRIES; /* reset */ return; + } /* transmit busy */ netpoll_poll(np); - } + udelay(50); + } while (npinfo->tries > 0); } void netpoll_send_udp(struct netpoll *np, const char *msg, int len) @@ -642,6 +648,7 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = NULL; npinfo->poll_lock = SPIN_LOCK_UNLOCKED; npinfo->poll_owner = -1; + npinfo->tries = MAX_RETRIES; npinfo->rx_lock = SPIN_LOCK_UNLOCKED; } else npinfo = ndev->npinfo; From 2652076507b662fc88ba16c27b59c7bdd9ccd956 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 11 Aug 2005 19:26:42 -0700 Subject: [PATCH 07/22] [NETPOLL]: pre-fill skb pool we could do one thing (see the patch below): i think it would be useful to fill up the netlogging skb queue straight at initialization time. Especially if netpoll is used for dumping alone, the system might not be in a situation to fill up the queue at the point of crash, so better be a bit more prepared and keep the pipeline filled. [ I've modified this to be called earlier - mpm ] Signed-off-by: Ingo Molnar Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index d09affdbad3c..c02a08da6d42 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -725,6 +725,10 @@ int netpoll_setup(struct netpoll *np) npinfo->rx_np = np; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } + + /* fill up the skb queue */ + refill_skbs(); + /* last thing to do is link it to the net device structure */ ndev->npinfo = npinfo; From 53fb95d3c14290fd6ee808b221e35493f096246f Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:27:43 -0700 Subject: [PATCH 08/22] [NETPOLL]: fix initialization/NAPI race This fixes a race during initialization with the NAPI softirq processing by using an RCU approach. This race was discovered when refill_skbs() was added to the setup code. Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- include/linux/netpoll.h | 19 +++++++++++++------ net/core/dev.c | 9 +++++---- net/core/netpoll.c | 3 +++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index be68d94b03d5..5ade54a78dbb 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -9,6 +9,7 @@ #include #include +#include #include struct netpoll; @@ -61,25 +62,31 @@ static inline int netpoll_rx(struct sk_buff *skb) return ret; } -static inline void netpoll_poll_lock(struct net_device *dev) +static inline void *netpoll_poll_lock(struct net_device *dev) { + rcu_read_lock(); /* deal with race on ->npinfo */ if (dev->npinfo) { spin_lock(&dev->npinfo->poll_lock); dev->npinfo->poll_owner = smp_processor_id(); + return dev->npinfo; } + return NULL; } -static inline void netpoll_poll_unlock(struct net_device *dev) +static inline void netpoll_poll_unlock(void *have) { - if (dev->npinfo) { - dev->npinfo->poll_owner = -1; - spin_unlock(&dev->npinfo->poll_lock); + struct netpoll_info *npi = have; + + if (npi) { + npi->poll_owner = -1; + spin_unlock(&npi->poll_lock); } + rcu_read_unlock(); } #else #define netpoll_rx(a) 0 -#define netpoll_poll_lock(a) +#define netpoll_poll_lock(a) 0 #define netpoll_poll_unlock(a) #endif diff --git a/net/core/dev.c b/net/core/dev.c index 52a3bf7ae177..faf59b02c4bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1696,7 +1696,8 @@ static void net_rx_action(struct softirq_action *h) struct softnet_data *queue = &__get_cpu_var(softnet_data); unsigned long start_time = jiffies; int budget = netdev_budget; - + void *have; + local_irq_disable(); while (!list_empty(&queue->poll_list)) { @@ -1709,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h) dev = list_entry(queue->poll_list.next, struct net_device, poll_list); - netpoll_poll_lock(dev); + have = netpoll_poll_lock(dev); if (dev->quota <= 0 || dev->poll(dev, &budget)) { - netpoll_poll_unlock(dev); + netpoll_poll_unlock(have); local_irq_disable(); list_del(&dev->poll_list); list_add_tail(&dev->poll_list, &queue->poll_list); @@ -1721,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h) else dev->quota = dev->weight; } else { - netpoll_poll_unlock(dev); + netpoll_poll_unlock(have); dev_put(dev); local_irq_disable(); } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c02a08da6d42..996787bca17f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -732,6 +732,9 @@ int netpoll_setup(struct netpoll *np) /* last thing to do is link it to the net device structure */ ndev->npinfo = npinfo; + /* avoid racing with NAPI reading npinfo */ + synchronize_rcu(); + return 0; release: From d7b9dfc8ea43936e6e8eec3040dcf4f110563868 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Thu, 11 Aug 2005 19:28:05 -0700 Subject: [PATCH 09/22] [NETPOLL]: remove unused variable Remove unused variable Signed-off-by: Matt Mackall Signed-off-by: David S. Miller --- net/core/netpoll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 996787bca17f..a1a9a7abff50 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -357,7 +357,6 @@ static void arp_reply(struct sk_buff *skb) unsigned char *arp_ptr; int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; u32 sip, tip; - unsigned long flags; struct sk_buff *send_skb; struct netpoll *np = NULL; From 349188f66da2fd88f8cb2407763051d8e136c9aa Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 11 Aug 2005 22:26:25 -0600 Subject: [PATCH 10/22] [PATCH] x86_64: Fix apicid versus cpu# confusion. Oops. I knew I didn't have the physical versus logical cpu identifiers right when I generated that patch. It's not nearly as bad as I feared at the time though. Signed-off-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 6e4807d64d46..b15761ff4101 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c @@ -334,7 +334,7 @@ static void __cpuinit tsc_sync_wait(void) { if (notscsync || !cpu_has_tsc) return; - sync_tsc(boot_cpu_id); + sync_tsc(0); } static __init int notscsync_setup(char *s) From 2da5bf80f754e28cc153362e5ed1edaa9740897a Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Fri, 12 Aug 2005 11:46:22 -0700 Subject: [PATCH 11/22] [PATCH] w1: more debug level decrease. Do not spam syslog each 10 seconds when there is nothing on the wire. Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- drivers/w1/w1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 8a9c42822502..0bbf029b1ef1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -593,7 +593,7 @@ void w1_search(struct w1_master *dev, w1_slave_found_callback cb) * Return 0 - device(s) present, 1 - no devices present. */ if (w1_reset_bus(dev)) { - dev_info(&dev->dev, "No devices present on the wire.\n"); + dev_dbg(&dev->dev, "No devices present on the wire.\n"); break; } From 4bb82551e165f887448f6f61055d7bcd90aefa2a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 13 Aug 2005 14:22:59 -0700 Subject: [PATCH 12/22] Fix up mmap of /dev/kmem This leaves the issue of whether we should deprecate the whole thing (or if we should check the whole mmap range, for that matter) open. Just do the minimal fix for now. --- drivers/char/mem.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 42187381506b..850a78c9c4bc 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -261,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) static int mmap_kmem(struct file * file, struct vm_area_struct * vma) { - unsigned long long val; + unsigned long pfn; + + /* Turn a kernel-virtual address into a physical page frame */ + pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; + /* * RED-PEN: on some architectures there is more mapped memory * than available in mem_map which pfn_valid checks @@ -269,10 +273,10 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) * * RED-PEN: vmalloc is not supported right now. */ - if (!pfn_valid(vma->vm_pgoff)) + if (!pfn_valid(pfn)) return -EIO; - val = (u64)vma->vm_pgoff << PAGE_SHIFT; - vma->vm_pgoff = __pa(val) >> PAGE_SHIFT; + + vma->vm_pgoff = pfn; return mmap_mem(file, vma); } From f73bc8cae3481adc4188a5f34a89025c10133b0a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 13 Aug 2005 20:28:06 +0300 Subject: [PATCH 13/22] [PATCH] sh: Make _syscall6() do the right thing. There was a rather silly and embarrassing typo in the sh _syscall6(). For the syscall ABI we have the trapa value specified as 0x10 + number of arguments, this was being set incorrectly in the _syscall6() case which ended up causing some problems for users. Signed-off-by: Paul Mundt Signed-off-by: Linus Torvalds --- include/asm-sh/unistd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h index 245447081f0d..4e7701d6d23c 100644 --- a/include/asm-sh/unistd.h +++ b/include/asm-sh/unistd.h @@ -406,7 +406,7 @@ register long __sc6 __asm__ ("r6") = (long) arg3; \ register long __sc7 __asm__ ("r7") = (long) arg4; \ register long __sc0 __asm__ ("r0") = (long) arg5; \ register long __sc1 __asm__ ("r1") = (long) arg6; \ -__asm__ __volatile__ ("trapa #0x15" \ +__asm__ __volatile__ ("trapa #0x16" \ : "=z" (__sc0) \ : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7), \ "r" (__sc3), "r" (__sc1) \ From 1b0a74d1c002320d5488333dd9c72126af1aab02 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sat, 13 Aug 2005 13:15:34 +0200 Subject: [PATCH 14/22] [PATCH] Fix error handling in reiserfs Initialize key object ID in inode so that we don't try to remove the inode when we fail on some checks even before we manage to allocate something. Signed-off-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/reiserfs/namei.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index a20bbc1642dc..3549067c42d9 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -593,6 +593,9 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) */ inode->i_uid = current->fsuid; inode->i_mode = mode; + /* Make inode invalid - just in case we are going to drop it before + * the initialization happens */ + INODE_PKEY(inode)->k_objectid = 0; if (dir->i_mode & S_ISGID) { inode->i_gid = dir->i_gid; From d024709deb4997aced6140a62e8ee82b10666c5f Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH 15/22] [PATCH] CIFS: Fix missing entries in search results Fix missing entries in search results when very long file names and more than 50 (or so) of such long search entries in the directory. FindNext could send corrupt last byte of resume name when resume key was a few hundred bytes long file name or longer. Fixes Samba Bug # 2932 Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifssmb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 3c628bf667a5..0db0b313d715 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2602,6 +2602,9 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, if(name_len < PATH_MAX) { memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len); byte_count += name_len; + /* 14 byte parm len above enough for 2 byte null terminator */ + pSMB->ResumeFileName[name_len] = 0; + pSMB->ResumeFileName[name_len+1] = 0; } else { rc = -EINVAL; goto FNext2_err_exit; From 27876d02b30aa34bb1ad35b81ccc40c174282f31 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sun, 14 Aug 2005 16:55:23 -0500 Subject: [PATCH 16/22] [PATCH] CIFS: Fix path name conversion for long filenames Fix path name conversion for long filenames when mapchars mount option was specified at mount time. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 6 ++++++ fs/cifs/misc.c | 1 + 2 files changed, 7 insertions(+) diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index dab4774ee7bb..3196d4c4eed3 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,9 @@ +Version 1.35 +------------ +Add writepage performance improvements. Fix path name conversions +for long filenames on mounts which were done with "mapchars" mount option +specified. + Version 1.34 ------------ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 072b4ee8c53e..20ae4153f791 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -611,6 +611,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, src_char = source[i]; switch (src_char) { case 0: + target[j] = 0; goto ctoUCS_out; case ':': target[j] = cpu_to_le16(UNI_COLON); From b4b08e581fac8e0ba9ae348bdc13246c9798c99e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Aug 2005 15:43:39 -0700 Subject: [PATCH 17/22] Revert "dc395x: Fix support for highmem" It introduces a repeatable oops in the driver, which is a bigger problem than the patch tries to solve. From the original description: Author: Jamie Lenehan Date: Thu Mar 3 14:41:40 2005 +0200 [PATCH] dc395x: Fix support for highmem From: Guennadi Liakhovetski Removes the page_to_virt and maps sg lists dynamically. This makes the driver work with highmem pages. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Jamie Lenehan Signed-off-by: James Bottomley Signed-off-by: Guennadi Liakhovetski Signed-off-by: Linus Torvalds --- drivers/scsi/dc395x.c | 48 ++++++++++++------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 929170dcd3cb..600ba1202864 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -183,7 +183,7 @@ * cross a page boundy. */ #define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY) -#define VIRTX_LEN (sizeof(void *) * DC395x_MAX_SG_LISTENTRY) + struct SGentry { u32 address; /* bus! address */ @@ -235,7 +235,6 @@ struct ScsiReqBlk { u8 sg_count; /* No of HW sg entries for this request */ u8 sg_index; /* Index of HW sg entry for this request */ u32 total_xfer_length; /* Total number of bytes remaining to be transfered */ - void **virt_map; unsigned char *virt_addr; /* Virtual address of current transfer position */ /* @@ -1022,14 +1021,14 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, reqlen, cmd->request_buffer, cmd->use_sg, srb->sg_count); + srb->virt_addr = page_address(sl->page); for (i = 0; i < srb->sg_count; i++) { - u32 seglen = (u32)sg_dma_len(sl + i); - sgp[i].address = (u32)sg_dma_address(sl + i); + u32 busaddr = (u32)sg_dma_address(&sl[i]); + u32 seglen = (u32)sl[i].length; + sgp[i].address = busaddr; sgp[i].length = seglen; srb->total_xfer_length += seglen; - srb->virt_map[i] = kmap(sl[i].page); } - srb->virt_addr = srb->virt_map[0]; sgp += srb->sg_count - 1; /* @@ -1976,7 +1975,6 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) int segment = cmd->use_sg; u32 xferred = srb->total_xfer_length - left; /* bytes transfered */ struct SGentry *psge = srb->segment_x + srb->sg_index; - void **virt = srb->virt_map; dprintkdbg(DBG_0, "sg_update_list: Transfered %i of %i bytes, %i remain\n", @@ -2016,16 +2014,16 @@ static void sg_update_list(struct ScsiReqBlk *srb, u32 left) /* We have to walk the scatterlist to find it */ sg = (struct scatterlist *)cmd->request_buffer; - idx = 0; while (segment--) { unsigned long mask = ~((unsigned long)sg->length - 1) & PAGE_MASK; if ((sg_dma_address(sg) & mask) == (psge->address & mask)) { - srb->virt_addr = virt[idx] + (psge->address & ~PAGE_MASK); + srb->virt_addr = (page_address(sg->page) + + psge->address - + (psge->address & PAGE_MASK)); return; } ++sg; - ++idx; } dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n"); @@ -2151,7 +2149,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, DC395x_read32(acb, TRM_S1040_DMA_CXCNT)); } /* - * calculate all the residue data that not yet transfered + * calculate all the residue data that not yet tranfered * SCSI transfer counter + left in SCSI FIFO data * * .....TRM_S1040_SCSI_COUNTER (24bits) @@ -3269,7 +3267,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) struct scsi_cmnd *cmd = srb->cmd; enum dma_data_direction dir = cmd->sc_data_direction; if (cmd->use_sg && dir != PCI_DMA_NONE) { - int i; /* unmap DC395x SG list */ dprintkdbg(DBG_SG, "pci_unmap_srb: list=%08x(%05x)\n", srb->sg_bus_addr, SEGMENTX_LEN); @@ -3279,8 +3276,6 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) dprintkdbg(DBG_SG, "pci_unmap_srb: segs=%i buffer=%p\n", cmd->use_sg, cmd->request_buffer); /* unmap the sg segments */ - for (i = 0; i < srb->sg_count; i++) - kunmap(virt_to_page(srb->virt_map[i])); pci_unmap_sg(acb->dev, (struct scatterlist *)cmd->request_buffer, cmd->use_sg, dir); @@ -3327,7 +3322,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (cmd->use_sg) { struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer; - ptr = (struct ScsiInqData *)(srb->virt_map[0] + sg->offset); + ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset); } else { ptr = (struct ScsiInqData *)(cmd->request_buffer); } @@ -4262,9 +4257,8 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN; for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) - kfree(acb->srb_array[i].segment_x); - - vfree(acb->srb_array[0].virt_map); + if (acb->srb_array[i].segment_x) + kfree(acb->srb_array[i].segment_x); } @@ -4280,12 +4274,9 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) int srb_idx = 0; unsigned i = 0; struct SGentry *ptr; - void **virt_array; - for (i = 0; i < DC395x_MAX_SRB_CNT; i++) { + for (i = 0; i < DC395x_MAX_SRB_CNT; i++) acb->srb_array[i].segment_x = NULL; - acb->srb_array[i].virt_map = NULL; - } dprintkdbg(DBG_1, "Allocate %i pages for SG tables\n", pages); while (pages--) { @@ -4306,19 +4297,6 @@ static int __devinit adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) ptr + (i * DC395x_MAX_SG_LISTENTRY); else dprintkl(KERN_DEBUG, "No space for tmsrb SG table reserved?!\n"); - - virt_array = vmalloc((DC395x_MAX_SRB_CNT + 1) * DC395x_MAX_SG_LISTENTRY * sizeof(void*)); - - if (!virt_array) { - adapter_sg_tables_free(acb); - return 1; - } - - for (i = 0; i < DC395x_MAX_SRB_CNT + 1; i++) { - acb->srb_array[i].virt_map = virt_array; - virt_array += DC395x_MAX_SG_LISTENTRY; - } - return 0; } From 2ba84684e8cf6f980e4e95a2300f53a505eb794e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Aug 2005 18:21:30 -0700 Subject: [PATCH 18/22] Revert PCIBIOS_MIN_IO changes for 2.6.13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commits 71db63acff69618b3d9d3114bd061938150e146b [PATCH] increase PCIBIOS_MIN_IO on x86 and 0b2bfb4e7ff61f286676867c3508569bea6fbf7a ACPI: increase PCIBIOS_MIN_IO on x86 since Lukas Sandströ reports that this breaks his on-board nvidia audio. We should re-visit this later. For now we revert the change Signed-off-by: Linus Torvalds --- drivers/acpi/motherboard.c | 2 +- include/asm-i386/pci.h | 4 +++- include/asm-x86_64/pci.h | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c index 2934475d67d6..61ea70742d49 100644 --- a/drivers/acpi/motherboard.c +++ b/drivers/acpi/motherboard.c @@ -43,7 +43,7 @@ ACPI_MODULE_NAME ("acpi_motherboard") */ #define IS_RESERVED_ADDR(base, len) \ (((len) > 0) && ((base) > 0) && ((base) + (len) < IO_SPACE_LIMIT) \ - && ((base) + (len) > 0x1000)) + && ((base) + (len) > PCIBIOS_MIN_IO)) /* * Clearing the flag (IORESOURCE_BUSY) allows drivers to use diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h index 2cbab30734d6..78c85985aee3 100644 --- a/include/asm-i386/pci.h +++ b/include/asm-i386/pci.h @@ -18,9 +18,11 @@ extern unsigned int pcibios_assign_all_busses(void); #define pcibios_scan_all_fns(a, b) 0 extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h index 9c4527eb55e2..eeb3088a1c9e 100644 --- a/include/asm-x86_64/pci.h +++ b/include/asm-x86_64/pci.h @@ -22,9 +22,11 @@ extern unsigned int pcibios_assign_all_busses(void); extern int no_iommu, force_iommu; extern unsigned long pci_mem_start; -#define PCIBIOS_MIN_IO 0x4000 +#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_MEM (pci_mem_start) +#define PCIBIOS_MIN_CARDBUS_IO 0x4000 + void pcibios_config_init(void); struct pci_bus * pcibios_scan_root(int bus); extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value); From 0bf955ce98cb3cf40e20d0cc435299eb76e8819e Mon Sep 17 00:00:00 2001 From: Robert Love Date: Mon, 15 Aug 2005 12:27:54 -0400 Subject: [PATCH 19/22] [PATCH] inotify: fix idr_get_new_above usage We are saving the wrong thing in ->last_wd. We want the wd, not the return value. Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/inotify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/inotify.c b/fs/inotify.c index 27ebcac5e07f..868901b1e779 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -402,7 +402,7 @@ static struct inotify_watch *create_watch(struct inotify_device *dev, return ERR_PTR(ret); } - dev->last_wd = ret; + dev->last_wd = watch->wd; watch->mask = mask; atomic_set(&watch->count, 0); INIT_LIST_HEAD(&watch->d_list); From 89204c40a03346cd951e698d854105db4cfedc28 Mon Sep 17 00:00:00 2001 From: John McCutchan Date: Mon, 15 Aug 2005 12:13:28 -0400 Subject: [PATCH 20/22] [PATCH] inotify: add MOVE_SELF event This adds a MOVE_SELF event to inotify. It is sent whenever the inode you are watching is moved. We need this event so that we can catch something like this: - app1: watch /etc/mtab - app2: cp /etc/mtab /tmp/mtab-work mv /etc/mtab /etc/mtab~ mv /tmp/mtab-work /etc/mtab app1 still thinks it's watching /etc/mtab but it's actually watching /etc/mtab~. Signed-off-by: John McCutchan Signed-off-by: Robert Love Signed-off-by: Linus Torvalds --- fs/namei.c | 3 ++- include/linux/fsnotify.h | 6 +++++- include/linux/inotify.h | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 57046d98a746..b85f158aef0c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2216,7 +2216,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry); if (!error) { const char *new_name = old_dentry->d_name.name; - fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, new_dentry->d_inode); + fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, + new_dentry->d_inode, old_dentry->d_inode); } fsnotify_oldname_free(old_name); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 602c305c8585..03b8e7932b83 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -21,7 +21,7 @@ */ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, const char *old_name, const char *new_name, - int isdir, struct inode *target) + int isdir, struct inode *target, struct inode *source) { u32 cookie = inotify_get_cookie(); @@ -41,6 +41,10 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL); inotify_inode_is_dead(target); } + + if (source) { + inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL); + } } /* diff --git a/include/linux/inotify.h b/include/linux/inotify.h index a40c2bf0408e..93bb3afe646b 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h @@ -35,6 +35,7 @@ struct inotify_event { #define IN_CREATE 0x00000100 /* Subfile was created */ #define IN_DELETE 0x00000200 /* Subfile was deleted */ #define IN_DELETE_SELF 0x00000400 /* Self was deleted */ +#define IN_MOVE_SELF 0x00000800 /* Self was moved */ /* the following are legal events. they are sent as needed to any watch */ #define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */ @@ -56,7 +57,8 @@ struct inotify_event { */ #define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \ - IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF) + IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \ + IN_MOVE_SELF) #ifdef __KERNEL__ From 6bd49341f2806168c877e12cefca77b93437bac2 Mon Sep 17 00:00:00 2001 From: Sylvain Meyer Date: Mon, 15 Aug 2005 21:27:13 +0800 Subject: [PATCH 21/22] [PATCH] intelfb: Do not ioremap entire graphics aperture Reported by: Pavel Kysilka (Bugzilla Bug 4738) modprobe of intelfb results in the following error message: intelfb: Framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G chi intelfb: Version 0.9.2 ACPI: PCI Interrupt 0000:00:02.0[A] -> GSI 16 (level, low) -> IRQ 16 allocation failed: out of vmalloc space - use vmalloc= to increase siz intelfb: Cannot remap FB region. This will fail if the graphics aperture size is greater than 128 MB. Fix is to ioremap only from the beginning of graphics aperture to the end of the used framebuffer memory. Signed-off-by: Sylvain Meyer Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/intelfb/intelfbdrv.c | 50 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 298bc9cd99e7..a112a1786855 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -583,23 +583,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - /* Map the fb and MMIO regions */ - dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache - (dinfo->aperture.physical, dinfo->aperture.size); - if (!dinfo->aperture.virtual) { - ERR_MSG("Cannot remap FB region.\n"); - cleanup(dinfo); - return -ENODEV; - } - dinfo->mmio_base = - (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, - INTEL_REG_SIZE); - if (!dinfo->mmio_base) { - ERR_MSG("Cannot remap MMIO region.\n"); - cleanup(dinfo); - return -ENODEV; - } - /* Get the chipset info. */ dinfo->pci_chipset = pdev->device; @@ -630,9 +613,15 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) dinfo->accel = 0; } + if (MB(voffset) < stolen_size) + offset = (stolen_size >> 12); + else + offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; + /* Framebuffer parameters - Use all the stolen memory if >= vram */ - if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) { + if (ROUND_UP_TO_PAGE(stolen_size) >= ((offset << 12) + MB(vram))) { dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size); + dinfo->fb.offset = 0; dinfo->fbmem_gart = 0; } else { dinfo->fb.size = MB(vram); @@ -663,11 +652,6 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } - if (MB(voffset) < stolen_size) - offset = (stolen_size >> 12); - else - offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE; - /* set the mem offsets - set them after the already used pages */ if (dinfo->accel) { dinfo->ring.offset = offset + gtt_info.current_memory; @@ -682,6 +666,26 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent) + (dinfo->cursor.size >> 12); } + /* Map the fb and MMIO regions */ + /* ioremap only up to the end of used aperture */ + dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache + (dinfo->aperture.physical, (dinfo->fb.offset << 12) + + dinfo->fb.size); + if (!dinfo->aperture.virtual) { + ERR_MSG("Cannot remap FB region.\n"); + cleanup(dinfo); + return -ENODEV; + } + + dinfo->mmio_base = + (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys, + INTEL_REG_SIZE); + if (!dinfo->mmio_base) { + ERR_MSG("Cannot remap MMIO region.\n"); + cleanup(dinfo); + return -ENODEV; + } + /* Allocate memories (which aren't stolen) */ if (dinfo->accel) { if (!(dinfo->gtt_ring_mem = From 3edea4833a1efcd43e1dff082bc8001fdfe74b34 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 15 Aug 2005 21:29:11 +0800 Subject: [PATCH 22/22] [PATCH] intelfb/fbdev: Save info->flags in a local variable Reported by: Pavel Kysilka (Bugzilla Bug 5059) The intelfb driver does not keep resolution set with fbset after switching to anot console and back. Steps to reproduce: initial options: tty1,tty2 - 1024x768-60 1) tty1 - fbset after booting (1024x768-60) 2) tty1 - fbset 800x600-100 tty1: 800x600-100 3) swith to tty2, swith to tty1 tty1: 1024x768-60 (the same resolution as default from kernel booting) This bug is caused by intelfb unintentionally destroying info->flags in set_par(). Therefore the flag, FBINFO_MISC_USEREVENT used to notify fbcon of a mode change was cleared causing the above problem. This bug though is not intelfb specific, as other drivers may also be affected. The fix is to save info->flags in a local variable before calling any of the driver hooks. A more definitive fix (for post 2.6.13) is to separate info->flags into one that is set by the driver and another that is set by core fbdev/fbcon. Signed-off-by: Antonino Daplas Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d2e19f6dd72c..4ff853fbe0be 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -628,7 +628,7 @@ fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var) int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) { - int err; + int err, flags = info->flags; if (var->activate & FB_ACTIVATE_INV_MODE) { struct fb_videomode mode1, mode2; @@ -682,7 +682,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) !list_empty(&info->modelist)) err = fb_add_videomode(&mode, &info->modelist); - if (!err && info->flags & FBINFO_MISC_USEREVENT) { + if (!err && (flags & FBINFO_MISC_USEREVENT)) { struct fb_event event; info->flags &= ~FBINFO_MISC_USEREVENT;