fs/nilfs2: fix potential underflow in call to crc32_le
[pandora-kernel.git] / fs / nilfs2 / the_nilfs.c
index d2acd1a..6a90908 100644 (file)
@@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
        nilfs->ns_bdev = bdev;
        atomic_set(&nilfs->ns_ndirtyblks, 0);
        init_rwsem(&nilfs->ns_sem);
+       mutex_init(&nilfs->ns_snapshot_mount_mutex);
        INIT_LIST_HEAD(&nilfs->ns_dirty_files);
        INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
        spin_lock_init(&nilfs->ns_inode_lock);
@@ -363,6 +364,24 @@ static unsigned long long nilfs_max_size(unsigned int blkbits)
        return res;
 }
 
+/**
+ * nilfs_nrsvsegs - calculate the number of reserved segments
+ * @nilfs: nilfs object
+ * @nsegs: total number of segments
+ */
+unsigned long nilfs_nrsvsegs(struct the_nilfs *nilfs, unsigned long nsegs)
+{
+       return max_t(unsigned long, NILFS_MIN_NRSVSEGS,
+                    DIV_ROUND_UP(nsegs * nilfs->ns_r_segments_percentage,
+                                 100));
+}
+
+void nilfs_set_nsegments(struct the_nilfs *nilfs, unsigned long nsegs)
+{
+       nilfs->ns_nsegments = nsegs;
+       nilfs->ns_nrsvsegs = nilfs_nrsvsegs(nilfs, nsegs);
+}
+
 static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
                                   struct nilfs_super_block *sbp)
 {
@@ -389,13 +408,9 @@ static int nilfs_store_disk_layout(struct the_nilfs *nilfs,
        }
 
        nilfs->ns_first_data_block = le64_to_cpu(sbp->s_first_data_block);
-       nilfs->ns_nsegments = le64_to_cpu(sbp->s_nsegments);
        nilfs->ns_r_segments_percentage =
                le32_to_cpu(sbp->s_r_segments_percentage);
-       nilfs->ns_nrsvsegs =
-               max_t(unsigned long, NILFS_MIN_NRSVSEGS,
-                     DIV_ROUND_UP(nilfs->ns_nsegments *
-                                  nilfs->ns_r_segments_percentage, 100));
+       nilfs_set_nsegments(nilfs, le64_to_cpu(sbp->s_nsegments));
        nilfs->ns_crc_seed = le32_to_cpu(sbp->s_crc_seed);
        return 0;
 }
@@ -410,7 +425,7 @@ static int nilfs_valid_sb(struct nilfs_super_block *sbp)
        if (!sbp || le16_to_cpu(sbp->s_magic) != NILFS_SUPER_MAGIC)
                return 0;
        bytes = le16_to_cpu(sbp->s_bytes);
-       if (bytes > BLOCK_SIZE)
+       if (bytes < sumoff + 4 || bytes > BLOCK_SIZE)
                return 0;
        crc = crc32_le(le32_to_cpu(sbp->s_crc_seed), (unsigned char *)sbp,
                       sumoff);
@@ -501,6 +516,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
                brelse(sbh[1]);
                sbh[1] = NULL;
                sbp[1] = NULL;
+               valid[1] = 0;
                swp = 0;
        }
        if (!valid[swp]) {