diff options
-rw-r--r-- | fs/ubifs/debug.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index f7515bd38b4f..b5ba2ea5b626 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -1818,6 +1818,8 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, | |||
1818 | struct rb_node **p, *parent = NULL; | 1818 | struct rb_node **p, *parent = NULL; |
1819 | struct fsck_inode *fscki; | 1819 | struct fsck_inode *fscki; |
1820 | ino_t inum = key_inum_flash(c, &ino->key); | 1820 | ino_t inum = key_inum_flash(c, &ino->key); |
1821 | struct inode *inode; | ||
1822 | struct ubifs_inode *ui; | ||
1821 | 1823 | ||
1822 | p = &fsckd->inodes.rb_node; | 1824 | p = &fsckd->inodes.rb_node; |
1823 | while (*p) { | 1825 | while (*p) { |
@@ -1841,19 +1843,46 @@ static struct fsck_inode *add_inode(struct ubifs_info *c, | |||
1841 | if (!fscki) | 1843 | if (!fscki) |
1842 | return ERR_PTR(-ENOMEM); | 1844 | return ERR_PTR(-ENOMEM); |
1843 | 1845 | ||
1846 | inode = ilookup(c->vfs_sb, inum); | ||
1847 | |||
1844 | fscki->inum = inum; | 1848 | fscki->inum = inum; |
1845 | fscki->nlink = le32_to_cpu(ino->nlink); | 1849 | /* |
1846 | fscki->size = le64_to_cpu(ino->size); | 1850 | * If the inode is present in the VFS inode cache, use it instead of |
1847 | fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); | 1851 | * the on-flash inode which might be out-of-date. E.g., the size might |
1848 | fscki->xattr_sz = le32_to_cpu(ino->xattr_size); | 1852 | * be out-of-date. If we do not do this, the following may happen, for |
1849 | fscki->xattr_nms = le32_to_cpu(ino->xattr_names); | 1853 | * example: |
1850 | fscki->mode = le32_to_cpu(ino->mode); | 1854 | * 1. A power cut happens |
1855 | * 2. We mount the file-system R/O, the replay process fixes up the | ||
1856 | * inode size in the VFS cache, but on on-flash. | ||
1857 | * 3. 'check_leaf()' fails because it hits a data node beyond inode | ||
1858 | * size. | ||
1859 | */ | ||
1860 | if (!inode) { | ||
1861 | fscki->nlink = le32_to_cpu(ino->nlink); | ||
1862 | fscki->size = le64_to_cpu(ino->size); | ||
1863 | fscki->xattr_cnt = le32_to_cpu(ino->xattr_cnt); | ||
1864 | fscki->xattr_sz = le32_to_cpu(ino->xattr_size); | ||
1865 | fscki->xattr_nms = le32_to_cpu(ino->xattr_names); | ||
1866 | fscki->mode = le32_to_cpu(ino->mode); | ||
1867 | } else { | ||
1868 | ui = ubifs_inode(inode); | ||
1869 | fscki->nlink = inode->i_nlink; | ||
1870 | fscki->size = inode->i_size; | ||
1871 | fscki->xattr_cnt = ui->xattr_cnt; | ||
1872 | fscki->xattr_sz = ui->xattr_size; | ||
1873 | fscki->xattr_nms = ui->xattr_names; | ||
1874 | fscki->mode = inode->i_mode; | ||
1875 | iput(inode); | ||
1876 | } | ||
1877 | |||
1851 | if (S_ISDIR(fscki->mode)) { | 1878 | if (S_ISDIR(fscki->mode)) { |
1852 | fscki->calc_sz = UBIFS_INO_NODE_SZ; | 1879 | fscki->calc_sz = UBIFS_INO_NODE_SZ; |
1853 | fscki->calc_cnt = 2; | 1880 | fscki->calc_cnt = 2; |
1854 | } | 1881 | } |
1882 | |||
1855 | rb_link_node(&fscki->rb, parent, p); | 1883 | rb_link_node(&fscki->rb, parent, p); |
1856 | rb_insert_color(&fscki->rb, &fsckd->inodes); | 1884 | rb_insert_color(&fscki->rb, &fsckd->inodes); |
1885 | |||
1857 | return fscki; | 1886 | return fscki; |
1858 | } | 1887 | } |
1859 | 1888 | ||