Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rk3328 can't playback rate up to 176.4k/192k via SPDIF #214

Open
willardting opened this issue Jun 1, 2020 · 4 comments
Open

rk3328 can't playback rate up to 176.4k/192k via SPDIF #214

willardting opened this issue Jun 1, 2020 · 4 comments

Comments

@willardting
Copy link

willardting commented Jun 1, 2020

Hello, contributors. @sjoerd-ccu @rkhuangtao @arndb @broonie @AxelLin
These days I've been testing spdif transmitting from rk3328, using firefly aio-rk3328-jd4 core board. I get stuck on playback of 88.2k/24bit, 96k/24bit, 176.4k/16bit(24bit) and 192k/16bit(24bit), as it sent nothing from spdifm1_tx pin.
I used dmesg to get the kernel log as follows:
[ 8252.009035] dma-pl330 ff1f0000.dmac: Reset Channel-4 CS-20400f FTC-1
[ 8267.250622] dma-pl330 ff1f0000.dmac: Reset Channel-4 CS-20400f FTC-2000
I used wav file with aplay command:
aplay -D plughw:2,0 192000-16.WAV
and got the feedback message:
Playing WAVE '192000-16.WAV' : Signed 16 bit Little Endian, Rate 192000 Hz, Stereo
^CAborted by signal Interrupt...
aplay: pcm_write:1939: write error: Input/output error
So what's the problem? Could somebody kindly test with the audio files as I mentioned above?
Sincerely,
Willard.

@sugaroneone
Copy link

Have you tried 48k playback?
plz dump info when do aplay:
1, plz dump the card params by "cat /proc/asound/card*/pcm0p/sub0/*"
2, plz dump the full dmesg.
3, plz dump the controller registers:
io -4 -l 0x100 0xff030000
io -4 -l 0x500 0xff1f0000
4, plz dump the clk tree by "cat /sys/kernel/debug/clk/clk_summary > file"

@willardting
Copy link
Author

willardting commented Jun 2, 2020

@sugaroneone I ultimately found out a way to fix the problem, eliminating any errors:

--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -118,6 +118,7 @@ static int rk_spdif_hw_params(struct snd_pcm_substream *substream,
                val |= SPDIF_CFGR_VDW_20;
                break;
        case SNDRV_PCM_FORMAT_S24_LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
                val |= SPDIF_CFGR_VDW_24;
                break;
        default:
@@ -201,11 +202,14 @@ static struct snd_soc_dai_driver rk_spdif_dai = {
                .rates = (SNDRV_PCM_RATE_32000 |
                          SNDRV_PCM_RATE_44100 |
                          SNDRV_PCM_RATE_48000 |
+                         SNDRV_PCM_RATE_88200 |
                          SNDRV_PCM_RATE_96000 |
+                         SNDRV_PCM_RATE_176400 |
                          SNDRV_PCM_RATE_192000),
                .formats = (SNDRV_PCM_FMTBIT_S16_LE |
                            SNDRV_PCM_FMTBIT_S20_3LE |
-                           SNDRV_PCM_FMTBIT_S24_LE),
+                           SNDRV_PCM_FMTBIT_S24_LE |
+                           SNDRV_PCM_FMTBIT_S24_3LE),
        },
        .ops = &rk_spdif_dai_ops,
 };
@@ -338,7 +342,7 @@ static int rk_spdif_probe(struct platform_device *pdev)
 
        spdif->playback_dma_data.addr = res->start + SPDIF_SMPDR;
        spdif->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-       spdif->playback_dma_data.maxburst = 4;
+       spdif->playback_dma_data.maxburst = 8;
 
        spdif->dev = &pdev->dev;
        dev_set_drvdata(&pdev->dev, spdif);

