]> Git Repo - linux.git/blobdiff - fs/udf/super.c
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorri...
[linux.git] / fs / udf / super.c
index e3d684ea320303630f4a75135ed4e4bcc408484c..ffd8038ff7283fc0d83211a1f5653a1589f10c4b 100644 (file)
@@ -1474,6 +1474,17 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
        if (lvd->integritySeqExt.extLength)
                udf_load_logicalvolint(sb, leea_to_cpu(lvd->integritySeqExt));
        ret = 0;
+
+       if (!sbi->s_lvid_bh) {
+               /* We can't generate unique IDs without a valid LVID */
+               if (sb_rdonly(sb)) {
+                       UDF_SET_FLAG(sb, UDF_FLAG_RW_INCOMPAT);
+               } else {
+                       udf_warn(sb, "Damaged or missing LVID, forcing "
+                                    "readonly mount\n");
+                       ret = -EACCES;
+               }
+       }
 out_bh:
        brelse(bh);
        return ret;
@@ -1943,13 +1954,24 @@ static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt,
        return 0;
 }
 
+static void udf_finalize_lvid(struct logicalVolIntegrityDesc *lvid)
+{
+       struct timespec64 ts;
+
+       ktime_get_real_ts64(&ts);
+       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
+       lvid->descTag.descCRC = cpu_to_le16(
+               crc_itu_t(0, (char *)lvid + sizeof(struct tag),
+                       le16_to_cpu(lvid->descTag.descCRCLength)));
+       lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+}
+
 static void udf_open_lvid(struct super_block *sb)
 {
        struct udf_sb_info *sbi = UDF_SB(sb);
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
        struct logicalVolIntegrityDescImpUse *lvidiu;
-       struct timespec64 ts;
 
        if (!bh)
                return;
@@ -1961,18 +1983,12 @@ static void udf_open_lvid(struct super_block *sb)
        mutex_lock(&sbi->s_alloc_mutex);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-       ktime_get_real_ts64(&ts);
-       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
        if (le32_to_cpu(lvid->integrityType) == LVID_INTEGRITY_TYPE_CLOSE)
                lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
        else
                UDF_SET_FLAG(sb, UDF_FLAG_INCONSISTENT);
 
-       lvid->descTag.descCRC = cpu_to_le16(
-               crc_itu_t(0, (char *)lvid + sizeof(struct tag),
-                       le16_to_cpu(lvid->descTag.descCRCLength)));
-
-       lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+       udf_finalize_lvid(lvid);
        mark_buffer_dirty(bh);
        sbi->s_lvid_dirty = 0;
        mutex_unlock(&sbi->s_alloc_mutex);
@@ -1986,7 +2002,6 @@ static void udf_close_lvid(struct super_block *sb)
        struct buffer_head *bh = sbi->s_lvid_bh;
        struct logicalVolIntegrityDesc *lvid;
        struct logicalVolIntegrityDescImpUse *lvidiu;
-       struct timespec64 ts;
 
        if (!bh)
                return;
@@ -1998,8 +2013,6 @@ static void udf_close_lvid(struct super_block *sb)
        mutex_lock(&sbi->s_alloc_mutex);
        lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
        lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
-       ktime_get_real_ts64(&ts);
-       udf_time_to_disk_stamp(&lvid->recordingDateAndTime, ts);
        if (UDF_MAX_WRITE_VERSION > le16_to_cpu(lvidiu->maxUDFWriteRev))
                lvidiu->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
        if (sbi->s_udfrev > le16_to_cpu(lvidiu->minUDFReadRev))
@@ -2009,17 +2022,13 @@ static void udf_close_lvid(struct super_block *sb)
        if (!UDF_QUERY_FLAG(sb, UDF_FLAG_INCONSISTENT))
                lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE);
 
-       lvid->descTag.descCRC = cpu_to_le16(
-                       crc_itu_t(0, (char *)lvid + sizeof(struct tag),
-                               le16_to_cpu(lvid->descTag.descCRCLength)));
-
-       lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
        /*
         * We set buffer uptodate unconditionally here to avoid spurious
         * warnings from mark_buffer_dirty() when previous EIO has marked
         * the buffer as !uptodate
         */
        set_buffer_uptodate(bh);
+       udf_finalize_lvid(lvid);
        mark_buffer_dirty(bh);
        sbi->s_lvid_dirty = 0;
        mutex_unlock(&sbi->s_alloc_mutex);
@@ -2048,8 +2057,8 @@ u64 lvid_get_unique_id(struct super_block *sb)
        if (!(++uniqueID & 0xFFFFFFFF))
                uniqueID += 16;
        lvhd->uniqueID = cpu_to_le64(uniqueID);
+       udf_updated_lvid(sb);
        mutex_unlock(&sbi->s_alloc_mutex);
-       mark_buffer_dirty(bh);
 
        return ret;
 }
@@ -2320,11 +2329,17 @@ static int udf_sync_fs(struct super_block *sb, int wait)
 
        mutex_lock(&sbi->s_alloc_mutex);
        if (sbi->s_lvid_dirty) {
+               struct buffer_head *bh = sbi->s_lvid_bh;
+               struct logicalVolIntegrityDesc *lvid;
+
+               lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
+               udf_finalize_lvid(lvid);
+
                /*
                 * Blockdevice will be synced later so we don't have to submit
                 * the buffer for IO
                 */
-               mark_buffer_dirty(sbi->s_lvid_bh);
+               mark_buffer_dirty(bh);
                sbi->s_lvid_dirty = 0;
        }
        mutex_unlock(&sbi->s_alloc_mutex);
This page took 0.034828 seconds and 4 git commands to generate.