]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 19:55:32 +0000 (12:55 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 2 Nov 2011 19:55:32 +0000 (12:55 -0700)
queue-3.0/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch [new file with mode: 0644]
queue-3.0/jsm-remove-buggy-write-queue.patch [new file with mode: 0644]
queue-3.0/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch [new file with mode: 0644]
queue-3.0/ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch [new file with mode: 0644]
queue-3.0/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/um-fix-ubd-cow-size.patch [new file with mode: 0644]
queue-3.0/vfs-automount-should-ignore-lookup_follow.patch [new file with mode: 0644]
queue-3.0/vfs-fix-automount-for-negative-autofs-dentries.patch [new file with mode: 0644]
queue-3.0/vfs-fix-the-remaining-automounter-semantics-regressions.patch [new file with mode: 0644]
queue-3.0/vfs-pathname-lookup-add-lookup_automount-flag.patch [new file with mode: 0644]

diff --git a/queue-3.0/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch b/queue-3.0/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch
new file mode 100644 (file)
index 0000000..bb513a5
--- /dev/null
@@ -0,0 +1,105 @@
+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;
diff --git a/queue-3.0/jsm-remove-buggy-write-queue.patch b/queue-3.0/jsm-remove-buggy-write-queue.patch
new file mode 100644 (file)
index 0000000..580f7f2
--- /dev/null
@@ -0,0 +1,300 @@
+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;
+-}
diff --git a/queue-3.0/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch b/queue-3.0/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch
new file mode 100644 (file)
index 0000000..d013199
--- /dev/null
@@ -0,0 +1,169 @@
+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.
diff --git a/queue-3.0/ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch b/queue-3.0/ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch
new file mode 100644 (file)
index 0000000..a5f2a42
--- /dev/null
@@ -0,0 +1,62 @@
+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);
diff --git a/queue-3.0/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch b/queue-3.0/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch
new file mode 100644 (file)
index 0000000..5b94d9a
--- /dev/null
@@ -0,0 +1,133 @@
+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)
index 1a3e942bcee5deb65006ff5069b9d32328f20401..ae4baa530c03b5e2f78ca3fc3f6ad4e36621be58 100644 (file)
@@ -122,3 +122,13 @@ tuner_xc2028-allow-selection-of-the-frequency-adjustment-code-for-xc3028.patch
 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
diff --git a/queue-3.0/um-fix-ubd-cow-size.patch b/queue-3.0/um-fix-ubd-cow-size.patch
new file mode 100644 (file)
index 0000000..2d03c6b
--- /dev/null
@@ -0,0 +1,66 @@
+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, &sector_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);
+ }
diff --git a/queue-3.0/vfs-automount-should-ignore-lookup_follow.patch b/queue-3.0/vfs-automount-should-ignore-lookup_follow.patch
new file mode 100644 (file)
index 0000000..c859788
--- /dev/null
@@ -0,0 +1,95 @@
+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;
diff --git a/queue-3.0/vfs-fix-automount-for-negative-autofs-dentries.patch b/queue-3.0/vfs-fix-automount-for-negative-autofs-dentries.patch
new file mode 100644 (file)
index 0000000..cb210ec
--- /dev/null
@@ -0,0 +1,65 @@
+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;
diff --git a/queue-3.0/vfs-fix-the-remaining-automounter-semantics-regressions.patch b/queue-3.0/vfs-fix-the-remaining-automounter-semantics-regressions.patch
new file mode 100644 (file)
index 0000000..21736a3
--- /dev/null
@@ -0,0 +1,67 @@
+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
diff --git a/queue-3.0/vfs-pathname-lookup-add-lookup_automount-flag.patch b/queue-3.0/vfs-pathname-lookup-add-lookup_automount-flag.patch
new file mode 100644 (file)
index 0000000..0a13192
--- /dev/null
@@ -0,0 +1,67 @@
+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