I simply changed the spdif->playback_dma_data.maxburst from 4 to 8, plus adding params supporting 88200 and 176400. Recompiling the snd_soc_rockchip_spdif module, and now I can smoothly "SPDIF out" 44100/16(24)bit, 48000/16(24)bit, 88200/16(24)bit, 96000/16(24)bit, 176400/16(24)bit, 192000/16(24)bit!!! I also tested with 32bit wav files, luckily it works as well!

Is it really the dma maxburst number's problem? Or elsewhere we could do better?

Thanks.

@willardting
Copy link
Author

After compiling the spdif module, I did the recommended steps as you said, playback 88200-24.wav, and this is the outcome:

closed
card: 0
device: 0
subdevice: 0
stream: PLAYBACK
id: ff010000.i2s-rk3328-hifi rk3328-hifi-0
name:
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1
512
18014398509481983
closed
closed
closed
card: 1
device: 0
subdevice: 0
stream: PLAYBACK
id: ff000000.i2s-i2s-hifi i2s-hifi-0
name:
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1
512
18014398509481983
closed
closed
access: MMAP_INTERLEAVED
format: S24_LE
subformat: STD
channels: 2
rate: 88200 (88200/1)
period_size: 11025
buffer_size: 44100
card: 2
device: 0
subdevice: 0
stream: PLAYBACK
id: ff030000.spdif-dit-hifi dit-hifi-0
name:
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 0
512
18014398509481983
state: RUNNING
owner_pid   : 10590
trigger_time: 4092.515362153
tstamp      : 0.000000000
delay       : 35876
avail       : 8224
avail_max   : 11213
-----
hw_ptr      : 1452499
appl_ptr    : 1488375
tstamp_mode: NONE
period_step: 1
avail_min: 11025
start_threshold: 44100
stop_threshold: 44100
silence_threshold: 0
silence_size: 0
boundary: 1445068800

dmesg with no specific warnings or errors

How can I dump the controller registers? I didn't find any 'io' command [cry][cry], could you detail how to implement this step?

   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase
