From 9825a2ccaa76df56679395e94b7f47e382990b50 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 2 Nov 2011 12:55:32 -0700 Subject: [PATCH] 3.0 patches --- ...input-amp-handling-for-cx20549-codec.patch | 105 ++++++ queue-3.0/jsm-remove-buggy-write-queue.patch | 300 ++++++++++++++++++ ...ss-in-vm_struct-via-proc-vmallocinfo.patch | 169 ++++++++++ ...ar-group_stop_sigmask-on-double-stop.patch | 62 ++++ ...he-empty-pathname-for-normal-lookups.patch | 133 ++++++++ queue-3.0/series | 10 + queue-3.0/um-fix-ubd-cow-size.patch | 66 ++++ ...utomount-should-ignore-lookup_follow.patch | 95 ++++++ ...tomount-for-negative-autofs-dentries.patch | 65 ++++ ...ng-automounter-semantics-regressions.patch | 67 ++++ ...ame-lookup-add-lookup_automount-flag.patch | 67 ++++ 11 files changed, 1139 insertions(+) create mode 100644 queue-3.0/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch create mode 100644 queue-3.0/jsm-remove-buggy-write-queue.patch create mode 100644 queue-3.0/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch create mode 100644 queue-3.0/ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch create mode 100644 queue-3.0/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch create mode 100644 queue-3.0/um-fix-ubd-cow-size.patch create mode 100644 queue-3.0/vfs-automount-should-ignore-lookup_follow.patch create mode 100644 queue-3.0/vfs-fix-automount-for-negative-autofs-dentries.patch create mode 100644 queue-3.0/vfs-fix-the-remaining-automounter-semantics-regressions.patch create mode 100644 queue-3.0/vfs-pathname-lookup-add-lookup_automount-flag.patch 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 index 00000000000..bb513a524db --- /dev/null +++ b/queue-3.0/alsa-hda-fix-adc-input-amp-handling-for-cx20549-codec.patch @@ -0,0 +1,105 @@ +From 6b45214277bec2193ad3ccb8d7aa6100b5a0f1a9 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 14 Oct 2011 15:26:20 +0200 +Subject: ALSA: hda - Fix ADC input-amp handling for Cx20549 codec + +From: Takashi Iwai + +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 +Signed-off-by: Greg Kroah-Hartman + + +--- + 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 index 00000000000..580f7f2f69e --- /dev/null +++ b/queue-3.0/jsm-remove-buggy-write-queue.patch @@ -0,0 +1,300 @@ +From 9d898966c4a07e4a5092215b5a2829d0ef02baa2 Mon Sep 17 00:00:00 2001 +From: Thadeu Lima de Souza Cascardo +Date: Wed, 24 Aug 2011 13:14:22 -0300 +Subject: jsm: remove buggy write queue + +From: Thadeu Lima de Souza Cascardo + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..d01319948ba --- /dev/null +++ b/queue-3.0/mm-avoid-null-pointer-access-in-vm_struct-via-proc-vmallocinfo.patch @@ -0,0 +1,169 @@ +From f5252e009d5b87071a919221e4f6624184005368 Mon Sep 17 00:00:00 2001 +From: Mitsuo Hayasaka +Date: Mon, 31 Oct 2011 17:08:13 -0700 +Subject: mm: avoid null pointer access in vm_struct via /proc/vmallocinfo + +From: Mitsuo Hayasaka + +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 +Cc: Andrew Morton +Cc: David Rientjes +Cc: Namhyung Kim +Cc: "Paul E. McKenney" +Cc: Jeremy Fitzhardinge +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..a5f2a4265d5 --- /dev/null +++ b/queue-3.0/ptrace-don-t-clear-group_stop_sigmask-on-double-stop.patch @@ -0,0 +1,62 @@ +From oleg@redhat.com Wed Nov 2 12:41:29 2011 +From: Oleg Nesterov +Date: Mon, 26 Sep 2011 19:06:32 +0200 +Subject: ptrace: don't clear GROUP_STOP_SIGMASK on double-stop +To: Greg KH +Cc: Tejun Heo , Luke Macken , stable@kernel.org, linux-kernel@vger.kernel.org +Message-ID: <20110926170632.GA16936@redhat.com> +Content-Disposition: inline + +From: Oleg Nesterov + +[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 +Signed-off-by: Oleg Nesterov +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..5b94d9aa6d8 --- /dev/null +++ b/queue-3.0/readlinkat-ensure-we-return-enoent-for-the-empty-pathname-for-normal-lookups.patch @@ -0,0 +1,133 @@ +From 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 Mon Sep 17 00:00:00 2001 +From: Andy Whitcroft +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 + +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 + 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 +Cc: Christoph Hellwig +Cc: Al Viro +Signed-off-by: Andrew Morton +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-3.0/series b/queue-3.0/series index 1a3e942bcee..ae4baa530c0 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 00000000000..2d03c6bc5e8 --- /dev/null +++ b/queue-3.0/um-fix-ubd-cow-size.patch @@ -0,0 +1,66 @@ +From 8535639810e578960233ad39def3ac2157b0c3ec Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Wed, 2 Nov 2011 13:17:27 +0100 +Subject: um: fix ubd cow size + +From: Richard Weinberger + +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + 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 index 00000000000..c859788c6fa --- /dev/null +++ b/queue-3.0/vfs-automount-should-ignore-lookup_follow.patch @@ -0,0 +1,95 @@ +From miklos@szeredi.hu Wed Nov 2 12:37:33 2011 +From: Miklos Szeredi +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 + +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 +Acked-by: Ian Kent +Cc: David Howells +Signed-off-by: Linus Torvalds +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..cb210ec9c3e --- /dev/null +++ b/queue-3.0/vfs-fix-automount-for-negative-autofs-dentries.patch @@ -0,0 +1,65 @@ +From miklos@szeredi.hu Wed Nov 2 12:37:16 2011 +From: David Howells +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 + +commit 5a30d8a2b8ddd5102c440c7e5a7c8e1fd729c818 upstream. +[ backport for 3.0.x: LOOKUP_PARENT => LOOKUP_CONTINUE by Chuck Ebbert + ] + +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 +Acked-by: Ian Kent +Signed-off-by: Al Viro +Cc: Chuck Ebbert +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..21736a38e76 --- /dev/null +++ b/queue-3.0/vfs-fix-the-remaining-automounter-semantics-regressions.patch @@ -0,0 +1,67 @@ +From miklos@szeredi.hu Wed Nov 2 12:38:17 2011 +From: Miklos Szeredi +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 + +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 +[ 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 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..0a131926ead --- /dev/null +++ b/queue-3.0/vfs-pathname-lookup-add-lookup_automount-flag.patch @@ -0,0 +1,67 @@ +From miklos@szeredi.hu Wed Nov 2 12:38:35 2011 +From: Miklos Szeredi +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 + +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 +Cc: Ian Kent +Cc: Jeff Layton +Cc: Miklos Szeredi +Cc: David Howells +Cc: Al Viro +Signed-off-by: Linus Torvalds +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 -- 2.47.3