From: Cliff Wickman <cpw@xxxxxxx> A customer used this example from the numactl.8 man page: numactl --offset=1G --length=1G --membind=1 --file /dev/shm/A --touch intending to cause a 1G allocation of memory on node 1. But they had only allocated a 1G /dev/shm/A file to begin with. In this case numactl fails with a SIGBUS. I don't think this example intended to imply that the --touch would extend a tmpfs file. Correct me if I'm wrong. Either way, numactl should avoid dying from a SIBUS. This patch: - Changes the example in numactl.8 for placing a tmpfs file. - Enhances checks of shm address/offset/length before addressing or mmap'ing of the shm region. This prevents invalid mmap calls and SIGBUS's. - The options to numactl are position dependent, which can confuse a user. So the warning messages are clarified. Signed-off-by: Cliff Wickman <cpw@xxxxxxx> --- numactl.8 | 6 ++++-- numactl.c | 18 +++++++++++++++--- shm.c | 16 +++++++++++----- shm.h | 4 ++-- 4 files changed, 32 insertions(+), 12 deletions(-) Index: numactl-test.x86_64/numactl.c =================================================================== --- numactl-test.x86_64.orig/numactl.c +++ numactl-test.x86_64/numactl.c @@ -356,6 +356,16 @@ void get_short_opts(struct option *o, ch *s = '\0'; } +void check_shmbeyond(char *msg) +{ + if (shmoffset >= shmlen) { + fprintf(stderr, + "numactl: region offset %#llx beyond its length %#llx at %s\n", + shmoffset, shmlen, msg); + exit(1); + } +} + int main(int ac, char **av) { int c, i, nnodes=0; @@ -478,13 +488,13 @@ int main(int ac, char **av) case 'S': /* --shm */ check_cpubind(did_cpubind); nopolicy(); - attach_sysvshm(optarg); + attach_sysvshm(optarg, "--shm"); shmattached = 1; break; case 'f': /* --file */ check_cpubind(did_cpubind); nopolicy(); - attach_shared(optarg); + attach_shared(optarg, "--file"); shmattached = 1; break; case 'L': /* --length */ @@ -533,6 +543,7 @@ int main(int ac, char **av) case 'T': /* --touch */ needshm("--touch"); + check_shmbeyond("--touch"); numa_police_memory(shmptr, shmlen); break; @@ -540,6 +551,7 @@ int main(int ac, char **av) needshm("--verify"); if (set_policy < 0) complain("Need a policy first to verify"); + check_shmbeyond("--verify"); numa_police_memory(shmptr, shmlen); if (!mask) complain("Need a mask to verify"); @@ -551,7 +563,7 @@ int main(int ac, char **av) usage(); } } - + av += optind; ac -= optind; Index: numactl-test.x86_64/shm.c =================================================================== --- numactl-test.x86_64.orig/shm.c +++ numactl-test.x86_64/shm.c @@ -61,12 +61,18 @@ long huge_page_size(void) return getpagesize(); } -static void check_region(void) +static void check_region(char *opt) { if (((unsigned long)shmptr % shm_pagesize) || (shmlen % shm_pagesize)) { fprintf(stderr, "numactl: policy region not page aligned\n"); exit(1); } + if (!shmlen) { + fprintf(stderr, + "numactl: policy region length not specified before %s\n", + opt); + exit(1); + } } static key_t sysvkey(char *name) @@ -89,7 +95,7 @@ static key_t sysvkey(char *name) } /* Attach a sysv style shared memory segment. */ -void attach_sysvshm(char *name) +void attach_sysvshm(char *name, char *opt) { struct shmid_ds s; key_t key = sysvkey(name); @@ -120,11 +126,11 @@ void attach_sysvshm(char *name) shm_pagesize = (shmflags & SHM_HUGETLB) ? huge_page_size() : getpagesize(); - check_region(); + check_region(opt); } /* Attach a shared memory file. */ -void attach_shared(char *name) +void attach_shared(char *name, char *opt) { struct stat64 st; @@ -150,7 +156,7 @@ void attach_shared(char *name) shm_pagesize = st.st_blksize; - check_region(); + check_region(opt); /* RED-PEN For shmlen > address space may need to map in pieces. Left for some poor 32bit soul. */ Index: numactl-test.x86_64/shm.h =================================================================== --- numactl-test.x86_64.orig/shm.h +++ numactl-test.x86_64/shm.h @@ -9,8 +9,8 @@ extern int shmflags; extern void dump_shm(void); extern void dump_shm_nodes(void); -extern void attach_shared(char *); -extern void attach_sysvshm(char *); +extern void attach_shared(char *, char *); +extern void attach_sysvshm(char *, char *); extern void verify_shm(int policy, struct bitmask *); /* in numactl.c */ Index: numactl-test.x86_64/numactl.8 =================================================================== --- numactl-test.x86_64.orig/numactl.8 +++ numactl-test.x86_64/numactl.8 @@ -261,8 +261,10 @@ numactl --interleave=all --shmkeyfile /t Interleave all of the sysv shared memory region specified by /tmp/shmkey over all nodes. -numactl --offset=1G --length=1G --membind=1 --file /dev/shm/A --touch -Bind the second gigabyte in the tmpfs file /dev/shm/A to node 1. +Place a tmpfs file on 2 nodes: + numactl --membind=2 dd if=/dev/zero of=/dev/shm/A bs=1M count=1024 + numactl --membind=3 dd if=/dev/zero of=/dev/shm/A seek=1024 bs=1M count=1024 + numactl --localalloc /dev/shm/file Reset the policy for the shared memory file -- To unsubscribe from this list: send the line "unsubscribe linux-numa" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html