----------------------------------------------------------------------------------------
 xin32k                                   0            0       32768          0 0
 gmac_clkin                               0            0    50000000          0 0
 xin24m                                  10           10    24000000          0 0
    hdmi_phy                              0            0   148500000          0 0
       hdmiphy                            0            0   148500000          0 0
          hdmiphy_peri                    0            0   148500000          0 0
          dclk_lcdc                       0            0   148500000          0 0
          clk_cif_src                     0            0   148500000          0 0
             clk_cif_out                  0            0     7425000          0 0
    usb480m_phy                           2            3   480000000          0 0
       usb480m                            0            1   480000000          0 0
          aclk_vpu_pre                    0            2    15000000          0 0
             aclk_vpu_niu                 0            0    15000000          0 0
             aclk_vpu                     0            4    15000000          0 0
             hclk_vpu_pre                 0            1     3750000          0 0
                hclk_vpu_niu              0            0     3750000          0 0
                hclk_vpu                  0            4     3750000          0 0
    sclk_uart1                            0            0    24000000          0 0
    sclk_uart0                            0            0    24000000          0 0
    xin12m                                0            0    12000000          0 0
    clk_usb3otg_ref                       1            1    24000000          0 0
    clk_ref_usb3otg                       0            0    24000000          0 0
    clk_sdmmc                             1            1      800000          0 0
       sdmmc_sample                       0            0      400000          0 0
       sdmmc_drv                          0            0      400000          0 180
    clk_hdmi_sfc                          1            1    24000000          0 0
    sclk_timer5                           0            0    24000000          0 0
    sclk_timer4                           0            0    24000000          0 0
    sclk_timer3                           0            0    24000000          0 0
    sclk_timer2                           0            0    24000000          0 0
    sclk_timer1                           0            0    24000000          0 0
    sclk_timer0                           0            0    24000000          0 0
    clk_efuse                             0            0    24000000          0 0
    clk_otp                               0            0    24000000          0 0
    sclk_uart2                            1            1    24000000          0 0
    clk_ddrmon                            0            0    24000000          0 0
    clk_24m                               2            2    24000000          0 0
       clk_saradc                         1            1     1000000          0 0
       clk_tsadc                          1            1       50000          0 0
    pll_npll                              0            0  1392000000          0 0
       npll                               0            0  1392000000          0 0
          npll_core                       0            0  1392000000          0 0
             armclk                       0            0  1392000000          0 0
                pclk_dbg                  1            1   232000000          0 0
                aclk_core                 2            2   696000000          0 0
                   aclk_gic400            1            1   696000000          0 0
                   aclk_core_niu           1            1   696000000          0 0
    pll_gpll                              1            1   491519999          0 0
       gpll                               4            6   491519999          0 0
          clk_spdif_div                   1            1   491519999          0 0
             clk_spdif_frac               1            1    11289599          0 0
                sclk_spdif                1            1    11289599          0 0
          sclk_vdec_core                  0            1   245760000          0 0
          aclk_rkvdec_pre                 0            2   491519999          0 0
             aclk_rkvdec_niu              0            0   491519999          0 0
             aclk_rkvdec                  0            2   491519999          0 0
             hclk_rkvdec_pre              0            1   122879999          0 0
                hclk_rkvdec_niu           0            0   122879999          0 0
                hclk_rkvdec               0            2   122879999          0 0
          clk_rtc32k                      3            3       32768          0 0
             clk_usb3otg_suspend           1            1       32768          0 0
          gpll_peri                       0            0   491519999          0 0
          clk_crypto                      0            0    61440000          0 0
          pclk_ddr                        3            3    98304000          0 0
             pclk_ddr_grf                 1            1    98304000          0 0
             pclk_ddrstdby                0            0    98304000          0 0
             pclk_ddr_mon                 1            1    98304000          0 0
             pclk_ddr_msch                1            1    98304000          0 0
             pclk_ddrupctl                0            0    98304000          0 0
          gpll_core                       1            1   491519999          0 0
    pll_cpll                              1            1  1200000000          0 0
       cpll                               9           16  1200000000          0 0
          aclk_gpu_pre                    0            1   200000000          0 0
             aclk_gpu_niu                 0            0   200000000          0 0
             aclk_gpu                     0            1   200000000          0 0
          clk_sdmmc_ext                   1            1    50000000          0 0
             sdmmc_ext_sample             0            0    25000000          0 0
             sdmmc_ext_drv                0            0    25000000          0 180
          clk_emmc                        1            1   300000000          0 0
             emmc_sample                  0            0   150000000          0 238
             emmc_drv                     0            0   150000000          0 180
          aclk_bus_pre                    4            4   150000000          0 0
             aclk_dmac_bus                1            1   150000000          0 0
             aclk_intmem                  1            1   150000000          0 0
             aclk_tsp                     0            0   150000000          0 0
             aclk_dcf                     0            0   150000000          0 0
             aclk_bus_niu                 0            0   150000000          0 0
             pclk_bus_pre                 2            2    75000000          0 0
                pclk_phy_pre              4            4    75000000          0 0
                   pclk_phy_niu           0            0    75000000          0 0
                   pclk_vdacphy           0            0    75000000          0 0
                   pclk_hdmiphy           1            1    75000000          0 0
                   pclk_acodecphy           0            0    75000000          0 0
                   pclk_ddrphy            1            1    75000000          0 0
                   pclk_usb2_grf           0            0    75000000          0 0
                   pclk_usb3_grf           0            0    75000000          0 0
                   pclk_usb3phy_pipe           2            2    75000000          0 0
                   pclk_usb3phy_otg           2            2    75000000          0 0
                pclk_bus                 12           15    75000000          0 0
                   pclk_pmu               1            1    75000000          0 0
                   pclk_saradc            1            1    75000000          0 0
                   pclk_sim               0            0    75000000          0 0
                   pclk_sgrf              1            1    75000000          0 0
                   pclk_acodec            1            1    75000000          0 0
                   pclk_cru               1            1    75000000          0 0
                   pclk_grf               1            1    75000000          0 0
                   pclk_dcf               0            0    75000000          0 0
                   pclk_tsadc             1            1    75000000          0 0
                   pclk_uart2             1            1    75000000          0 0
                   pclk_uart1             0            0    75000000          0 0
                   pclk_uart0             0            0    75000000          0 0
                   pclk_gpio3             1            1    75000000          0 0
                   pclk_gpio2             0            1    75000000          0 0
                   pclk_gpio1             1            1    75000000          0 0
                   pclk_gpio0             0            1    75000000          0 0
                   pclk_rk_pwm            0            0    75000000          0 0
                   pclk_spi               0            0    75000000          0 0
                   pclk_stimer            0            0    75000000          0 0
                   pclk_timer0            1            1    75000000          0 0
                   pclk_i2c3              0            0    75000000          0 0
                   pclk_i2c2              0            0    75000000          0 0
                   pclk_i2c1              0            1    75000000          0 0
                   pclk_i2c0              0            0    75000000          0 0
                   pclk_otp               0            0    75000000          0 0
                   pclk_efuse             0            0    75000000          0 0
                   pclk_bus_niu           0            0    75000000          0 0
                   pclk_wdt               0            0    75000000          0 0
             hclk_bus_pre                 4            4    75000000          0 0
                hclk_pdm                  0            0    75000000          0 0
                hclk_bus_niu              0            0    75000000          0 0
                hclk_crypto_slv           0            0    75000000          0 0
                hclk_crypto_mst           0            0    75000000          0 0
                hclk_tsp                  0            0    75000000          0 0
                hclk_spdif_8ch            1            2    75000000          0 0
                hclk_i2s2_2ch             0            0    75000000          0 0
                hclk_i2s1_8ch             1            1    75000000          0 0
                hclk_i2s0_8ch             1            1    75000000          0 0
                hclk_rom                  1            1    75000000          0 0
          aclk_gmac                       2            2   150000000          0 0
             aclk_gmac_niu                0            0   150000000          0 0
             aclk_mac2io                  1            1   150000000          0 0
             aclk_mac2phy                 0            0   150000000          0 0
             pclk_gmac                    1            1    50000000          0 0
                pclk_gmac_niu             0            0    50000000          0 0
                pclk_mac2io               2            2    50000000          0 0
                pclk_mac2phy              0            0    50000000          0 0
          clk_rga                         0            0   200000000          0 0
          sclk_vdec_cabac                 0            1   300000000          0 0
          aclk_rga_pre                    1            1   300000000          0 0
             aclk_rga_niu                 1            1   300000000          0 0
             aclk_rga                     0            0   300000000          0 0
          clk_mac2phy_src                 0            0    75000000          0 0
             clk_mac2phy                  0            0    75000000          0 0
                clk_mac2phy_ref           0            0    75000000          0 0
                clk_mac2phy_rxtx           0            0    75000000          0 0
                clk_mac2phy_out           0            0    75000000          0 0
          clk_mac2io_out                  0            0    50000000          0 0
          clk_mac2io_src                  1            1    50000000          0 0
             clk_mac2io                   5            5    50000000          0 0
                clk_mac2io_ext            0            0    50000000          0 0
                clk_mac2io_ref            1            1    50000000          0 0
                clk_mac2io_rx             1            1    50000000          0 0
                clk_mac2io_tx             1            1    50000000          0 0
                clk_mac2io_refout           1            1    50000000          0 0
          clk_ref_usb3otg_src             0            0    37500000          0 0
          clk_sdio                        0            0    50000000          0 0
             sdio_sample                  0            0    25000000          0 0
             sdio_drv                     0            0    25000000          0 180
          cpll_peri                       1            1  1200000000          0 0
             aclk_peri_pre                3            3   150000000          0 0
                aclk_peri                 2            2   150000000          0 0
                   aclk_usb3otg           1            1   150000000          0 0
                   aclk_peri_noc           0            0   150000000          0 0
                hclk_peri                 8            8    75000000          0 0
                   pclk_peri_niu           0            0    75000000          0 0
                   hclk_peri_niu           0            0    75000000          0 0
                   hclk_otg_pmu           2            2    75000000          0 0
                   hclk_otg               1            1    75000000          0 0
                   hclk_host0_arb           2            2    75000000          0 0
                   hclk_host0             2            2    75000000          0 0
                   hclk_sdmmc_ext           1            1    75000000          0 0
                   hclk_emmc              1            1    75000000          0 0
                   hclk_sdio              0            0    75000000          0 0
                   hclk_sdmmc             1            1    75000000          0 0
                pclk_peri                 1            1    75000000          0 0
          dclk_lcdc_src                   0            0    24000000          0 0
             dclk_hdmiphy                 0            0     8000000          0 0
          aclk_vop_pre                    0            1   400000000          0 0
             aclk_vop_niu                 0            0   400000000          0 0
             aclk_vop                     0            1   400000000          0 0
          aclk_vio_pre                    1            1   300000000          0 0
             aclk_vio_niu                 0            0   300000000          0 0
             aclk_hdcp                    0            0   300000000          0 0
             aclk_cif                     0            0   300000000          0 0
             aclk_iep                     0            0   300000000          0 0
             hclk_vio_pre                 5            6   100000000          0 0
                pclk_hdcp                 0            0   100000000          0 0
                pclk_hdmi                 1            1   100000000          0 0
                hclk_vio                  1            1   100000000          0 0
                hclk_hdcp                 0            0   100000000          0 0
                hclk_vio_h2p              1            1   100000000          0 0
                pclk_vio_h2p              1            1   100000000          0 0
                hclk_ahb1tom              1            1   100000000          0 0
                hclk_rga                  0            0   100000000          0 0
                hclk_cif                  0            0   100000000          0 0
                hclk_iep                  0            0   100000000          0 0
                hclk_vop_niu              0            0   100000000          0 0
                hclk_vop                  0            1   100000000          0 0
          sclk_venc_dsp                   0            1   100000000          0 0
          sclk_venc_core                  0            2   200000000          0 0
          aclk_rkvenc                     0            5   200000000          0 0
             aclk_axisram                 0            1   200000000          0 0
             aclk_h264                    0            3   200000000          0 0
             aclk_h265                    0            3   200000000          0 0
             aclk_rkvenc_niu              0            0   200000000          0 0
             hclk_rkvenc                  0            2    50000000          0 0
                hclk_h264                 0            3    50000000          0 0
                pclk_h265                 0            3    50000000          0 0
                hclk_rkvenc_niu           0            0    50000000          0 0
          clk_wifi                        0            0    24000000          0 0
          clk_pwm                         0            0    50000000          0 0
          clk_spi                         0            0    50000000          0 0
          clk_i2c3                        0            0   150000000          0 0
          clk_i2c2                        0            0   150000000          0 0
          clk_i2c1                        0            1   150000000          0 0
          clk_i2c0                        0            0   150000000          0 0
          clk_uart2_div                   0            0   150000000          0 0
             clk_uart2_frac               0            0     7500000          0 0
          clk_uart1_div                   0            0   150000000          0 0
             clk_uart1_frac               0            0     7500000          0 0
          clk_uart0_div                   0            0   150000000          0 0
             clk_uart0_frac               0            0     7500000          0 0
          clk_i2s2_div                    0            0    75000000          0 0
             i2s2_pre                     0            0    75000000          0 0
                clk_i2s2                  0            0    75000000          0 0
                   i2s2_out               0            0    75000000          0 0
             clk_i2s2_frac                0            0     3750000          0 0
          clk_i2s1_div                    1            1   600000000          0 0
             clk_i2s1_frac                1            1    11289600          0 0
                i2s1_pre                  1            1    11289600          0 0
                   clk_i2s1               1            1    11289600          0 0
                      i2s1_out            0            0    11289600          0 0
          clk_i2s0_div                    0            0    75000000          0 0
             i2s0_pre                     0            0    75000000          0 0
                clk_i2s0                  0            0    75000000          0 0
             clk_i2s0_frac                0            0     3750000          0 0
          clk_tsp                         0            0    50000000          0 0
    pll_dpll                              1            1   664000000          0 0
       dpll                               1            1   664000000          0 0
          sclk_ddrc                       2            2   332000000          0 0
             aclk_ddrupctl                0            0   332000000          0 0
             clk_ddrupctl                 1            1   332000000          0 0
             clk_ddrmsch                  1            1   332000000          0 0
          dpll_core                       0            0   664000000          0 0
    pll_apll                              0            0    61439999          0 0
       apll                               0            0    61439999          0 0
          clk_pdm                         0            0    61439999          0 0
          apll_core                       0            0    61439999          0 0
 clk_hsadc_tsp                            0            0           0          0 0
 clk_jtag                                 1            1           0          0 0

