return slot;
}
-static bool udf_add_free_space(struct udf_sb_info *sbi,
- u16 partition, u32 cnt)
+static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt)
{
+ struct udf_sb_info *sbi = UDF_SB(sb);
struct logicalVolIntegrityDesc *lvid;
- if (sbi->s_lvid_bh == NULL)
- return false;
+ if (!sbi->s_lvid_bh)
+ return;
lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data;
le32_add_cpu(&lvid->freeSpaceTable[partition], cnt);
- return true;
+ udf_updated_lvid(sb);
}
static void udf_bitmap_free_blocks(struct super_block *sb,
} else {
if (inode)
vfs_dq_free_block(inode, 1);
- udf_add_free_space(sbi, sbi->s_partition, 1);
+ udf_add_free_space(sb, sbi->s_partition, 1);
}
}
mark_buffer_dirty(bh);
} while (overflow);
error_return:
- sb->s_dirt = 1;
- if (sbi->s_lvid_bh)
- mark_buffer_dirty(sbi->s_lvid_bh);
mutex_unlock(&sbi->s_alloc_mutex);
}
} while (block_count > 0);
out:
- if (udf_add_free_space(sbi, partition, -alloc_count))
- mark_buffer_dirty(sbi->s_lvid_bh);
- sb->s_dirt = 1;
+ udf_add_free_space(sb, partition, -alloc_count);
mutex_unlock(&sbi->s_alloc_mutex);
return alloc_count;
}
mark_buffer_dirty(bh);
- if (udf_add_free_space(sbi, partition, -1))
- mark_buffer_dirty(sbi->s_lvid_bh);
- sb->s_dirt = 1;
+ udf_add_free_space(sb, partition, -1);
mutex_unlock(&sbi->s_alloc_mutex);
*err = 0;
return newblock;
could occure, but.. oh well */
if (inode)
vfs_dq_free_block(inode, count);
- if (udf_add_free_space(sbi, sbi->s_partition, count))
- mark_buffer_dirty(sbi->s_lvid_bh);
+ udf_add_free_space(sb, sbi->s_partition, count);
start = bloc->logicalBlockNum + offset;
end = bloc->logicalBlockNum + offset + count - 1;
brelse(oepos.bh);
error_return:
- sb->s_dirt = 1;
mutex_unlock(&sbi->s_alloc_mutex);
return;
}
brelse(epos.bh);
- if (alloc_count && udf_add_free_space(sbi, partition, -alloc_count)) {
- mark_buffer_dirty(sbi->s_lvid_bh);
- sb->s_dirt = 1;
- }
+ if (alloc_count)
+ udf_add_free_space(sb, partition, -alloc_count);
mutex_unlock(&sbi->s_alloc_mutex);
return alloc_count;
}
udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
brelse(goal_epos.bh);
- if (udf_add_free_space(sbi, partition, -1))
- mark_buffer_dirty(sbi->s_lvid_bh);
+ udf_add_free_space(sb, partition, -1);
- sb->s_dirt = 1;
mutex_unlock(&sbi->s_alloc_mutex);
*err = 0;
return newblock;
le32_add_cpu(&lvidiu->numDirs, -1);
else
le32_add_cpu(&lvidiu->numFiles, -1);
-
- mark_buffer_dirty(sbi->s_lvid_bh);
+ udf_updated_lvid(sb);
}
mutex_unlock(&sbi->s_alloc_mutex);
if (!(++uniqueID & 0x00000000FFFFFFFFUL))
uniqueID += 16;
lvhd->uniqueID = cpu_to_le64(uniqueID);
- mark_buffer_dirty(sbi->s_lvid_bh);
+ udf_updated_lvid(sb);
}
mutex_unlock(&sbi->s_alloc_mutex);
inode->i_mode = mode;
/* These are the "meat" - everything else is stuffing */
static int udf_fill_super(struct super_block *, void *, int);
static void udf_put_super(struct super_block *);
-static void udf_write_super(struct super_block *);
+static int udf_sync_fs(struct super_block *, int);
static int udf_remount_fs(struct super_block *, int *, char *);
static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad);
static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *,
.delete_inode = udf_delete_inode,
.clear_inode = udf_clear_inode,
.put_super = udf_put_super,
- .write_super = udf_write_super,
+ .sync_fs = udf_sync_fs,
.statfs = udf_statfs,
.remount_fs = udf_remount_fs,
.show_options = udf_show_options,
return 1;
}
-static void udf_write_super(struct super_block *sb)
-{
- lock_kernel();
-
- if (!(sb->s_flags & MS_RDONLY))
- udf_open_lvid(sb);
- sb->s_dirt = 0;
-
- unlock_kernel();
-}
-
static int udf_remount_fs(struct super_block *sb, int *flags, char *options)
{
struct udf_options uopt;
struct buffer_head *bh = sbi->s_lvid_bh;
struct logicalVolIntegrityDesc *lvid;
struct logicalVolIntegrityDescImpUse *lvidiu;
+
if (!bh)
return;
-
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
lvidiu = udf_sb_lvidiu(sbi);
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
udf_time_to_disk_stamp(&lvid->recordingDateAndTime,
CURRENT_TIME);
- lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN;
+ lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN);
lvid->descTag.descCRC = cpu_to_le16(
crc_itu_t(0, (char *)lvid + sizeof(struct tag),
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
mark_buffer_dirty(bh);
+ sbi->s_lvid_dirty = 0;
}
static void udf_close_lvid(struct super_block *sb)
return;
lvid = (struct logicalVolIntegrityDesc *)bh->b_data;
-
- if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN)
- return;
-
lvidiu = udf_sb_lvidiu(sbi);
lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
mark_buffer_dirty(bh);
+ sbi->s_lvid_dirty = 0;
}
static void udf_sb_free_bitmap(struct udf_bitmap *bitmap)
sb->s_fs_info = NULL;
}
+static int udf_sync_fs(struct super_block *sb, int wait)
+{
+ struct udf_sb_info *sbi = UDF_SB(sb);
+
+ mutex_lock(&sbi->s_alloc_mutex);
+ if (sbi->s_lvid_dirty) {
+ /*
+ * Blockdevice will be synced later so we don't have to submit
+ * the buffer for IO
+ */
+ mark_buffer_dirty(sbi->s_lvid_bh);
+ sb->s_dirt = 0;
+ sbi->s_lvid_dirty = 0;
+ }
+ mutex_unlock(&sbi->s_alloc_mutex);
+
+ return 0;
+}
+
static int udf_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct super_block *sb = dentry->d_sb;
struct inode *s_vat_inode;
struct mutex s_alloc_mutex;
+ /* Protected by s_alloc_mutex */
+ unsigned int s_lvid_dirty;
};
static inline struct udf_sb_info *UDF_SB(struct super_block *sb)
/* super.c */
extern void udf_warning(struct super_block *, const char *, const char *, ...);
+static inline void udf_updated_lvid(struct super_block *sb)
+{
+ struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh;
+
+ BUG_ON(!bh);
+ WARN_ON_ONCE(((struct logicalVolIntegrityDesc *)
+ bh->b_data)->integrityType !=
+ cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN));
+ sb->s_dirt = 1;
+ UDF_SB(sb)->s_lvid_dirty = 1;
+}
/* namei.c */
extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,