Skip to content

Commit 63c04ee

Browse files
committed
Merge tag 'upstream-4.7-rc5' of git://git.infradead.org/linux-ubifs
Pull UBI/UBIFS fixes from Richard Weinberger: "This contains fixes for two critical bugs in UBI and UBIFS: - fix the possibility of losing data upon a power cut when UBI tries to recover from a write error - fix page migration on UBIFS. It turned out that the default page migration function is not suitable for UBIFS" * tag 'upstream-4.7-rc5' of git://git.infradead.org/linux-ubifs: UBIFS: Implement ->migratepage() mm: Export migrate_page_move_mapping and migrate_page_copy ubi: Make recover_peb power cut aware gpio: make library immune to error pointers gpio: make sure gpiod_to_irq() returns negative on NULL desc gpio: 104-idi-48: Fix missing spin_lock_init for ack_lock
2 parents 0bf0ea4 + 4ac1c17 commit 63c04ee

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

drivers/mtd/ubi/eba.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
575575
int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
576576
struct ubi_volume *vol = ubi->volumes[idx];
577577
struct ubi_vid_hdr *vid_hdr;
578+
uint32_t crc;
578579

579580
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
580581
if (!vid_hdr)
@@ -599,14 +600,8 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
599600
goto out_put;
600601
}
601602

602-
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
603-
err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
604-
if (err) {
605-
up_read(&ubi->fm_eba_sem);
606-
goto write_error;
607-
}
603+
ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
608604

609-
data_size = offset + len;
610605
mutex_lock(&ubi->buf_mutex);
611606
memset(ubi->peb_buf + offset, 0xFF, len);
612607

@@ -621,6 +616,19 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
621616

622617
memcpy(ubi->peb_buf + offset, buf, len);
623618

619+
data_size = offset + len;
620+
crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
621+
vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
622+
vid_hdr->copy_flag = 1;
623+
vid_hdr->data_size = cpu_to_be32(data_size);
624+
vid_hdr->data_crc = cpu_to_be32(crc);
625+
err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
626+
if (err) {
627+
mutex_unlock(&ubi->buf_mutex);
628+
up_read(&ubi->fm_eba_sem);
629+
goto write_error;
630+
}
631+
624632
err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
625633
if (err) {
626634
mutex_unlock(&ubi->buf_mutex);

fs/ubifs/file.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "ubifs.h"
5353
#include <linux/mount.h>
5454
#include <linux/slab.h>
55+
#include <linux/migrate.h>
5556

5657
static int read_block(struct inode *inode, void *addr, unsigned int block,
5758
struct ubifs_data_node *dn)
@@ -1452,6 +1453,26 @@ static int ubifs_set_page_dirty(struct page *page)
14521453
return ret;
14531454
}
14541455

1456+
#ifdef CONFIG_MIGRATION
1457+
static int ubifs_migrate_page(struct address_space *mapping,
1458+
struct page *newpage, struct page *page, enum migrate_mode mode)
1459+
{
1460+
int rc;
1461+
1462+
rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
1463+
if (rc != MIGRATEPAGE_SUCCESS)
1464+
return rc;
1465+
1466+
if (PagePrivate(page)) {
1467+
ClearPagePrivate(page);
1468+
SetPagePrivate(newpage);
1469+
}
1470+
1471+
migrate_page_copy(newpage, page);
1472+
return MIGRATEPAGE_SUCCESS;
1473+
}
1474+
#endif
1475+
14551476
static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
14561477
{
14571478
/*
@@ -1591,6 +1612,9 @@ const struct address_space_operations ubifs_file_address_operations = {
15911612
.write_end = ubifs_write_end,
15921613
.invalidatepage = ubifs_invalidatepage,
15931614
.set_page_dirty = ubifs_set_page_dirty,
1615+
#ifdef CONFIG_MIGRATION
1616+
.migratepage = ubifs_migrate_page,
1617+
#endif
15941618
.releasepage = ubifs_releasepage,
15951619
};
15961620

mm/migrate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
431431

432432
return MIGRATEPAGE_SUCCESS;
433433
}
434+
EXPORT_SYMBOL(migrate_page_move_mapping);
434435

435436
/*
436437
* The expected number of remaining references is the same as that
@@ -586,6 +587,7 @@ void migrate_page_copy(struct page *newpage, struct page *page)
586587

587588
mem_cgroup_migrate(page, newpage);
588589
}
590+
EXPORT_SYMBOL(migrate_page_copy);
589591

590592
/************************************************************
591593
* Migration functions

0 commit comments

Comments
 (0)