So are these messages enough to spark any bug fix?

Thanks a lot,
Willard.

@sugaroneone
Copy link

I think the root cause is the unalinged bursts xfer,plz enable the pl330 dmac debug and then dump the full kmsg.
`diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 5572334..35d715a 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -253,7 +253,7 @@ enum pl330_byteswap {
/* Use this only to wait on transient states */
#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax();

-#ifdef PL330_DEBUG_MCGEN
+#if 1//def PL330_DEBUG_MCGEN
static unsigned cmd_line;
`

scpcom pushed a commit to scpcom/linux that referenced this issue Jul 2, 2024
commit e4c3b72 upstream.

While performing the IO fault injection test, I caught the following data
corruption report:

 XFS (dm-0): Internal error ltbno + ltlen > bno at line 1957 of file fs/xfs/libxfs/xfs_alloc.c.  Caller xfs_free_ag_extent+0x79c/0x1130
 CPU: 3 PID: 33 Comm: kworker/3:0 Not tainted 6.5.0-rc7-next-20230825-00001-g7f8666926889 rockchip-linux#214
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ?-20190727_073836-buildvm-ppc64le-16.ppc.fedoraproject.org-3.fc31 04/01/2014
 Workqueue: xfs-inodegc/dm-0 xfs_inodegc_worker
 Call Trace:
  <TASK>
  dump_stack_lvl+0x50/0x70
  xfs_corruption_error+0x134/0x150
  xfs_free_ag_extent+0x7d3/0x1130
  __xfs_free_extent+0x201/0x3c0
  xfs_trans_free_extent+0x29b/0xa10
  xfs_extent_free_finish_item+0x2a/0xb0
  xfs_defer_finish_noroll+0x8d1/0x1b40
  xfs_defer_finish+0x21/0x200
  xfs_itruncate_extents_flags+0x1cb/0x650
  xfs_free_eofblocks+0x18f/0x250
  xfs_inactive+0x485/0x570
  xfs_inodegc_worker+0x207/0x530
  process_scheduled_works+0x24a/0xe10
  worker_thread+0x5ac/0xc60
  kthread+0x2cd/0x3c0
  ret_from_fork+0x4a/0x80
  ret_from_fork_asm+0x11/0x20
  </TASK>
 XFS (dm-0): Corruption detected. Unmount and run xfs_repair

