if (ni->name_len != na->name_len)
return 0;
if (na->name_len && memcmp(ni->name, na->name,
- na->name_len * sizeof(uchar_t)))
+ na->name_len * sizeof(ntfschar)))
return 0;
}
/* Match! */
if (na->name && na->name_len && na->name != I30) {
unsigned int i;
- i = na->name_len * sizeof(uchar_t);
- ni->name = (uchar_t*)kmalloc(i + sizeof(uchar_t), GFP_ATOMIC);
+ i = na->name_len * sizeof(ntfschar);
+ ni->name = (ntfschar*)kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
if (!ni->name)
return -ENOMEM;
memcpy(ni->name, na->name, i);
* obtained from PTR_ERR().
*/
struct inode *ntfs_attr_iget(struct inode *base_vi, ATTR_TYPES type,
- uchar_t *name, u32 name_len)
+ ntfschar *name, u32 name_len)
{
struct inode *vi;
ntfs_attr na;
/* Setup the operations for this inode. */
vi->i_op = &ntfs_dir_inode_ops;
vi->i_fop = &ntfs_dir_ops;
- vi->i_mapping->a_ops = &ntfs_aops;
+ vi->i_mapping->a_ops = &ntfs_mst_aops;
} else {
/* It is a file. */
reinit_attr_search_ctx(ctx);
/* Setup the operations for this attribute inode. */
vi->i_op = NULL;
vi->i_fop = NULL;
- vi->i_mapping->a_ops = &ntfs_aops;
+ if (NInoMstProtected(ni))
+ vi->i_mapping->a_ops = &ntfs_mst_aops;
+ else
+ vi->i_mapping->a_ops = &ntfs_aops;
if (!NInoCompressed(ni))
vi->i_blocks = ni->allocated_size >> 9;
* This should work but there are two possible pit falls (see inline comments
* below), but only time will tell if they are real pits or just smoke...
*/
-void ntfs_read_inode_mount(struct inode *vi)
+int ntfs_read_inode_mount(struct inode *vi)
{
VCN next_vcn, last_vcn, highest_vcn;
s64 block;
ntfs_debug("Entering.");
- if (vi->i_ino != FILE_MFT) {
- ntfs_error(sb, "Called for inode 0x%lx but only inode %d "
- "allowed.", vi->i_ino, FILE_MFT);
- goto err_out;
- }
-
/* Initialize the ntfs specific part of @vi. */
ntfs_init_big_inode(vi);
ni->name_len = 0;
/*
- * This sets up our little cheat allowing us to reuse the async io
+ * This sets up our little cheat allowing us to reuse the async read io
* completion handler for directories.
*/
ni->itype.index.block_size = vol->mft_record_size;
/*
* We have got the first extent of the run_list for
* $MFT which means it is now relatively safe to call
- * the normal ntfs_read_inode() function. Thus, take
- * us out of the calling chain. Also we need to do this
- * now because we need ntfs_read_inode() in place to
- * get at subsequent extents.
- */
- sb->s_op = &ntfs_sops;
- /*
+ * the normal ntfs_read_inode() function.
* Complete reading the inode, this will actually
* re-read the mft record for $MFT, this time entering
* it into the page cache with which we complete the
"sourceforge.net");
put_attr_search_ctx(ctx);
/* Revert to the safe super operations. */
- sb->s_op = &ntfs_mount_sops;
- goto out_now;
+ ntfs_free(m);
+ return -1;
}
/*
* Re-initialize some specifics about $MFT's inode as
}
put_attr_search_ctx(ctx);
ntfs_debug("Done.");
-out_now:
ntfs_free(m);
- return;
+ return 0;
+
em_put_err_out:
ntfs_error(sb, "Couldn't find first extent of $DATA attribute in "
"attribute list. $MFT is corrupt. Run chkdsk.");
put_err_out:
put_attr_search_ctx(ctx);
err_out:
- /* Make sure we revert to the safe super operations. */
- sb->s_op = &ntfs_mount_sops;
ntfs_error(sb, "Failed. Marking inode as bad.");
make_bad_inode(vi);
- goto out_now;
-}
-
-/**
- * ntfs_commit_inode - write out a dirty inode
- * @ni: inode to write out
- *
- */
-int ntfs_commit_inode(ntfs_inode *ni)
-{
- ntfs_debug("Entering for inode 0x%lx.", ni->mft_no);
- NInoClearDirty(ni);
- return 0;
+ ntfs_free(m);
+ return -1;
}
/**
void __ntfs_clear_inode(ntfs_inode *ni)
{
- int err;
-
- ntfs_debug("Entering for inode 0x%lx.", ni->mft_no);
- if (NInoDirty(ni)) {
- err = ntfs_commit_inode(ni);
- if (err) {
- ntfs_error(ni->vol->sb, "Failed to commit dirty "
- "inode synchronously.");
- // FIXME: Do something!!!
- }
- }
- /* Synchronize with ntfs_commit_inode(). */
- down(&ni->mrec_lock);
- up(&ni->mrec_lock);
- if (NInoDirty(ni)) {
- ntfs_error(ni->vol->sb, "Failed to commit dirty inode "
- "asynchronously.");
- // FIXME: Do something!!!
- }
- /* No need to lock at this stage as no one else has a reference. */
- if (ni->nr_extents > 0) {
- int i;
-
- // FIXME: Handle dirty case for each extent inode!
- for (i = 0; i < ni->nr_extents; i++)
- ntfs_clear_extent_inode(ni->ext.extent_ntfs_inos[i]);
- kfree(ni->ext.extent_ntfs_inos);
- }
/* Free all alocated memory. */
down_write(&ni->run_list.lock);
if (ni->run_list.rl) {
void ntfs_clear_extent_inode(ntfs_inode *ni)
{
+ ntfs_debug("Entering for inode 0x%lx.", ni->mft_no);
+
+ BUG_ON(NInoAttr(ni));
+ BUG_ON(ni->nr_extents != -1);
+
+#ifdef NTFS_RW
+ if (NInoDirty(ni)) {
+ if (!is_bad_inode(VFS_I(ni->ext.base_ntfs_ino)))
+ ntfs_error(ni->vol->sb, "Clearing dirty extent inode! "
+ "Losing data! This is a BUG!!!");
+ // FIXME: Do something!!!
+ }
+#endif /* NTFS_RW */
+
__ntfs_clear_inode(ni);
/* Bye, bye... */
{
ntfs_inode *ni = NTFS_I(vi);
+#ifdef NTFS_RW
+ if (NInoDirty(ni)) {
+ BOOL was_bad = (is_bad_inode(vi));
+
+ /* Committing the inode also commits all extent inodes. */
+ ntfs_commit_inode(vi);
+
+ if (!was_bad && (is_bad_inode(vi) || NInoDirty(ni))) {
+ ntfs_error(vi->i_sb, "Failed to commit dirty inode "
+ "0x%lx. Losing data!", vi->i_ino);
+ // FIXME: Do something!!!
+ }
+ }
+#endif /* NTFS_RW */
+
+ /* No need to lock at this stage as no one else has a reference. */
+ if (ni->nr_extents > 0) {
+ int i;
+
+ for (i = 0; i < ni->nr_extents; i++)
+ ntfs_clear_extent_inode(ni->ext.extent_ntfs_inos[i]);
+ kfree(ni->ext.extent_ntfs_inos);
+ }
+
__ntfs_clear_inode(ni);
if (NInoAttr(ni)) {
return err;
}
-#endif
+void ntfs_write_inode(struct inode *vi, int sync)
+{
+ ntfs_inode *ni = NTFS_I(vi);
+
+ ntfs_debug("Entering for %sinode 0x%lx.", NInoAttr(ni) ? "attr " : "",
+ vi->i_ino);
+
+ /*
+ * Dirty attribute inodes are written via their real inodes so just
+ * clean them here.
+ */
+ if (NInoAttr(ni)) {
+ NInoClearDirty(ni);
+ return;
+ }
+
+ /* Write this base mft record. */
+ if (NInoDirty(ni)) {
+ ntfs_warning(vi->i_sb, "Cleaning dirty inode 0x%lx without "
+ "writing to disk as this is not yet "
+ "implemented.", vi->i_ino);
+ NInoClearDirty(ni);
+ }
+
+ /* Write all attached extent mft records. */
+ down(&ni->extent_lock);
+ if (ni->nr_extents > 0) {
+ int i;
+ ntfs_inode **extent_nis = ni->ext.extent_ntfs_inos;
+
+ for (i = 0; i < ni->nr_extents; i++) {
+ ntfs_inode *tni = extent_nis[i];
+
+ if (NInoDirty(tni)) {
+ ntfs_warning(vi->i_sb, "Cleaning dirty extent "
+ "inode 0x%lx without writing "
+ "to disk as this is not yet "
+ "implemented.", tni->mft_no);
+ NInoClearDirty(tni);
+ }
+ }
+ }
+ up(&ni->extent_lock);
+}
+
+#endif /* NTFS_RW */