* Re: [PATCH v1] earlyprintk configuration for rk3399 boards
From: Ihor Matushchak @ 2018-07-23 16:37 UTC (permalink / raw)
To: Julien Grall
Cc: xen-devel, Stefano Stabellini,
Ігор Матущак,
xen-devel
In-Reply-To: <d6883cd0-1138-5df2-34ee-cf9a2774cfcb@arm.com>
[-- Attachment #1.1: Type: text/plain, Size: 3543 bytes --]
Julien,
Got it, thanks.
*BR,*
*Ihor Matushchak*
2018-07-23 17:59 GMT+03:00 Julien Grall <julien.grall@arm.com>:
>
>
> On 23/07/18 15:47, Ihor Matushchak wrote:
>
>> Hi Julien,
>>
>
> Hi Ihor,
>
>
>> Sure, I would be glad to do that.
>>
>> I suppose it should be placed somewhere on wiki.xenproject.org <
>> http://wiki.xenproject.org>?
>>
>
> We usually create a new platform under https://wiki.xenproject.org/wi
> ki/Xen_ARM_with_Virtualization_Extensions
>
> We can then add a link on the main page to the documentation of the rk3399.
>
> Cheers,
>
> /
>> /
>> /BR,/
>> /Ihor Matushchak/
>>
>> 2018-07-23 17:33 GMT+03:00 Julien Grall <julien.grall@arm.com <mailto:
>> julien.grall@arm.com>>:
>>
>> On 06/07/18 12:04, Ігор Матущак wrote:
>>
>> Hello Julien,
>>
>>
>> Hi Ihor,
>>
>> Sorry for the late reply.
>>
>>
>> I suppose there is no such documentation, at least I didn't find
>> any.
>> Bringing up XEN 4.10.0 on RK3399 is my pet-project.
>> My current target board is Ibox3399
>> <https://www.aliexpress.com/item/RK3399-Development-Board-Ib
>> ox3399-2GB-DDR3-16GB-EMMC-Six-Core-A72-A53-Mali-T860-GPU-
>> Android6/32816273232.html
>> <https://www.aliexpress.com/item/RK3399-Development-Board-Ib
>> ox3399-2GB-DDR3-16GB-EMMC-Six-Core-A72-A53-Mali-T860-GPU-
>> Android6/32816273232.html>>
>>
>> At the moment I got dom0 running on this board and some test
>> guest domain (both 4.4 kernels).
>> Actually no changes made to XEN (except earlyprintk) at the
>> moment, Xen works from the box.
>>
>>
>> Glad to see Xen booting out of box on RK3399 :).
>>
>> The alias is only for convience. It would be possible to do the same
>> with 8250,0xff1a0000,2.
>>
>> So instead of that patch, I would suggest to write down a
>> documentation for booting Xen on the board and early debugging.
>>
>> What do you think?
>>
>> Cheers,
>>
>>
>> /BR,/
>> /Ihor Matushchak/
>>
>> 2018-07-06 13:36 GMT+03:00 Julien Grall <julien.grall@arm.com
>> <mailto:julien.grall@arm.com> <mailto:julien.grall@arm.com
>> <mailto:julien.grall@arm.com>>>:
>>
>> Hello,
>>
>> On 04/07/18 21:55, ihor.matushchak@foobox.net
>> <mailto:ihor.matushchak@foobox.net>
>> <mailto:ihor.matushchak@foobox.net
>> <mailto:ihor.matushchak@foobox.net>> wrote:
>>
>> From: Ihor Matushchak <ihor.matushchak@foobox.net
>> <mailto:ihor.matushchak@foobox.net>
>> <mailto:ihor.matushchak@foobox.net
>> <mailto:ihor.matushchak@foobox.net>>>
>>
>> This patch enables earlyprintk for Rockchip rk3399
>> based SoC.
>>
>> Is there any missing pieces in Xen to boot on Rockchip? I
>> would also
>> quite like to see some documentation how to boot Xen on
>> that platform.
>>
>> Cheers,
>>
>>
>>
>> Ihor Matushchak (1):
>> xen:arm:earlyprintk configuration for rk3399 boards
>>
>> docs/misc/arm/early-printk.txt | 1 +
>> xen/arch/arm/Rules.mk | 1 +
>> 2 files changed, 2 insertions(+)
>>
>>
>> -- Julien Grall
>>
>>
>>
>> -- Julien Grall
>>
>>
>>
> --
> Julien Grall
>
[-- Attachment #1.2: Type: text/html, Size: 6497 bytes --]
[-- Attachment #2: Type: text/plain, Size: 157 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
^ permalink raw reply
* Re: arch/arc/ allmodconfig
From: Vineet Gupta @ 2018-07-23 16:36 UTC (permalink / raw)
To: Ofer Levi(SW), Vineet Gupta, Randy Dunlap, LKML,
linux-snps-arc@lists.infradead.org
Cc: Leon Romanovsky, Meir Lichtinger
In-Reply-To: <DB6PR05MB4597A63819F227B17652B5B2B2560@DB6PR05MB4597.eurprd05.prod.outlook.com>
Hi Ofer,
On 07/23/2018 01:34 AM, Ofer Levi(SW) wrote:
> Hi Vineet, randy
>
> Indeed this structure is missing, following is a patch based on linux-4.17.9.
> Sorry about that.
>
> Thanks
>
>
> diff -uprN linux-4.17.9.org/arch/arc/plat-eznps/include/plat/ctop.h linux-4.17.9/arch/arc/plat-eznps/include/plat/ctop.h
> --- linux-4.17.9.org/arch/arc/plat-eznps/include/plat/ctop.h 2018-07-22 16:16:09.000000000 +0300
> +++ linux-4.17.9/arch/arc/plat-eznps/include/plat/ctop.h 2018-07-23 11:18:12.179402620 +0300
> @@ -143,6 +143,15 @@ struct nps_host_reg_gim_p_int_dst {
> };
>
> /* AUX registers definition */
> +struct nps_host_reg_aux_dpc {
> + union {
> + struct {
> + u32 ien:1, men:1, hen:1, reserved:29;
> + };
> + u32 value;
> + };
> +};
> +
> struct nps_host_reg_aux_udmc {
> union {
> struct {
Thx for this change. Can you please send a proper patch with changelog, citing the
issue as Reported-by etc.
Also if Mellanox is interested in maintaining the NPS port going fwd, someone (you
?) should add their name to MAINTAINERS file under arch/arc/plat-eznps and send
that patch as well.
Thx,
-Vineet
>
>
>
>
>> -----Original Message-----
>> From: Meir Lichtinger
>> Sent: Friday, July 20, 2018 10:19
>> To: Vineet Gupta <Vineet.Gupta1@synopsys.com>; Randy Dunlap
>> <rdunlap@infradead.org>; LKML <linux-kernel@vger.kernel.org>; linux-
>> snps-arc@lists.infradead.org; Ofer Levi(SW) <oferle@mellanox.com>
>> Cc: Leon Romanovsky <leonro@mellanox.com>
>> Subject: RE: arch/arc/ allmodconfig
>>
>> Hi Vineet,
>> Ofer Levi is now the maintainer of arch/arc/plat-eznps
>>
>> Ofer,
>> Please take care of the issue below
>>
>> Thanks
>>
>>
>> -----Original Message-----
>> From: Vineet Gupta [mailto:Vineet.Gupta1@synopsys.com]
>> Sent: Thursday, July 19, 2018 19:22
>> To: Randy Dunlap <rdunlap@infradead.org>; LKML <linux-
>> kernel@vger.kernel.org>; Vineet Gupta <Vineet.Gupta1@synopsys.com>;
>> linux-snps-arc@lists.infradead.org
>> Cc: Elad Kanfi <eladkan@mellanox.com>; Leon Romanovsky
>> <leonro@mellanox.com>
>> Subject: Re: arch/arc/ allmodconfig
>>
>> +CC some folks from Mellanox
>>
>> On 07/18/2018 10:37 PM, Randy Dunlap wrote:
>>> Hi,
>>>
>>> When I try to (cross-)build arch/arc/ allmodconfig, I get a syntax error here:
>>>
>>> ./arch/arc/plat-eznps/mtm.c: In function 'mtm_enable_core':
>>> ../arch/arc/plat-eznps/mtm.c:113:30: error: storage size of 'dpc' isn't known
>>> struct nps_host_reg_aux_dpc dpc;
>>> ^~~
>>>
>>> There is no struct nps_host_reg_aux_dpc in the kernel tree.
>>>
>>> Can you do something about this, please?
>> Thx for the report Randy. I'm calling out Mellanox folks to see if they can
>> provide a fixup, else we will revert the corresponding change.
>>
>> @Elad, upstream commit 3f9cd874dcc8705 "ARC: [plat-eznps] avoid toggling
>> of DPC register" added reference to struct nps_host_reg_aux_dpc but the
>> definition is missing. Can you please provide a fixup as I have no idea of that
>> platform specific struct.
>>
>> @ Leon, reaching our to you, since it seems you removed Elad from
>> MAINTAINERS file, so I'm not sure if he is still at Mellanox.
>> The two folks I worked with on EZCHiip Linux port Noam Camus and Gilad
>> have left Mellanox.
>> If you or someone from Mellanox are interested in maintaining this platform,
>> please update the arch/arc/plat-eznps section of MAINTAINERS file.
>>
>>
>> Thx,
>> -Vineet
^ permalink raw reply
* arch/arc/ allmodconfig
From: Vineet Gupta @ 2018-07-23 16:36 UTC (permalink / raw)
To: linux-snps-arc
In-Reply-To: <DB6PR05MB4597A63819F227B17652B5B2B2560@DB6PR05MB4597.eurprd05.prod.outlook.com>
Hi Ofer,
On 07/23/2018 01:34 AM, Ofer Levi(SW) wrote:
> Hi Vineet, randy
>
> Indeed this structure is missing, following is a patch based on linux-4.17.9.
> Sorry about that.
>
> Thanks
>
>
> diff -uprN linux-4.17.9.org/arch/arc/plat-eznps/include/plat/ctop.h linux-4.17.9/arch/arc/plat-eznps/include/plat/ctop.h
> --- linux-4.17.9.org/arch/arc/plat-eznps/include/plat/ctop.h 2018-07-22 16:16:09.000000000 +0300
> +++ linux-4.17.9/arch/arc/plat-eznps/include/plat/ctop.h 2018-07-23 11:18:12.179402620 +0300
> @@ -143,6 +143,15 @@ struct nps_host_reg_gim_p_int_dst {
> };
>
> /* AUX registers definition */
> +struct nps_host_reg_aux_dpc {
> + union {
> + struct {
> + u32 ien:1, men:1, hen:1, reserved:29;
> + };
> + u32 value;
> + };
> +};
> +
> struct nps_host_reg_aux_udmc {
> union {
> struct {
Thx for this change. Can you please send a proper patch with changelog, citing the
issue as Reported-by etc.
Also if Mellanox is interested in maintaining the NPS port going fwd, someone (you
?) should add their name to MAINTAINERS file under arch/arc/plat-eznps and send
that patch as well.
Thx,
-Vineet
>
>
>
>
>> -----Original Message-----
>> From: Meir Lichtinger
>> Sent: Friday, July 20, 2018 10:19
>> To: Vineet Gupta <Vineet.Gupta1 at synopsys.com>; Randy Dunlap
>> <rdunlap at infradead.org>; LKML <linux-kernel at vger.kernel.org>; linux-
>> snps-arc at lists.infradead.org; Ofer Levi(SW) <oferle at mellanox.com>
>> Cc: Leon Romanovsky <leonro at mellanox.com>
>> Subject: RE: arch/arc/ allmodconfig
>>
>> Hi Vineet,
>> Ofer Levi is now the maintainer of arch/arc/plat-eznps
>>
>> Ofer,
>> Please take care of the issue below
>>
>> Thanks
>>
>>
>> -----Original Message-----
>> From: Vineet Gupta [mailto:Vineet.Gupta1 at synopsys.com]
>> Sent: Thursday, July 19, 2018 19:22
>> To: Randy Dunlap <rdunlap at infradead.org>; LKML <linux-
>> kernel at vger.kernel.org>; Vineet Gupta <Vineet.Gupta1 at synopsys.com>;
>> linux-snps-arc at lists.infradead.org
>> Cc: Elad Kanfi <eladkan at mellanox.com>; Leon Romanovsky
>> <leonro at mellanox.com>
>> Subject: Re: arch/arc/ allmodconfig
>>
>> +CC some folks from Mellanox
>>
>> On 07/18/2018 10:37 PM, Randy Dunlap wrote:
>>> Hi,
>>>
>>> When I try to (cross-)build arch/arc/ allmodconfig, I get a syntax error here:
>>>
>>> ./arch/arc/plat-eznps/mtm.c: In function 'mtm_enable_core':
>>> ../arch/arc/plat-eznps/mtm.c:113:30: error: storage size of 'dpc' isn't known
>>> struct nps_host_reg_aux_dpc dpc;
>>> ^~~
>>>
>>> There is no struct nps_host_reg_aux_dpc in the kernel tree.
>>>
>>> Can you do something about this, please?
>> Thx for the report Randy. I'm calling out Mellanox folks to see if they can
>> provide a fixup, else we will revert the corresponding change.
>>
>> @Elad, upstream commit 3f9cd874dcc8705 "ARC: [plat-eznps] avoid toggling
>> of DPC register" added reference to struct nps_host_reg_aux_dpc but the
>> definition is missing. Can you please provide a fixup as I have no idea of that
>> platform specific struct.
>>
>> @ Leon, reaching our to you, since it seems you removed Elad from
>> MAINTAINERS file, so I'm not sure if he is still at Mellanox.
>> The two folks I worked with on EZCHiip Linux port Noam Camus and Gilad
>> have left Mellanox.
>> If you or someone from Mellanox are interested in maintaining this platform,
>> please update the arch/arc/plat-eznps section of MAINTAINERS file.
>>
>>
>> Thx,
>> -Vineet
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v3 24/40] target/mips: Add updating BadInstr and BadInstrP registers for nanoMIPS
From: Richard Henderson @ 2018-07-23 16:36 UTC (permalink / raw)
To: Stefan Markovic, qemu-devel
Cc: laurent, riku.voipio, philippe.mathieu.daude, aurelien, amarkovic,
smarkovic, pjovanovic, pburton
In-Reply-To: <1532004912-13899-25-git-send-email-stefan.markovic@rt-rk.com>
On 07/19/2018 05:54 AM, Stefan Markovic wrote:
> + if (!(env->insn_flags & ISA_NANOMIPS32)) {
> + /* TODO: add BadInstr support for pre-nanoMIPS */
> + return;
> + }
> + if (env->CP0_Config3 & (1 << CP0C3_BI)) {
> + instr = (cpu_lduw_code(env, env->active_tc.PC)) << 16;
> + if ((env->insn_flags & ISA_NANOMIPS32) &&
Redundant check for nanomips.
r~
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v3 25/40] target/mips: Add updating CP0 BadInstrX register for nanoMIPs only
From: Richard Henderson @ 2018-07-23 16:35 UTC (permalink / raw)
To: Stefan Markovic, qemu-devel
Cc: laurent, riku.voipio, philippe.mathieu.daude, aurelien, amarkovic,
smarkovic, pjovanovic, pburton
In-Reply-To: <1532004912-13899-26-git-send-email-stefan.markovic@rt-rk.com>
On 07/19/2018 05:54 AM, Stefan Markovic wrote:
> From: Stefan Markovic <smarkovic@wavecomp.com>
>
> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com>
> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
> ---
> target/mips/helper.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/target/mips/helper.c b/target/mips/helper.c
> index 5299f21..9535131 100644
> --- a/target/mips/helper.c
> +++ b/target/mips/helper.c
> @@ -695,6 +695,12 @@ static inline void set_badinstr_registers(CPUMIPSState *env)
> instr |= cpu_lduw_code(env, env->active_tc.PC + 2);
> }
> env->CP0_BadInstr = instr;
> +
> + if ((env->insn_flags & ISA_NANOMIPS32) &&
> + ((instr & 0xFC000000) == 0x60000000)) {
> + instr = cpu_lduw_code(env, env->active_tc.PC + 4) << 16;
> + env->CP0_BadInstrX = instr;
> + }
The nanomips condition has been checked just above.
This patch should probably be merged with 24/40.
r~
^ permalink raw reply
* [Intel-wired-lan] [jkirsher-next-queue:dev-queue] BUILD SUCCESS 17927989beff0dca67895983ed9110707a387a07
From: kbuild test robot @ 2018-07-23 16:35 UTC (permalink / raw)
To: intel-wired-lan
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue.git dev-queue
branch HEAD: 17927989beff0dca67895983ed9110707a387a07 e1000: ensure to free old tx/rx rings in set_ringparam()
elapsed time: 29m
configs tested: 110
The following configs have been built successfully.
More configs may be tested in the coming days.
x86_64 randconfig-it0-07231322
i386 tinyconfig
i386 randconfig-n0-201829
x86_64 randconfig-x007-201829
x86_64 randconfig-x003-201829
x86_64 randconfig-x000-201829
x86_64 randconfig-x005-201829
x86_64 randconfig-x004-201829
x86_64 randconfig-x008-201829
x86_64 randconfig-x001-201829
x86_64 randconfig-x009-201829
x86_64 randconfig-x002-201829
x86_64 randconfig-x006-201829
powerpc allnoconfig
powerpc defconfig
powerpc ppc64_defconfig
s390 default_defconfig
i386 randconfig-i0-201829
i386 randconfig-i1-201829
alpha alldefconfig
arm iop32x_defconfig
alpha defconfig
parisc allnoconfig
parisc b180_defconfig
parisc c3000_defconfig
parisc defconfig
i386 allmodconfig
x86_64 randconfig-x010-201829
x86_64 randconfig-x011-201829
x86_64 randconfig-x012-201829
x86_64 randconfig-x013-201829
x86_64 randconfig-x014-201829
x86_64 randconfig-x015-201829
x86_64 randconfig-x016-201829
x86_64 randconfig-x017-201829
x86_64 randconfig-x018-201829
x86_64 randconfig-x019-201829
i386 randconfig-a0-201829
i386 randconfig-a1-201829
arm lpd270_defconfig
arm vexpress_defconfig
arm zeus_defconfig
mips fuloong2e_defconfig
i386 alldefconfig
i386 allnoconfig
i386 defconfig
m68k m5475evb_defconfig
m68k multi_defconfig
m68k sun3_defconfig
i386 randconfig-s0-201829
i386 randconfig-s1-201829
openrisc or1ksim_defconfig
um i386_defconfig
um x86_64_defconfig
i386 randconfig-x012-201829
i386 randconfig-x017-201829
i386 randconfig-x014-201829
i386 randconfig-x016-201829
i386 randconfig-x013-201829
i386 randconfig-x011-201829
i386 randconfig-x018-201829
i386 randconfig-x010-201829
i386 randconfig-x015-201829
i386 randconfig-x019-201829
i386 randconfig-x078-201829
i386 randconfig-x070-201829
i386 randconfig-x075-201829
i386 randconfig-x076-201829
i386 randconfig-x074-201829
i386 randconfig-x079-201829
i386 randconfig-x071-201829
i386 randconfig-x073-201829
i386 randconfig-x072-201829
i386 randconfig-x077-201829
sh allnoconfig
sh rsk7269_defconfig
sh sh7785lcr_32bit_defconfig
sh titan_defconfig
i386 randconfig-x008-201829
i386 randconfig-x009-201829
i386 randconfig-x005-201829
i386 randconfig-x000-201829
i386 randconfig-x003-201829
i386 randconfig-x001-201829
i386 randconfig-x004-201829
i386 randconfig-x006-201829
i386 randconfig-x007-201829
i386 randconfig-x002-201829
mips 32r2_defconfig
mips 64r6el_defconfig
mips allnoconfig
mips jz4740
mips malta_kvm_defconfig
mips txx9
microblaze mmu_defconfig
microblaze nommu_defconfig
arm allnoconfig
arm at91_dt_defconfig
arm efm32_defconfig
arm exynos_defconfig
arm multi_v5_defconfig
arm multi_v7_defconfig
arm shmobile_defconfig
arm sunxi_defconfig
arm64 allnoconfig
arm64 defconfig
x86_64 acpi-redef
x86_64 allyesdebian
x86_64 nfsroot
powerpc mpc836x_mds_defconfig
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* Re: [PATCH v2 00/19] Fixes for sched/numa_balancing
From: Srikar Dronamraju @ 2018-07-23 16:29 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Ingo Molnar, LKML, Mel Gorman, Rik van Riel, Thomas Gleixner
In-Reply-To: <20180723152147.GE2494@hirez.programming.kicks-ass.net>
* Peter Zijlstra <peterz@infradead.org> [2018-07-23 17:21:47]:
> On Mon, Jul 23, 2018 at 08:09:55AM -0700, Srikar Dronamraju wrote:
>
> > > > sched/numa: Stop multiple tasks from moving to the cpu at the same time
> >
> > This patch has go-ahead from Mel and Rik and no outstanding comments.
>
> I left it out because it's part of the big xchg() mess.
>
> In particular:
>
> + if (xchg(&rq->numa_migrate_on, 1))
> + return;
> +
> + if (env->best_cpu != -1) {
> + rq = cpu_rq(env->best_cpu);
> + WRITE_ONCE(rq->numa_migrate_on, 0);
> + }
>
> I'm again confused by clearing numa_migrate_on at this point..
First task choose a cpu to swap/migrate, sets the cpu to best_cpu and
also numa_migrate_on. Next it finds a better cpu to swap/move. Now if
the task is able to move to the better cpu, then it should clear
numa_migrate_on on the previous best_cpu.
If we dont reset numa_migrate_on on finding a better cpu, the
numa_migrate_on stays set for the previous cpu, causing previous cpu to
never be a target of numa balance.
>
> > > > sched/numa: Updation of scan period need not be in lock
> >
> > I didnt see any comments for this apart from an ack from Rik.
> > + It thought it was trivial and shouldnt have any side-effect.
>
> Oh, my bad I actually have this one.
>
^ permalink raw reply
* Re: [igt-dev] ✗ Fi.CI.BAT: failure for series starting with [i-g-t,1/4] lib/igt_pm: Make exit handlers signal safe (rev3)
From: Tvrtko Ursulin @ 2018-07-23 16:35 UTC (permalink / raw)
To: igt-dev, Patchwork, Tvrtko Ursulin
In-Reply-To: <20180723155447.14391.78678@emeril.freedesktop.org>
On 23/07/2018 16:54, Patchwork wrote:
> == Series Details ==
>
> Series: series starting with [i-g-t,1/4] lib/igt_pm: Make exit handlers signal safe (rev3)
> URL : https://patchwork.freedesktop.org/series/47052/
> State : failure
>
> == Summary ==
>
> = CI Bug Log - changes from CI_DRM_4521 -> IGTPW_1631 =
>
> == Summary - FAILURE ==
>
> Serious unknown changes coming with IGTPW_1631 absolutely need to be
> verified manually.
>
> If you think the reported changes have nothing to do with the changes
> introduced in IGTPW_1631, please notify your bug team to allow them
> to document this new failure mode, which will reduce false positives in CI.
>
> External URL: https://patchwork.freedesktop.org/api/1.0/series/47052/revisions/3/mbox/
>
> == Possible new issues ==
>
> Here are the unknown changes that may have been introduced in IGTPW_1631:
>
> === IGT changes ===
>
> ==== Possible regressions ====
>
> igt@pm_rpm@basic-rte:
> fi-bdw-5557u: PASS -> FAIL +1
Okay there seems to be two PCI devices claimed by snd_hda_intel on some
platforms and this patch apparently picks the wrong one. So it seems I
would need some logic to figure out which one is which, and which one we
actually want to touch. The one tied with i915 I guess. Just figuring
out how to find it.
Tvrtko
>
> == Known issues ==
>
> Here are the changes found in IGTPW_1631 that come from known issues:
>
> === IGT changes ===
>
> ==== Issues hit ====
>
> igt@drv_module_reload@basic-reload:
> fi-glk-j4005: PASS -> DMESG-WARN (fdo#106725, fdo#106248)
>
> igt@pm_rpm@basic-rte:
> fi-hsw-peppy: PASS -> FAIL (fdo#106539) +1
> fi-hsw-4770r: PASS -> FAIL (fdo#106539) +1
> fi-hsw-4770: PASS -> FAIL (fdo#106539) +1
>
>
> ==== Possible fixes ====
>
> igt@debugfs_test@read_all_entries:
> fi-snb-2520m: INCOMPLETE (fdo#103713) -> PASS
>
> igt@prime_vgem@basic-fence-flip:
> fi-ilk-650: FAIL (fdo#104008) -> PASS
>
>
> fdo#103713 https://bugs.freedesktop.org/show_bug.cgi?id=103713
> fdo#104008 https://bugs.freedesktop.org/show_bug.cgi?id=104008
> fdo#106248 https://bugs.freedesktop.org/show_bug.cgi?id=106248
> fdo#106539 https://bugs.freedesktop.org/show_bug.cgi?id=106539
> fdo#106725 https://bugs.freedesktop.org/show_bug.cgi?id=106725
>
>
> == Participating hosts (47 -> 43) ==
>
> Additional (1): fi-bsw-kefka
> Missing (5): fi-ctg-p8600 fi-ilk-m540 fi-byt-squawks fi-bsw-cyan fi-hsw-4200u
>
>
> == Build changes ==
>
> * IGT: IGT_4570 -> IGTPW_1631
>
> CI_DRM_4521: a4ebbd84c682fd30edbde6ac0e48d150d4c5c066 @ git://anongit.freedesktop.org/gfx-ci/linux
> IGTPW_1631: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1631/
> IGT_4570: 65cdccdc7bcbb791d791aeeeecb784a382110a3c @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
>
> == Logs ==
>
> For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_1631/issues.html
> _______________________________________________
> igt-dev mailing list
> igt-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/igt-dev
>
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev
^ permalink raw reply
* [Intel-wired-lan] [jkirsher/next-queue PATCH 2/2] ixgbe: Refactor queue disable logic to take completion time into account
From: Shannon Nelson @ 2018-07-23 16:34 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <20180720222934.3568.15842.stgit@ahduyck-green-test.jf.intel.com>
On 7/20/2018 3:29 PM, Alexander Duyck wrote:
> This change is meant to allow us to take completion time into account when
> disabling queues. Previously we were just working with hard coded values
> for how long we should wait. This worked fine for the standard case where
> completion timeout was operating in the 50us to 50ms range, however on
> platforms that have higher completion timeout times this was resulting in
> Rx queues disable messages being displayed as we weren't waiting long
> enough for outstanding Rx DMA completions.
>
> Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
> ---
[...]
> +
> +void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
> +{
> + unsigned long wait_delay, delay_interval;
> + struct ixgbe_hw *hw = &adapter->hw;
> + int i, wait_loop;
> + u32 txdctl;
> +
> + if (ixgbe_removed(hw->hw_addr))
> + return;
> +
> + /* disable all enabled Tx queues */
> + for (i = 0; i < adapter->num_tx_queues; i++) {
> + struct ixgbe_ring *ring = adapter->tx_ring[i];
> + u8 reg_idx = ring->reg_idx;
> +
> + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
> + }
> +
> + /* disable all enabled XDP Tx queues */
> + for (i = 0; i < adapter->num_xdp_queues; i++) {
> + struct ixgbe_ring *ring = adapter->xdp_ring[i];
> + u8 reg_idx = ring->reg_idx;
> +
> + IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
> + }
> +
> + /* If the link is now up there shouldn't be much in the way of
I think you mean "not" up rather than "now" up, which has the opposite
meaning and could be a bit confusing.
> + * pending transactions. Those that are left will be flushed out
> + * when the reset logic goes through the flush sequence to clean out
> + * the pending Tx transactions.
> + */
> + if (!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
> + goto dma_engine_disable;
> +
> + /* Determine our minimum delay interval. We will increase this value
> + * with each subsequent test. This way if the device returns quickly
> + * we should spend as little time as possible waiting, however as
> + * the time increases we will wait for larger periods of time.
> + *
> + * The trick here is that we increase the interval using the
> + * following pattern: 1x 3x 5x 7x 9x 11x 13x 15x 17x 19x. The result
> + * of that wait is that it totals up to 100x whatever interval we
> + * choose. Since our minimum wait is 100us we can just divide the
> + * total timeout by 100 to get our minimum delay interval.
> + */
> + delay_interval = ixgbe_get_completion_timeout(adapter) / 100;
> +
> + wait_loop = IXGBE_MAX_RX_DESC_POLL;
> + wait_delay = delay_interval;
> +
> + while (wait_loop--) {
> + usleep_range(wait_delay, wait_delay + 10);
> + wait_delay += delay_interval * 2;
> + txdctl = 0;
> +
> + /* OR together the reading of all the active TXDCTL registers,
> + * and then test the result. We need the disable to complete
> + * before we start freeing the memory and invalidating the
> + * DMA mappings.
> + */
> + for (i = 0; i < adapter->num_tx_queues; i++) {
> + struct ixgbe_ring *ring = adapter->tx_ring[i];
> + u8 reg_idx = ring->reg_idx;
> +
> + txdctl |= IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
> + }
> + for (i = 0; i < adapter->num_xdp_queues; i++) {
> + struct ixgbe_ring *ring = adapter->xdp_ring[i];
> + u8 reg_idx = ring->reg_idx;
> +
> + txdctl |= IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
> + }
> +
> + if (!(txdctl & IXGBE_TXDCTL_ENABLE))
> + goto dma_engine_disable;
> + }
> +
> + e_err(drv,
> + "TXDCTL.ENABLE for one or more queues not cleared within the polling period\n");
> +
> +dma_engine_disable:
> + /* Disable the Tx DMA engine on 82599 and later MAC */
> + switch (hw->mac.type) {
> + case ixgbe_mac_82599EB:
> + case ixgbe_mac_X540:
> + case ixgbe_mac_X550:
> + case ixgbe_mac_X550EM_x:
> + case ixgbe_mac_x550em_a:
> + IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
> + (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
> + ~IXGBE_DMATXCTL_TE));
> + /* fall through */
> + default:
> + break;
> + }
Picky bike-shed thoughts: I realize you're just moving the previously
existing code, but with the comment "... and later MAC" I would think
the translation to code puts all the later MACs into the default and
have the WRITE_REG() as the default action. This would make it default
to the correct action for any new MACs if someone forgot to fix up this
part of the code.
switch (hw->mac.type) {
case ixgbe_mac_82598EB:
break;
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
default:
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
~IXGBE_DMATXCTL_TE));
break;
}
Or even simpler,
if (hw->mac.type != ixgbe_mac_82598EB)
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
~IXGBE_DMATXCTL_TE));
Okay, I'll stop now.
Cheers,
sln
^ permalink raw reply
* data corruption with 'splt' workload to XFS on DM cache with its 3 underlying devices being on same NVMe device
From: Mike Snitzer @ 2018-07-23 16:33 UTC (permalink / raw)
Hi,
I've opened the following public BZ:
https://bugzilla.redhat.com/show_bug.cgi?id=1607527
Feel free to add comments to that BZ if you have a redhat bugzilla
account.
But otherwise, happy to get as much feedback and discussion going purely
on the relevant lists. I've taken ~1.5 weeks to categorize and isolate
this issue. But I've reached a point where I'm getting diminishing
returns and could _really_ use the collective eyeballs and expertise of
the community. This is by far one of the most nasty cases of corruption
I've seen in a while. Not sure where the ultimate cause of corruption
lies (that the money question) but it _feels_ rooted in NVMe and is
unique to this particular workload I've stumbled onto via customer
escalation and then trying to replicate an rbd device using a more
approachable one (request-based DM multipath in this case).
>From the BZ's comment#0:
The following occurs with latest v4.18-rc3 and v4.18-rc6 and also occurs
with v4.15. When corruption occurs from this test it also destroys the
DOS partition table (created during step 0 below).. yeah, corruption is
_that_ bad. Almost like the corruption is temporal (recently accessed
regions of the NVMe device)?
Anyway: I stumbled onto rampant corruption when using request-based DM
multipath ontop of an NVMe device (not exclusive to a particular drive
either, happens to NVMe devices from multiple vendors). But the
corruption only occurs if the request-based multipath IO is issued to an
NVMe device in parallel to other IO issued to the _same_ underlying NVMe
by the DM cache target. See topology detailed below (at the very end of
this comment).. basically all 3 devices that are used to create a DM
cache device need to be backed by the same NVMe device (via partitions
or linear volumes).
Again, using request-based DM multipath for dm-cache's "slow" device is
_required_ to reproduce. Not 100% clear why really... other than
request-based DM multipath builds large IOs (due to merging).
--- Additional comment from Mike Snitzer on 2018-07-20 10:14:09 EDT ---
To reproduce this issue using device-mapper-test-suite:
0) Partition an NVMe device. First primary partition with at least a
5GB, seconf primary partition with at least 48GB.
NOTE: larger partitions (e.g. 1: 50GB 2: >= 220GB) can be used to
reproduce XFS corruption much quicker.
1) create a request-based multipath device ontop of an NVMe device,
e.g.:
#!/bin/sh
modprobe dm-service-time
DEVICE=/dev/nvme1n1p2
SIZE=`blockdev --getsz $DEVICE`
echo "0 $SIZE multipath 2 queue_mode mq 0 1 1 service-time 0 1 2 $DEVICE
1000 1" | dmsetup create nvme_mpath
# Just a note for how to fail/reinstate path:
# dmsetup message nvme_mpath 0 "fail_path $DEVICE"
# dmsetup message nvme_mpath 0 "reinstate_path $DEVICE"
2) checkout device-mapper-test-suite from my github repo:
git clone git://github.com/snitm/device-mapper-test-suite.git
cd device-mapper-test-suite
git checkout -b devel origin/devel
3) follow device-mapper-test-suite's README.md to get it all setup
4) Configure /root/.dmtest/config with something like:
profile :nvme_shared do
metadata_dev '/dev/nvme1n1p1'
#data_dev '/dev/nvme1n1p2'
data_dev '/dev/mapper/nvme_mpath'
end
default_profile :nvme_shared
------
NOTE: configured 'metadata_dev' gets carved up by
device-mapper-test-suite to provide both the dm-cache's metadata device
and the "fast" data device. The configured 'data_dev' is used for
dm-cache's "slow" data device.
5) run the test:
# tail -f /var/log/messages &
# time dmtest run --suite cache -n /split_large_file/
6) If multipath device failed the lone NVMe path you'll need to
reinstate the path before the next iteration of your test, e.g. (from #1
above):
dmsetup message nvme_mpath 0 "reinstate_path $DEVICE"
--- Additional comment from Mike Snitzer on 2018-07-20 12:02:45 EDT ---
(In reply to Mike Snitzer from comment #6)
> SO seems pretty clear something is still wrong with request-based DM
> multipath ontop of NVMe... sadly we don't have any negative check in
> blk-core, NVMe or elsewhere to offer any clue :(
Building on this comment:
"Anyway, fact that I'm getting this corruption on multiple different
NVMe drives: I am definitely concerned that this BZ is due to a bug
somewhere in NVMe core (or block core code that is specific to NVMe)."
I'm left thinking that request-based DM multipath is somehow causing
NVMe's SG lists or other infrastructure to be "wrong" and it is
resulting in corruption. I get corruption to the dm-cache's metadata
device (which while theoretically unrelated as its a separate device
from the "slow" dm-cache data device) if the dm-cache slow data device
is backed by request-based dm-multipath ontop of NVMe (which is a
partition from the _same_ NVMe device that is used by the dm-cache
metadata device).
Basically I'm back to thinking NVMe is corrupting the data due to the IO
pattern or nature of the cloned requests dm-multipath is issuing. And
it is causing corruption to other NVMe partitions on the same parent
NVMe device. Certainly that is a concerning hypothesis but I'm not
seeing much else that would explain this weird corruption.
If I don't use the same NVMe device (with multiple partitions) for _all_
3 sub-devices that dm-cache needs I don't see the corruption. It is
almost like the mix of IO issued by DM cache's metadata (on nvme1n1p1
using dm-linear) and "fast" device (also on nvme1n1p1 via dm-linear
volume) in conjunction with IO issued by request-based DM multipath to
NVMe for "slow" device (on nvme1n1p2) is triggering NVMe to respond
negatively. But this same observation can be made on completely
different hardware using 2 totally different NVMe devices:
testbed1: Intel Corporation Optane SSD 900P Series (2700)
testbed2: Samsung Electronics Co Ltd NVMe SSD Controller 171X (rev 03)
Which is why it feels like some bug in Linux (be it dm-rq.c, blk-core.c,
blk-merge.c or the common NVMe driver)
topology before starting the device-mapper-test-suite test:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
??nvme1n1p2 259:5 0 695.2G 0 part
? ??nvme_mpath 253:2 0 695.2G 0 dm
??nvme1n1p1 259:4 0 50G 0 part
topology during the device-mapper-test-suite test:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
??nvme1n1p2 259:5 0 695.2G 0 part
? ??nvme_mpath 253:2 0 695.2G 0 dm
? ??test-dev-458572 253:5 0 48G 0 dm
? ??test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
??nvme1n1p1 259:4 0 50G 0 part
??test-dev-126378 253:4 0 4G 0 dm
? ??test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
??test-dev-652491 253:3 0 40M 0 dm
??test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
pruning that tree a bit (removing the dm-cache device 253:6) for
clarity:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
??nvme1n1p2 259:5 0 695.2G 0 part
? ??nvme_mpath 253:2 0 695.2G 0 dm
? ??test-dev-458572 253:5 0 48G 0 dm
??nvme1n1p1 259:4 0 50G 0 part
??test-dev-126378 253:4 0 4G 0 dm
??test-dev-652491 253:3 0 40M 0 dm
40M device is dm-cache "metadata" device
4G device is dm-cache "fast" data device
48G device is dm-cache "slow" data device
^ permalink raw reply
* data corruption with 'splt' workload to XFS on DM cache with its 3 underlying devices being on same NVMe device
From: Mike Snitzer @ 2018-07-23 16:33 UTC (permalink / raw)
To: linux-nvme, linux-block, dm-devel
Hi,
I've opened the following public BZ:
https://bugzilla.redhat.com/show_bug.cgi?id=1607527
Feel free to add comments to that BZ if you have a redhat bugzilla
account.
But otherwise, happy to get as much feedback and discussion going purely
on the relevant lists. I've taken ~1.5 weeks to categorize and isolate
this issue. But I've reached a point where I'm getting diminishing
returns and could _really_ use the collective eyeballs and expertise of
the community. This is by far one of the most nasty cases of corruption
I've seen in a while. Not sure where the ultimate cause of corruption
lies (that the money question) but it _feels_ rooted in NVMe and is
unique to this particular workload I've stumbled onto via customer
escalation and then trying to replicate an rbd device using a more
approachable one (request-based DM multipath in this case).
>From the BZ's comment#0:
The following occurs with latest v4.18-rc3 and v4.18-rc6 and also occurs
with v4.15. When corruption occurs from this test it also destroys the
DOS partition table (created during step 0 below).. yeah, corruption is
_that_ bad. Almost like the corruption is temporal (recently accessed
regions of the NVMe device)?
Anyway: I stumbled onto rampant corruption when using request-based DM
multipath ontop of an NVMe device (not exclusive to a particular drive
either, happens to NVMe devices from multiple vendors). But the
corruption only occurs if the request-based multipath IO is issued to an
NVMe device in parallel to other IO issued to the _same_ underlying NVMe
by the DM cache target. See topology detailed below (at the very end of
this comment).. basically all 3 devices that are used to create a DM
cache device need to be backed by the same NVMe device (via partitions
or linear volumes).
Again, using request-based DM multipath for dm-cache's "slow" device is
_required_ to reproduce. Not 100% clear why really... other than
request-based DM multipath builds large IOs (due to merging).
--- Additional comment from Mike Snitzer on 2018-07-20 10:14:09 EDT ---
To reproduce this issue using device-mapper-test-suite:
0) Partition an NVMe device. First primary partition with at least a
5GB, seconf primary partition with at least 48GB.
NOTE: larger partitions (e.g. 1: 50GB 2: >= 220GB) can be used to
reproduce XFS corruption much quicker.
1) create a request-based multipath device ontop of an NVMe device,
e.g.:
#!/bin/sh
modprobe dm-service-time
DEVICE=/dev/nvme1n1p2
SIZE=`blockdev --getsz $DEVICE`
echo "0 $SIZE multipath 2 queue_mode mq 0 1 1 service-time 0 1 2 $DEVICE
1000 1" | dmsetup create nvme_mpath
# Just a note for how to fail/reinstate path:
# dmsetup message nvme_mpath 0 "fail_path $DEVICE"
# dmsetup message nvme_mpath 0 "reinstate_path $DEVICE"
2) checkout device-mapper-test-suite from my github repo:
git clone git://github.com/snitm/device-mapper-test-suite.git
cd device-mapper-test-suite
git checkout -b devel origin/devel
3) follow device-mapper-test-suite's README.md to get it all setup
4) Configure /root/.dmtest/config with something like:
profile :nvme_shared do
metadata_dev '/dev/nvme1n1p1'
#data_dev '/dev/nvme1n1p2'
data_dev '/dev/mapper/nvme_mpath'
end
default_profile :nvme_shared
------
NOTE: configured 'metadata_dev' gets carved up by
device-mapper-test-suite to provide both the dm-cache's metadata device
and the "fast" data device. The configured 'data_dev' is used for
dm-cache's "slow" data device.
5) run the test:
# tail -f /var/log/messages &
# time dmtest run --suite cache -n /split_large_file/
6) If multipath device failed the lone NVMe path you'll need to
reinstate the path before the next iteration of your test, e.g. (from #1
above):
dmsetup message nvme_mpath 0 "reinstate_path $DEVICE"
--- Additional comment from Mike Snitzer on 2018-07-20 12:02:45 EDT ---
(In reply to Mike Snitzer from comment #6)
> SO seems pretty clear something is still wrong with request-based DM
> multipath ontop of NVMe... sadly we don't have any negative check in
> blk-core, NVMe or elsewhere to offer any clue :(
Building on this comment:
"Anyway, fact that I'm getting this corruption on multiple different
NVMe drives: I am definitely concerned that this BZ is due to a bug
somewhere in NVMe core (or block core code that is specific to NVMe)."
I'm left thinking that request-based DM multipath is somehow causing
NVMe's SG lists or other infrastructure to be "wrong" and it is
resulting in corruption. I get corruption to the dm-cache's metadata
device (which while theoretically unrelated as its a separate device
from the "slow" dm-cache data device) if the dm-cache slow data device
is backed by request-based dm-multipath ontop of NVMe (which is a
partition from the _same_ NVMe device that is used by the dm-cache
metadata device).
Basically I'm back to thinking NVMe is corrupting the data due to the IO
pattern or nature of the cloned requests dm-multipath is issuing. And
it is causing corruption to other NVMe partitions on the same parent
NVMe device. Certainly that is a concerning hypothesis but I'm not
seeing much else that would explain this weird corruption.
If I don't use the same NVMe device (with multiple partitions) for _all_
3 sub-devices that dm-cache needs I don't see the corruption. It is
almost like the mix of IO issued by DM cache's metadata (on nvme1n1p1
using dm-linear) and "fast" device (also on nvme1n1p1 via dm-linear
volume) in conjunction with IO issued by request-based DM multipath to
NVMe for "slow" device (on nvme1n1p2) is triggering NVMe to respond
negatively. But this same observation can be made on completely
different hardware using 2 totally different NVMe devices:
testbed1: Intel Corporation Optane SSD 900P Series (2700)
testbed2: Samsung Electronics Co Ltd NVMe SSD Controller 171X (rev 03)
Which is why it feels like some bug in Linux (be it dm-rq.c, blk-core.c,
blk-merge.c or the common NVMe driver)
topology before starting the device-mapper-test-suite test:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
├─nvme1n1p2 259:5 0 695.2G 0 part
│ └─nvme_mpath 253:2 0 695.2G 0 dm
└─nvme1n1p1 259:4 0 50G 0 part
topology during the device-mapper-test-suite test:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
├─nvme1n1p2 259:5 0 695.2G 0 part
│ └─nvme_mpath 253:2 0 695.2G 0 dm
│ └─test-dev-458572 253:5 0 48G 0 dm
│ └─test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
└─nvme1n1p1 259:4 0 50G 0 part
├─test-dev-126378 253:4 0 4G 0 dm
│ └─test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
└─test-dev-652491 253:3 0 40M 0 dm
└─test-dev-613083 253:6 0 48G 0 dm
/root/snitm/git/device-mapper-test-suite/kernel_builds
pruning that tree a bit (removing the dm-cache device 253:6) for
clarity:
# lsblk /dev/nvme1n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1 259:1 0 745.2G 0 disk
├─nvme1n1p2 259:5 0 695.2G 0 part
│ └─nvme_mpath 253:2 0 695.2G 0 dm
│ └─test-dev-458572 253:5 0 48G 0 dm
└─nvme1n1p1 259:4 0 50G 0 part
├─test-dev-126378 253:4 0 4G 0 dm
└─test-dev-652491 253:3 0 40M 0 dm
40M device is dm-cache "metadata" device
4G device is dm-cache "fast" data device
48G device is dm-cache "slow" data device
--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
^ permalink raw reply
* Re: [PATCH 0/4][RFC v2] Introduce the in-kernel hibernation encryption
From: Yu Chen @ 2018-07-23 16:38 UTC (permalink / raw)
To: Pavel Machek
Cc: Oliver Neukum, Rafael J . Wysocki, Eric Biggers, Lee, Chun-Yi,
Theodore Ts o, Stephan Mueller, Denis Kenzior, linux-pm,
linux-crypto, linux-kernel, Gu, Kookoo, Zhang, Rui
In-Reply-To: <20180723122227.GA30092@amd>
Hello,
On Mon, Jul 23, 2018 at 02:22:27PM +0200, Pavel Machek wrote:
> Hi!
>
> > > > 2. Ideally kernel memory should be encrypted by the
> > > > kernel itself. We have uswsusp to support user
> > > > space hibernation, however doing the encryption
> > > > in kernel space has more advantages:
> > > > 2.1 Not having to transfer plain text kernel memory to
> > > > user space. Per Lee, Chun-Yi, uswsusp is disabled
> > > > when the kernel is locked down:
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/
> > > > linux-fs.git/commit/?h=lockdown-20180410&
> > > > id=8732c1663d7c0305ae01ba5a1ee4d2299b7b4612
> > > > due to:
> > > > "There have some functions be locked-down because
> > > > there have no appropriate mechanisms to check the
> > > > integrity of writing data."
> > > > https://patchwork.kernel.org/patch/10476751/
> > >
> > > So your goal is to make hibernation compatible with kernel
> > > lockdown? Do your patches provide sufficient security that hibernation
> > > can be enabled with kernel lockdown?
> >
> > OK, maybe I am dense, but if the key comes from user space, will that
> > be enough?
>
> Yes, that seems to be one of problems of Yu Chen's patchset.
>
It is a trade off to derive the key in user space, we once
tried to derive the key in user space, and people suggested
a better way is to do it in user space. And there is a similar
user case of kernel using key from user space is derived from ecryptfs
for ext4.
> > > > Joey Lee and I had a discussion on his previous work at
> > > > https://patchwork.kernel.org/patch/10476751
> > > > We collaborate on this task and his snapshot signature
> > > > feature can be based on this patch set.
> > >
> > > Well, his work can also work without your patchset, right?
> >
> > Yes. But you are objecting to encryption in kernel space at all,
> > aren't you?
>
> I don't particulary love the idea of doing hibernation encryption in
> the kernel, correct.
>
> But we have this weird thing called secure boot, some people seem to
> want. So we may need some crypto in the kernel -- but I'd like
> something that works with uswsusp, too. Plus, it is mandatory that
> patch explains what security guarantees they want to provide against
> what kinds of attacks...
>
> Lee, Chun-Yi's patch seemed more promising. Pavel
>
The only difference between Chun-Yi's hibernation encrytion solution
and our solution is that his strategy encrypts the snapshot from sratch,
and ours encryts each page before them going to block device. The benefit
of his solution is that the snapshot can be encrypt in kernel first
thus the uswsusp is allowed to read it to user space even kernel
is lock down. And I had a discussion with Chun-Yi that we can use
his snapshot solution to make uswsusp happy, and we share the crypto
help code and he can also use our user provided key for his signature.
From this point of view, our code are actually the same, except that
we can help clean up the code and also enhance some encrytion process
for his solution. I don't know why you don't like encryption in kernel,
because from my point of view, without encryption hibernation in kernel,
uswsusp could not be enabled if kernel is lock down : -) Or do I miss something?
Best,
Yu
> --
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* RE: fio max blocksize
From: Jeff Furlong @ 2018-07-23 16:33 UTC (permalink / raw)
To: Jens Axboe, fio@vger.kernel.org
In-Reply-To: <6fae3201-41af-e59e-1f4b-72e17a39f6c2@kernel.dk>
> Please test current -git and ensure that it works properly for you.
Ran latest git (fio-3.8-5-g464b) and tests pass. Thanks.
Regards,
Jeff
^ permalink raw reply
* Re: [PATCH 00/14] format-patch: add --interdiff and --range-diff options
From: Duy Nguyen @ 2018-07-23 16:32 UTC (permalink / raw)
To: Eric Sunshine
Cc: Git Mailing List, Johannes Schindelin,
Ævar Arnfjörð Bjarmason, Stefan Beller
In-Reply-To: <20180722095717.17912-1-sunshine@sunshineco.com>
On Sun, Jul 22, 2018 at 11:57 AM Eric Sunshine <sunshine@sunshineco.com> wrote:
>
> When re-submitting a patch series, it is often helpful (for reviewers)
> to include an interdiff or range-diff against the previous version.
> Doing so requires manually running git-diff or git-range-diff and
> copy/pasting the result into the cover letter of the new version.
>
> This series automates the process by introducing git-format-patch
> options --interdiff and --range-diff which insert such a diff into the
> cover-letter or into the commentary section of the lone patch of a
> 1-patch series. In the latter case, the interdiff or range-diff is
> indented to avoid confusing git-am and human readers.
I gave up after 10/14. But what I've seen is nice (yes I have a couple
comments here and there but you probably won't need to update
anything).
--
Duy
^ permalink raw reply
* Re: [Bridge] [PATCH net-next v3 0/2] net: bridge: add support for backup port
From: David Miller @ 2018-07-23 16:32 UTC (permalink / raw)
To: nikolay; +Cc: netdev, roopa, bridge, wkok, anuradhak
In-Reply-To: <20180723081659.21986-1-nikolay@cumulusnetworks.com>
From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Date: Mon, 23 Jul 2018 11:16:57 +0300
> This set introduces a new bridge port option that allows any port to have
> any other port (in the same bridge of course) as its backup and traffic
> will be forwarded to the backup port when the primary goes down. This is
> mainly used in MLAG and EVPN setups where we have peerlink path which is
> a backup of many (or even all) ports and is a participating bridge port
> itself. There's more detailed information in patch 02. Patch 01 just
> prepares the port sysfs code for options that take raw value. The main
> issues that this set solves are scalability and fallback latency.
...
Series applied, thanks Nikolay.
^ permalink raw reply
* [PATCH] drm/amdgpu/pm: Fix potential Spectre v1
From: Gustavo A. R. Silva @ 2018-07-23 16:32 UTC (permalink / raw)
To: Alex Deucher, Christian König, David (ChunMing) Zhou,
David Airlie
Cc: amd-gfx, dri-devel, linux-kernel, Gustavo A. R. Silva
idx can be indirectly controlled by user-space, hence leading to a
potential exploitation of the Spectre variant 1 vulnerability.
This issue was detected with the help of Smatch:
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c:408 amdgpu_set_pp_force_state()
warn: potential spectre issue 'data.states'
Fix this by sanitizing idx before using it to index data.states
Notice that given that speculation windows are large, the policy is
to kill the speculation on the first load and not worry if it can be
completed with a dependent load/store [1].
[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2
Cc: stable@vger.kernel.org
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 15a1192..a446c7c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -31,7 +31,7 @@
#include <linux/power_supply.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-
+#include <linux/nospec.h>
static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev);
@@ -403,6 +403,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev,
count = -EINVAL;
goto fail;
}
+ idx = array_index_nospec(idx, ARRAY_SIZE(data.states));
amdgpu_dpm_get_pp_num_states(adev, &data);
state = data.states[idx];
--
2.7.4
^ permalink raw reply related
* [RFC][PATCH 0/5] Mount, Filesystem and Keyrings notifications
From: Casey Schaufler @ 2018-07-23 16:31 UTC (permalink / raw)
To: linux-security-module
In-Reply-To: <153235954191.32640.5792167066538704794.stgit@warthog.procyon.org.uk>
On 7/23/2018 8:25 AM, David Howells wrote:
> Hi Al,
>
> Here's a set of patches to add a general variable-length notification queue
> concept and to add sources of events for:
Overall I approve. The interface is a bit clunky. Some concerns below.
>
> (1) Mount topology and reconfiguration change events.
With the possibility of unprivileged mounting you're
going to have to address access control on events.
If root in a user namespace mounts a filesystem you
may have a case where the "real" user wouldn't want the
listener to receive a notification.
> (2) Superblocks EIO, ENOSPC and EDQUOT events (not complete yet).
Here, too. If SELinux (for example) policy says you can't see
anything on a filesystem you shouldn't get notifications about
things that happen to that filesystem.
> (3) Key/keyring changes events
And again, I should only get notifications about keys and
keyrings I have access to.
I expect that you intentionally left off
(4) User injected events
at this point, but it's an obvious extension. That is going
to require access controls (remember kdbus) so I think you'd
do well to design them in now rather than have some security
module hack like me come along later and "fix" it.
> One of the reasons for this is so that we can remove the issue of processes
> having to repeatedly and regularly scan /proc/mounts, which has proven to be a
> system performance problem.
>
>
> Design decisions:
>
> (1) A misc chardev is used to create and open a ring buffer:
>
> fd = open("/dev/watch_queue", O_RDWR);
>
> which is then configured and mmap'd into userspace:
>
> ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, BUF_SIZE);
> ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter);
> buf = mmap(NULL, BUF_SIZE * page_size, PROT_READ | PROT_WRITE,
> MAP_SHARED, fd, 0);
>
> The fd cannot be read or written (though there is a facility to use write
> to inject records for debugging) and userspace just pulls data directly
> out of the buffer.
>
> (2) The ring index pointers are stored inside the ring and are thus
> accessible to userspace. Userspace should only update the tail pointer
> and never the head pointer or risk breaking the buffer. The kernel
> checks that the pointers appear valid before trying to use them. A
> 'skip' record is maintained around the pointers.
>
> (3) poll() can be used to wait for data to appear in the buffer.
>
> (4) Records in the buffer are binary, typed and have a length so that they
> can be of varying size.
>
> This means that multiple heterogeneous sources can share a common
> buffer. Tags may be specified when a watchpoint is created to help
> distinguish the sources.
>
> (5) The queue is reusable as there are 16 million types available, of which
> I've used 4, so there is scope for others to be used.
>
> (6) Records are filterable as types have up to 256 subtypes that can be
> individually filtered. Other filtration is also available.
>
> (7) Each time the buffer is opened, a new buffer is created - this means that
> there's no interference between watchers.
>
> (8) When recording a notification, the kernel will not sleep, but will rather
> mark a queue as overrun if there's insufficient space, thereby avoiding
> userspace causing the kernel to hang.
>
> (9) The 'watchpoint' should be specific where possible, meaning that you
> specify the object that you want to watch.
>
> (10) The buffer is created and then watchpoints are attached to it, using one
> of:
>
> keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fd, 0x01);
> mount_notify(AT_FDCWD, "/", 0, fd, 0x02);
> sb_notify(AT_FDCWD, "/mnt", 0, fd, 0x03);
>
> where in all three cases, fd indicates the queue and the number after is
> a tag between 0 and 255.
>
> (11) The watch must be removed if either the watch buffer is destroyed or the
> watched object is destroyed.
>
>
> Things I want to avoid:
>
> (1) Introducing features that make the core VFS dependent on the network
> stack or networking namespaces (ie. usage of netlink).
>
> (2) Dumping all this stuff into dmesg and having a daemon that sits there
> parsing the output and distributing it as this then puts the
> responsibility for security into userspace and makes handling namespaces
> tricky. Further, dmesg might not exist or might be inaccessible inside a
> container.
>
> (3) Letting users see events they shouldn't be able to see.
>
>
> Further things that need to be done:
>
> (1) fsinfo() syscall needs to find superblocks by ID as well as by path so
> that it can query a superblock for information without the need to try
> and work out how to reach it - if the calling process even can.
>
> (2) A mount_info() syscall is needed that can enumerate all the children of a
> mount. This is necessary because mountpoints can hide each other by
> stacking, so paths are not unique keys. This will require the ability to
> look up a mount by ID. This avoids the need to parse /proc/mounts.
>
> (3) A keyctl call is needed to allow a watch on a keyring to be extended to
> "children" of that keyring, such that the watch is removed from the child
> if it is unlinked from the keyring.
>
> (4) A global superblock event queue maybe?
>
> (5) Propagating watches to child superblock over automounts?
>
>
> The patches can be found here also:
>
> http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=notifications
>
> David
> ---
> David Howells (5):
> General notification queue with user mmap()'able ring buffer
> KEYS: Add a notification facility
> vfs: Add a mount-notification facility
> vfs: Add superblock notifications
> Add sample notification program
>
>
> Documentation/security/keys/core.rst | 59 ++
> Documentation/watch_queue.rst | 305 ++++++++++++
> arch/x86/entry/syscalls/syscall_32.tbl | 2
> arch/x86/entry/syscalls/syscall_64.tbl | 2
> drivers/misc/Kconfig | 9
> drivers/misc/Makefile | 1
> drivers/misc/watch_queue.c | 835 ++++++++++++++++++++++++++++++++
> fs/Kconfig | 21 +
> fs/Makefile | 1
> fs/fs_context.c | 1
> fs/mount.h | 26 +
> fs/mount_notify.c | 178 +++++++
> fs/namespace.c | 18 +
> fs/super.c | 116 ++++
> include/linux/dcache.h | 1
> include/linux/fs.h | 77 +++
> include/linux/key.h | 4
> include/linux/syscalls.h | 4
> include/linux/watch_queue.h | 87 +++
> include/uapi/linux/keyctl.h | 1
> include/uapi/linux/watch_queue.h | 156 ++++++
> kernel/sys_ni.c | 6
> mm/interval_tree.c | 2
> mm/memory.c | 1
> samples/Kconfig | 6
> samples/Makefile | 2
> samples/watch_queue/Makefile | 9
> samples/watch_queue/watch_test.c | 232 +++++++++
> security/keys/Kconfig | 10
> security/keys/compat.c | 3
> security/keys/gc.c | 5
> security/keys/internal.h | 29 +
> security/keys/key.c | 37 +
> security/keys/keyctl.c | 90 +++
> security/keys/keyring.c | 17 -
> security/keys/request_key.c | 4
> 36 files changed, 2332 insertions(+), 25 deletions(-)
> create mode 100644 Documentation/watch_queue.rst
> create mode 100644 drivers/misc/watch_queue.c
> create mode 100644 fs/mount_notify.c
> create mode 100644 include/linux/watch_queue.h
> create mode 100644 include/uapi/linux/watch_queue.h
> create mode 100644 samples/watch_queue/Makefile
> create mode 100644 samples/watch_queue/watch_test.c
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC][PATCH 0/5] Mount, Filesystem and Keyrings notifications
From: Casey Schaufler @ 2018-07-23 16:31 UTC (permalink / raw)
To: David Howells, viro
Cc: linux-fsdevel, linux-kernel, raven, keyrings,
linux-security-module
In-Reply-To: <153235954191.32640.5792167066538704794.stgit@warthog.procyon.org.uk>
On 7/23/2018 8:25 AM, David Howells wrote:
> Hi Al,
>
> Here's a set of patches to add a general variable-length notification queue
> concept and to add sources of events for:
Overall I approve. The interface is a bit clunky. Some concerns below.
>
> (1) Mount topology and reconfiguration change events.
With the possibility of unprivileged mounting you're
going to have to address access control on events.
If root in a user namespace mounts a filesystem you
may have a case where the "real" user wouldn't want the
listener to receive a notification.
> (2) Superblocks EIO, ENOSPC and EDQUOT events (not complete yet).
Here, too. If SELinux (for example) policy says you can't see
anything on a filesystem you shouldn't get notifications about
things that happen to that filesystem.
> (3) Key/keyring changes events
And again, I should only get notifications about keys and
keyrings I have access to.
I expect that you intentionally left off
(4) User injected events
at this point, but it's an obvious extension. That is going
to require access controls (remember kdbus) so I think you'd
do well to design them in now rather than have some security
module hack like me come along later and "fix" it.
> One of the reasons for this is so that we can remove the issue of processes
> having to repeatedly and regularly scan /proc/mounts, which has proven to be a
> system performance problem.
>
>
> Design decisions:
>
> (1) A misc chardev is used to create and open a ring buffer:
>
> fd = open("/dev/watch_queue", O_RDWR);
>
> which is then configured and mmap'd into userspace:
>
> ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, BUF_SIZE);
> ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter);
> buf = mmap(NULL, BUF_SIZE * page_size, PROT_READ | PROT_WRITE,
> MAP_SHARED, fd, 0);
>
> The fd cannot be read or written (though there is a facility to use write
> to inject records for debugging) and userspace just pulls data directly
> out of the buffer.
>
> (2) The ring index pointers are stored inside the ring and are thus
> accessible to userspace. Userspace should only update the tail pointer
> and never the head pointer or risk breaking the buffer. The kernel
> checks that the pointers appear valid before trying to use them. A
> 'skip' record is maintained around the pointers.
>
> (3) poll() can be used to wait for data to appear in the buffer.
>
> (4) Records in the buffer are binary, typed and have a length so that they
> can be of varying size.
>
> This means that multiple heterogeneous sources can share a common
> buffer. Tags may be specified when a watchpoint is created to help
> distinguish the sources.
>
> (5) The queue is reusable as there are 16 million types available, of which
> I've used 4, so there is scope for others to be used.
>
> (6) Records are filterable as types have up to 256 subtypes that can be
> individually filtered. Other filtration is also available.
>
> (7) Each time the buffer is opened, a new buffer is created - this means that
> there's no interference between watchers.
>
> (8) When recording a notification, the kernel will not sleep, but will rather
> mark a queue as overrun if there's insufficient space, thereby avoiding
> userspace causing the kernel to hang.
>
> (9) The 'watchpoint' should be specific where possible, meaning that you
> specify the object that you want to watch.
>
> (10) The buffer is created and then watchpoints are attached to it, using one
> of:
>
> keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fd, 0x01);
> mount_notify(AT_FDCWD, "/", 0, fd, 0x02);
> sb_notify(AT_FDCWD, "/mnt", 0, fd, 0x03);
>
> where in all three cases, fd indicates the queue and the number after is
> a tag between 0 and 255.
>
> (11) The watch must be removed if either the watch buffer is destroyed or the
> watched object is destroyed.
>
>
> Things I want to avoid:
>
> (1) Introducing features that make the core VFS dependent on the network
> stack or networking namespaces (ie. usage of netlink).
>
> (2) Dumping all this stuff into dmesg and having a daemon that sits there
> parsing the output and distributing it as this then puts the
> responsibility for security into userspace and makes handling namespaces
> tricky. Further, dmesg might not exist or might be inaccessible inside a
> container.
>
> (3) Letting users see events they shouldn't be able to see.
>
>
> Further things that need to be done:
>
> (1) fsinfo() syscall needs to find superblocks by ID as well as by path so
> that it can query a superblock for information without the need to try
> and work out how to reach it - if the calling process even can.
>
> (2) A mount_info() syscall is needed that can enumerate all the children of a
> mount. This is necessary because mountpoints can hide each other by
> stacking, so paths are not unique keys. This will require the ability to
> look up a mount by ID. This avoids the need to parse /proc/mounts.
>
> (3) A keyctl call is needed to allow a watch on a keyring to be extended to
> "children" of that keyring, such that the watch is removed from the child
> if it is unlinked from the keyring.
>
> (4) A global superblock event queue maybe?
>
> (5) Propagating watches to child superblock over automounts?
>
>
> The patches can be found here also:
>
> http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=notifications
>
> David
> ---
> David Howells (5):
> General notification queue with user mmap()'able ring buffer
> KEYS: Add a notification facility
> vfs: Add a mount-notification facility
> vfs: Add superblock notifications
> Add sample notification program
>
>
> Documentation/security/keys/core.rst | 59 ++
> Documentation/watch_queue.rst | 305 ++++++++++++
> arch/x86/entry/syscalls/syscall_32.tbl | 2
> arch/x86/entry/syscalls/syscall_64.tbl | 2
> drivers/misc/Kconfig | 9
> drivers/misc/Makefile | 1
> drivers/misc/watch_queue.c | 835 ++++++++++++++++++++++++++++++++
> fs/Kconfig | 21 +
> fs/Makefile | 1
> fs/fs_context.c | 1
> fs/mount.h | 26 +
> fs/mount_notify.c | 178 +++++++
> fs/namespace.c | 18 +
> fs/super.c | 116 ++++
> include/linux/dcache.h | 1
> include/linux/fs.h | 77 +++
> include/linux/key.h | 4
> include/linux/syscalls.h | 4
> include/linux/watch_queue.h | 87 +++
> include/uapi/linux/keyctl.h | 1
> include/uapi/linux/watch_queue.h | 156 ++++++
> kernel/sys_ni.c | 6
> mm/interval_tree.c | 2
> mm/memory.c | 1
> samples/Kconfig | 6
> samples/Makefile | 2
> samples/watch_queue/Makefile | 9
> samples/watch_queue/watch_test.c | 232 +++++++++
> security/keys/Kconfig | 10
> security/keys/compat.c | 3
> security/keys/gc.c | 5
> security/keys/internal.h | 29 +
> security/keys/key.c | 37 +
> security/keys/keyctl.c | 90 +++
> security/keys/keyring.c | 17 -
> security/keys/request_key.c | 4
> 36 files changed, 2332 insertions(+), 25 deletions(-)
> create mode 100644 Documentation/watch_queue.rst
> create mode 100644 drivers/misc/watch_queue.c
> create mode 100644 fs/mount_notify.c
> create mode 100644 include/linux/watch_queue.h
> create mode 100644 include/uapi/linux/watch_queue.h
> create mode 100644 samples/watch_queue/Makefile
> create mode 100644 samples/watch_queue/watch_test.c
>
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] block/file-posix: add bdrv_attach_aio_context callback for host dev and cdrom
From: Stefan Hajnoczi @ 2018-07-23 16:30 UTC (permalink / raw)
To: Farhan Ali
Cc: Nishanth Aravamudan, Eric Blake, Kevin Wolf, John Snow, Max Reitz,
Fam Zheng, Paolo Bonzini, qemu-block, qemu-devel
In-Reply-To: <a1269390-a798-9165-aaf5-a2aa6270bd54@linux.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 1955 bytes --]
On Fri, Jul 20, 2018 at 03:11:14PM -0400, Farhan Ali wrote:
> I am seeing another issue pop up, in a different test. Even though it's a
> different assertion, it might be related based on the call trace.
Which test case?
> Stack trace of thread 276199:
> #0 0x000003ff8473e274 raise (libc.so.6)
> #1 0x000003ff847239a8 abort (libc.so.6)
> #2 0x000003ff847362ce __assert_fail_base (libc.so.6)
> #3 0x000003ff8473634c __assert_fail (libc.so.6)
> #4 0x000002aa30aba0c4 iov_memset (qemu-system-s390x)
> #5 0x000002aa30aba9a6 qemu_iovec_memset (qemu-system-s390x)
> #6 0x000002aa30a23e88 qemu_laio_process_completion (qemu-system-s390x)
What are the values of laiocb->qiov->size and laiocb->ret?
> #7 0x000002aa30a23f68 qemu_laio_process_completions (qemu-system-s390x)
> #8 0x000002aa30a2418e qemu_laio_process_completions_and_submit
> (qemu-system-s390x)
> #9 0x000002aa30a24220 qemu_laio_poll_cb (qemu-system-s390x)
> #10 0x000002aa30ab22c4 run_poll_handlers_once (qemu-system-s390x)
> #11 0x000002aa30ab2e78 aio_poll (qemu-system-s390x)
> #12 0x000002aa30a29f4e bdrv_do_drained_begin (qemu-system-s390x)
> #13 0x000002aa30a2a276 bdrv_drain (qemu-system-s390x)
> #14 0x000002aa309d45aa bdrv_set_aio_context (qemu-system-s390x)
> #15 0x000002aa3085acfe virtio_blk_data_plane_stop (qemu-system-s390x)
> #16 0x000002aa3096994c virtio_bus_stop_ioeventfd.part.1 (qemu-system-s390x)
> #17 0x000002aa3087d1d6 virtio_vmstate_change (qemu-system-s390x)
> #18 0x000002aa308e8a12 vm_state_notify (qemu-system-s390x)
> #19 0x000002aa3080ed54 do_vm_stop (qemu-system-s390x)
> #20 0x000002aa307bea04 main (qemu-system-s390x)
> #21 0x000003ff84723dd2 __libc_start_main (libc.so.6)
> #22 0x000002aa307c0414 _start (qemu-system-s390x)
>
>
> The failing assertion is:
>
> qemu-kvm: util/iov.c:78: iov_memset: Assertion `offset == 0' failed.
I wonder if the offset is beyond the end of the iovecs.
Thanks,
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* Re: [PATCH 0/5] Misc Coccinelle-related improvements
From: René Scharfe @ 2018-07-23 16:30 UTC (permalink / raw)
To: SZEDER Gábor, Junio C Hamano
Cc: git, Derrick Stolee, Nguyễn Thái Ngọc Duy
In-Reply-To: <20180723135100.24288-1-szeder.dev@gmail.com>
Am 23.07.2018 um 15:50 schrieb SZEDER Gábor:
> Just a couple of minor Coccinelle-related improvements:
>
> - The first two patches are small cleanups.
>
> - The last three could make life perhaps just a tad bit easier for
> devs running 'make coccicheck'.
>
>
> SZEDER Gábor (5):
> coccinelle: mark the 'coccicheck' make target as .PHONY
> coccinelle: use $(addsuffix) in 'coccicheck' make target
> coccinelle: exclude sha1dc source files from static analysis
> coccinelle: put sane filenames into output patches
> coccinelle: extract dedicated make target to clean Coccinelle's
> results
These patches look good to me. Thanks a lot!
René
^ permalink raw reply
* Re: [PATCH libdrm] tests/modetest: Add modetest_atomic tool
From: Eric Engestrom @ 2018-07-23 16:30 UTC (permalink / raw)
To: Benjamin Gaignard; +Cc: dri-devel
In-Reply-To: <20180720113329.9789-1-benjamin.gaignard@linaro.org>
On Friday, 2018-07-20 13:33:29 +0200, Benjamin Gaignard wrote:
> This is a modetest like tool but using atomic API.
>
> With modetest_atomic it is mandatory to specify a mode ("-s")
> and a plane ("-P") to display a pattern on screen.
>
> "-v" does a loop swapping between two framebuffers for each
> active planes.
>
> modetest_atomic doesn't offer cursor support
>
> Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
> ---
>
> The code is based on modetest and keep most of it infrastructure
> like arguments parsing, finding properties id from their name,
> resources dumping or the general way of working.
> It duplicates modetest code but adding compilation flags or
> conditional tests everywhere in modetest would have made it
> more complex and unreadable.
I don't have an opinion on whether duplicating the test is the right
thing, but if you do, please also duplicate the lines in
tests/modetest/meson.build :)
>
> Creating modetest_atomic could allow to test atomic API without
> need to use "big" frameworks like weston, drm_hwcomposer or igt
> with all their dependencies.
> kmscube could also be used to test atomic API but it need EGL.
>
> It have been tested (only) on stm driver with one or two planes
> actived.
>
> tests/modetest/Makefile.am | 13 +-
> tests/modetest/Makefile.sources | 7 +
> tests/modetest/modetest_atomic.c | 1546 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 1564 insertions(+), 2 deletions(-)
> create mode 100644 tests/modetest/modetest_atomic.c
>
> diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am
> index 4b296c83..8f697bb3 100644
> --- a/tests/modetest/Makefile.am
> +++ b/tests/modetest/Makefile.am
> @@ -10,10 +10,12 @@ AM_CFLAGS += \
>
> if HAVE_INSTALL_TESTS
> bin_PROGRAMS = \
> - modetest
> + modetest \
> + modetest_atomic
> else
> noinst_PROGRAMS = \
> - modetest
> + modetest \
> + modetest_atomic
> endif
>
> modetest_SOURCES = $(MODETEST_FILES)
> @@ -22,3 +24,10 @@ modetest_LDADD = \
> $(top_builddir)/libdrm.la \
> $(top_builddir)/tests/util/libutil.la \
> $(CAIRO_LIBS)
> +
> +modetest_atomic_SOURCES = $(MODETEST_ATOMIC_FILES)
> +
> +modetest_atomic_LDADD = \
> + $(top_builddir)/libdrm.la \
> + $(top_builddir)/tests/util/libutil.la \
> + $(CAIRO_LIBS)
> diff --git a/tests/modetest/Makefile.sources b/tests/modetest/Makefile.sources
> index 399af0df..0a1df4c0 100644
> --- a/tests/modetest/Makefile.sources
> +++ b/tests/modetest/Makefile.sources
> @@ -4,3 +4,10 @@ MODETEST_FILES := \
> cursor.c \
> cursor.h \
> modetest.c
> +
> +MODETEST_ATOMIC_FILES := \
> + buffers.c \
> + buffers.h \
> + cursor.c \
> + cursor.h \
> + modetest_atomic.c
> diff --git a/tests/modetest/modetest_atomic.c b/tests/modetest/modetest_atomic.c
> new file mode 100644
> index 00000000..8c877860
> --- /dev/null
> +++ b/tests/modetest/modetest_atomic.c
> @@ -0,0 +1,1546 @@
> +/*
> + * DRM based mode setting test program
> + * Copyright 2008 Tungsten Graphics
> + * Jakob Bornecrantz <jakob@tungstengraphics.com>
> + * Copyright 2008 Intel Corporation
> + * Jesse Barnes <jesse.barnes@intel.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +/*
> + * This fairly simple test program dumps output in a similar format to the
> + * "xrandr" tool everyone knows & loves. It's necessarily slightly different
> + * since the kernel separates outputs into encoder and connector structures,
> + * each with their own unique ID. The program also allows test testing of the
> + * memory management and mode setting APIs by allowing the user to specify a
> + * connector and mode to use for mode setting. If all works as expected, a
> + * blue background should be painted on the monitor attached to the specified
> + * connector after the selected mode is set.
> + *
> + * TODO: use cairo to write the mode info on the selected output once
> + * the mode has been programmed, along with possible test patterns.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <assert.h>
> +#include <ctype.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <inttypes.h>
> +#include <unistd.h>
> +#include <string.h>
> +#include <strings.h>
> +#include <errno.h>
> +#include <poll.h>
> +#include <sys/time.h>
> +#ifdef HAVE_SYS_SELECT_H
> +#include <sys/select.h>
> +#endif
> +
> +#include "xf86drm.h"
> +#include "xf86drmMode.h"
> +#include "drm_fourcc.h"
> +
> +#include "util/common.h"
> +#include "util/format.h"
> +#include "util/kms.h"
> +#include "util/pattern.h"
> +
> +#include "buffers.h"
> +
> +struct crtc {
> + drmModeCrtc *crtc;
> + drmModeObjectProperties *props;
> + drmModePropertyRes **props_info;
> + drmModeModeInfo *mode;
> +};
> +
> +struct encoder {
> + drmModeEncoder *encoder;
> +};
> +
> +struct connector {
> + drmModeConnector *connector;
> + drmModeObjectProperties *props;
> + drmModePropertyRes **props_info;
> + char *name;
> +};
> +
> +struct fb {
> + drmModeFB *fb;
> +};
> +
> +struct plane {
> + drmModePlane *plane;
> + drmModeObjectProperties *props;
> + drmModePropertyRes **props_info;
> +};
> +
> +struct resources {
> + drmModeRes *res;
> + drmModePlaneRes *plane_res;
> +
> + struct crtc *crtcs;
> + struct encoder *encoders;
> + struct connector *connectors;
> + struct fb *fbs;
> + struct plane *planes;
> +};
> +
> +struct device {
> + int fd;
> +
> + struct resources *resources;
> + drmModeAtomicReq *req;
> +};
> +
> +static inline int64_t U642I64(uint64_t val)
> +{
> + return (int64_t)*((int64_t *)&val);
> +}
> +
> +#define bit_name_fn(res) \
> +const char * res##_str(int type) { \
> + unsigned int i; \
> + const char *sep = ""; \
> + for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
> + if (type & (1 << i)) { \
> + printf("%s%s", sep, res##_names[i]); \
> + sep = ", "; \
> + } \
> + } \
> + return NULL; \
> +}
> +
> +static const char *mode_type_names[] = {
> + "builtin",
> + "clock_c",
> + "crtc_c",
> + "preferred",
> + "default",
> + "userdef",
> + "driver",
> +};
> +
> +static bit_name_fn(mode_type)
> +
> +static const char *mode_flag_names[] = {
> + "phsync",
> + "nhsync",
> + "pvsync",
> + "nvsync",
> + "interlace",
> + "dblscan",
> + "csync",
> + "pcsync",
> + "ncsync",
> + "hskew",
> + "bcast",
> + "pixmux",
> + "dblclk",
> + "clkdiv2"
> +};
> +
> +static bit_name_fn(mode_flag)
> +
> +static void dump_fourcc(uint32_t fourcc)
> +{
> + printf(" %c%c%c%c",
> + fourcc,
> + fourcc >> 8,
> + fourcc >> 16,
> + fourcc >> 24);
> +}
> +
> +static void dump_encoders(struct device *dev)
> +{
> + drmModeEncoder *encoder;
> + int i;
> +
> + printf("Encoders:\n");
> + printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
> + for (i = 0; i < dev->resources->res->count_encoders; i++) {
> + encoder = dev->resources->encoders[i].encoder;
> + if (!encoder)
> + continue;
> +
> + printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
> + encoder->encoder_id,
> + encoder->crtc_id,
> + util_lookup_encoder_type_name(encoder->encoder_type),
> + encoder->possible_crtcs,
> + encoder->possible_clones);
> + }
> + printf("\n");
> +}
> +
> +static void dump_mode(drmModeModeInfo *mode)
> +{
> + printf(" %s %d %d %d %d %d %d %d %d %d %d",
> + mode->name,
> + mode->vrefresh,
> + mode->hdisplay,
> + mode->hsync_start,
> + mode->hsync_end,
> + mode->htotal,
> + mode->vdisplay,
> + mode->vsync_start,
> + mode->vsync_end,
> + mode->vtotal,
> + mode->clock);
> +
> + printf(" flags: ");
> + mode_flag_str(mode->flags);
> + printf("; type: ");
> + mode_type_str(mode->type);
> + printf("\n");
> +}
> +
> +static void dump_blob(struct device *dev, uint32_t blob_id)
> +{
> + uint32_t i;
> + unsigned char *blob_data;
> + drmModePropertyBlobPtr blob;
> +
> + blob = drmModeGetPropertyBlob(dev->fd, blob_id);
> + if (!blob) {
> + printf("\n");
> + return;
> + }
> +
> + blob_data = blob->data;
> +
> + for (i = 0; i < blob->length; i++) {
> + if (i % 16 == 0)
> + printf("\n\t\t\t");
> + printf("%.2hhx", blob_data[i]);
> + }
> + printf("\n");
> +
> + drmModeFreePropertyBlob(blob);
> +}
> +
> +static void dump_prop(struct device *dev, drmModePropertyPtr prop,
> + uint32_t prop_id, uint64_t value)
> +{
> + int i;
> + printf("\t%d", prop_id);
> + if (!prop) {
> + printf("\n");
> + return;
> + }
> +
> + printf(" %s:\n", prop->name);
> +
> + printf("\t\tflags:");
> + if (prop->flags & DRM_MODE_PROP_PENDING)
> + printf(" pending");
> + if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
> + printf(" immutable");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
> + printf(" signed range");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE))
> + printf(" range");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM))
> + printf(" enum");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK))
> + printf(" bitmask");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
> + printf(" blob");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_OBJECT))
> + printf(" object");
> + printf("\n");
> +
> + if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE)) {
> + printf("\t\tvalues:");
> + for (i = 0; i < prop->count_values; i++)
> + printf(" %"PRId64, U642I64(prop->values[i]));
> + printf("\n");
> + }
> +
> + if (drm_property_type_is(prop, DRM_MODE_PROP_RANGE)) {
> + printf("\t\tvalues:");
> + for (i = 0; i < prop->count_values; i++)
> + printf(" %"PRIu64, prop->values[i]);
> + printf("\n");
> + }
> +
> + if (drm_property_type_is(prop, DRM_MODE_PROP_ENUM)) {
> + printf("\t\tenums:");
> + for (i = 0; i < prop->count_enums; i++)
> + printf(" %s=%llu", prop->enums[i].name,
> + prop->enums[i].value);
> + printf("\n");
> + } else if (drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
> + printf("\t\tvalues:");
> + for (i = 0; i < prop->count_enums; i++)
> + printf(" %s=0x%llx", prop->enums[i].name,
> + (1LL << prop->enums[i].value));
> + printf("\n");
> + } else {
> + assert(prop->count_enums == 0);
> + }
> +
> + if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB)) {
> + printf("\t\tblobs:\n");
> + for (i = 0; i < prop->count_blobs; i++)
> + dump_blob(dev, prop->blob_ids[i]);
> + printf("\n");
> + } else {
> + assert(prop->count_blobs == 0);
> + }
> +
> + printf("\t\tvalue:");
> + if (drm_property_type_is(prop, DRM_MODE_PROP_BLOB))
> + dump_blob(dev, value);
> + else if (drm_property_type_is(prop, DRM_MODE_PROP_SIGNED_RANGE))
> + printf(" %"PRId64"\n", value);
> + else
> + printf(" %"PRIu64"\n", value);
> +}
> +
> +static void dump_connectors(struct device *dev)
> +{
> + int i, j;
> +
> + printf("Connectors:\n");
> + printf("id\tencoder\tstatus\t\tname\t\tsize (mm)\tmodes\tencoders\n");
> + for (i = 0; i < dev->resources->res->count_connectors; i++) {
> + struct connector *_connector = &dev->resources->connectors[i];
> + drmModeConnector *connector = _connector->connector;
> + if (!connector)
> + continue;
> +
> + printf("%d\t%d\t%s\t%-15s\t%dx%d\t\t%d\t",
> + connector->connector_id,
> + connector->encoder_id,
> + util_lookup_connector_status_name(connector->connection),
> + _connector->name,
> + connector->mmWidth, connector->mmHeight,
> + connector->count_modes);
> +
> + for (j = 0; j < connector->count_encoders; j++)
> + printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
> + printf("\n");
> +
> + if (connector->count_modes) {
> + printf(" modes:\n");
> + printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
> + "vss vse vtot)\n");
> + for (j = 0; j < connector->count_modes; j++)
> + dump_mode(&connector->modes[j]);
> + }
> +
> + if (_connector->props) {
> + printf(" props:\n");
> + for (j = 0; j < (int)_connector->props->count_props; j++)
> + dump_prop(dev, _connector->props_info[j],
> + _connector->props->props[j],
> + _connector->props->prop_values[j]);
> + }
> + }
> + printf("\n");
> +}
> +
> +static void dump_crtcs(struct device *dev)
> +{
> + int i;
> + uint32_t j;
> +
> + printf("CRTCs:\n");
> + printf("id\tfb\tpos\tsize\n");
> + for (i = 0; i < dev->resources->res->count_crtcs; i++) {
> + struct crtc *_crtc = &dev->resources->crtcs[i];
> + drmModeCrtc *crtc = _crtc->crtc;
> + if (!crtc)
> + continue;
> +
> + printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
> + crtc->crtc_id,
> + crtc->buffer_id,
> + crtc->x, crtc->y,
> + crtc->width, crtc->height);
> + dump_mode(&crtc->mode);
> +
> + if (_crtc->props) {
> + printf(" props:\n");
> + for (j = 0; j < _crtc->props->count_props; j++)
> + dump_prop(dev, _crtc->props_info[j],
> + _crtc->props->props[j],
> + _crtc->props->prop_values[j]);
> + } else {
> + printf(" no properties found\n");
> + }
> + }
> + printf("\n");
> +}
> +
> +static void dump_framebuffers(struct device *dev)
> +{
> + drmModeFB *fb;
> + int i;
> +
> + printf("Frame buffers:\n");
> + printf("id\tsize\tpitch\n");
> + for (i = 0; i < dev->resources->res->count_fbs; i++) {
> + fb = dev->resources->fbs[i].fb;
> + if (!fb)
> + continue;
> +
> + printf("%u\t(%ux%u)\t%u\n",
> + fb->fb_id,
> + fb->width, fb->height,
> + fb->pitch);
> + }
> + printf("\n");
> +}
> +
> +static void dump_planes(struct device *dev)
> +{
> + unsigned int i, j;
> +
> + printf("Planes:\n");
> + printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\tpossible crtcs\n");
> +
> + if (!dev->resources->plane_res)
> + return;
> +
> + for (i = 0; i < dev->resources->plane_res->count_planes; i++) {
> + struct plane *plane = &dev->resources->planes[i];
> + drmModePlane *ovr = plane->plane;
> + if (!ovr)
> + continue;
> +
> + printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%-8d\t0x%08x\n",
> + ovr->plane_id, ovr->crtc_id, ovr->fb_id,
> + ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
> + ovr->gamma_size, ovr->possible_crtcs);
> +
> + if (!ovr->count_formats)
> + continue;
> +
> + printf(" formats:");
> + for (j = 0; j < ovr->count_formats; j++)
> + dump_fourcc(ovr->formats[j]);
> + printf("\n");
> +
> + if (plane->props) {
> + printf(" props:\n");
> + for (j = 0; j < plane->props->count_props; j++)
> + dump_prop(dev, plane->props_info[j],
> + plane->props->props[j],
> + plane->props->prop_values[j]);
> + } else {
> + printf(" no properties found\n");
> + }
> + }
> + printf("\n");
> +
> + return;
> +}
> +
> +static void free_resources(struct resources *res)
> +{
> + int i;
> +
> + if (!res)
> + return;
> +
> +#define free_resource(_res, __res, type, Type) \
> + do { \
> + if (!(_res)->type##s) \
> + break; \
> + for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) { \
> + if (!(_res)->type##s[i].type) \
> + break; \
> + drmModeFree##Type((_res)->type##s[i].type); \
> + } \
> + free((_res)->type##s); \
> + } while (0)
> +
> +#define free_properties(_res, __res, type) \
> + do { \
> + for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) { \
> + drmModeFreeObjectProperties(res->type##s[i].props); \
> + free(res->type##s[i].props_info); \
> + } \
> + } while (0)
> +
> + if (res->res) {
> + free_properties(res, res, crtc);
> +
> + free_resource(res, res, crtc, Crtc);
> + free_resource(res, res, encoder, Encoder);
> +
> + for (i = 0; i < res->res->count_connectors; i++)
> + free(res->connectors[i].name);
> +
> + free_resource(res, res, connector, Connector);
> + free_resource(res, res, fb, FB);
> +
> + drmModeFreeResources(res->res);
> + }
> +
> + if (res->plane_res) {
> + free_properties(res, plane_res, plane);
> +
> + free_resource(res, plane_res, plane, Plane);
> +
> + drmModeFreePlaneResources(res->plane_res);
> + }
> +
> + free(res);
> +}
> +
> +static struct resources *get_resources(struct device *dev)
> +{
> + struct resources *res;
> + int i;
> +
> + res = calloc(1, sizeof(*res));
> + if (res == 0)
> + return NULL;
> +
> + drmSetClientCap(dev->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
> +
> + res->res = drmModeGetResources(dev->fd);
> + if (!res->res) {
> + fprintf(stderr, "drmModeGetResources failed: %s\n",
> + strerror(errno));
> + goto error;
> + }
> +
> + res->crtcs = calloc(res->res->count_crtcs, sizeof(*res->crtcs));
> + res->encoders = calloc(res->res->count_encoders, sizeof(*res->encoders));
> + res->connectors = calloc(res->res->count_connectors, sizeof(*res->connectors));
> + res->fbs = calloc(res->res->count_fbs, sizeof(*res->fbs));
> +
> + if (!res->crtcs || !res->encoders || !res->connectors || !res->fbs)
> + goto error;
> +
> +#define get_resource(_res, __res, type, Type) \
> + do { \
> + for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) { \
> + (_res)->type##s[i].type = \
> + drmModeGet##Type(dev->fd, (_res)->__res->type##s[i]); \
> + if (!(_res)->type##s[i].type) \
> + fprintf(stderr, "could not get %s %i: %s\n", \
> + #type, (_res)->__res->type##s[i], \
> + strerror(errno)); \
> + } \
> + } while (0)
> +
> + get_resource(res, res, crtc, Crtc);
> + get_resource(res, res, encoder, Encoder);
> + get_resource(res, res, connector, Connector);
> + get_resource(res, res, fb, FB);
> +
> + /* Set the name of all connectors based on the type name and the per-type ID. */
> + for (i = 0; i < res->res->count_connectors; i++) {
> + struct connector *connector = &res->connectors[i];
> + drmModeConnector *conn = connector->connector;
> + int num;
> +
> + num = asprintf(&connector->name, "%s-%u",
> + util_lookup_connector_type_name(conn->connector_type),
> + conn->connector_type_id);
> + if (num < 0)
> + goto error;
> + }
> +
> +#define get_properties(_res, __res, type, Type) \
> + do { \
> + for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) { \
> + struct type *obj = &res->type##s[i]; \
> + unsigned int j; \
> + obj->props = \
> + drmModeObjectGetProperties(dev->fd, obj->type->type##_id, \
> + DRM_MODE_OBJECT_##Type); \
> + if (!obj->props) { \
> + fprintf(stderr, \
> + "could not get %s %i properties: %s\n", \
> + #type, obj->type->type##_id, \
> + strerror(errno)); \
> + continue; \
> + } \
> + obj->props_info = calloc(obj->props->count_props, \
> + sizeof(*obj->props_info)); \
> + if (!obj->props_info) \
> + continue; \
> + for (j = 0; j < obj->props->count_props; ++j) \
> + obj->props_info[j] = \
> + drmModeGetProperty(dev->fd, obj->props->props[j]); \
> + } \
> + } while (0)
> +
> + get_properties(res, res, crtc, CRTC);
> + get_properties(res, res, connector, CONNECTOR);
> +
> + for (i = 0; i < res->res->count_crtcs; ++i)
> + res->crtcs[i].mode = &res->crtcs[i].crtc->mode;
> +
> + res->plane_res = drmModeGetPlaneResources(dev->fd);
> + if (!res->plane_res) {
> + fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
> + strerror(errno));
> + return res;
> + }
> +
> + res->planes = calloc(res->plane_res->count_planes, sizeof(*res->planes));
> + if (!res->planes)
> + goto error;
> +
> + get_resource(res, plane_res, plane, Plane);
> + get_properties(res, plane_res, plane, PLANE);
> +
> + return res;
> +
> +error:
> + free_resources(res);
> + return NULL;
> +}
> +
> +static int get_crtc_index(struct device *dev, uint32_t id)
> +{
> + int i;
> +
> + for (i = 0; i < dev->resources->res->count_crtcs; ++i) {
> + drmModeCrtc *crtc = dev->resources->crtcs[i].crtc;
> + if (crtc && crtc->crtc_id == id)
> + return i;
> + }
> +
> + return -1;
> +}
> +
> +static drmModeConnector *get_connector_by_name(struct device *dev, const char *name)
> +{
> + struct connector *connector;
> + int i;
> +
> + for (i = 0; i < dev->resources->res->count_connectors; i++) {
> + connector = &dev->resources->connectors[i];
> +
> + if (strcmp(connector->name, name) == 0)
> + return connector->connector;
> + }
> +
> + return NULL;
> +}
> +
> +static drmModeConnector *get_connector_by_id(struct device *dev, uint32_t id)
> +{
> + drmModeConnector *connector;
> + int i;
> +
> + for (i = 0; i < dev->resources->res->count_connectors; i++) {
> + connector = dev->resources->connectors[i].connector;
> + if (connector && connector->connector_id == id)
> + return connector;
> + }
> +
> + return NULL;
> +}
> +
> +static drmModeEncoder *get_encoder_by_id(struct device *dev, uint32_t id)
> +{
> + drmModeEncoder *encoder;
> + int i;
> +
> + for (i = 0; i < dev->resources->res->count_encoders; i++) {
> + encoder = dev->resources->encoders[i].encoder;
> + if (encoder && encoder->encoder_id == id)
> + return encoder;
> + }
> +
> + return NULL;
> +}
> +
> +/* -----------------------------------------------------------------------------
> + * Pipes and planes
> + */
> +
> +/*
> + * Mode setting with the kernel interfaces is a bit of a chore.
> + * First you have to find the connector in question and make sure the
> + * requested mode is available.
> + * Then you need to find the encoder attached to that connector so you
> + * can bind it with a free crtc.
> + */
> +struct pipe_arg {
> + const char **cons;
> + uint32_t *con_ids;
> + unsigned int num_cons;
> + uint32_t crtc_id;
> + char mode_str[64];
> + char format_str[5];
> + unsigned int vrefresh;
> + unsigned int fourcc;
> + drmModeModeInfo *mode;
> + struct crtc *crtc;
> + unsigned int fb_id[2], current_fb_id;
> + struct timeval start;
> +
> + int swap_count;
> +};
> +
> +struct plane_arg {
> + uint32_t plane_id; /* the id of plane to use */
> + uint32_t crtc_id; /* the id of CRTC to bind to */
> + bool has_position;
> + int32_t x, y;
> + uint32_t w, h;
> + double scale;
> + unsigned int fb_id;
> + unsigned int old_fb_id;
> + struct bo *bo;
> + struct bo *old_bo;
> + char format_str[5]; /* need to leave room for terminating \0 */
> + unsigned int fourcc;
> +};
> +
> +static drmModeModeInfo *
> +connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
> + const unsigned int vrefresh)
> +{
> + drmModeConnector *connector;
> + drmModeModeInfo *mode;
> + int i;
> +
> + connector = get_connector_by_id(dev, con_id);
> + if (!connector || !connector->count_modes)
> + return NULL;
> +
> + for (i = 0; i < connector->count_modes; i++) {
> + mode = &connector->modes[i];
> + if (!strcmp(mode->name, mode_str)) {
> + /* If the vertical refresh frequency is not specified then return the
> + * first mode that match with the name. Else, return the mode that match
> + * the name and the specified vertical refresh frequency.
> + */
> + if (vrefresh == 0)
> + return mode;
> + else if (mode->vrefresh == vrefresh)
> + return mode;
> + }
> + }
> +
> + return NULL;
> +}
> +
> +static struct crtc *pipe_find_crtc(struct device *dev, struct pipe_arg *pipe)
> +{
> + uint32_t possible_crtcs = ~0;
> + uint32_t active_crtcs = 0;
> + unsigned int crtc_idx;
> + unsigned int i;
> + int j;
> +
> + for (i = 0; i < pipe->num_cons; ++i) {
> + uint32_t crtcs_for_connector = 0;
> + drmModeConnector *connector;
> + drmModeEncoder *encoder;
> + int idx;
> +
> + connector = get_connector_by_id(dev, pipe->con_ids[i]);
> + if (!connector)
> + return NULL;
> +
> + for (j = 0; j < connector->count_encoders; ++j) {
> + encoder = get_encoder_by_id(dev, connector->encoders[j]);
> + if (!encoder)
> + continue;
> +
> + crtcs_for_connector |= encoder->possible_crtcs;
> +
> + idx = get_crtc_index(dev, encoder->crtc_id);
> + if (idx >= 0)
> + active_crtcs |= 1 << idx;
> + }
> +
> + possible_crtcs &= crtcs_for_connector;
> + }
> +
> + if (!possible_crtcs)
> + return NULL;
> +
> + /* Return the first possible and active CRTC if one exists, or the first
> + * possible CRTC otherwise.
> + */
> + if (possible_crtcs & active_crtcs)
> + crtc_idx = ffs(possible_crtcs & active_crtcs);
> + else
> + crtc_idx = ffs(possible_crtcs);
> +
> + return &dev->resources->crtcs[crtc_idx - 1];
> +}
> +
> +static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe)
> +{
> + drmModeModeInfo *mode = NULL;
> + int i;
> +
> + pipe->mode = NULL;
> +
> + for (i = 0; i < (int)pipe->num_cons; i++) {
> + mode = connector_find_mode(dev, pipe->con_ids[i],
> + pipe->mode_str, pipe->vrefresh);
> + if (mode == NULL) {
> + fprintf(stderr,
> + "failed to find mode \"%s\" for connector %s\n",
> + pipe->mode_str, pipe->cons[i]);
> + return -EINVAL;
> + }
> + }
> +
> + /* If the CRTC ID was specified, get the corresponding CRTC. Otherwise
> + * locate a CRTC that can be attached to all the connectors.
> + */
> + if (pipe->crtc_id != (uint32_t)-1) {
> + for (i = 0; i < dev->resources->res->count_crtcs; i++) {
> + struct crtc *crtc = &dev->resources->crtcs[i];
> +
> + if (pipe->crtc_id == crtc->crtc->crtc_id) {
> + pipe->crtc = crtc;
> + break;
> + }
> + }
> + } else {
> + pipe->crtc = pipe_find_crtc(dev, pipe);
> + }
> +
> + if (!pipe->crtc) {
> + fprintf(stderr, "failed to find CRTC for pipe\n");
> + return -EINVAL;
> + }
> +
> + pipe->mode = mode;
> + pipe->crtc->mode = mode;
> +
> + return 0;
> +}
> +
> +/* -----------------------------------------------------------------------------
> + * Properties
> + */
> +
> +struct property_arg {
> + uint32_t obj_id;
> + uint32_t obj_type;
> + char name[DRM_PROP_NAME_LEN+1];
> + uint32_t prop_id;
> + uint64_t value;
> +};
> +
> +static void set_property(struct device *dev, struct property_arg *p)
> +{
> + drmModeObjectProperties *props = NULL;
> + drmModePropertyRes **props_info = NULL;
> + const char *obj_type;
> + int ret;
> + int i;
> +
> + p->obj_type = 0;
> + p->prop_id = 0;
> +
> +#define find_object(_res, __res, type, Type) \
> + do { \
> + for (i = 0; i < (int)(_res)->__res->count_##type##s; ++i) { \
> + struct type *obj = &(_res)->type##s[i]; \
> + if (obj->type->type##_id != p->obj_id) \
> + continue; \
> + p->obj_type = DRM_MODE_OBJECT_##Type; \
> + obj_type = #Type; \
> + props = obj->props; \
> + props_info = obj->props_info; \
> + } \
> + } while(0) \
> +
> + find_object(dev->resources, res, crtc, CRTC);
> + if (p->obj_type == 0)
> + find_object(dev->resources, res, connector, CONNECTOR);
> + if (p->obj_type == 0)
> + find_object(dev->resources, plane_res, plane, PLANE);
> + if (p->obj_type == 0) {
> + fprintf(stderr, "Object %i not found, can't set property\n",
> + p->obj_id);
> + return;
> + }
> +
> + if (!props) {
> + fprintf(stderr, "%s %i has no properties\n",
> + obj_type, p->obj_id);
> + return;
> + }
> +
> + for (i = 0; i < (int)props->count_props; ++i) {
> + if (!props_info[i])
> + continue;
> + if (strcmp(props_info[i]->name, p->name) == 0)
> + break;
> + }
> +
> + if (i == (int)props->count_props) {
> + fprintf(stderr, "%s %i has no %s property\n",
> + obj_type, p->obj_id, p->name);
> + return;
> + }
> +
> + p->prop_id = props->props[i];
> +
> + ret = drmModeAtomicAddProperty(dev->req, p->obj_id, p->prop_id, p->value);
> + if (ret < 0)
> + fprintf(stderr, "failed to set %s %i property %s to %" PRIu64 ": %s\n",
> + obj_type, p->obj_id, p->name, p->value, strerror(errno));
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
> +/*static bool format_support(const drmModePlanePtr ovr, uint32_t fmt)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < ovr->count_formats; ++i) {
> + if (ovr->formats[i] == fmt)
> + return true;
> + }
> +
> + return false;
> +}*/
> +
> +static void add_property(struct device *dev, uint32_t obj_id,
> + const char *name, uint64_t value)
> +{
> + struct property_arg p;
> +
> + p.obj_id = obj_id;
> + strcpy(p.name, name);
> + p.value = value;
> +
> + set_property(dev, &p);
> +}
> +
> +static int set_plane(struct device *dev, struct plane_arg *p,
> + int pattern, bool update)
> +{
> + uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
> + struct bo *plane_bo;
> + int crtc_x, crtc_y, crtc_w, crtc_h;
> + struct crtc *crtc = NULL;
> + unsigned int i;
> + unsigned int old_fb_id;
> +
> + /* Find an unused plane which can be connected to our CRTC. Find the
> + * CRTC index first, then iterate over available planes.
> + */
> + for (i = 0; i < (unsigned int)dev->resources->res->count_crtcs; i++) {
> + if (p->crtc_id == dev->resources->res->crtcs[i]) {
> + crtc = &dev->resources->crtcs[i];
> + break;
> + }
> + }
> +
> + if (!crtc) {
> + fprintf(stderr, "CRTC %u not found\n", p->crtc_id);
> + return -1;
> + }
> +
> + if (!update)
> + fprintf(stderr, "testing %dx%d@%s on plane %u, crtc %u\n",
> + p->w, p->h, p->format_str, p->plane_id, p->crtc_id);
> +
> + plane_bo = p->old_bo;
> + p->old_bo = p->bo;
> +
> + if (!plane_bo) {
> + plane_bo = bo_create(dev->fd, p->fourcc, p->w, p->h,
> + handles, pitches, offsets, pattern);
> +
> + if (plane_bo == NULL)
> + return -1;
> +
> + if (drmModeAddFB2(dev->fd, p->w, p->h, p->fourcc,
> + handles, pitches, offsets, &p->fb_id, 0)) {
> + fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
> + return -1;
> + }
> + }
> +
> + p->bo = plane_bo;
> +
> + old_fb_id = p->fb_id;
> + p->old_fb_id = old_fb_id;
> +
> + crtc_w = p->w * p->scale;
> + crtc_h = p->h * p->scale;
> + if (!p->has_position) {
> + /* Default to the middle of the screen */
> + crtc_x = (crtc->mode->hdisplay - crtc_w) / 2;
> + crtc_y = (crtc->mode->vdisplay - crtc_h) / 2;
> + } else {
> + crtc_x = p->x;
> + crtc_y = p->y;
> + }
> +
> + add_property(dev, p->plane_id, "FB_ID", p->fb_id);
> + add_property(dev, p->plane_id, "CRTC_ID", p->crtc_id);
> + add_property(dev, p->plane_id, "SRC_X", 0);
> + add_property(dev, p->plane_id, "SRC_Y", 0);
> + add_property(dev, p->plane_id, "SRC_W", p->w << 16);
> + add_property(dev, p->plane_id, "SRC_H", p->h << 16);
> + add_property(dev, p->plane_id, "CRTC_X", crtc_x);
> + add_property(dev, p->plane_id, "CRTC_Y", crtc_y);
> + add_property(dev, p->plane_id, "CRTC_W", crtc_w);
> + add_property(dev, p->plane_id, "CRTC_H", crtc_h);
> +
> + return 0;
> +}
> +
> +static void set_planes(struct device *dev, struct plane_arg *p,
> + unsigned int count, bool update)
> +{
> + unsigned int i, pattern = UTIL_PATTERN_SMPTE;
> +
> + /* set up planes */
> + for (i = 0; i < count; i++) {
> + if (i > 0)
> + pattern = UTIL_PATTERN_TILES;
> +
> + if (set_plane(dev, &p[i], pattern, update))
> + return;
> + }
> +}
> +
> +static void clear_planes(struct device *dev, struct plane_arg *p, unsigned int count)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < count; i++) {
> + add_property(dev, p[i].plane_id, "FB_ID", 0);
> + add_property(dev, p[i].plane_id, "CRTC_ID", 0);
> + add_property(dev, p[i].plane_id, "SRC_X", 0);
> + add_property(dev, p[i].plane_id, "SRC_Y", 0);
> + add_property(dev, p[i].plane_id, "SRC_W", 0);
> + add_property(dev, p[i].plane_id, "SRC_H", 0);
> + add_property(dev, p[i].plane_id, "CRTC_X", 0);
> + add_property(dev, p[i].plane_id, "CRTC_Y", 0);
> + add_property(dev, p[i].plane_id, "CRTC_W", 0);
> + add_property(dev, p[i].plane_id, "CRTC_H", 0);
> + }
> +}
> +
> +static void clear_FB(struct device *dev, struct plane_arg *p, unsigned int count)
> +{
> + unsigned int i;
> +
> + for (i = 0; i < count; i++) {
> + if (p[i].fb_id) {
> + drmModeRmFB(dev->fd, p[i].fb_id);
> + p[i].fb_id = 0;
> + }
> + if (p[i].old_fb_id) {
> + drmModeRmFB(dev->fd, p[i].old_fb_id);
> + p[i].old_fb_id = 0;
> + }
> + if (p[i].bo) {
> + bo_destroy(p[i].bo);
> + p[i].bo = NULL;
> + }
> + if (p[i].old_bo) {
> + bo_destroy(p[i].old_bo);
> + p[i].old_bo = NULL;
> + }
> +
> + }
> +}
> +
> +static void set_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
> +{
> + unsigned int i;
> + unsigned int j;
> + int ret;
> +
> + for (i = 0; i < count; i++) {
> + struct pipe_arg *pipe = &pipes[i];
> +
> + ret = pipe_find_crtc_and_mode(dev, pipe);
> + if (ret < 0)
> + continue;
> + }
> +
> + for (i = 0; i < count; i++) {
> + struct pipe_arg *pipe = &pipes[i];
> + uint32_t blob_id;
> +
> + if (pipe->mode == NULL)
> + continue;
> +
> + printf("setting mode %s-%dHz@%s on connectors ",
> + pipe->mode_str, pipe->mode->vrefresh, pipe->format_str);
> + for (j = 0; j < pipe->num_cons; ++j) {
> + printf("%s, ", pipe->cons[j]);
> + add_property(dev, pipe->con_ids[j], "CRTC_ID", pipe->crtc->crtc->crtc_id);
> + }
> + printf("crtc %d\n", pipe->crtc->crtc->crtc_id);
> +
> + drmModeCreatePropertyBlob(dev->fd, pipe->mode, sizeof(*pipe->mode), &blob_id);
> + add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", blob_id);
> + add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 1);
> + }
> +}
> +
> +static void clear_mode(struct device *dev, struct pipe_arg *pipes, unsigned int count)
> +{
> + unsigned int i;
> + unsigned int j;
> +
> + for (i = 0; i < count; i++) {
> + struct pipe_arg *pipe = &pipes[i];
> +
> + if (pipe->mode == NULL)
> + continue;
> +
> + for (j = 0; j < pipe->num_cons; ++j)
> + add_property(dev, pipe->con_ids[j], "CRTC_ID",0);
> +
> + add_property(dev, pipe->crtc->crtc->crtc_id, "MODE_ID", 0);
> + add_property(dev, pipe->crtc->crtc->crtc_id, "ACTIVE", 0);
> + }
> +
> +}
> +
> +#define min(a, b) ((a) < (b) ? (a) : (b))
> +
> +static int parse_connector(struct pipe_arg *pipe, const char *arg)
> +{
> + unsigned int len;
> + unsigned int i;
> + const char *p;
> + char *endp;
> +
> + pipe->vrefresh = 0;
> + pipe->crtc_id = (uint32_t)-1;
> + strcpy(pipe->format_str, "XR24");
> +
> + /* Count the number of connectors and allocate them. */
> + pipe->num_cons = 1;
> + for (p = arg; *p && *p != ':' && *p != '@'; ++p) {
> + if (*p == ',')
> + pipe->num_cons++;
> + }
> +
> + pipe->con_ids = calloc(pipe->num_cons, sizeof(*pipe->con_ids));
> + pipe->cons = calloc(pipe->num_cons, sizeof(*pipe->cons));
> + if (pipe->con_ids == NULL || pipe->cons == NULL)
> + return -1;
> +
> + /* Parse the connectors. */
> + for (i = 0, p = arg; i < pipe->num_cons; ++i, p = endp + 1) {
> + endp = strpbrk(p, ",@:");
> + if (!endp)
> + break;
> +
> + pipe->cons[i] = strndup(p, endp - p);
> +
> + if (*endp != ',')
> + break;
> + }
> +
> + if (i != pipe->num_cons - 1)
> + return -1;
> +
> + /* Parse the remaining parameters. */
> + if (*endp == '@') {
> + arg = endp + 1;
> + pipe->crtc_id = strtoul(arg, &endp, 10);
> + }
> + if (*endp != ':')
> + return -1;
> +
> + arg = endp + 1;
> +
> + /* Search for the vertical refresh or the format. */
> + p = strpbrk(arg, "-@");
> + if (p == NULL)
> + p = arg + strlen(arg);
> + len = min(sizeof pipe->mode_str - 1, (unsigned int)(p - arg));
> + strncpy(pipe->mode_str, arg, len);
> + pipe->mode_str[len] = '\0';
> +
> + if (*p == '-') {
> + pipe->vrefresh = strtoul(p + 1, &endp, 10);
> + p = endp;
> + }
> +
> + if (*p == '@') {
> + strncpy(pipe->format_str, p + 1, 4);
> + pipe->format_str[4] = '\0';
> + }
> +
> + pipe->fourcc = util_format_fourcc(pipe->format_str);
> + if (pipe->fourcc == 0) {
> + fprintf(stderr, "unknown format %s\n", pipe->format_str);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int parse_plane(struct plane_arg *plane, const char *p)
> +{
> + char *end;
> +
> + plane->plane_id = strtoul(p, &end, 10);
> + if (*end != '@')
> + return -EINVAL;
> +
> + p = end + 1;
> + plane->crtc_id = strtoul(p, &end, 10);
> + if (*end != ':')
> + return -EINVAL;
> +
> + p = end + 1;
> + plane->w = strtoul(p, &end, 10);
> + if (*end != 'x')
> + return -EINVAL;
> +
> + p = end + 1;
> + plane->h = strtoul(p, &end, 10);
> +
> + if (*end == '+' || *end == '-') {
> + plane->x = strtol(end, &end, 10);
> + if (*end != '+' && *end != '-')
> + return -EINVAL;
> + plane->y = strtol(end, &end, 10);
> +
> + plane->has_position = true;
> + }
> +
> + if (*end == '*') {
> + p = end + 1;
> + plane->scale = strtod(p, &end);
> + if (plane->scale <= 0.0)
> + return -EINVAL;
> + } else {
> + plane->scale = 1.0;
> + }
> +
> + if (*end == '@') {
> + p = end + 1;
> + if (strlen(p) != 4)
> + return -EINVAL;
> +
> + strcpy(plane->format_str, p);
> + } else {
> + strcpy(plane->format_str, "XR24");
> + }
> +
> + plane->fourcc = util_format_fourcc(plane->format_str);
> + if (plane->fourcc == 0) {
> + fprintf(stderr, "unknown format %s\n", plane->format_str);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static int parse_property(struct property_arg *p, const char *arg)
> +{
> + if (sscanf(arg, "%d:%32[^:]:%" SCNu64, &p->obj_id, p->name, &p->value) != 3)
> + return -1;
> +
> + p->obj_type = 0;
> + p->name[DRM_PROP_NAME_LEN] = '\0';
> +
> + return 0;
> +}
> +
> +static void usage(char *name)
> +{
> + fprintf(stderr, "usage: %s [-cDdefMPpsCvw]\n", name);
> +
> + fprintf(stderr, "\n Query options:\n\n");
> + fprintf(stderr, "\t-c\tlist connectors\n");
> + fprintf(stderr, "\t-e\tlist encoders\n");
> + fprintf(stderr, "\t-f\tlist framebuffers\n");
> + fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
> +
> + fprintf(stderr, "\n Test options:\n\n");
> + fprintf(stderr, "\t-P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]\tset a plane\n");
> + fprintf(stderr, "\t-s <connector_id>[,<connector_id>][@<crtc_id>]:<mode>[-<vrefresh>][@<format>]\tset a mode\n");
> + fprintf(stderr, "\t-v\ttest loop\n");
> + fprintf(stderr, "\t-w <obj_id>:<prop_name>:<value>\tset property\n");
> +
> + fprintf(stderr, "\n Generic options:\n\n");
> + fprintf(stderr, "\t-d\tdrop master after mode set\n");
> + fprintf(stderr, "\t-M module\tuse the given driver\n");
> + fprintf(stderr, "\t-D device\tuse the given device\n");
> +
> + fprintf(stderr, "\n\tDefault is to dump all info.\n");
> + exit(0);
> +}
> +
> +static int pipe_resolve_connectors(struct device *dev, struct pipe_arg *pipe)
> +{
> + drmModeConnector *connector;
> + unsigned int i;
> + uint32_t id;
> + char *endp;
> +
> + for (i = 0; i < pipe->num_cons; i++) {
> + id = strtoul(pipe->cons[i], &endp, 10);
> + if (endp == pipe->cons[i]) {
> + connector = get_connector_by_name(dev, pipe->cons[i]);
> + if (!connector) {
> + fprintf(stderr, "no connector named '%s'\n",
> + pipe->cons[i]);
> + return -ENODEV;
> + }
> +
> + id = connector->connector_id;
> + }
> +
> + pipe->con_ids[i] = id;
> + }
> +
> + return 0;
> +}
> +
> +static char optstr[] = "cdD:efM:P:ps:vw:";
> +
> +int main(int argc, char **argv)
> +{
> + struct device dev;
> +
> + int c;
> + int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
> + int drop_master = 0;
> + int test_loop = 0;
> + char *device = NULL;
> + char *module = NULL;
> + unsigned int i;
> + unsigned int count = 0, plane_count = 0;
> + unsigned int prop_count = 0;
> + struct pipe_arg *pipe_args = NULL;
> + struct plane_arg *plane_args = NULL;
> + struct property_arg *prop_args = NULL;
> + unsigned int args = 0;
> + int ret;
> +
> + memset(&dev, 0, sizeof dev);
> +
> + opterr = 0;
> + while ((c = getopt(argc, argv, optstr)) != -1) {
> + args++;
> +
> + switch (c) {
> + case 'c':
> + connectors = 1;
> + break;
> + case 'D':
> + device = optarg;
> + args--;
> + break;
> + case 'd':
> + drop_master = 1;
> + break;
> + case 'e':
> + encoders = 1;
> + break;
> + case 'f':
> + framebuffers = 1;
> + break;
> + case 'M':
> + module = optarg;
> + /* Preserve the default behaviour of dumping all information. */
> + args--;
> + break;
> + case 'P':
> + plane_args = realloc(plane_args,
> + (plane_count + 1) * sizeof *plane_args);
> + if (plane_args == NULL) {
> + fprintf(stderr, "memory allocation failed\n");
> + return 1;
> + }
> + memset(&plane_args[plane_count], 0, sizeof(*plane_args));
> +
> + if (parse_plane(&plane_args[plane_count], optarg) < 0)
> + usage(argv[0]);
> +
> + plane_count++;
> + break;
> + case 'p':
> + crtcs = 1;
> + planes = 1;
> + break;
> + case 's':
> + pipe_args = realloc(pipe_args,
> + (count + 1) * sizeof *pipe_args);
> + if (pipe_args == NULL) {
> + fprintf(stderr, "memory allocation failed\n");
> + return 1;
> + }
> + memset(&pipe_args[count], 0, sizeof(*pipe_args));
> +
> + if (parse_connector(&pipe_args[count], optarg) < 0)
> + usage(argv[0]);
> +
> + count++;
> + break;
> + case 'v':
> + test_loop = 1;
> + break;
> + case 'w':
> + prop_args = realloc(prop_args,
> + (prop_count + 1) * sizeof *prop_args);
> + if (prop_args == NULL) {
> + fprintf(stderr, "memory allocation failed\n");
> + return 1;
> + }
> + memset(&prop_args[prop_count], 0, sizeof(*prop_args));
> +
> + if (parse_property(&prop_args[prop_count], optarg) < 0)
> + usage(argv[0]);
> +
> + prop_count++;
> + break;
> + default:
> + usage(argv[0]);
> + break;
> + }
> + }
> +
> + if (!args)
> + encoders = connectors = crtcs = planes = framebuffers = 1;
> +
> + dev.fd = util_open(device, module);
> + if (dev.fd < 0)
> + return -1;
> +
> + ret = drmSetClientCap(dev.fd, DRM_CLIENT_CAP_ATOMIC, 1);
> + if (ret) {
> + fprintf(stderr, "no atomic modesetting support: %s\n", strerror(errno));
> + drmClose(dev.fd);
> + return -1;
> + }
> +
> + dev.resources = get_resources(&dev);
> + if (!dev.resources) {
> + drmClose(dev.fd);
> + return 1;
> + }
> +
> + for (i = 0; i < count; i++) {
> + if (pipe_resolve_connectors(&dev, &pipe_args[i]) < 0) {
> + free_resources(dev.resources);
> + drmClose(dev.fd);
> + return 1;
> + }
> + }
> +
> +#define dump_resource(dev, res) if (res) dump_##res(dev)
> +
> + dump_resource(&dev, encoders);
> + dump_resource(&dev, connectors);
> + dump_resource(&dev, crtcs);
> + dump_resource(&dev, planes);
> + dump_resource(&dev, framebuffers);
> +
> + dev.req = drmModeAtomicAlloc();
> +
> + for (i = 0; i < prop_count; ++i)
> + set_property(&dev, &prop_args[i]);
> +
> + if (count && plane_count) {
> + uint64_t cap = 0;
> +
> + ret = drmGetCap(dev.fd, DRM_CAP_DUMB_BUFFER, &cap);
> + if (ret || cap == 0) {
> + fprintf(stderr, "driver doesn't support the dumb buffer API\n");
> + drmModeAtomicFree(dev.req);
> + return 1;
> + }
> +
> + set_mode(&dev, pipe_args, count);
> + set_planes(&dev, plane_args, plane_count, false);
> +
> + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
> + if (ret) {
> + fprintf(stderr, "Atomic Commit failed [1]\n");
> + return 1;
> + }
> +
> + gettimeofday(&pipe_args->start, NULL);
> + pipe_args->swap_count = 0;
> +
> + while (test_loop) {
> + drmModeAtomicFree(dev.req);
> + dev.req = drmModeAtomicAlloc();
> + set_planes(&dev, plane_args, plane_count, true);
> +
> + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
> + if (ret) {
> + fprintf(stderr, "Atomic Commit failed [2]\n");
> + return 1;
> + }
> +
> + pipe_args->swap_count++;
> + if (pipe_args->swap_count == 60) {
> + struct timeval end;
> + double t;
> +
> + gettimeofday(&end, NULL);
> + t = end.tv_sec + end.tv_usec * 1e-6 -
> + (pipe_args->start.tv_sec + pipe_args->start.tv_usec * 1e-6);
> + fprintf(stderr, "freq: %.02fHz\n", pipe_args->swap_count / t);
> + pipe_args->swap_count = 0;
> + pipe_args->start = end;
> + }
> + }
> +
> + if (drop_master)
> + drmDropMaster(dev.fd);
> +
> + getchar();
> +
> + drmModeAtomicFree(dev.req);
> + dev.req = drmModeAtomicAlloc();
> +
> + clear_mode(&dev, pipe_args, count);
> + clear_planes(&dev, plane_args, plane_count);
> + ret = drmModeAtomicCommit(dev.fd, dev.req, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
> + if (ret) {
> + fprintf(stderr, "Atomic Commit failed\n");
> + return 1;
> + }
> +
> + clear_FB(&dev, plane_args, plane_count);
> + }
> +
> + drmModeAtomicFree(dev.req);
> + free_resources(dev.resources);
> +
> + return 0;
> +}
> --
> 2.15.0
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH 11/20] wil6210: send L2UF on behalf of newly associated station
From: merez @ 2018-07-23 15:27 UTC (permalink / raw)
To: Johannes Berg
Cc: Kalle Valo, Ahmad Masri, linux-wireless, wil6210,
linux-wireless-owner
In-Reply-To: <1532289708.3680.3.camel@sipsolutions.net>
On 2018-07-22 23:01, Johannes Berg wrote:
> On Sun, 2018-07-22 at 10:47 +0300, Maya Erez wrote:
>> From: Ahmad Masri <amasri@codeaurora.org>
>>
>> Send L2UF (Level 2 Update Frame) to update forwarding tables in layer
>> 2
>> in AP mode. Wil6210 driver creates and sends this frame once a new
>> station connects to the AP.
>
> Might be worth unifying with ieee80211_send_layer2_update() into a new
> cfg80211 function?
>
> johannes
We will do that. I'll revert this patch.
--
Maya Erez
Qualcomm Israel, Inc. on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
Linux Foundation Collaborative Project
^ permalink raw reply
* Re: [PATCH 10/14] format-patch: add --range-diff option to embed diff in cover letter
From: Duy Nguyen @ 2018-07-23 16:28 UTC (permalink / raw)
To: Eric Sunshine
Cc: Git Mailing List, Johannes Schindelin,
Ævar Arnfjörð Bjarmason, Stefan Beller
In-Reply-To: <20180722095717.17912-11-sunshine@sunshineco.com>
On Sun, Jul 22, 2018 at 11:58 AM Eric Sunshine <sunshine@sunshineco.com> wrote:
> diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
> index f8a061794d..e7f404be3d 100644
> --- a/Documentation/git-format-patch.txt
> +++ b/Documentation/git-format-patch.txt
> @@ -24,6 +24,7 @@ SYNOPSIS
> [--to=<email>] [--cc=<email>]
> [--[no-]cover-letter] [--quiet] [--notes[=<ref>]]
> [--interdiff=<previous>]
> + [--range-diff=<previous>]
I wonder if people will use both --interdiff=<rev> and
--range-diff=<rev> often enough to justify a shortcut
"--all-kinds-of-diff=<rev>" so that we don't have to type <previous>
twice. But I guess we don't have to worry about this right now.
--
Duy
^ permalink raw reply
* Re: [PATCH resend 1/2] btrfs: allow defrag on a file opened ro that has rw permissions
From: David Sterba @ 2018-07-23 15:26 UTC (permalink / raw)
To: Adam Borowski; +Cc: David Sterba, Mark Fasheh, linux-btrfs
In-Reply-To: <20180717220900.3588-1-kilobyte@angband.pl>
On Wed, Jul 18, 2018 at 12:08:59AM +0200, Adam Borowski wrote:
> Requiring a rw descriptor conflicts both ways with exec, returning ETXTBSY
> whenever you try to defrag a program that's currently being run, or
> causing intermittent exec failures on a live system being defragged.
>
> As defrag doesn't change the file's contents in any way, there's no reason
> to consider it a rw operation. Thus, let's check only whether the file
> could have been opened rw. Such access control is still needed as
> currently defrag can use extra disk space, and might trigger bugs.
>
> Signed-off-by: Adam Borowski <kilobyte@angband.pl>
> ---
> fs/btrfs/ioctl.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 43ecbe620dea..01c150b6ab62 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -2941,7 +2941,8 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
> ret = btrfs_defrag_root(root);
> break;
> case S_IFREG:
> - if (!(file->f_mode & FMODE_WRITE)) {
> + if (!capable(CAP_SYS_ADMIN) &&
> + inode_permission(inode, MAY_WRITE)) {
The dedupe ioctl does the admin check or the FMODE_WRITE, which means
admin can dedupe anything but user has to have the file write open.
Doing the same for defrag should be ok for same reasons it is for
dedupe.
I'm not sure about using plain inode_permissions here, though it looks
correct and I'm not able to see inode vs file descriptor issues that
could cause trouble here. There are uid/gid, rws, acl, immutable,
capabilities, namespace aware checks, security hooks.
So, I'll add the patch to 4.19 queue. It's small and isolated change so
a revert would be easy in case we find something bad. The 2nd patch
should be IMHO part of this change as it's logical to return the error
code in the patch that modifies the user visible behaviour.
^ permalink raw reply
* [PATCH 5/5] Add sample notification program
From: David Howells @ 2018-07-23 15:26 UTC (permalink / raw)
To: viro
Cc: linux-fsdevel, dhowells, linux-kernel, raven, keyrings,
linux-security-module
In-Reply-To: <153235954191.32640.5792167066538704794.stgit@warthog.procyon.org.uk>
This needs to be linked with -lkeyutils.
It is run like:
./watch_test
and watches "/" for mount changes and the current session keyring for key
changes:
# keyctl add user a a @s
1035096409
# keyctl unlink 1035096409 @s
# mount -t tmpfs none /mnt/nfsv3tcp/
# umount /mnt/nfsv3tcp
producing:
# ./watch_test
ptrs h=4 t=2 m=20003
NOTIFY[00000004-00000002] ty=0003 sy=0002 i=01000010
KEY 2ffc2e5d change=2[linked] aux=1035096409
ptrs h=6 t=4 m=20003
NOTIFY[00000006-00000004] ty=0003 sy=0003 i=01000010
KEY 2ffc2e5d change=3[unlinked] aux=1035096409
ptrs h=8 t=6 m=20003
NOTIFY[00000008-00000006] ty=0001 sy=0000 i=02000010
MOUNT 00000013 change=0[new_mount] aux=168
ptrs h=a t=8 m=20003
NOTIFY[0000000a-00000008] ty=0001 sy=0001 i=02000010
MOUNT 00000013 change=1[unmount] aux=168
---
samples/Kconfig | 6 +
samples/Makefile | 2
samples/watch_queue/Makefile | 9 +
samples/watch_queue/watch_test.c | 232 ++++++++++++++++++++++++++++++++++++++
4 files changed, 248 insertions(+), 1 deletion(-)
create mode 100644 samples/watch_queue/Makefile
create mode 100644 samples/watch_queue/watch_test.c
diff --git a/samples/Kconfig b/samples/Kconfig
index 1c5658bc6224..dac30cefe895 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -156,4 +156,10 @@ config SAMPLE_MOUNT_API
help
Build example userspace program(s) that use the new mount API.
+config SAMPLE_WATCH_QUEUE
+ bool "Build example /dev/watch_queue notification consumer"
+ help
+ Build example userspace program to use the new mount_notify(),
+ sb_notify() syscalls and the KEYCTL_WATCH_KEY keyctl() function.
+
endif # SAMPLES
diff --git a/samples/Makefile b/samples/Makefile
index 31d08cc71a5c..ed545cbf65c8 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -3,4 +3,4 @@
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
configfs/ connector/ v4l/ trace_printk/ \
- vfio-mdev/ statx/ qmi/ mount_api/
+ vfio-mdev/ statx/ qmi/ mount_api/ watch_queue/
diff --git a/samples/watch_queue/Makefile b/samples/watch_queue/Makefile
new file mode 100644
index 000000000000..1f20ee2b0add
--- /dev/null
+++ b/samples/watch_queue/Makefile
@@ -0,0 +1,9 @@
+# List of programs to build
+hostprogs-$(CONFIG_SAMPLE_WATCH_QUEUE) := watch_test
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
+
+HOSTCFLAGS_watch_test.o += -I$(objtree)/usr/include
+
+HOSTLOADLIBES_watch_test += -lkeyutils
diff --git a/samples/watch_queue/watch_test.c b/samples/watch_queue/watch_test.c
new file mode 100644
index 000000000000..cdbaaf5a1163
--- /dev/null
+++ b/samples/watch_queue/watch_test.c
@@ -0,0 +1,232 @@
+/* Use /dev/watch_queue to watch for keyring and mount topology changes.
+ *
+ * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <poll.h>
+#include <limits.h>
+#include <linux/watch_queue.h>
+#include <linux/unistd.h>
+#include <linux/keyctl.h>
+
+#define BUF_SIZE 4
+
+static const char *key_subtypes[] = {
+ [notify_key_instantiated] = "instantiated",
+ [notify_key_updated] = "updated",
+ [notify_key_linked] = "linked",
+ [notify_key_unlinked] = "unlinked",
+ [notify_key_cleared] = "cleared",
+ [notify_key_revoked] = "revoked",
+ [notify_key_invalidated] = "invalidated",
+ [notify_key_setattr] = "setattr",
+};
+
+static void saw_key_change(struct watch_notification *n)
+{
+ struct key_notification *k = (struct key_notification *)n;
+ unsigned int len = n->info & WATCH_INFO_LENGTH;
+
+ if (len != sizeof(struct key_notification))
+ return;
+
+ printf("KEY %08x change=%u[%s] aux=%u\n",
+ k->key_id, n->subtype, key_subtypes[n->subtype], k->aux);
+}
+
+static const char *mount_subtypes[] = {
+ [notify_mount_new_mount] = "new_mount",
+ [notify_mount_unmount] = "unmount",
+ [notify_mount_expiry] = "expiry",
+ [notify_mount_readonly] = "readonly",
+ [notify_mount_setattr] = "setattr",
+ [notify_mount_move_from] = "move_from",
+ [notify_mount_move_to] = "move_to",
+};
+
+static long keyctl_watch_key(int key, int watch_fd, int watch_id)
+{
+ return syscall(__NR_keyctl, KEYCTL_WATCH_KEY, key, watch_fd, watch_id);
+}
+
+static void saw_mount_change(struct watch_notification *n)
+{
+ struct mount_notification *m = (struct mount_notification *)n;
+ unsigned int len = n->info & WATCH_INFO_LENGTH;
+
+ if (len != sizeof(struct mount_notification))
+ return;
+
+ printf("MOUNT %08x change=%u[%s] aux=%u\n",
+ m->triggered_on, n->subtype, mount_subtypes[n->subtype], m->changed_mount);
+}
+
+static const char *super_subtypes[] = {
+ [notify_superblock_readonly] = "readonly",
+ [notify_superblock_error] = "error",
+ [notify_superblock_edquot] = "edquot",
+ [notify_superblock_network] = "network",
+};
+
+static void saw_super_change(struct watch_notification *n)
+{
+ struct superblock_notification *s = (struct superblock_notification *)n;
+ unsigned int len = n->info & WATCH_INFO_LENGTH;
+
+ if (len < sizeof(struct superblock_notification))
+ return;
+
+ printf("SUPER %08llx change=%u[%s]\n",
+ s->sb_id, n->subtype, super_subtypes[n->subtype]);
+}
+
+/*
+ * Consume and display events.
+ */
+static int consumer(int fd, struct watch_queue_buffer *buf)
+{
+ struct watch_notification *n;
+ struct pollfd p[1];
+ unsigned int head, tail, mask = buf->meta.mask;
+
+ for (;;) {
+ p[0].fd = fd;
+ p[0].events = POLLIN | POLLERR;
+ p[0].revents = 0;
+
+ if (poll(p, 1, -1) == -1) {
+ perror("poll");
+ break;
+ }
+
+ printf("ptrs h=%x t=%x m=%x\n",
+ buf->meta.head, buf->meta.tail, buf->meta.mask);
+
+ while (head = buf->meta.head,
+ tail = buf->meta.tail,
+ tail != head
+ ) {
+ asm ("lfence" : : : "memory" );
+ n = &buf->slots[tail & mask];
+ printf("NOTIFY[%08x-%08x] ty=%04x sy=%04x i=%08x\n",
+ head, tail, n->type, n->subtype, n->info);
+ if ((n->info & WATCH_INFO_LENGTH) == 0)
+ goto out;
+
+ switch (n->type) {
+ case WATCH_TYPE_META:
+ if (n->subtype == watch_meta_removal_notification)
+ printf("REMOVAL of watchpoint %08x\n",
+ n->info & WATCH_INFO_ID);
+ break;
+ case WATCH_TYPE_MOUNT_NOTIFY:
+ saw_mount_change(n);
+ break;
+ case WATCH_TYPE_SB_NOTIFY:
+ saw_super_change(n);
+ break;
+ case WATCH_TYPE_KEY_NOTIFY:
+ saw_key_change(n);
+ break;
+ }
+
+ tail += (n->info & WATCH_INFO_LENGTH) >> WATCH_LENGTH_SHIFT;
+ asm("mfence" ::: "memory");
+ buf->meta.tail = tail;
+ }
+ }
+
+out:
+ return 0;
+}
+
+static struct watch_notification_filter filter = {
+ .nr_filters = 3,
+ .__reserved = 0,
+ .filters = {
+ [0] = {
+ .type = WATCH_TYPE_MOUNT_NOTIFY,
+ // Reject move-from notifications
+ .subtype_filter[0] = UINT_MAX & ~(1 << notify_mount_move_from),
+ },
+ [1] = {
+ .type = WATCH_TYPE_SB_NOTIFY,
+ // Only accept notification of changes to R/O state
+ .subtype_filter[0] = (1 << notify_superblock_readonly),
+ // Only accept notifications of change-to-R/O
+ .info_mask = WATCH_INFO_FLAG_0,
+ .info_filter = WATCH_INFO_FLAG_0,
+ },
+ [2] = {
+ .type = WATCH_TYPE_KEY_NOTIFY,
+ .subtype_filter[0] = UINT_MAX,
+ },
+ },
+};
+
+int main(int argc, char **argv)
+{
+ struct watch_queue_buffer *buf;
+ size_t page_size;
+ int fd;
+
+ fd = open("/dev/watch_queue", O_RDWR);
+ if (fd == -1) {
+ perror("/dev/watch_queue");
+ exit(1);
+ }
+
+ if (ioctl(fd, IOC_WATCH_QUEUE_SET_SIZE, BUF_SIZE) == -1) {
+ perror("/dev/watch_queue(size)");
+ exit(1);
+ }
+
+ if (ioctl(fd, IOC_WATCH_QUEUE_SET_FILTER, &filter) == -1) {
+ perror("/dev/watch_queue(filter)");
+ exit(1);
+ }
+
+ page_size = sysconf(_SC_PAGESIZE);
+ buf = mmap(NULL, BUF_SIZE * page_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (buf == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+
+ if (keyctl_watch_key(KEY_SPEC_SESSION_KEYRING, fd, 0x01) == -1) {
+ perror("keyctl");
+ exit(1);
+ }
+
+ if (syscall(__NR_mount_notify, AT_FDCWD, "/", 0, fd, 0x02) == -1) {
+ perror("mount_notify");
+ exit(1);
+ }
+
+ if (syscall(__NR_sb_notify, AT_FDCWD, "/mnt", 0, fd, 0x03) == -1) {
+ perror("sb_notify");
+ exit(1);
+ }
+
+ return consumer(fd, buf);
+}
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.