--- /dev/null
+From 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Fri, 14 Oct 2011 15:26:20 +0200
+Subject: ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 upstream.
+
+It seems that Conexant CX20549 chip handle only a single input-amp even
+though the audio-input widget has multiple sources. This has been never
+clear, and I implemented in the current way based on the debug information
+I got at the early time -- the device reacts individual input-amp values
+for different sources. This is true for another Conexant codec, but it's
+not applied to CX20549 actually.
+
+This patch changes the auto-parser code to handle a single input-amp
+per audio-in widget for CX20549. After applying this, you'll see only a
+single "Capture" volume control instead of separate "Mic" or "Line"
+captures when the device is set up to use a single ADC.
+
+We haven't tested 20551 and 20561 codecs yet. If these show the similar
+behavior like 20549, they need to set spec->single_adc_amp=1, too.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+
+---
+ sound/pci/hda/patch_conexant.c | 30 ++++++++++++++++++++++++++++--
+ 1 file changed, 28 insertions(+), 2 deletions(-)
+
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -136,6 +136,7 @@ struct conexant_spec {
+ unsigned int thinkpad:1;
+ unsigned int hp_laptop:1;
+ unsigned int asus:1;
++ unsigned int single_adc_amp:1;
+
+ unsigned int adc_switching:1;
+
+@@ -4205,6 +4206,8 @@ static int cx_auto_add_capture_volume(st
+ int idx = get_input_connection(codec, adc_nid, nid);
+ if (idx < 0)
+ continue;
++ if (spec->single_adc_amp)
++ idx = 0;
+ return cx_auto_add_volume_idx(codec, label, pfx,
+ cidx, adc_nid, HDA_INPUT, idx);
+ }
+@@ -4245,14 +4248,21 @@ static int cx_auto_build_input_controls(
+ struct hda_input_mux *imux = &spec->private_imux;
+ const char *prev_label;
+ int input_conn[HDA_MAX_NUM_INPUTS];
+- int i, err, cidx;
++ int i, j, err, cidx;
+ int multi_connection;
+
++ if (!imux->num_items)
++ return 0;
++
+ multi_connection = 0;
+ for (i = 0; i < imux->num_items; i++) {
+ cidx = get_input_connection(codec, spec->imux_info[i].adc,
+ spec->imux_info[i].pin);
+- input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
++ if (cidx < 0)
++ continue;
++ input_conn[i] = spec->imux_info[i].adc;
++ if (!spec->single_adc_amp)
++ input_conn[i] |= cidx << 8;
+ if (i > 0 && input_conn[i] != input_conn[0])
+ multi_connection = 1;
+ }
+@@ -4281,6 +4291,15 @@ static int cx_auto_build_input_controls(
+ err = cx_auto_add_capture_volume(codec, nid,
+ "Capture", "", cidx);
+ } else {
++ bool dup_found = false;
++ for (j = 0; j < i; j++) {
++ if (input_conn[j] == input_conn[i]) {
++ dup_found = true;
++ break;
++ }
++ }
++ if (dup_found)
++ continue;
+ err = cx_auto_add_capture_volume(codec, nid,
+ label, " Capture", cidx);
+ }
+@@ -4357,6 +4376,13 @@ static int patch_conexant_auto(struct hd
+ return -ENOMEM;
+ codec->spec = spec;
+ codec->pin_amp_workaround = 1;
++
++ switch (codec->vendor_id) {
++ case 0x14f15045:
++ spec->single_adc_amp = 1;
++ break;
++ }
++
+ err = cx_auto_search_adcs(codec);
+ if (err < 0)
+ return err;
--- /dev/null
+From 9d898966c4a07e4a5092215b5a2829d0ef02baa2 Mon Sep 17 00:00:00 2001
+From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+Date: Wed, 24 Aug 2011 13:14:22 -0300
+Subject: jsm: remove buggy write queue
+
+From: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+
+commit 9d898966c4a07e4a5092215b5a2829d0ef02baa2 upstream.
+
+jsm uses a write queue that copies from uart_core circular buffer. This
+copying however has some bugs, like not wrapping the head counter. Since
+this write queue is also a circular buffer, the consumer function is
+ready to use the uart_core circular buffer directly.
+
+This buggy copying function was making some bytes be dropped when
+transmitting to a raw tty, doing something like this.
+
+[root@hostname ~]$ cat /dev/ttyn1 > cascardo/dump &
+[1] 2658
+[root@hostname ~]$ cat /proc/tty/drivers > /dev/ttyn0
+[root@hostname ~]$ cat /proc/tty/drivers
+/dev/tty /dev/tty 5 0 system:/dev/tty
+/dev/console /dev/console 5 1 system:console
+/dev/ptmx /dev/ptmx 5 2 system
+/dev/vc/0 /dev/vc/0 4 0 system:vtmaster
+jsm /dev/ttyn 250 0-31 serial
+serial /dev/ttyS 4 64-95 serial
+hvc /dev/hvc 229 0-7 system
+pty_slave /dev/pts 136 0-1048575 pty:slave
+pty_master /dev/ptm 128 0-1048575 pty:master
+unknown /dev/tty 4 1-63 console
+[root@hostname ~]$ cat cascardo/dump
+/dev/tty /dev/tty 5 0 system:/dev/tty
+/dev/console /dev/console 5 1 system:console
+/dev/ptmx /dev/ptmx 5 2 system
+/dev/vc/0 /dev/vc/0 4 0 system:vtmaste[root@hostname ~]$
+
+This patch drops the driver write queue entirely, using the circular
+buffer from uart_core only.
+
+Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/tty/serial/jsm/jsm.h | 7 --
+ drivers/tty/serial/jsm/jsm_driver.c | 1
+ drivers/tty/serial/jsm/jsm_neo.c | 29 +++++------
+ drivers/tty/serial/jsm/jsm_tty.c | 94 ++++--------------------------------
+ 4 files changed, 28 insertions(+), 103 deletions(-)
+
+--- a/drivers/tty/serial/jsm/jsm.h
++++ b/drivers/tty/serial/jsm/jsm.h
+@@ -183,10 +183,8 @@ struct jsm_board
+ /* Our Read/Error/Write queue sizes */
+ #define RQUEUEMASK 0x1FFF /* 8 K - 1 */
+ #define EQUEUEMASK 0x1FFF /* 8 K - 1 */
+-#define WQUEUEMASK 0x0FFF /* 4 K - 1 */
+ #define RQUEUESIZE (RQUEUEMASK + 1)
+ #define EQUEUESIZE RQUEUESIZE
+-#define WQUEUESIZE (WQUEUEMASK + 1)
+
+
+ /************************************************************************
+@@ -226,10 +224,6 @@ struct jsm_channel {
+ u16 ch_e_head; /* Head location of the error queue */
+ u16 ch_e_tail; /* Tail location of the error queue */
+
+- u8 *ch_wqueue; /* Our write queue buffer - malloc'ed */
+- u16 ch_w_head; /* Head location of the write queue */
+- u16 ch_w_tail; /* Tail location of the write queue */
+-
+ u64 ch_rxcount; /* total of data received so far */
+ u64 ch_txcount; /* total of data transmitted so far */
+
+@@ -378,7 +372,6 @@ extern int jsm_debug;
+ * Prototypes for non-static functions used in more than one module
+ *
+ *************************************************************************/
+-int jsm_tty_write(struct uart_port *port);
+ int jsm_tty_init(struct jsm_board *);
+ int jsm_uart_port_init(struct jsm_board *);
+ int jsm_remove_uart_port(struct jsm_board *);
+--- a/drivers/tty/serial/jsm/jsm_driver.c
++++ b/drivers/tty/serial/jsm/jsm_driver.c
+@@ -211,7 +211,6 @@ static void __devexit jsm_remove_one(str
+ if (brd->channels[i]) {
+ kfree(brd->channels[i]->ch_rqueue);
+ kfree(brd->channels[i]->ch_equeue);
+- kfree(brd->channels[i]->ch_wqueue);
+ kfree(brd->channels[i]);
+ }
+ }
+--- a/drivers/tty/serial/jsm/jsm_neo.c
++++ b/drivers/tty/serial/jsm/jsm_neo.c
+@@ -496,12 +496,15 @@ static void neo_copy_data_from_queue_to_
+ int s;
+ int qlen;
+ u32 len_written = 0;
++ struct circ_buf *circ;
+
+ if (!ch)
+ return;
+
++ circ = &ch->uart_port.state->xmit;
++
+ /* No data to write to the UART */
+- if (ch->ch_w_tail == ch->ch_w_head)
++ if (uart_circ_empty(circ))
+ return;
+
+ /* If port is "stopped", don't send any data to the UART */
+@@ -517,11 +520,10 @@ static void neo_copy_data_from_queue_to_
+ if (ch->ch_cached_lsr & UART_LSR_THRE) {
+ ch->ch_cached_lsr &= ~(UART_LSR_THRE);
+
+- writeb(ch->ch_wqueue[ch->ch_w_tail], &ch->ch_neo_uart->txrx);
++ writeb(circ->buf[circ->tail], &ch->ch_neo_uart->txrx);
+ jsm_printk(WRITE, INFO, &ch->ch_bd->pci_dev,
+- "Tx data: %x\n", ch->ch_wqueue[ch->ch_w_head]);
+- ch->ch_w_tail++;
+- ch->ch_w_tail &= WQUEUEMASK;
++ "Tx data: %x\n", circ->buf[circ->head]);
++ circ->tail = (circ->tail + 1) & (UART_XMIT_SIZE - 1);
+ ch->ch_txcount++;
+ }
+ return;
+@@ -536,36 +538,36 @@ static void neo_copy_data_from_queue_to_
+ n = UART_17158_TX_FIFOSIZE - ch->ch_t_tlevel;
+
+ /* cache head and tail of queue */
+- head = ch->ch_w_head & WQUEUEMASK;
+- tail = ch->ch_w_tail & WQUEUEMASK;
+- qlen = (head - tail) & WQUEUEMASK;
++ head = circ->head & (UART_XMIT_SIZE - 1);
++ tail = circ->tail & (UART_XMIT_SIZE - 1);
++ qlen = uart_circ_chars_pending(circ);
+
+ /* Find minimum of the FIFO space, versus queue length */
+ n = min(n, qlen);
+
+ while (n > 0) {
+
+- s = ((head >= tail) ? head : WQUEUESIZE) - tail;
++ s = ((head >= tail) ? head : UART_XMIT_SIZE) - tail;
+ s = min(s, n);
+
+ if (s <= 0)
+ break;
+
+- memcpy_toio(&ch->ch_neo_uart->txrxburst, ch->ch_wqueue + tail, s);
++ memcpy_toio(&ch->ch_neo_uart->txrxburst, circ->buf + tail, s);
+ /* Add and flip queue if needed */
+- tail = (tail + s) & WQUEUEMASK;
++ tail = (tail + s) & (UART_XMIT_SIZE - 1);
+ n -= s;
+ ch->ch_txcount += s;
+ len_written += s;
+ }
+
+ /* Update the final tail */
+- ch->ch_w_tail = tail & WQUEUEMASK;
++ circ->tail = tail & (UART_XMIT_SIZE - 1);
+
+ if (len_written >= ch->ch_t_tlevel)
+ ch->ch_flags &= ~(CH_TX_FIFO_EMPTY | CH_TX_FIFO_LWM);
+
+- if (!jsm_tty_write(&ch->uart_port))
++ if (uart_circ_empty(circ))
+ uart_write_wakeup(&ch->uart_port);
+ }
+
+@@ -946,7 +948,6 @@ static void neo_param(struct jsm_channel
+ if ((ch->ch_c_cflag & (CBAUD)) == 0) {
+ ch->ch_r_head = ch->ch_r_tail = 0;
+ ch->ch_e_head = ch->ch_e_tail = 0;
+- ch->ch_w_head = ch->ch_w_tail = 0;
+
+ neo_flush_uart_write(ch);
+ neo_flush_uart_read(ch);
+--- a/drivers/tty/serial/jsm/jsm_tty.c
++++ b/drivers/tty/serial/jsm/jsm_tty.c
+@@ -118,6 +118,19 @@ static void jsm_tty_set_mctrl(struct uar
+ udelay(10);
+ }
+
++/*
++ * jsm_tty_write()
++ *
++ * Take data from the user or kernel and send it out to the FEP.
++ * In here exists all the Transparent Print magic as well.
++ */
++static void jsm_tty_write(struct uart_port *port)
++{
++ struct jsm_channel *channel;
++ channel = container_of(port, struct jsm_channel, uart_port);
++ channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
++}
++
+ static void jsm_tty_start_tx(struct uart_port *port)
+ {
+ struct jsm_channel *channel = (struct jsm_channel *)port;
+@@ -216,14 +229,6 @@ static int jsm_tty_open(struct uart_port
+ return -ENOMEM;
+ }
+ }
+- if (!channel->ch_wqueue) {
+- channel->ch_wqueue = kzalloc(WQUEUESIZE, GFP_KERNEL);
+- if (!channel->ch_wqueue) {
+- jsm_printk(INIT, ERR, &channel->ch_bd->pci_dev,
+- "unable to allocate write queue buf");
+- return -ENOMEM;
+- }
+- }
+
+ channel->ch_flags &= ~(CH_OPENING);
+ /*
+@@ -237,7 +242,6 @@ static int jsm_tty_open(struct uart_port
+ */
+ channel->ch_r_head = channel->ch_r_tail = 0;
+ channel->ch_e_head = channel->ch_e_tail = 0;
+- channel->ch_w_head = channel->ch_w_tail = 0;
+
+ brd->bd_ops->flush_uart_write(channel);
+ brd->bd_ops->flush_uart_read(channel);
+@@ -836,75 +840,3 @@ void jsm_check_queue_flow_control(struct
+ }
+ }
+ }
+-
+-/*
+- * jsm_tty_write()
+- *
+- * Take data from the user or kernel and send it out to the FEP.
+- * In here exists all the Transparent Print magic as well.
+- */
+-int jsm_tty_write(struct uart_port *port)
+-{
+- int bufcount;
+- int data_count = 0,data_count1 =0;
+- u16 head;
+- u16 tail;
+- u16 tmask;
+- u32 remain;
+- int temp_tail = port->state->xmit.tail;
+- struct jsm_channel *channel = (struct jsm_channel *)port;
+-
+- tmask = WQUEUEMASK;
+- head = (channel->ch_w_head) & tmask;
+- tail = (channel->ch_w_tail) & tmask;
+-
+- if ((bufcount = tail - head - 1) < 0)
+- bufcount += WQUEUESIZE;
+-
+- bufcount = min(bufcount, 56);
+- remain = WQUEUESIZE - head;
+-
+- data_count = 0;
+- if (bufcount >= remain) {
+- bufcount -= remain;
+- while ((port->state->xmit.head != temp_tail) &&
+- (data_count < remain)) {
+- channel->ch_wqueue[head++] =
+- port->state->xmit.buf[temp_tail];
+-
+- temp_tail++;
+- temp_tail &= (UART_XMIT_SIZE - 1);
+- data_count++;
+- }
+- if (data_count == remain) head = 0;
+- }
+-
+- data_count1 = 0;
+- if (bufcount > 0) {
+- remain = bufcount;
+- while ((port->state->xmit.head != temp_tail) &&
+- (data_count1 < remain)) {
+- channel->ch_wqueue[head++] =
+- port->state->xmit.buf[temp_tail];
+-
+- temp_tail++;
+- temp_tail &= (UART_XMIT_SIZE - 1);
+- data_count1++;
+-
+- }
+- }
+-
+- port->state->xmit.tail = temp_tail;
+-
+- data_count += data_count1;
+- if (data_count) {
+- head &= tmask;
+- channel->ch_w_head = head;
+- }
+-
+- if (data_count) {
+- channel->ch_bd->bd_ops->copy_data_from_queue_to_uart(channel);
+- }
+-
+- return data_count;
+-}
--- /dev/null
+From f5252e009d5b87071a919221e4f6624184005368 Mon Sep 17 00:00:00 2001
+From: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+Date: Mon, 31 Oct 2011 17:08:13 -0700
+Subject: mm: avoid null pointer access in vm_struct via /proc/vmallocinfo
+
+From: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+
+commit f5252e009d5b87071a919221e4f6624184005368 upstream.
+
+The /proc/vmallocinfo shows information about vmalloc allocations in
+vmlist that is a linklist of vm_struct. It, however, may access pages
+field of vm_struct where a page was not allocated. This results in a null
+pointer access and leads to a kernel panic.
+
+Why this happens: In __vmalloc_node_range() called from vmalloc(), newly
+allocated vm_struct is added to vmlist at __get_vm_area_node() and then,
+some fields of vm_struct such as nr_pages and pages are set at
+__vmalloc_area_node(). In other words, it is added to vmlist before it is
+fully initialized. At the same time, when the /proc/vmallocinfo is read,
+it accesses the pages field of vm_struct according to the nr_pages field
+at show_numa_info(). Thus, a null pointer access happens.
+
+The patch adds the newly allocated vm_struct to the vmlist *after* it is
+fully initialized. So, it can avoid accessing the pages field with
+unallocated page when show_numa_info() is called.
+
+Signed-off-by: Mitsuo Hayasaka <mitsuo.hayasaka.hu@hitachi.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: David Rientjes <rientjes@google.com>
+Cc: Namhyung Kim <namhyung@gmail.com>
+Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
+Cc: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ include/linux/vmalloc.h | 1
+ mm/vmalloc.c | 65 +++++++++++++++++++++++++++++++++++-------------
+ 2 files changed, 49 insertions(+), 17 deletions(-)
+
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -13,6 +13,7 @@ struct vm_area_struct; /* vma defining
+ #define VM_MAP 0x00000004 /* vmap()ed pages */
+ #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */
+ #define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */
++#define VM_UNLIST 0x00000020 /* vm_struct is not listed in vmlist */
+ /* bits [20..32] reserved for arch specific ioremap internals */
+
+ /*
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -1267,18 +1267,22 @@ EXPORT_SYMBOL_GPL(map_vm_area);
+ DEFINE_RWLOCK(vmlist_lock);
+ struct vm_struct *vmlist;
+
+-static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
++static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
+ unsigned long flags, void *caller)
+ {
+- struct vm_struct *tmp, **p;
+-
+ vm->flags = flags;
+ vm->addr = (void *)va->va_start;
+ vm->size = va->va_end - va->va_start;
+ vm->caller = caller;
+ va->private = vm;
+ va->flags |= VM_VM_AREA;
++}
++
++static void insert_vmalloc_vmlist(struct vm_struct *vm)
++{
++ struct vm_struct *tmp, **p;
+
++ vm->flags &= ~VM_UNLIST;
+ write_lock(&vmlist_lock);
+ for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
+ if (tmp->addr >= vm->addr)
+@@ -1289,6 +1293,13 @@ static void insert_vmalloc_vm(struct vm_
+ write_unlock(&vmlist_lock);
+ }
+
++static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
++ unsigned long flags, void *caller)
++{
++ setup_vmalloc_vm(vm, va, flags, caller);
++ insert_vmalloc_vmlist(vm);
++}
++
+ static struct vm_struct *__get_vm_area_node(unsigned long size,
+ unsigned long align, unsigned long flags, unsigned long start,
+ unsigned long end, int node, gfp_t gfp_mask, void *caller)
+@@ -1327,7 +1338,18 @@ static struct vm_struct *__get_vm_area_n
+ return NULL;
+ }
+
+- insert_vmalloc_vm(area, va, flags, caller);
++ /*
++ * When this function is called from __vmalloc_node_range,
++ * we do not add vm_struct to vmlist here to avoid
++ * accessing uninitialized members of vm_struct such as
++ * pages and nr_pages fields. They will be set later.
++ * To distinguish it from others, we use a VM_UNLIST flag.
++ */
++ if (flags & VM_UNLIST)
++ setup_vmalloc_vm(area, va, flags, caller);
++ else
++ insert_vmalloc_vm(area, va, flags, caller);
++
+ return area;
+ }
+
+@@ -1395,17 +1417,20 @@ struct vm_struct *remove_vm_area(const v
+ va = find_vmap_area((unsigned long)addr);
+ if (va && va->flags & VM_VM_AREA) {
+ struct vm_struct *vm = va->private;
+- struct vm_struct *tmp, **p;
+- /*
+- * remove from list and disallow access to this vm_struct
+- * before unmap. (address range confliction is maintained by
+- * vmap.)
+- */
+- write_lock(&vmlist_lock);
+- for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
+- ;
+- *p = tmp->next;
+- write_unlock(&vmlist_lock);
++
++ if (!(vm->flags & VM_UNLIST)) {
++ struct vm_struct *tmp, **p;
++ /*
++ * remove from list and disallow access to
++ * this vm_struct before unmap. (address range
++ * confliction is maintained by vmap.)
++ */
++ write_lock(&vmlist_lock);
++ for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
++ ;
++ *p = tmp->next;
++ write_unlock(&vmlist_lock);
++ }
+
+ vmap_debug_free_range(va->va_start, va->va_end);
+ free_unmap_vmap_area(va);
+@@ -1616,8 +1641,8 @@ void *__vmalloc_node_range(unsigned long
+ if (!size || (size >> PAGE_SHIFT) > totalram_pages)
+ return NULL;
+
+- area = __get_vm_area_node(size, align, VM_ALLOC, start, end, node,
+- gfp_mask, caller);
++ area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNLIST,
++ start, end, node, gfp_mask, caller);
+
+ if (!area)
+ return NULL;
+@@ -1625,6 +1650,12 @@ void *__vmalloc_node_range(unsigned long
+ addr = __vmalloc_area_node(area, gfp_mask, prot, node, caller);
+
+ /*
++ * In this function, newly allocated vm_struct is not added
++ * to vmlist at __get_vm_area_node(). so, it is added here.
++ */
++ insert_vmalloc_vmlist(area);
++
++ /*
+ * A ref_count = 3 is needed because the vm_struct and vmap_area
+ * structures allocated in the __get_vm_area_node() function contain
+ * references to the virtual address of the vmalloc'ed block.
--- /dev/null
+From oleg@redhat.com Wed Nov 2 12:41:29 2011
+From: Oleg Nesterov <oleg@redhat.com>
+Date: Mon, 26 Sep 2011 19:06:32 +0200
+Subject: ptrace: don't clear GROUP_STOP_SIGMASK on double-stop
+To: Greg KH <gregkh@suse.de>
+Cc: Tejun Heo <htejun@gmail.com>, Luke Macken <lmacken@redhat.com>, stable@kernel.org, linux-kernel@vger.kernel.org
+Message-ID: <20110926170632.GA16936@redhat.com>
+Content-Disposition: inline
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[This does not correspond to any specific patch in the upstream tree as it was
+fixed accidentally by rewriting the code in the 3.1 release]
+
+https://bugzilla.redhat.com/show_bug.cgi?id=740121
+
+1. Luke Macken triggered WARN_ON(!(group_stop & GROUP_STOP_SIGMASK))
+ in do_signal_stop().
+
+ This is because do_signal_stop() clears GROUP_STOP_SIGMASK part
+ unconditionally but doesn't update it if task_is_stopped().
+
+2. Looking at this problem I noticed that WARN_ON_ONCE(!ptrace) is
+ not right, a stopped-but-resumed tracee can clone the untraced
+ thread in the SIGNAL_STOP_STOPPED group, the new thread can start
+ another group-stop.
+
+ Remove this warning, we need more fixes to make it true.
+
+Reported-by: Luke Macken <lmacken@redhat.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/signal.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1894,21 +1894,19 @@ static int do_signal_stop(int signr)
+ */
+ if (!(sig->flags & SIGNAL_STOP_STOPPED))
+ sig->group_exit_code = signr;
+- else
+- WARN_ON_ONCE(!task_ptrace(current));
+
+ current->group_stop &= ~GROUP_STOP_SIGMASK;
+ current->group_stop |= signr | gstop;
+ sig->group_stop_count = 1;
+ for (t = next_thread(current); t != current;
+ t = next_thread(t)) {
+- t->group_stop &= ~GROUP_STOP_SIGMASK;
+ /*
+ * Setting state to TASK_STOPPED for a group
+ * stop is always done with the siglock held,
+ * so this check has no races.
+ */
+ if (!(t->flags & PF_EXITING) && !task_is_stopped(t)) {
++ t->group_stop &= ~GROUP_STOP_SIGMASK;
+ t->group_stop |= signr | gstop;
+ sig->group_stop_count++;
+ signal_wake_up(t, 0);
--- /dev/null
+From 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 Mon Sep 17 00:00:00 2001
+From: Andy Whitcroft <apw@canonical.com>
+Date: Wed, 2 Nov 2011 09:44:39 +0100
+Subject: readlinkat: ensure we return ENOENT for the empty pathname for normal lookups
+
+From: Andy Whitcroft <apw@canonical.com>
+
+commit 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 upstream.
+
+Since the commit below which added O_PATH support to the *at() calls, the
+error return for readlink/readlinkat for the empty pathname has switched
+from ENOENT to EINVAL:
+
+ commit 65cfc6722361570bfe255698d9cd4dccaf47570d
+ Author: Al Viro <viro@zeniv.linux.org.uk>
+ Date: Sun Mar 13 15:56:26 2011 -0400
+
+ readlinkat(), fchownat() and fstatat() with empty relative pathnames
+
+This is both unexpected for userspace and makes readlink/readlinkat
+inconsistant with all other interfaces; and inconsistant with our stated
+return for these pathnames.
+
+As the readlinkat call does not have a flags parameter we cannot use the
+AT_EMPTY_PATH approach used in the other calls. Therefore expose whether
+the original path is infact entry via a new user_path_at_empty() path
+lookup function. Use this to determine whether to default to EINVAL or
+ENOENT for failures.
+
+Addresses http://bugs.launchpad.net/bugs/817187
+
+[akpm@linux-foundation.org: remove unused getname_flags()]
+Signed-off-by: Andy Whitcroft <apw@canonical.com>
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c | 18 +++++++++++++-----
+ fs/stat.c | 5 +++--
+ include/linux/namei.h | 1 +
+ 3 files changed, 17 insertions(+), 7 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -136,7 +136,7 @@ static int do_getname(const char __user
+ return retval;
+ }
+
+-static char *getname_flags(const char __user * filename, int flags)
++static char *getname_flags(const char __user *filename, int flags, int *empty)
+ {
+ char *tmp, *result;
+
+@@ -147,6 +147,8 @@ static char *getname_flags(const char __
+
+ result = tmp;
+ if (retval < 0) {
++ if (retval == -ENOENT && empty)
++ *empty = 1;
+ if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
+ __putname(tmp);
+ result = ERR_PTR(retval);
+@@ -159,7 +161,7 @@ static char *getname_flags(const char __
+
+ char *getname(const char __user * filename)
+ {
+- return getname_flags(filename, 0);
++ return getname_flags(filename, 0, 0);
+ }
+
+ #ifdef CONFIG_AUDITSYSCALL
+@@ -1747,11 +1749,11 @@ struct dentry *lookup_one_len(const char
+ return __lookup_hash(&this, base, NULL);
+ }
+
+-int user_path_at(int dfd, const char __user *name, unsigned flags,
+- struct path *path)
++int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
++ struct path *path, int *empty)
+ {
+ struct nameidata nd;
+- char *tmp = getname_flags(name, flags);
++ char *tmp = getname_flags(name, flags, empty);
+ int err = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+
+@@ -1765,6 +1767,12 @@ int user_path_at(int dfd, const char __u
+ return err;
+ }
+
++int user_path_at(int dfd, const char __user *name, unsigned flags,
++ struct path *path)
++{
++ return user_path_at_empty(dfd, name, flags, path, 0);
++}
++
+ static int user_path_parent(int dfd, const char __user *path,
+ struct nameidata *nd, char **name)
+ {
+--- a/fs/stat.c
++++ b/fs/stat.c
+@@ -296,15 +296,16 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, co
+ {
+ struct path path;
+ int error;
++ int empty = 0;
+
+ if (bufsiz <= 0)
+ return -EINVAL;
+
+- error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
++ error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty);
+ if (!error) {
+ struct inode *inode = path.dentry->d_inode;
+
+- error = -EINVAL;
++ error = empty ? -ENOENT : -EINVAL;
+ if (inode->i_op->readlink) {
+ error = security_inode_readlink(path.dentry);
+ if (!error) {
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -67,6 +67,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA
+ #define LOOKUP_EMPTY 0x4000
+
+ extern int user_path_at(int, const char __user *, unsigned, struct path *);
++extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty);
+
+ #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
+ #define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)
proc-self-numa_maps-restore-huge-tag-for-hugetlb-vmas.patch
plat-mxc-iomux-v3.h-implicitly-enable-pull-up-down-when-that-s-desired.patch
arm-mach-ux500-unlock-i-d-l2x0-caches-before-init.patch
+mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch
+alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch
+um-fix-ubd-cow-size.patch
+readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch
+vfs-fix-automount-for-negative-autofs-dentries.patch
+vfs-automount-should-ignore-lookup_follow.patch
+vfs-fix-the-remaining-automounter-semantics-regressions.patch
+vfs-pathname-lookup-add-lookup_automount-flag.patch
+ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch
+jsm-remove-buggy-write-queue.patch
--- /dev/null
+From 8535639810e578960233ad39def3ac2157b0c3ec Mon Sep 17 00:00:00 2001
+From: Richard Weinberger <richard@nod.at>
+Date: Wed, 2 Nov 2011 13:17:27 +0100
+Subject: um: fix ubd cow size
+
+From: Richard Weinberger <richard@nod.at>
+
+commit 8535639810e578960233ad39def3ac2157b0c3ec upstream.
+
+ubd_file_size() cannot use ubd_dev->cow.file because at this time
+ubd_dev->cow.file is not initialized.
+Therefore, ubd_file_size() will always report a wrong disk size when
+COW files are used.
+Reading from /dev/ubd* would crash the kernel.
+
+We have to read the correct disk size from the COW file's backing
+file.
+
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/um/drivers/ubd_kern.c | 31 ++++++++++++++++++++++++++++++-
+ 1 file changed, 30 insertions(+), 1 deletion(-)
+
+--- a/arch/um/drivers/ubd_kern.c
++++ b/arch/um/drivers/ubd_kern.c
+@@ -513,8 +513,37 @@ __uml_exitcall(kill_io_thread);
+ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
+ {
+ char *file;
++ int fd;
++ int err;
+
+- file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file;
++ __u32 version;
++ __u32 align;
++ char *backing_file;
++ time_t mtime;
++ unsigned long long size;
++ int sector_size;
++ int bitmap_offset;
++
++ if (ubd_dev->file && ubd_dev->cow.file) {
++ file = ubd_dev->cow.file;
++
++ goto out;
++ }
++
++ fd = os_open_file(ubd_dev->file, global_openflags, 0);
++ if (fd < 0)
++ return fd;
++
++ err = read_cow_header(file_reader, &fd, &version, &backing_file, \
++ &mtime, &size, §or_size, &align, &bitmap_offset);
++ os_close_file(fd);
++
++ if(err == -EINVAL)
++ file = ubd_dev->file;
++ else
++ file = backing_file;
++
++out:
+ return os_file_size(file, size_out);
+ }
+
--- /dev/null
+From miklos@szeredi.hu Wed Nov 2 12:37:33 2011
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 25 Oct 2011 13:59:46 +0200
+Subject: vfs: automount should ignore LOOKUP_FOLLOW
+To: stable@vger.kernel.org
+Cc: gregkh@suse.de, dhowells@redhat.com, raven@themaw.net, viro@zeniv.linux.org.uk
+Message-ID: <1319543988-12968-3-git-send-email-miklos@szeredi.hu>
+
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 0ec26fd0698285b31248e34bf1abb022c00f23d6 upstream.
+
+Prior to 2.6.38 automount would not trigger on either stat(2) or
+lstat(2) on the automount point.
+
+After 2.6.38, with the introduction of the ->d_automount()
+infrastructure, stat(2) and others would start triggering automount
+while lstat(2), etc. still would not. This is a regression and a
+userspace ABI change.
+
+Problem originally reported here:
+
+ http://thread.gmane.org/gmane.linux.kernel.autofs/6098
+
+It appears that there was an attempt at fixing various userspace tools
+to not trigger the automount. But since the stat system call is
+rather common it is impossible to "fix" all userspace.
+
+This patch reverts the original behavior, which is to not trigger on
+stat(2) and other symlink following syscalls.
+
+[ It's not really clear what the right behavior is. Apparently Solaris
+ does the "automount on stat, leave alone on lstat". And some programs
+ can get unhappy when "stat+open+fstat" ends up giving a different
+ result from the fstat than from the initial stat.
+
+ But the change in 2.6.38 resulted in problems for some people, so
+ we're going back to old behavior. Maybe we can re-visit this
+ discussion at some future date - Linus ]
+
+Reported-by: Leonardo Chiquitto <leonardo.lists@gmail.com>
+Acked-by: Ian Kent <raven@themaw.net>
+Cc: David Howells <dhowells@redhat.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c | 33 +++++++++++++++------------------
+ 1 file changed, 15 insertions(+), 18 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -781,25 +781,22 @@ static int follow_automount(struct path
+ if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_CONTINUE))
+ return -EISDIR; /* we actually want to stop here */
+
+- /*
+- * We don't want to mount if someone's just doing a stat and they've
+- * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
+- * appended a '/' to the name.
++ /* We don't want to mount if someone's just doing a stat -
++ * unless they're stat'ing a directory and appended a '/' to
++ * the name.
++ *
++ * We do, however, want to mount if someone wants to open or
++ * create a file of any type under the mountpoint, wants to
++ * traverse through the mountpoint or wants to open the
++ * mounted directory. Also, autofs may mark negative dentries
++ * as being automount points. These will need the attentions
++ * of the daemon to instantiate them before they can be used.
+ */
+- if (!(flags & LOOKUP_FOLLOW)) {
+- /* We do, however, want to mount if someone wants to open or
+- * create a file of any type under the mountpoint, wants to
+- * traverse through the mountpoint or wants to open the mounted
+- * directory.
+- * Also, autofs may mark negative dentries as being automount
+- * points. These will need the attentions of the daemon to
+- * instantiate them before they can be used.
+- */
+- if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
+- LOOKUP_OPEN | LOOKUP_CREATE)) &&
+- path->dentry->d_inode)
+- return -EISDIR;
+- }
++ if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
++ LOOKUP_OPEN | LOOKUP_CREATE)) &&
++ path->dentry->d_inode)
++ return -EISDIR;
++
+ current->total_link_count++;
+ if (current->total_link_count >= 40)
+ return -ELOOP;
--- /dev/null
+From miklos@szeredi.hu Wed Nov 2 12:37:16 2011
+From: David Howells <dhowells@redhat.com>
+Date: Tue, 25 Oct 2011 13:59:45 +0200
+Subject: VFS: Fix automount for negative autofs dentries
+To: stable@vger.kernel.org
+Cc: gregkh@suse.de, dhowells@redhat.com, raven@themaw.net, viro@zeniv.linux.org.uk
+Message-ID: <1319543988-12968-2-git-send-email-miklos@szeredi.hu>
+
+From: David Howells <dhowells@redhat.com>
+
+commit 5a30d8a2b8ddd5102c440c7e5a7c8e1fd729c818 upstream.
+[ backport for 3.0.x: LOOKUP_PARENT => LOOKUP_CONTINUE by Chuck Ebbert
+<cebbert@redhat.com> ]
+
+Autofs may set the DCACHE_NEED_AUTOMOUNT flag on negative dentries. These
+need attention from the automounter daemon regardless of the LOOKUP_FOLLOW flag.
+
+Signed-off-by: David Howells <dhowells@redhat.com>
+Acked-by: Ian Kent <raven@themaw.net>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Chuck Ebbert <cebbert@redhat.com>
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c | 24 +++++++++++++++---------
+ 1 file changed, 15 insertions(+), 9 deletions(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -781,19 +781,25 @@ static int follow_automount(struct path
+ if ((flags & LOOKUP_NO_AUTOMOUNT) && !(flags & LOOKUP_CONTINUE))
+ return -EISDIR; /* we actually want to stop here */
+
+- /* We want to mount if someone is trying to open/create a file of any
+- * type under the mountpoint, wants to traverse through the mountpoint
+- * or wants to open the mounted directory.
+- *
++ /*
+ * We don't want to mount if someone's just doing a stat and they've
+ * set AT_SYMLINK_NOFOLLOW - unless they're stat'ing a directory and
+ * appended a '/' to the name.
+ */
+- if (!(flags & LOOKUP_FOLLOW) &&
+- !(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
+- LOOKUP_OPEN | LOOKUP_CREATE)))
+- return -EISDIR;
+-
++ if (!(flags & LOOKUP_FOLLOW)) {
++ /* We do, however, want to mount if someone wants to open or
++ * create a file of any type under the mountpoint, wants to
++ * traverse through the mountpoint or wants to open the mounted
++ * directory.
++ * Also, autofs may mark negative dentries as being automount
++ * points. These will need the attentions of the daemon to
++ * instantiate them before they can be used.
++ */
++ if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
++ LOOKUP_OPEN | LOOKUP_CREATE)) &&
++ path->dentry->d_inode)
++ return -EISDIR;
++ }
+ current->total_link_count++;
+ if (current->total_link_count >= 40)
+ return -ELOOP;
--- /dev/null
+From miklos@szeredi.hu Wed Nov 2 12:38:17 2011
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 25 Oct 2011 13:59:47 +0200
+Subject: VFS: Fix the remaining automounter semantics regressions
+To: stable@vger.kernel.org
+Cc: gregkh@suse.de, dhowells@redhat.com, raven@themaw.net, viro@zeniv.linux.org.uk
+Message-ID: <1319543988-12968-4-git-send-email-miklos@szeredi.hu>
+
+
+From: Trond Myklebust <Trond.Myklebust@netapp.com>
+
+commit 815d405ceff0d6964683f033e18b9b23a88fba87 upstream.
+
+The concensus seems to be that system calls such as stat() etc should
+not trigger an automount. Neither should the l* versions.
+
+This patch therefore adds a LOOKUP_AUTOMOUNT flag to tag those lookups
+that _should_ trigger an automount on the last path element.
+
+Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
+[ Edited to leave out the cases that are already covered by LOOKUP_OPEN,
+ LOOKUP_DIRECTORY and LOOKUP_CREATE - all of which also fundamentally
+ force automounting for their own reasons - Linus ]
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namespace.c | 2 +-
+ fs/nfs/super.c | 2 +-
+ fs/quota/quota.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -1758,7 +1758,7 @@ static int do_loopback(struct path *path
+ return err;
+ if (!old_name || !*old_name)
+ return -EINVAL;
+- err = kern_path(old_name, LOOKUP_FOLLOW, &old_path);
++ err = kern_path(old_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
+ if (err)
+ return err;
+
+--- a/fs/nfs/super.c
++++ b/fs/nfs/super.c
+@@ -2793,7 +2793,7 @@ static struct dentry *nfs_follow_remote_
+ goto out_put_mnt_ns;
+
+ ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
+- export_path, LOOKUP_FOLLOW, nd);
++ export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, nd);
+
+ nfs_referral_loop_unprotect();
+ put_mnt_ns(ns_private);
+--- a/fs/quota/quota.c
++++ b/fs/quota/quota.c
+@@ -355,7 +355,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int,
+ * resolution (think about autofs) and thus deadlocks could arise.
+ */
+ if (cmds == Q_QUOTAON) {
+- ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW, &path);
++ ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+ if (ret)
+ pathp = ERR_PTR(ret);
+ else
--- /dev/null
+From miklos@szeredi.hu Wed Nov 2 12:38:35 2011
+From: Miklos Szeredi <miklos@szeredi.hu>
+Date: Tue, 25 Oct 2011 13:59:48 +0200
+Subject: vfs pathname lookup: Add LOOKUP_AUTOMOUNT flag
+To: stable@vger.kernel.org
+Cc: gregkh@suse.de, dhowells@redhat.com, raven@themaw.net, viro@zeniv.linux.org.uk
+Message-ID: <1319543988-12968-5-git-send-email-miklos@szeredi.hu>
+
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+Since we've now turned around and made LOOKUP_FOLLOW *not* force an
+automount, we want to add the ability to force an automount event on
+lookup even if we don't happen to have one of the other flags that force
+it implicitly (LOOKUP_OPEN, LOOKUP_DIRECTORY, LOOKUP_PARENT..)
+
+Most cases will never want to use this, since you'd normally want to
+delay automounting as long as possible, which usually implies
+LOOKUP_OPEN (when we open a file or directory, we really cannot avoid
+the automount any more).
+
+But Trond argued sufficiently forcefully that at a minimum bind mounting
+a file and quotactl will want to force the automount lookup. Some other
+cases (like nfs_follow_remote_path()) could use it too, although
+LOOKUP_DIRECTORY would work there as well.
+
+This commit just adds the flag and logic, no users yet, though. It also
+doesn't actually touch the LOOKUP_NO_AUTOMOUNT flag that is related, and
+was made irrelevant by the same change that made us not follow on
+LOOKUP_FOLLOW.
+
+Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
+Cc: Ian Kent <raven@themaw.net>
+Cc: Jeff Layton <jlayton@redhat.com>
+Cc: Miklos Szeredi <miklos@szeredi.hu>
+Cc: David Howells <dhowells@redhat.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/namei.c | 2 +-
+ include/linux/namei.h | 1 +
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -793,7 +793,7 @@ static int follow_automount(struct path
+ * of the daemon to instantiate them before they can be used.
+ */
+ if (!(flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY |
+- LOOKUP_OPEN | LOOKUP_CREATE)) &&
++ LOOKUP_OPEN | LOOKUP_CREATE | LOOKUP_AUTOMOUNT)) &&
+ path->dentry->d_inode)
+ return -EISDIR;
+
+--- a/include/linux/namei.h
++++ b/include/linux/namei.h
+@@ -49,6 +49,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LA
+ #define LOOKUP_FOLLOW 0x0001
+ #define LOOKUP_DIRECTORY 0x0002
+ #define LOOKUP_CONTINUE 0x0004
++#define LOOKUP_AUTOMOUNT 0x0008
+
+ #define LOOKUP_PARENT 0x0010
+ #define LOOKUP_REVAL 0x0020