raid5-cache.c (016c76ac76e4c678b01a75a602dc6be0282f5b29) raid5-cache.c (1ad45a9bc4e0cd5a6e6fb0e6c5d35d6c87f14c76)
1/*
2 * Copyright (C) 2015 Shaohua Li <shli@fb.com>
3 * Copyright (C) 2016 Song Liu <songliubraving@fb.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *

--- 1988 unchanged lines hidden (view full) ---

1997 page = alloc_page(GFP_KERNEL);
1998 if (!page)
1999 return -ENOMEM;
2000
2001 while (mb_offset < le32_to_cpu(mb->meta_size)) {
2002 payload = (void *)mb + mb_offset;
2003 payload_flush = (void *)mb + mb_offset;
2004
1/*
2 * Copyright (C) 2015 Shaohua Li <shli@fb.com>
3 * Copyright (C) 2016 Song Liu <songliubraving@fb.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *

--- 1988 unchanged lines hidden (view full) ---

1997 page = alloc_page(GFP_KERNEL);
1998 if (!page)
1999 return -ENOMEM;
2000
2001 while (mb_offset < le32_to_cpu(mb->meta_size)) {
2002 payload = (void *)mb + mb_offset;
2003 payload_flush = (void *)mb + mb_offset;
2004
2005 if (payload->header.type == R5LOG_PAYLOAD_DATA) {
2005 if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_DATA) {
2006 if (r5l_recovery_verify_data_checksum(
2007 log, ctx, page, log_offset,
2008 payload->checksum[0]) < 0)
2009 goto mismatch;
2006 if (r5l_recovery_verify_data_checksum(
2007 log, ctx, page, log_offset,
2008 payload->checksum[0]) < 0)
2009 goto mismatch;
2010 } else if (payload->header.type == R5LOG_PAYLOAD_PARITY) {
2010 } else if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_PARITY) {
2011 if (r5l_recovery_verify_data_checksum(
2012 log, ctx, page, log_offset,
2013 payload->checksum[0]) < 0)
2014 goto mismatch;
2015 if (conf->max_degraded == 2 && /* q for RAID 6 */
2016 r5l_recovery_verify_data_checksum(
2017 log, ctx, page,
2018 r5l_ring_add(log, log_offset,
2019 BLOCK_SECTORS),
2020 payload->checksum[1]) < 0)
2021 goto mismatch;
2011 if (r5l_recovery_verify_data_checksum(
2012 log, ctx, page, log_offset,
2013 payload->checksum[0]) < 0)
2014 goto mismatch;
2015 if (conf->max_degraded == 2 && /* q for RAID 6 */
2016 r5l_recovery_verify_data_checksum(
2017 log, ctx, page,
2018 r5l_ring_add(log, log_offset,
2019 BLOCK_SECTORS),
2020 payload->checksum[1]) < 0)
2021 goto mismatch;
2022 } else if (payload->header.type == R5LOG_PAYLOAD_FLUSH) {
2022 } else if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_FLUSH) {
2023 /* nothing to do for R5LOG_PAYLOAD_FLUSH here */
2024 } else /* not R5LOG_PAYLOAD_DATA/PARITY/FLUSH */
2025 goto mismatch;
2026
2023 /* nothing to do for R5LOG_PAYLOAD_FLUSH here */
2024 } else /* not R5LOG_PAYLOAD_DATA/PARITY/FLUSH */
2025 goto mismatch;
2026
2027 if (payload->header.type == R5LOG_PAYLOAD_FLUSH) {
2027 if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_FLUSH) {
2028 mb_offset += sizeof(struct r5l_payload_flush) +
2029 le32_to_cpu(payload_flush->size);
2030 } else {
2031 /* DATA or PARITY payload */
2032 log_offset = r5l_ring_add(log, log_offset,
2033 le32_to_cpu(payload->size));
2034 mb_offset += sizeof(struct r5l_payload_data_parity) +
2035 sizeof(__le32) *

--- 50 unchanged lines hidden (view full) ---

2086 log_offset = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
2087
2088 while (mb_offset < le32_to_cpu(mb->meta_size)) {
2089 int dd;
2090
2091 payload = (void *)mb + mb_offset;
2092 payload_flush = (void *)mb + mb_offset;
2093
2028 mb_offset += sizeof(struct r5l_payload_flush) +
2029 le32_to_cpu(payload_flush->size);
2030 } else {
2031 /* DATA or PARITY payload */
2032 log_offset = r5l_ring_add(log, log_offset,
2033 le32_to_cpu(payload->size));
2034 mb_offset += sizeof(struct r5l_payload_data_parity) +
2035 sizeof(__le32) *

--- 50 unchanged lines hidden (view full) ---

2086 log_offset = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
2087
2088 while (mb_offset < le32_to_cpu(mb->meta_size)) {
2089 int dd;
2090
2091 payload = (void *)mb + mb_offset;
2092 payload_flush = (void *)mb + mb_offset;
2093
2094 if (payload->header.type == R5LOG_PAYLOAD_FLUSH) {
2094 if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_FLUSH) {
2095 int i, count;
2096
2097 count = le32_to_cpu(payload_flush->size) / sizeof(__le64);
2098 for (i = 0; i < count; ++i) {
2099 stripe_sect = le64_to_cpu(payload_flush->flush_stripes[i]);
2100 sh = r5c_recovery_lookup_stripe(cached_stripe_list,
2101 stripe_sect);
2102 if (sh) {

--- 5 unchanged lines hidden (view full) ---

2108 }
2109
2110 mb_offset += sizeof(struct r5l_payload_flush) +
2111 le32_to_cpu(payload_flush->size);
2112 continue;
2113 }
2114
2115 /* DATA or PARITY payload */
2095 int i, count;
2096
2097 count = le32_to_cpu(payload_flush->size) / sizeof(__le64);
2098 for (i = 0; i < count; ++i) {
2099 stripe_sect = le64_to_cpu(payload_flush->flush_stripes[i]);
2100 sh = r5c_recovery_lookup_stripe(cached_stripe_list,
2101 stripe_sect);
2102 if (sh) {

--- 5 unchanged lines hidden (view full) ---

2108 }
2109
2110 mb_offset += sizeof(struct r5l_payload_flush) +
2111 le32_to_cpu(payload_flush->size);
2112 continue;
2113 }
2114
2115 /* DATA or PARITY payload */
2116 stripe_sect = (payload->header.type == R5LOG_PAYLOAD_DATA) ?
2116 stripe_sect = (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_DATA) ?
2117 raid5_compute_sector(
2118 conf, le64_to_cpu(payload->location), 0, &dd,
2119 NULL)
2120 : le64_to_cpu(payload->location);
2121
2122 sh = r5c_recovery_lookup_stripe(cached_stripe_list,
2123 stripe_sect);
2124

--- 21 unchanged lines hidden (view full) ---

2146 if (!sh) {
2147 pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
2148 mdname(mddev));
2149 return -ENOMEM;
2150 }
2151 list_add_tail(&sh->lru, cached_stripe_list);
2152 }
2153
2117 raid5_compute_sector(
2118 conf, le64_to_cpu(payload->location), 0, &dd,
2119 NULL)
2120 : le64_to_cpu(payload->location);
2121
2122 sh = r5c_recovery_lookup_stripe(cached_stripe_list,
2123 stripe_sect);
2124

--- 21 unchanged lines hidden (view full) ---

2146 if (!sh) {
2147 pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
2148 mdname(mddev));
2149 return -ENOMEM;
2150 }
2151 list_add_tail(&sh->lru, cached_stripe_list);
2152 }
2153
2154 if (payload->header.type == R5LOG_PAYLOAD_DATA) {
2154 if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_DATA) {
2155 if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
2156 test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
2157 r5l_recovery_replay_one_stripe(conf, sh, ctx);
2158 list_move_tail(&sh->lru, cached_stripe_list);
2159 }
2160 r5l_recovery_load_data(log, sh, ctx, payload,
2161 log_offset);
2155 if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
2156 test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
2157 r5l_recovery_replay_one_stripe(conf, sh, ctx);
2158 list_move_tail(&sh->lru, cached_stripe_list);
2159 }
2160 r5l_recovery_load_data(log, sh, ctx, payload,
2161 log_offset);
2162 } else if (payload->header.type == R5LOG_PAYLOAD_PARITY)
2162 } else if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_PARITY)
2163 r5l_recovery_load_parity(log, sh, ctx, payload,
2164 log_offset);
2165 else
2166 return -EINVAL;
2167
2168 log_offset = r5l_ring_add(log, log_offset,
2169 le32_to_cpu(payload->size));
2170

