aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/lguest/lguest.txt4
-rw-r--r--Documentation/sysctl/vm.txt19
-rw-r--r--Documentation/vm/hugetlbpage.txt35
-rw-r--r--arch/alpha/Makefile10
-rw-r--r--arch/alpha/kernel/err_ev7.c2
-rw-r--r--arch/alpha/kernel/err_marvel.c2
-rw-r--r--arch/alpha/kernel/err_titan.c2
-rw-r--r--arch/alpha/kernel/machvec_impl.h2
-rw-r--r--arch/alpha/lib/ev6-stxncpy.S14
-rw-r--r--arch/alpha/lib/strncpy.S2
-rw-r--r--arch/alpha/lib/stxncpy.S14
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/slip_user.c12
-rw-r--r--arch/um/drivers/slirp_user.c15
-rw-r--r--arch/um/drivers/ubd_user.c3
-rw-r--r--arch/um/include/os.h2
-rw-r--r--arch/um/os-Linux/aio.c4
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c10
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c38
-rw-r--r--arch/um/os-Linux/process.c4
-rw-r--r--arch/um/os-Linux/skas/process.c12
-rw-r--r--arch/um/os-Linux/util.c2
-rw-r--r--arch/x86/kernel/suspend_64.c39
-rw-r--r--drivers/block/pktcdvd.c4
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq_stats.c2
-rw-r--r--drivers/dma/ioat_dma.c144
-rw-r--r--drivers/dma/ioatdma.h2
-rw-r--r--drivers/macintosh/via-pmu.c1
-rw-r--r--drivers/parport/procfs.c2
-rw-r--r--drivers/rtc/rtc-at32ap700x.c20
-rw-r--r--fs/Kconfig2
-rw-r--r--fs/dquot.c4
-rw-r--r--fs/ecryptfs/keystore.c2
-rw-r--r--fs/ecryptfs/main.c1
-rw-r--r--fs/ecryptfs/mmap.c31
-rw-r--r--fs/ecryptfs/read_write.c27
-rw-r--r--fs/ext3/super.c2
-rw-r--r--fs/ext4/super.c2
-rw-r--r--include/asm-alpha/io_trivial.h12
-rw-r--r--include/asm-generic/tlb.h4
-rw-r--r--include/linux/Kbuild1
-rw-r--r--include/linux/apm_bios.h6
-rw-r--r--include/linux/hugetlb.h2
-rw-r--r--kernel/sysctl.c8
-rw-r--r--kernel/sysctl_check.c7
-rw-r--r--mm/Kconfig15
-rw-r--r--mm/hugetlb.c68
-rw-r--r--mm/page_alloc.c11
-rw-r--r--mm/slub.c3
-rw-r--r--mm/sparse.c20
-rwxr-xr-xscripts/bloat-o-meter3
53 files changed, 399 insertions, 270 deletions
diff --git a/Documentation/lguest/lguest.txt b/Documentation/lguest/lguest.txt
index 7885ab2d5f5..722d4e7fbeb 100644
--- a/Documentation/lguest/lguest.txt
+++ b/Documentation/lguest/lguest.txt
@@ -109,10 +109,6 @@ Running Lguest:
See http://linux-net.osdl.org/index.php/Bridge for general information
on how to get bridging working.
-- You can also create an inter-guest network using
- "--sharenet=<filename>": any two guests using the same file are on
- the same network. This file is created if it does not exist.
-
There is a helpful mailing list at http://ozlabs.org/mailman/listinfo/lguest
Good luck!
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index b89570c3043..6f31f0a247d 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -34,6 +34,8 @@ Currently, these files are in /proc/sys/vm:
- oom_kill_allocating_task
- mmap_min_address
- numa_zonelist_order
+- nr_hugepages
+- nr_overcommit_hugepages
==============================================================
@@ -305,3 +307,20 @@ will select "node" order in following case.
Otherwise, "zone" order will be selected. Default order is recommended unless
this is causing problems for your system/application.
+
+==============================================================
+
+nr_hugepages
+
+Change the minimum size of the hugepage pool.
+
+See Documentation/vm/hugetlbpage.txt
+
+==============================================================
+
+nr_overcommit_hugepages
+
+Change the maximum size of the hugepage pool. The maximum is
+nr_hugepages + nr_overcommit_hugepages.
+
+See Documentation/vm/hugetlbpage.txt
diff --git a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
index 51ccc48aa76..f962d01bea2 100644
--- a/Documentation/vm/hugetlbpage.txt
+++ b/Documentation/vm/hugetlbpage.txt
@@ -30,9 +30,10 @@ alignment and size of the arguments to the above system calls.
The output of "cat /proc/meminfo" will have lines like:
.....
-HugePages_Total: xxx
-HugePages_Free: yyy
-HugePages_Rsvd: www
+HugePages_Total: vvv
+HugePages_Free: www
+HugePages_Rsvd: xxx
+HugePages_Surp: yyy
Hugepagesize: zzz kB
where:
@@ -42,6 +43,10 @@ allocated.
HugePages_Rsvd is short for "reserved," and is the number of hugepages
for which a commitment to allocate from the pool has been made, but no
allocation has yet been made. It's vaguely analogous to overcommit.
+HugePages_Surp is short for "surplus," and is the number of hugepages in
+the pool above the value in /proc/sys/vm/nr_hugepages. The maximum
+number of surplus hugepages is controlled by
+/proc/sys/vm/nr_overcommit_hugepages.
/proc/filesystems should also show a filesystem of type "hugetlbfs" configured
in the kernel.
@@ -71,7 +76,25 @@ or failure of allocation depends on the amount of physically contiguous
memory that is preset in system at this time. System administrators may want
to put this command in one of the local rc init files. This will enable the
kernel to request huge pages early in the boot process (when the possibility
-of getting physical contiguous pages is still very high).
+of getting physical contiguous pages is still very high). In either
+case, adminstrators will want to verify the number of hugepages actually
+allocated by checking the sysctl or meminfo.
+
+/proc/sys/vm/nr_overcommit_hugepages indicates how large the pool of
+hugepages can grow, if more hugepages than /proc/sys/vm/nr_hugepages are
+requested by applications. echo'ing any non-zero value into this file
+indicates that the hugetlb subsystem is allowed to try to obtain
+hugepages from the buddy allocator, if the normal pool is exhausted. As
+these surplus hugepages go out of use, they are freed back to the buddy
+allocator.
+
+Caveat: Shrinking the pool via nr_hugepages while a surplus is in effect
+will allow the number of surplus huge pages to exceed the overcommit
+value, as the pool hugepages (which must have been in use for a surplus
+hugepages to be allocated) will become surplus hugepages. As long as
+this condition holds, however, no more surplus huge pages will be
+allowed on the system until one of the two sysctls are increased
+sufficiently, or the surplus huge pages go out of use and are freed.
If the user applications are going to request hugepages using mmap system
call, then it is required that system administrator mount a file system of
@@ -94,8 +117,8 @@ provided on command line then no limits are set. For size and nr_inodes
options, you can use [G|g]/[M|m]/[K|k] to represent giga/mega/kilo. For
example, size=2K has the same meaning as size=2048.
-read and write system calls are not supported on files that reside on hugetlb
-file systems.
+While read system calls are supported on files that reside on hugetlb
+file systems, write system calls are not.
Regular chown, chgrp, and chmod commands (with right permissions) could be
used to change the file attributes on hugetlbfs.
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 63104ebd180..4e1a8e2c454 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -14,13 +14,13 @@ LDFLAGS_vmlinux := -static -N #-relax
CHECKFLAGS += -D__alpha__ -m64
cflags-y := -pipe -mno-fp-regs -ffixed-8 -msmall-data
-cpuflags-$(CONFIG_ALPHA_EV67) := -mcpu=ev67
-cpuflags-$(CONFIG_ALPHA_EV6) := -mcpu=ev6
+cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4
+cpuflags-$(CONFIG_ALPHA_EV5) := -mcpu=ev5
+cpuflags-$(CONFIG_ALPHA_EV56) := -mcpu=ev56
cpuflags-$(CONFIG_ALPHA_POLARIS) := -mcpu=pca56
cpuflags-$(CONFIG_ALPHA_SX164) := -mcpu=pca56
-cpuflags-$(CONFIG_ALPHA_EV56) := -mcpu=ev56
-cpuflags-$(CONFIG_ALPHA_EV5) := -mcpu=ev5
-cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4
+cpuflags-$(CONFIG_ALPHA_EV6) := -mcpu=ev6
+cpuflags-$(CONFIG_ALPHA_EV67) := -mcpu=ev67
# If GENERIC, make sure to turn off any instruction set extensions that
# the host compiler might have on by default. Given that EV4 and EV5
# have the same instruction set, prefer EV5 because an EV5 schedule is
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
index bc799f72d8c..68cd493f54c 100644
--- a/arch/alpha/kernel/err_ev7.c
+++ b/arch/alpha/kernel/err_ev7.c
@@ -273,7 +273,7 @@ ev7_process_pal_subpacket(struct el_subpacket *header)
struct el_subpacket_handler ev7_pal_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
-void
+void __init
ev7_register_error_handlers(void)
{
int i;
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
index 497877bf201..413bf37eb09 100644
--- a/arch/alpha/kernel/err_marvel.c
+++ b/arch/alpha/kernel/err_marvel.c
@@ -1152,7 +1152,7 @@ marvel_machine_check(u64 vector, u64 la_ptr)
mb();
}
-void
+void __init
marvel_register_error_handlers(void)
{
ev7_register_error_handlers();
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
index 6f3867877d9..257449ed15e 100644
--- a/arch/alpha/kernel/err_titan.c
+++ b/arch/alpha/kernel/err_titan.c
@@ -564,7 +564,7 @@ static struct el_subpacket_handler titan_subpacket_handler =
SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY,
el_process_regatta_subpacket);
-void
+void __init
titan_register_error_handlers(void)
{
size_t i;
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
index 0caa45aa128..466c9dff818 100644
--- a/arch/alpha/kernel/machvec_impl.h
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -134,7 +134,7 @@
#define __initmv __initdata
#define ALIAS_MV(x)
#else
-#define __initmv
+#define __initmv __initdata_refok
/* GCC actually has a syntax for defining aliases, but is under some
delusion that you shouldn't be able to declare it extern somewhere
diff --git a/arch/alpha/lib/ev6-stxncpy.S b/arch/alpha/lib/ev6-stxncpy.S
index b581a7af245..1aa6e97e04b 100644
--- a/arch/alpha/lib/ev6-stxncpy.S
+++ b/arch/alpha/lib/ev6-stxncpy.S
@@ -362,10 +362,10 @@ $unaligned:
extql t2, a1, t2 # U :
cmpbge zero, t1, t8 # E : is there a zero?
- andnot t2, t6, t12 # E : dest mask for a single word copy
+ andnot t2, t6, t2 # E : dest mask for a single word copy
or t8, t10, t5 # E : test for end-of-count too
- cmpbge zero, t12, t3 # E :
+ cmpbge zero, t2, t3 # E :
cmoveq a2, t5, t8 # E : Latency=2, extra map slot
nop # E : keep with cmoveq
andnot t8, t3, t8 # E : (stall)
@@ -379,13 +379,13 @@ $unaligned:
negq t8, t6 # E : build bitmask of bytes <= zero
mskqh t1, t4, t1 # U :
- and t6, t8, t2 # E :
- subq t2, 1, t6 # E : (stall)
- or t6, t2, t8 # E : (stall)
- zapnot t12, t8, t12 # U : prepare source word; mirror changes (stall)
+ and t6, t8, t12 # E :
+ subq t12, 1, t6 # E : (stall)
+ or t6, t12, t8 # E : (stall)
+ zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
zapnot t1, t8, t1 # U : to source validity mask
- andnot t0, t12, t0 # E : zero place for source to reside
+ andnot t0, t2, t0 # E : zero place for source to reside
or t0, t1, t0 # E : and put it there (stall both t0, t1)
stq_u t0, 0(a0) # L : (stall)
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
index bbdef1be5f9..a46f7f3ad8c 100644
--- a/arch/alpha/lib/strncpy.S
+++ b/arch/alpha/lib/strncpy.S
@@ -35,7 +35,7 @@ strncpy:
or $3, $24, $3 # clear the bits between the last
or $4, $27, $4 # written byte and the last byte in COUNT
- andnot $4, $3, $4
+ andnot $3, $4, $4
zap $1, $4, $1
stq_u $1, 0($16)
diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S
index da1a72740d2..3dece25283a 100644
--- a/arch/alpha/lib/stxncpy.S
+++ b/arch/alpha/lib/stxncpy.S
@@ -315,9 +315,9 @@ $unaligned:
extql t2, a1, t2 # e0 :
cmpbge zero, t1, t8 # .. e1 : is there a zero?
- andnot t2, t6, t12 # e0 : dest mask for a single word copy
+ andnot t2, t6, t2 # e0 : dest mask for a single word copy
or t8, t10, t5 # .. e1 : test for end-of-count too
- cmpbge zero, t12, t3 # e0 :
+ cmpbge zero, t2, t3 # e0 :
cmoveq a2, t5, t8 # .. e1 :
andnot t8, t3, t8 # e0 :
beq t8, $u_head # .. e1 (zdb)
@@ -330,14 +330,14 @@ $unaligned:
ldq_u t0, 0(a0) # e0 :
negq t8, t6 # .. e1 : build bitmask of bytes <= zero
mskqh t1, t4, t1 # e0 :
- and t6, t8, t2 # .. e1 :
- subq t2, 1, t6 # e0 :
- or t6, t2, t8 # e1 :
+ and t6, t8, t12 # .. e1 :
+ subq t12, 1, t6 # e0 :
+ or t6, t12, t8 # e1 :
- zapnot t12, t8, t12 # e0 : prepare source word; mirror changes
+ zapnot t2, t8, t2 # e0 : prepare source word; mirror changes
zapnot t1, t8, t1 # .. e1 : to source validity mask
- andnot t0, t12, t0 # e0 : zero place for source to reside
+ andnot t0, t2, t0 # e0 : zero place for source to reside
or t0, t1, t0 # e1 : and put it there
stq_u t0, 0(a0) # e0 :
ret (t9) # .. e1 :
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 90d7f2e8ead..29185cad9ff 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
close(fds[1]);
if (pid > 0)
- CATCH_EINTR(err = waitpid(pid, NULL, 0));
+ helper_wait(pid, 0, "change_tramp");
return pid;
}
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 5f06204d687..b8711e50da8 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -77,7 +77,7 @@ static int slip_tramp(char **argv, int fd)
{
struct slip_pre_exec_data pe_data;
char *output;
- int status, pid, fds[2], err, output_len;
+ int pid, fds[2], err, output_len;
err = os_pipe(fds, 1, 0);
if (err < 0) {
@@ -109,15 +109,7 @@ static int slip_tramp(char **argv, int fd)
read_output(fds[0], output, output_len);
printk("%s", output);
- CATCH_EINTR(err = waitpid(pid, &status, 0));
- if (err < 0)
- err = errno;
- else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
- printk(UM_KERN_ERR "'%s' didn't exit with status 0\n", argv[0]);
- err = -EINVAL;
- }
- else err = 0;
-
+ err = helper_wait(pid, 0, argv[0]);
close(fds[0]);
out_free:
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index 1865089ff41..89c1be225fd 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -79,7 +79,7 @@ out:
static void slirp_close(int fd, void *data)
{
struct slirp_data *pri = data;
- int status,err;
+ int err;
close(fd);
close(pri->slave);
@@ -98,18 +98,9 @@ static void slirp_close(int fd, void *data)
"(%d)\n", pri->pid, errno);
}
#endif
-
- CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG));
- if (err < 0) {
- printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno);
- return;
- }
-
- if (err == 0) {
- printk(UM_KERN_ERR "slirp_close: process %d has not exited\n",
- pri->pid);
+ err = helper_wait(pri->pid, 1, "slirp_close");
+ if (err < 0)
return;
- }
pri->pid = -1;
}
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 41d254bd38d..48fc7452bc1 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -49,8 +49,7 @@ int start_io_thread(unsigned long sp, int *fd_out)
goto out_close;
}
- pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
- NULL);
+ pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM, NULL);
if(pid < 0){
err = -errno;
printk("start_io_thread - clone failed : errno = %d\n", errno);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index fbf0a87c6ea..6f0d1c741bc 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -214,7 +214,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
extern int run_helper_thread(int (*proc)(void *), void *arg,
unsigned int flags, unsigned long *stack_out);
-extern int helper_wait(int pid);
+extern int helper_wait(int pid, int nohang, char *pname);
/* tls.c */
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
index 4158118c4a5..93dc0c80eba 100644
--- a/arch/um/os-Linux/aio.c
+++ b/arch/um/os-Linux/aio.c
@@ -218,7 +218,7 @@ static int init_aio_24(void)
goto out_close_pipe;
err = run_helper_thread(not_aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
+ CLONE_FILES | CLONE_VM, &aio_stack);
if (err < 0)
goto out_close_pipe;
@@ -254,7 +254,7 @@ static int init_aio_26(void)
}
err = run_helper_thread(aio_thread, NULL,
- CLONE_FILES | CLONE_VM | SIGCHLD, &aio_stack);
+ CLONE_FILES | CLONE_VM, &aio_stack);
if (err < 0)
return err;
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 4ff55360344..07ca0cb472a 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -94,7 +94,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
int control_remote, int data_me, int data_remote)
{
struct etap_pre_exec_data pe_data;
- int pid, status, err, n;
+ int pid, err, n;
char version_buf[sizeof("nnnnn\0")];
char data_fd_buf[sizeof("nnnnnn\0")];
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
@@ -131,13 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
}
if (c != 1) {
printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
- err = -EINVAL;
- CATCH_EINTR(n = waitpid(pid, &status, 0));
- if (n < 0)
- err = -errno;
- else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
- printk(UM_KERN_ERR "uml_net didn't exit with "
- "status 1\n");
+ err = helper_wait(pid, 0, "uml_net");
}
return err;
}
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 6c55d3c8ead..1037a3b6386 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -107,7 +107,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
"errno = %d\n", errno);
return err;
}
- CATCH_EINTR(waitpid(pid, NULL, 0));
+ helper_wait(pid, 0, "tuntap_open_tramp");
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 7a72dbb61b0..fba3f0fefee 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -76,7 +76,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
data.fd = fds[1];
data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
kmalloc(PATH_MAX, UM_GFP_KERNEL);
- pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
+ pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
if (pid < 0) {
ret = -errno;
printk("run_helper : clone failed, errno = %d\n", errno);
@@ -101,7 +101,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
ret = n;
kill(pid, SIGKILL);
}
- CATCH_EINTR(waitpid(pid, NULL, 0));
+ CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
}
out_free2:
@@ -126,7 +126,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
return -ENOMEM;
sp = stack + UM_KERN_PAGE_SIZE - sizeof(void *);
- pid = clone(proc, (void *) sp, flags | SIGCHLD, arg);
+ pid = clone(proc, (void *) sp, flags, arg);
if (pid < 0) {
err = -errno;
printk("run_helper_thread : clone failed, errno = %d\n",
@@ -134,7 +134,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
return err;
}
if (stack_out == NULL) {
- CATCH_EINTR(pid = waitpid(pid, &status, 0));
+ CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
if (pid < 0) {
err = -errno;
printk("run_helper_thread - wait failed, errno = %d\n",
@@ -150,14 +150,30 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
return pid;
}
-int helper_wait(int pid)
+int helper_wait(int pid, int nohang, char *pname)
{
- int ret;
+ int ret, status;
+ int wflags = __WCLONE;
- CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG));
+ if (nohang)
+ wflags |= WNOHANG;
+
+ if (!pname)
+ pname = "helper_wait";
+
+ CATCH_EINTR(ret = waitpid(pid, &status, wflags));
if (ret < 0) {
- ret = -errno;
- printk("helper_wait : waitpid failed, errno = %d\n", errno);
- }
- return ret;
+ printk(UM_KERN_ERR "%s : waitpid process %d failed, "
+ "errno = %d\n", pname, pid, errno);
+ return -errno;
+ } else if (nohang && ret == 0) {
+ printk(UM_KERN_ERR "%s : process %d has not exited\n",
+ pname, pid);
+ return -ECHILD;
+ } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ printk(UM_KERN_ERR "%s : process %d didn't exit with "
+ "status 0\n", pname, pid);
+ return -ECHILD;
+ } else
+ return 0;
}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 37781db4cec..bda5c3150d6 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -101,7 +101,7 @@ void os_kill_process(int pid, int reap_child)
{
kill(pid, SIGKILL);
if (reap_child)
- CATCH_EINTR(waitpid(pid, NULL, 0));
+ CATCH_EINTR(waitpid(pid, NULL, __WALL));
}
/* This is here uniquely to have access to the userspace errno, i.e. the one
@@ -130,7 +130,7 @@ void os_kill_ptraced_process(int pid, int reap_child)
ptrace(PTRACE_KILL, pid);
ptrace(PTRACE_CONT, pid);
if (reap_child)
- CATCH_EINTR(waitpid(pid, NULL, 0));
+ CATCH_EINTR(waitpid(pid, NULL, __WALL));
}
/* Don't use the glibc version, which caches the result in TLS. It misses some
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index d77c81d7068..e8b7a97e83d 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -64,7 +64,7 @@ void wait_stub_done(int pid)
int n, status, err;
while (1) {
- CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
if ((n < 0) || !WIFSTOPPED(status))
goto bad_wait;
@@ -153,7 +153,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
panic("handle_trap - continuing to end of syscall "
"failed, errno = %d\n", errno);
- CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
if ((err < 0) || !WIFSTOPPED(status) ||
(WSTOPSIG(status) != SIGTRAP + 0x80)) {
err = ptrace_dump_regs(pid);
@@ -255,16 +255,18 @@ int start_userspace(unsigned long stub_stack)
panic("start_userspace : mmap failed, errno = %d", errno);
sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
- flags = CLONE_FILES | SIGCHLD;
+ flags = CLONE_FILES;
if (proc_mm)
flags |= CLONE_VM;
+ else
+ flags |= SIGCHLD;
pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
if (pid < 0)
panic("start_userspace : clone failed, errno = %d", errno);
do {
- CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
if (n < 0)
panic("start_userspace : wait failed, errno = %d",
errno);
@@ -314,7 +316,7 @@ void userspace(struct uml_pt_regs *regs)
"pid=%d, ptrace operation = %d, errno = %d\n",
pid, op, errno);
- CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
+ CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
if (err < 0)
panic("userspace - waitpid failed, errno = %d\n",
errno);
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index ef095436a78..3e058ce9ffb 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -141,7 +141,7 @@ void os_dump_core(void)
* nothing reasonable to do if that fails.
*/
- while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
+ while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
os_kill_ptraced_process(pid, 0);
abort();
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c
index db284ef44d5..2e5efaaf880 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/kernel/suspend_64.c
@@ -192,42 +192,25 @@ static int res_phys_pud_init(pud_t *pud, unsigned long address, unsigned long en
return 0;
}
-static int res_kernel_text_pud_init(pud_t *pud, unsigned long start)
-{
- pmd_t *pmd;
- unsigned long paddr;
-
- pmd = (pmd_t *)get_safe_page(GFP_ATOMIC);
- if (!pmd)
- return -ENOMEM;
- set_pud(pud + pud_index(start), __pud(__pa(pmd) | _KERNPG_TABLE));
- for (paddr = 0; paddr < KERNEL_TEXT_SIZE; pmd++, paddr += PMD_SIZE) {
- unsigned long pe;
-
- pe = __PAGE_KERNEL_LARGE_EXEC | _PAGE_GLOBAL | paddr;
- pe &= __supported_pte_mask;
- set_pmd(pmd, __pmd(pe));
- }
-
- return 0;
-}
-
static int set_up_temporary_mappings(void)
{
unsigned long start, end, next;
- pud_t *pud;
int error;
temp_level4_pgt = (pgd_t *)get_safe_page(GFP_ATOMIC);
if (!temp_level4_pgt)
return -ENOMEM;
+ /* It is safe to reuse the original kernel mapping */
+ set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
+ init_level4_pgt[pgd_index(__START_KERNEL_map)]);
+
/* Set up the direct mapping from scratch */
start = (unsigned long)pfn_to_kaddr(0);
end = (unsigned long)pfn_to_kaddr(end_pfn);
for (; start < end; start = next) {
- pud = (pud_t *)get_safe_page(GFP_ATOMIC);
+ pud_t *pud = (pud_t *)get_safe_page(GFP_ATOMIC);
if (!pud)
return -ENOMEM;
next = start + PGDIR_SIZE;
@@ -238,17 +221,7 @@ static int set_up_temporary_mappings(void)
set_pgd(temp_level4_pgt + pgd_index(start),
mk_kernel_pgd(__pa(pud)));
}
-
- /* Set up the kernel text mapping from scratch */
- pud = (pud_t *)get_safe_page(GFP_ATOMIC);
- if (!pud)
- return -ENOMEM;
- error = res_kernel_text_pud_init(pud, __START_KERNEL_map);
- if (!error)
- set_pgd(temp_level4_pgt + pgd_index(__START_KERNEL_map),
- __pgd(__pa(pud) | _PAGE_TABLE));
-
- return error;
+ return 0;
}
int swsusp_arch_resume(void)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index a5ee21319d3..3535ef89667 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -117,8 +117,10 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
p->kobj.parent = parent;
p->kobj.ktype = ktype;
p->pd = pd;
- if (kobject_register(&p->kobj) != 0)
+ if (kobject_register(&p->kobj) != 0) {
+ kobject_put(&p->kobj);
return NULL;
+ }
return p;
}
/*
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 5e626b12b97..79581fab82d 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -841,19 +841,25 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
drv_attr = cpufreq_driver->attr;
while ((drv_attr) && (*drv_attr)) {
ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
- if (ret)
+ if (ret) {
+ unlock_policy_rwsem_write(cpu);
goto err_out_driver_exit;
+ }
drv_attr++;
}
if (cpufreq_driver->get){
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
- if (ret)
+ if (ret) {
+ unlock_policy_rwsem_write(cpu);
goto err_out_driver_exit;
+ }
}
if (cpufreq_driver->target){
ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr);
- if (ret)
+ if (ret) {
+ unlock_policy_rwsem_write(cpu);
goto err_out_driver_exit;
+ }
}
spin_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 8a45d0f93e2..1b8312b0200 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -164,7 +164,7 @@ freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
return -1;
}
-static void __cpuexit cpufreq_stats_free_table(unsigned int cpu)
+static void cpufreq_stats_free_table(unsigned int cpu)
{
struct cpufreq_stats *stat = cpufreq_stats_table[cpu];
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c
index c1c2dcc6fc2..45e7b4666c7 100644
--- a/drivers/dma/ioat_dma.c
+++ b/drivers/dma/ioat_dma.c
@@ -173,10 +173,47 @@ static void ioat_set_dest(dma_addr_t addr,
tx_to_ioat_desc(tx)->dst = addr;
}
+/**
+ * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
+ * descriptors to hw
+ * @chan: DMA channel handle
+ */
static inline void __ioat1_dma_memcpy_issue_pending(
- struct ioat_dma_chan *ioat_chan);
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);
+}
+
+static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat1_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
+
static inline void __ioat2_dma_memcpy_issue_pending(
- struct ioat_dma_chan *ioat_chan);
+ struct ioat_dma_chan *ioat_chan)
+{
+ ioat_chan->pending = 0;
+ writew(ioat_chan->dmacount,
+ ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
+}
+
+static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+ struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+ if (ioat_chan->pending != 0) {
+ spin_lock_bh(&ioat_chan->desc_lock);
+ __ioat2_dma_memcpy_issue_pending(ioat_chan);
+ spin_unlock_bh(&ioat_chan->desc_lock);
+ }
+}
static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
{
@@ -203,7 +240,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx)
prev = to_ioat_desc(ioat_chan->used_desc.prev);
prefetch(prev->hw);
do {
- copy = min((u32) len, ioat_chan->xfercap);
+ copy = min_t(size_t, len, ioat_chan->xfercap);
new->async_tx.ack = 1;
@@ -291,10 +328,12 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx)
orig_ack = first->async_tx.ack;
new = first;
- /* ioat_chan->desc_lock is still in force in version 2 path */
-
+ /*
+ * ioat_chan->desc_lock is still in force in version 2 path
+ * it gets unlocked at end of this function
+ */
do {
- copy = min((u32) len, ioat_chan->xfercap);
+ copy = min_t(size_t, len, ioat_chan->xfercap);
new->async_tx.ack = 1;
@@ -432,7 +471,7 @@ static void ioat2_dma_massage_chan_desc(struct ioat_dma_chan *ioat_chan)
static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
{
struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
- struct ioat_desc_sw *desc = NULL;
+ struct ioat_desc_sw *desc;
u16 chanctrl;
u32 chanerr;
int i;
@@ -575,7 +614,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan)
static struct ioat_desc_sw *
ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
{
- struct ioat_desc_sw *new = NULL;
+ struct ioat_desc_sw *new;
if (!list_empty(&ioat_chan->free_desc)) {
new = to_ioat_desc(ioat_chan->free_desc.next);
@@ -583,9 +622,11 @@ ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
} else {
/* try to get another desc */
new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
- /* will this ever happen? */
- /* TODO add upper limit on these */
- BUG_ON(!new);
+ if (!new) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "alloc failed\n");
+ return NULL;
+ }
}
prefetch(new->hw);
@@ -595,7 +636,7 @@ ioat1_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
static struct ioat_desc_sw *
ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
{
- struct ioat_desc_sw *new = NULL;
+ struct ioat_desc_sw *new;
/*
* used.prev points to where to start processing
@@ -609,8 +650,8 @@ ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
if (ioat_chan->used_desc.prev &&
ioat_chan->used_desc.next == ioat_chan->used_desc.prev->prev) {
- struct ioat_desc_sw *desc = NULL;
- struct ioat_desc_sw *noop_desc = NULL;
+ struct ioat_desc_sw *desc;
+ struct ioat_desc_sw *noop_desc;
int i;
/* set up the noop descriptor */
@@ -624,10 +665,14 @@ ioat2_dma_get_next_descriptor(struct ioat_dma_chan *ioat_chan)
ioat_chan->pending++;
ioat_chan->dmacount++;
- /* get a few more descriptors */
+ /* try to get a few more descriptors */
for (i = 16; i; i--) {
desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
- BUG_ON(!desc);
+ if (!desc) {
+ dev_err(&ioat_chan->device->pdev->dev,
+ "alloc failed\n");
+ break;
+ }
list_add_tail(&desc->node, ioat_chan->used_desc.next);
desc->hw->next
@@ -677,10 +722,13 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy(
spin_lock_bh(&ioat_chan->desc_lock);
new = ioat_dma_get_next_descriptor(ioat_chan);
- new->len = len;
spin_unlock_bh(&ioat_chan->desc_lock);
- return new ? &new->async_tx : NULL;
+ if (new) {
+ new->len = len;
+ return &new->async_tx;
+ } else
+ return NULL;
}
static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
@@ -693,53 +741,17 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy(
spin_lock_bh(&ioat_chan->desc_lock);
new = ioat2_dma_get_next_descriptor(ioat_chan);
- new->len = len;
-
- /* leave ioat_chan->desc_lock set in version 2 path */
- return new ? &new->async_tx : NULL;
-}
+ /*
+ * leave ioat_chan->desc_lock set in ioat 2 path
+ * it will get unlocked at end of tx_submit
+ */
-/**
- * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended
- * descriptors to hw
- * @chan: DMA channel handle
- */
-static inline void __ioat1_dma_memcpy_issue_pending(
- struct ioat_dma_chan *ioat_chan)
-{
- ioat_chan->pending = 0;
- writeb(IOAT_CHANCMD_APPEND, ioat_chan->reg_base + IOAT1_CHANCMD_OFFSET);
-}
-
-static void ioat1_dma_memcpy_issue_pending(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- if (ioat_chan->pending != 0) {
- spin_lock_bh(&ioat_chan->desc_lock);
- __ioat1_dma_memcpy_issue_pending(ioat_chan);
- spin_unlock_bh(&ioat_chan->desc_lock);
- }
-}
-
-static inline void __ioat2_dma_memcpy_issue_pending(
- struct ioat_dma_chan *ioat_chan)
-{
- ioat_chan->pending = 0;
- writew(ioat_chan->dmacount,
- ioat_chan->reg_base + IOAT_CHAN_DMACOUNT_OFFSET);
-}
-
-static void ioat2_dma_memcpy_issue_pending(struct dma_chan *chan)
-{
- struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
-
- if (ioat_chan->pending != 0) {
- spin_lock_bh(&ioat_chan->desc_lock);
- __ioat2_dma_memcpy_issue_pending(ioat_chan);
- spin_unlock_bh(&ioat_chan->desc_lock);
- }
+ if (new) {
+ new->len = len;
+ return &new->async_tx;
+ } else
+ return NULL;
}
static void ioat_dma_cleanup_tasklet(unsigned long data)
@@ -1019,7 +1031,7 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
static void ioat_dma_test_callback(void *dma_async_param)
{
printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n",
- dma_async_param);
+ dma_async_param);
}
/**
@@ -1032,7 +1044,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
u8 *src;
u8 *dest;
struct dma_chan *dma_chan;
- struct dma_async_tx_descriptor *tx = NULL;
+ struct dma_async_tx_descriptor *tx;
dma_addr_t addr;
dma_cookie_t cookie;
int err = 0;
@@ -1351,7 +1363,7 @@ err_completion_pool:
err_dma_pool:
kfree(device);
err_kzalloc:
- dev_err(&device->pdev->dev,
+ dev_err(&pdev->dev,
"Intel(R) I/OAT DMA Engine initialization failed\n");
return NULL;
}
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
index b668234ef65..f2c7fedbf00 100644
--- a/drivers/dma/ioatdma.h
+++ b/drivers/dma/ioatdma.h
@@ -76,7 +76,7 @@ struct ioat_dma_chan {
dma_cookie_t completed_cookie;
unsigned long last_completion;
- u32 xfercap; /* XFERCAP register value expanded out */
+ size_t xfercap; /* XFERCAP register value expanded out */
spinlock_t cleanup_lock;
spinlock_t desc_lock;
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index dc741d3a453..6123c70153d 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2336,6 +2336,7 @@ powerbook_sleep_3400(void)
ret = pmac_suspend_devices();
if (ret) {
pbook_free_pci_save();
+ iounmap(mem_ctrl);
printk(KERN_ERR "Sleep rejected by devices\n");
return ret;
}
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index ed82e41210d..d950fc34320 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -384,7 +384,7 @@ parport_device_sysctl_template = {
{
.procname = "timeslice",
.data = NULL,
- .maxlen = sizeof(int),
+ .maxlen = sizeof(unsigned long),
.mode = 0644,
.proc_handler = &proc_doulongvec_ms_jiffies_minmax,
.extra1 = (void*) &parport_min_timeslice_value,
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index 2999214ca53..d3b9b14267a 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -225,18 +225,12 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
goto out;
}
- ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
- if (ret) {
- dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
- goto out;
- }
-
rtc->irq = irq;
rtc->regs = ioremap(regs->start, regs->end - regs->start + 1);
if (!rtc->regs) {
ret = -ENOMEM;
dev_dbg(&pdev->dev, "could not map I/O memory\n");
- goto out_free_irq;
+ goto out;
}
spin_lock_init(&rtc->lock);
@@ -253,12 +247,18 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
| RTC_BIT(CTRL_EN));
}
+ ret = request_irq(irq, at32_rtc_interrupt, IRQF_SHARED, "rtc", rtc);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq %d\n", irq);
+ goto out_iounmap;
+ }
+
rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
&at32_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
dev_dbg(&pdev->dev, "could not register rtc device\n");
ret = PTR_ERR(rtc->rtc);
- goto out_iounmap;
+ goto out_free_irq;
}
platform_set_drvdata(pdev, rtc);
@@ -268,10 +268,10 @@ static int __init at32_rtc_probe(struct platform_device *pdev)
return 0;
-out_iounmap:
- iounmap(rtc->regs);
out_free_irq:
free_irq(irq, rtc);
+out_iounmap:
+ iounmap(rtc->regs);
out:
kfree(rtc);
return ret;
diff --git a/fs/Kconfig b/fs/Kconfig
index 635f3e286ad..487236c6583 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1305,7 +1305,7 @@ config JFFS2_COMPRESSION_OPTIONS
help
Enabling this option allows you to explicitly choose which
compression modules, if any, are enabled in JFFS2. Removing
- compressors and mean you cannot read existing file systems,
+ compressors can mean you cannot read existing file systems,
and enabling experimental compressors can mean that you
write a file system which cannot be read by a standard kernel.
diff --git a/fs/dquot.c b/fs/dquot.c
index 2809768d9c4..686ab63a7c6 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -965,7 +965,7 @@ err_out:
}
#endif
-static inline void flush_warnings(struct dquot **dquots, char *warntype)
+static inline void flush_warnings(struct dquot * const *dquots, char *warntype)
{
int i;
@@ -1216,7 +1216,7 @@ warn_put_all:
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (inode->i_dquot[cnt])
mark_dquot_dirty(inode->i_dquot[cnt]);
- flush_warnings((struct dquot **)inode->i_dquot, warntype);
+ flush_warnings(inode->i_dquot, warntype);
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return ret;
}
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 263fed88c0c..f458c1f3556 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -1860,7 +1860,7 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
struct ecryptfs_global_auth_tok *new_auth_tok;
int rc = 0;
- new_auth_tok = kmem_cache_alloc(ecryptfs_global_auth_tok_cache,
+ new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache,
GFP_KERNEL);
if (!new_auth_tok) {
rc = -ENOMEM;
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b83a512b7e0..a277754da17 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -523,6 +523,7 @@ static int ecryptfs_read_super(struct super_block *sb, const char *dev_name)
lower_mnt = nd.mnt;
ecryptfs_set_superblock_lower(sb, lower_root->d_sb);
sb->s_maxbytes = lower_root->d_sb->s_maxbytes;
+ sb->s_blocksize = lower_root->d_sb->s_blocksize;
ecryptfs_set_dentry_lower(sb->s_root, lower_root);
ecryptfs_set_dentry_lower_mnt(sb->s_root, lower_mnt);
rc = ecryptfs_interpose(lower_root, sb->s_root, sb, 0);
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 16a7a555f39..32c5711d79a 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -263,14 +263,13 @@ out:
return 0;
}
+/* This function must zero any hole we create */
static int ecryptfs_prepare_write(struct file *file, struct page *page,
unsigned from, unsigned to)
{
int rc = 0;
+ loff_t prev_page_end_size;
- if (from == 0 && to == PAGE_CACHE_SIZE)
- goto out; /* If we are writing a full page, it will be
- up to date. */
if (!PageUptodate(page)) {
rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
PAGE_CACHE_SIZE,
@@ -283,22 +282,32 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
} else
SetPageUptodate(page);
}
- if (page->index != 0) {
- loff_t end_of_prev_pg_pos =
- (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1);
- if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) {
+ prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
+
+ /*
+ * If creating a page or more of holes, zero them out via truncate.
+ * Note, this will increase i_size.
+ */
+ if (page->index != 0) {
+ if (prev_page_end_size > i_size_read(page->mapping->host)) {
rc = ecryptfs_truncate(file->f_path.dentry,
- end_of_prev_pg_pos);
+ prev_page_end_size);
if (rc) {
printk(KERN_ERR "Error on attempt to "
"truncate to (higher) offset [%lld];"
- " rc = [%d]\n", end_of_prev_pg_pos, rc);
+ " rc = [%d]\n", prev_page_end_size, rc);
goto out;
}
}
- if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host))
- zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
+ }
+ /*
+ * Writing to a new page, and creating a small hole from start of page?
+ * Zero it out.
+ */
+ if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
+ (from != 0)) {
+ zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
}
out:
return rc;
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 6b7474a4336..948f57624c0 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -124,6 +124,10 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
loff_t pos;
int rc = 0;
+ /*
+ * if we are writing beyond current size, then start pos
+ * at the current size - we'll fill in zeros from there.
+ */
if (offset > ecryptfs_file_size)
pos = ecryptfs_file_size;
else
@@ -137,6 +141,7 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes;
if (pos < offset) {
+ /* remaining zeros to write, up to destination offset */
size_t total_remaining_zeros = (offset - pos);
if (num_bytes > total_remaining_zeros)
@@ -167,17 +172,27 @@ int ecryptfs_write(struct file *ecryptfs_file, char *data, loff_t offset,
}
}
ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
+
+ /*
+ * pos: where we're now writing, offset: where the request was
+ * If current pos is before request, we are filling zeros
+ * If we are at or beyond request, we are writing the *data*
+ * If we're in a fresh page beyond eof, zero it in either case
+ */
+ if (pos < offset || !start_offset_in_page) {
+ /* We are extending past the previous end of the file.
+ * Fill in zero values to the end of the page */
+ memset(((char *)ecryptfs_page_virt
+ + start_offset_in_page), 0,
+ PAGE_CACHE_SIZE - start_offset_in_page);
+ }
+
+ /* pos >= offset, we are now writing the data request */
if (pos >= offset) {
memcpy(((char *)ecryptfs_page_virt
+ start_offset_in_page),
(data + data_offset), num_bytes);
data_offset += num_bytes;
- } else {
- /* We are extending past the previous end of the file.
- * Fill in zero values up to the start of where we
- * will be writing data. */
- memset(((char *)ecryptfs_page_virt
- + start_offset_in_page), 0, num_bytes);
}
kunmap_atomic(ecryptfs_page_virt, KM_USER0);
flush_dcache_page(ecryptfs_page);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index de55da9e28b..cb14de1502c 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1676,7 +1676,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
- if (EXT3_INODE_SIZE(sb) == 0)
+ if (EXT3_INODE_SIZE(sb) == 0 || EXT3_INODES_PER_GROUP(sb) == 0)
goto cantfind_ext3;
sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);
if (sbi->s_inodes_per_block == 0)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 8031dc0e24e..1ca0f546c46 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1797,7 +1797,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent)
sbi->s_desc_size = EXT4_MIN_DESC_SIZE;
sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
- if (EXT4_INODE_SIZE(sb) == 0)
+ if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
goto cantfind_ext4;
sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
if (sbi->s_inodes_per_block == 0)
diff --git a/include/asm-alpha/io_trivial.h b/include/asm-alpha/io_trivial.h
index b10d1aa4cdd..1c77f10b4b3 100644
--- a/include/asm-alpha/io_trivial.h
+++ b/include/asm-alpha/io_trivial.h
@@ -72,25 +72,29 @@ IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
__EXTERN_INLINE u8
IO_CONCAT(__IO_PREFIX,readb)(const volatile void __iomem *a)
{
- return IO_CONCAT(__IO_PREFIX,ioread8)((void __iomem *)a);
+ void __iomem *addr = (void __iomem *)a;
+ return IO_CONCAT(__IO_PREFIX,ioread8)(addr);
}
__EXTERN_INLINE u16
IO_CONCAT(__IO_PREFIX,readw)(const volatile void __iomem *a)
{
- return IO_CONCAT(__IO_PREFIX,ioread16)((void __iomem *)a);
+ void __iomem *addr = (void __iomem *)a;
+ return IO_CONCAT(__IO_PREFIX,ioread16)(addr);
}
__EXTERN_INLINE void
IO_CONCAT(__IO_PREFIX,writeb)(u8 b, volatile void __iomem *a)
{
- IO_CONCAT(__IO_PREFIX,iowrite8)(b, (void __iomem *)a);
+ void __iomem *addr = (void __iomem *)a;
+ IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
}
__EXTERN_INLINE void
IO_CONCAT(__IO_PREFIX,writew)(u16 b, volatile void __iomem *a)
{
- IO_CONCAT(__IO_PREFIX,iowrite16)(b, (void __iomem *)a);
+ void __iomem *addr = (void __iomem *)a;
+ IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
}
#endif
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index f490e43a90b..799307eea40 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -14,6 +14,7 @@
#define _ASM_GENERIC__TLB_H
#include <linux/swap.h>
+#include <linux/quicklist.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
@@ -85,6 +86,9 @@ tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
static inline void
tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
{
+#ifdef CONFIG_QUICKLIST
+ tlb->need_flush += &__get_cpu_var(quicklist)[0].nr_pages != 0;
+#endif
tlb_flush_mmu(tlb, start, end);
/* keep the page table cache within bounds */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 37bfa19d806..9abf5a806c1 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -145,7 +145,6 @@ header-y += sound.h
header-y += taskstats.h
header-y += telephony.h
header-y += termios.h
-header-y += ticable.h
header-y += times.h
header-y += tiocl.h
header-y += tipc.h
diff --git a/include/linux/apm_bios.h b/include/linux/apm_bios.h
index 9754baa1492..01a6244c9bc 100644
--- a/include/linux/apm_bios.h
+++ b/include/linux/apm_bios.h
@@ -18,6 +18,9 @@
#include <linux/types.h>
+typedef unsigned short apm_event_t;
+typedef unsigned short apm_eventinfo_t;
+
struct apm_bios_info {
__u16 version;
__u16 cseg;
@@ -32,9 +35,6 @@ struct apm_bios_info {
#ifdef __KERNEL__
-typedef unsigned short apm_event_t;
-typedef unsigned short apm_eventinfo_t;
-
#define APM_CS (GDT_ENTRY_APMBIOS_BASE * 8)
#define APM_CS_16 (APM_CS + 8)
#define APM_DS (APM_CS_16 + 8)
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 24968790bc3..30d606afcaf 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -33,7 +33,7 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
extern unsigned long max_huge_pages;
extern unsigned long hugepages_treat_as_movable;
-extern int hugetlb_dynamic_pool;
+extern unsigned long nr_overcommit_huge_pages;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8ac51714b08..1135de73087 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -906,11 +906,11 @@ static struct ctl_table vm_table[] = {
},
{
.ctl_name = CTL_UNNUMBERED,
- .procname = "hugetlb_dynamic_pool",
- .data = &hugetlb_dynamic_pool,
- .maxlen = sizeof(hugetlb_dynamic_pool),
+ .procname = "nr_overcommit_hugepages",
+ .data = &nr_overcommit_huge_pages,
+ .maxlen = sizeof(nr_overcommit_huge_pages),
.mode = 0644,
- .proc_handler = &proc_dointvec,
+ .proc_handler = &proc_doulongvec_minmax,
},
#endif
{
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index bed939f82c3..a68425a5cc1 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -428,7 +428,7 @@ static struct trans_ctl_table trans_net_netrom_table[] = {
{}
};
-static struct trans_ctl_table trans_net_ax25_table[] = {
+static struct trans_ctl_table trans_net_ax25_param_table[] = {
{ NET_AX25_IP_DEFAULT_MODE, "ip_default_mode" },
{ NET_AX25_DEFAULT_MODE, "ax25_default_mode" },
{ NET_AX25_BACKOFF_TYPE, "backoff_type" },
@@ -446,6 +446,11 @@ static struct trans_ctl_table trans_net_ax25_table[] = {
{}
};
+static struct trans_ctl_table trans_net_ax25_table[] = {
+ { 0, NULL, trans_net_ax25_param_table },
+ {}
+};
+
static struct trans_ctl_table trans_net_bridge_table[] = {
{ NET_BRIDGE_NF_CALL_ARPTABLES, "bridge-nf-call-arptables" },
{ NET_BRIDGE_NF_CALL_IPTABLES, "bridge-nf-call-iptables" },
diff --git a/mm/Kconfig b/mm/Kconfig
index c070ec0c15b..9ef97417a0b 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -112,18 +112,17 @@ config SPARSEMEM_EXTREME
def_bool y
depends on SPARSEMEM && !SPARSEMEM_STATIC
-#
-# SPARSEMEM_VMEMMAP uses a virtually mapped mem_map to optimise pfn_to_page
-# and page_to_pfn. The most efficient option where kernel virtual space is
-# not under pressure.
-#
config SPARSEMEM_VMEMMAP_ENABLE
def_bool n
config SPARSEMEM_VMEMMAP
- bool
- depends on SPARSEMEM
- default y if (SPARSEMEM_VMEMMAP_ENABLE)
+ bool "Sparse Memory virtual memmap"
+ depends on SPARSEMEM && SPARSEMEM_VMEMMAP_ENABLE
+ default y
+ help
+ SPARSEMEM_VMEMMAP uses a virtually mapped memmap to optimise
+ pfn_to_page and page_to_pfn operations. This is the most
+ efficient option when sufficient kernel resources are available.
# eventually, we can have this option just 'select SPARSEMEM'
config MEMORY_HOTPLUG
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 6f978218c2c..7224a4f0710 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -31,7 +31,7 @@ static unsigned int free_huge_pages_node[MAX_NUMNODES];
static unsigned int surplus_huge_pages_node[MAX_NUMNODES];
static gfp_t htlb_alloc_mask = GFP_HIGHUSER;
unsigned long hugepages_treat_as_movable;
-int hugetlb_dynamic_pool;
+unsigned long nr_overcommit_huge_pages;
static int hugetlb_next_nid;
/*
@@ -227,22 +227,58 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma,
unsigned long address)
{
struct page *page;
+ unsigned int nid;
- /* Check if the dynamic pool is enabled */
- if (!hugetlb_dynamic_pool)
+ /*
+ * Assume we will successfully allocate the surplus page to
+ * prevent racing processes from causing the surplus to exceed
+ * overcommit
+ *
+ * This however introduces a different race, where a process B
+ * tries to grow the static hugepage pool while alloc_pages() is
+ * called by process A. B will only examine the per-node
+ * counters in determining if surplus huge pages can be
+ * converted to normal huge pages in adjust_pool_surplus(). A
+ * won't be able to increment the per-node counter, until the
+ * lock is dropped by B, but B doesn't drop hugetlb_lock until
+ * no more huge pages can be converted from surplus to normal
+ * state (and doesn't try to convert again). Thus, we have a
+ * case where a surplus huge page exists, the pool is grown, and
+ * the surplus huge page still exists after, even though it
+ * should just have been converted to a normal huge page. This
+ * does not leak memory, though, as the hugepage will be freed
+ * once it is out of use. It also does not allow the counters to
+ * go out of whack in adjust_pool_surplus() as we don't modify
+ * the node values until we've gotten the hugepage and only the
+ * per-node value is checked there.
+ */
+ spin_lock(&hugetlb_lock);
+ if (surplus_huge_pages >= nr_overcommit_huge_pages) {
+ spin_unlock(&hugetlb_lock);
return NULL;
+ } else {
+ nr_huge_pages++;
+ surplus_huge_pages++;
+ }
+ spin_unlock(&hugetlb_lock);
page = alloc_pages(htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN,
HUGETLB_PAGE_ORDER);
+
+ spin_lock(&hugetlb_lock);
if (page) {
+ nid = page_to_nid(page);
set_compound_page_dtor(page, free_huge_page);
- spin_lock(&hugetlb_lock);
- nr_huge_pages++;
- nr_huge_pages_node[page_to_nid(page)]++;
- surplus_huge_pages++;
- surplus_huge_pages_node[page_to_nid(page)]++;
- spin_unlock(&hugetlb_lock);
+ /*
+ * We incremented the global counters already
+ */
+ nr_huge_pages_node[nid]++;
+ surplus_huge_pages_node[nid]++;
+ } else {
+ nr_huge_pages--;
+ surplus_huge_pages--;
}
+ spin_unlock(&hugetlb_lock);
return page;
}
@@ -481,6 +517,12 @@ static unsigned long set_max_huge_pages(unsigned long count)
* Increase the pool size
* First take pages out of surplus state. Then make up the
* remaining difference by allocating fresh huge pages.
+ *
+ * We might race with alloc_buddy_huge_page() here and be unable
+ * to convert a surplus huge page to a normal huge page. That is
+ * not critical, though, it just means the overall size of the
+ * pool might be one hugepage larger than it needs to be, but
+ * within all the constraints specified by the sysctls.
*/
spin_lock(&hugetlb_lock);
while (surplus_huge_pages && count > persistent_huge_pages) {
@@ -509,6 +551,14 @@ static unsigned long set_max_huge_pages(unsigned long count)
* to keep enough around to satisfy reservations). Then place
* pages into surplus state as needed so the pool will shrink
* to the desired size as pages become free.
+ *
+ * By placing pages into the surplus state independent of the
+ * overcommit value, we are allowing the surplus pool size to
+ * exceed overcommit. There are few sane options here. Since
+ * alloc_buddy_huge_page() is checking the global counter,
+ * though, we'll note that we're not allowed to exceed surplus
+ * and won't grow the pool anywhere else. Not until one of the
+ * sysctls are changed, or the surplus pages go out of use.
*/
min_count = resv_huge_pages + nr_huge_pages - free_huge_pages;
min_count = max(count, min_count);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b5a58d476c1..d73bfad1c32 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -847,8 +847,19 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
struct page *page = __rmqueue(zone, order, migratetype);
if (unlikely(page == NULL))
break;
+
+ /*
+ * Split buddy pages returned by expand() are received here
+ * in physical page order. The page is added to the callers and
+ * list and the list head then moves forward. From the callers
+ * perspective, the linked list is ordered by page number in
+ * some conditions. This is useful for IO devices that can
+ * merge IO requests if the physical pages are ordered
+ * properly.
+ */
list_add(&page->lru, list);
set_page_private(page, migratetype);
+ list = &page->lru;
}
spin_unlock(&zone->lock);
return i;
diff --git a/mm/slub.c b/mm/slub.c
index 9c1d9f3b364..b9f37cb0f2e 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1468,9 +1468,6 @@ static void *__slab_alloc(struct kmem_cache *s,
void **object;
struct page *new;
- /* We handle __GFP_ZERO in the caller */
- gfpflags &= ~__GFP_ZERO;
-
if (!c->page)
goto new_slab;
diff --git a/mm/sparse.c b/mm/sparse.c
index e06f514fe04..a2183cb5d52 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
return -EEXIST;
section = sparse_index_alloc(nid);
+ if (!section)
+ return -ENOMEM;
/*
* This lock keeps two different sections from
* reallocating for the same index
@@ -389,9 +391,17 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
* no locking for this, because it does its own
* plus, it does a kmalloc
*/
- sparse_index_init(section_nr, pgdat->node_id);
+ ret = sparse_index_init(section_nr, pgdat->node_id);
+ if (ret < 0 && ret != -EEXIST)
+ return ret;
memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+ if (!memmap)
+ return -ENOMEM;
usemap = __kmalloc_section_usemap();
+ if (!usemap) {
+ __kfree_section_memmap(memmap, nr_pages);
+ return -ENOMEM;
+ }
pgdat_resize_lock(pgdat, &flags);
@@ -401,18 +411,16 @@ int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
goto out;
}
- if (!usemap) {
- ret = -ENOMEM;
- goto out;
- }
ms->section_mem_map |= SECTION_MARKED_PRESENT;
ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
out:
pgdat_resize_unlock(pgdat, &flags);
- if (ret <= 0)
+ if (ret <= 0) {
+ kfree(usemap);
__kfree_section_memmap(memmap, nr_pages);
+ }
return ret;
}
#endif
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index ce59fc2d8de..6501a50e17f 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -18,7 +18,8 @@ def getsizes(file):
for l in os.popen("nm --size-sort " + file).readlines():
size, type, name = l[:-1].split()
if type in "tTdDbB":
- if "." in name: name = "static." + name.split(".")[0]
+ # function names begin with '.' on 64-bit powerpc
+ if "." in name[1:]: name = "static." + name.split(".")[0]
sym[name] = sym.get(name, 0) + int(size, 16)
return sym