From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753048AbbKZQX5 (ORCPT ); Thu, 26 Nov 2015 11:23:57 -0500 Received: from mail.lysator.liu.se ([130.236.254.3]:40196 "EHLO mail.lysator.liu.se" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751532AbbKZQXy (ORCPT ); Thu, 26 Nov 2015 11:23:54 -0500 To: linux-kernel@vger.kernel.org From: =?UTF-8?Q?Mattias_R=c3=b6nnblom?= Subject: TASKSTATS_CMD_ATTR_REGISTER_CPUMASK broken in recent kernels Message-ID: <56573217.9080803@lysator.liu.se> Date: Thu, 26 Nov 2015 17:23:51 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi. I've noticed that using taskstats and TASKSTATS_CMD_ATTR_REGISTER_CPUMASK doesn't work on my x86_64 system with the stock Ubuntu 15.10 kernel 4.2. It displays the same behaviour with mainline 4.0 and 4.2 (Ubuntu config). CONFIG_CPUMASK_OFFSTACK is not set. This can be reproduced with the getdelays.c sample program found in the Documentation directory. In kernel 3.9, TASKSTATS_CMD_ATTR_REGISTER_CPUMASK works (although from what I can tell, this is by accident only and may vary across different systems). matro@isengard:~/src/c$ sudo ./getdelays -m 0-1 -l cpumask 0-1 maskset 1 listen forever fatal reply error, errno -22 Sent deregister mask, retval 0 matro@isengard:~/src/c$ The netlink message returned signals EINVAL. Looking at the kernel code, it's taskstats.c:add_del_listener that doens't accept seemingly valid cpu ranges (valid, as in cpu_possible_mask, is 0-15). cpumask_subset() returns false. taskstat.c:cmd_attr_register_cpumask (and the deregister-function), which are the two users of add_del_listener(), use a stack-allocated struct cpumask, and parses the user-supplied range string by means of cpulist_parse(). This function delegates to bitmap_parselist() using a bit set length of nr_cpu_ids bits (16, in my case). In bitmap_parselist the uninitialized cpuset is indeed cleared, but only up to nr_cpu_ids bits (16). cpumask_subset(), used by add_del_listener() to validate user input, uses cpumask_bits (=NR_CPUS, 256 in my case) of the bit set, erroneously returns false because uninitialized parts of the bitset is taken into account. You either need to replace alloc_cpumask_var() with zalloc_cpumask_var() in taskstat.c:cmd_attr_register_cpumask (and the deregister function) or limit cpumask_subset() to nr_cpu_ids bits for this to work, from what I can tell. zalloc_cpumask_var() make the getdelay program work again. I must say this is all a fairly complex machinery for a seemingly simple function. I had a brief look at 4.4 RC2, and judging from the code, the problem is still there. Regards, Mattias