--- 185 unchanged lines hidden (view full) ---

2356 struct r5dev *dev = &sh->dev[i];
2357 struct r5l_payload_data_parity *payload;
2358 void *addr;
2359
2360 if (test_bit(R5_InJournal, &dev->flags)) {
2361 payload = (void *)mb + offset;
2362 payload->header.type = cpu_to_le16(
2363 R5LOG_PAYLOAD_DATA);
2163 r5l_recovery_load_parity(log, sh, ctx, payload,
2164 log_offset);
2165 else
2166 return -EINVAL;
2167
2168 log_offset = r5l_ring_add(log, log_offset,
2169 le32_to_cpu(payload->size));
2170

--- 185 unchanged lines hidden (view full) ---

2356 struct r5dev *dev = &sh->dev[i];
2357 struct r5l_payload_data_parity *payload;
2358 void *addr;
2359
2360 if (test_bit(R5_InJournal, &dev->flags)) {
2361 payload = (void *)mb + offset;
2362 payload->header.type = cpu_to_le16(
2363 R5LOG_PAYLOAD_DATA);
2364 payload->size = BLOCK_SECTORS;
2364 payload->size = cpu_to_le32(BLOCK_SECTORS);
2365 payload->location = cpu_to_le64(
2366 raid5_compute_blocknr(sh, i, 0));
2367 addr = kmap_atomic(dev->page);
2368 payload->checksum[0] = cpu_to_le32(
2369 crc32c_le(log->uuid_checksum, addr,
2370 PAGE_SIZE));
2371 kunmap_atomic(addr);
2372 sync_page_io(log->rdev, write_pos, PAGE_SIZE,

--- 735 unchanged lines hidden ---
2365 payload->location = cpu_to_le64(
2366 raid5_compute_blocknr(sh, i, 0));
2367 addr = kmap_atomic(dev->page);
2368 payload->checksum[0] = cpu_to_le32(
2369 crc32c_le(log->uuid_checksum, addr,
2370 PAGE_SIZE));
2371 kunmap_atomic(addr);
2372 sync_page_io(log->rdev, write_pos, PAGE_SIZE,

--- 735 unchanged lines hidden ---