After analyzing the disk image, it was found that the corruption was
triggered by the fact that extent was recorded in both inode datafork
and AGF btree blocks. After a long time of reproduction and analysis,
we found that the reason of free sapce btree corruption was that the
AGF btree was not recovered correctly.

Consider the following situation, Checkpoint A and Checkpoint B are in
the same record and share the same start LSN1, buf items of same object
(AGF btree block) is included in both Checkpoint A and Checkpoint B. If
the buf item in Checkpoint A has been recovered and updates metadata LSN
permanently, then the buf item in Checkpoint B cannot be recovered,
because log recovery skips items with a metadata LSN >= the current LSN
of the recovery item. If there is still an inode item in Checkpoint B
that records the Extent X, the Extent X will be recorded in both inode
datafork and AGF btree block after Checkpoint B is recovered. Such
transaction can be seen when allocing enxtent for inode bmap, it record
both the addition of extent to the inode extent list and the removing
extent from the AGF.

  |------------Record (LSN1)------------------|---Record (LSN2)---|
  |-------Checkpoint A----------|----------Checkpoint B-----------|
  |     Buf Item(Extent X)      | Buf Item / Inode item(Extent X) |
  |     Extent X is freed       |     Extent X is allocated       |

After commit 12818d2 ("xfs: rework log recovery to submit buffers
on LSN boundaries") was introduced, we submit buffers on lsn boundaries
during log recovery. The above problem can be avoided under normal paths,
but it's not guaranteed under abnormal paths. Consider the following
process, if an error was encountered after recover buf item in Checkpoint
A and before recover buf item in Checkpoint B, buffers that have been
added to the buffer_list will still be submitted, this violates the
submits rule on lsn boundaries. So buf item in Checkpoint B cannot be
recovered on the next mount due to current lsn of transaction equal to
metadata lsn on disk. The detailed process of the problem is as follows.

First Mount:

  xlog_do_recovery_pass
    error = xlog_recover_process
      xlog_recover_process_data
        xlog_recover_process_ophdr
          xlog_recovery_process_trans
            ...
              /* recover buf item in Checkpoint A */
              xlog_recover_buf_commit_pass2
                xlog_recover_do_reg_buffer
                /* add buffer of agf btree block to buffer_list */
                xfs_buf_delwri_queue(bp, buffer_list)
            ...
            ==> Encounter read IO error and return
    /* submit buffers regardless of error */
    if (!list_empty(&buffer_list))
      xfs_buf_delwri_submit(&buffer_list);

    <buf items of agf btree block in Checkpoint A recovery success>

Second Mount:

  xlog_do_recovery_pass
    error = xlog_recover_process
      xlog_recover_process_data
        xlog_recover_process_ophdr
          xlog_recovery_process_trans
            ...
              /* recover buf item in Checkpoint B */
              xlog_recover_buf_commit_pass2
                /* buffer of agf btree block wouldn't added to
                   buffer_list due to lsn equal to current_lsn */
                if (XFS_LSN_CMP(lsn, current_lsn) >= 0)
                  goto out_release

    <buf items of agf btree block in Checkpoint B wouldn't recovery>

In order to make sure that submits buffers on lsn boundaries in the
abnormal paths, we need to check error status before submit buffers that
have been added from the last record processed. If error status exist,
buffers in the bufffer_list should not be writen to disk.

Canceling the buffers in the buffer_list directly isn't correct, unlike
any other place where write list was canceled, these buffers has been
initialized by xfs_buf_item_init() during recovery and held by buf item,
buf items will not be released in xfs_buf_delwri_cancel(), it's not easy
to solve.

If the filesystem has been shut down, then delwri list submission will
error out all buffers on the list via IO submission/completion and do
all the correct cleanup automatically. So shutting down the filesystem
could prevents buffers in the bufffer_list from being written to disk.

Fixes: 50d5c8d ("xfs: check LSN ordering for v5 superblocks during recovery")
Signed-off-by: Long Li <leo.lilong@huawei.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
Signed-off-by: Catherine Hoang <catherine.hoang@oracle.com>
Acked-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants