Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
30b44c02
Commit
30b44c02
authored
Sep 29, 2004
by
Anton Altaparmakov
Committed by
Richard Russon
Sep 29, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NTFS: Implement extent mft record deallocation.
Signed-off-by:
Anton Altaparmakov
<
aia21@cantab.net
>
parent
e5373176
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
164 additions
and
1 deletion
+164
-1
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+5
-0
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/mft.c
fs/ntfs/mft.c
+156
-0
fs/ntfs/mft.h
fs/ntfs/mft.h
+2
-0
No files found.
fs/ntfs/ChangeLog
View file @
30b44c02
...
...
@@ -21,6 +21,11 @@ ToDo/Notes:
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
2.1.20-WIP
- Implement extent mft record deallocation
fs/ntfs/mft.c::ntfs_extent_mft_record_free().
2.1.19 - Many cleanups, improvements, and a minor bug fix.
- Update ->setattr (fs/ntfs/inode.c::ntfs_setattr()) to refuse to
...
...
fs/ntfs/Makefile
View file @
30b44c02
...
...
@@ -6,7 +6,7 @@ ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o
\
upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.
19
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.1.
20-WIP
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/mft.c
View file @
30b44c02
...
...
@@ -23,6 +23,7 @@
#include <linux/swap.h>
#include "ntfs.h"
#include "bitmap.h"
/**
* __format_mft_record - initialize an empty mft record
...
...
@@ -1095,4 +1096,159 @@ static int ntfs_mft_writepage(struct page *page, struct writeback_control *wbc)
return
0
;
}
static
const
char
*
es
=
" Leaving inconsistent metadata. Unmount and run "
"chkdsk."
;
/**
* ntfs_extent_mft_record_free - free an extent mft record on an ntfs volume
* @ni: ntfs inode of the mapped extent mft record to free
* @m: mapped extent mft record of the ntfs inode @ni
*
* Free the mapped extent mft record @m of the extent ntfs inode @ni.
*
* Note that this function unmaps the mft record and closes and destroys @ni
* internally and hence you cannot use either @ni nor @m any more after this
* function returns success.
*
* On success return 0 and on error return -errno. @ni and @m are still valid
* in this case and have not been freed.
*
* For some errors an error message is displayed and the success code 0 is
* returned and the volume is then left dirty on umount. This makes sense in
* case we could not rollback the changes that were already done since the
* caller no longer wants to reference this mft record so it does not matter to
* the caller if something is wrong with it as long as it is properly detached
* from the base inode.
*/
int
ntfs_extent_mft_record_free
(
ntfs_inode
*
ni
,
MFT_RECORD
*
m
)
{
unsigned
long
mft_no
=
ni
->
mft_no
;
ntfs_volume
*
vol
=
ni
->
vol
;
ntfs_inode
*
base_ni
;
ntfs_inode
**
extent_nis
;
int
i
,
err
;
le16
old_seq_no
;
u16
seq_no
;
BUG_ON
(
NInoAttr
(
ni
));
BUG_ON
(
ni
->
nr_extents
!=
-
1
);
down
(
&
ni
->
extent_lock
);
base_ni
=
ni
->
ext
.
base_ntfs_ino
;
up
(
&
ni
->
extent_lock
);
BUG_ON
(
base_ni
->
nr_extents
<=
0
);
ntfs_debug
(
"Entering for extent inode 0x%lx, base inode 0x%lx.
\n
"
,
mft_no
,
base_ni
->
mft_no
);
down
(
&
base_ni
->
extent_lock
);
/* Make sure we are holding the only reference to the extent inode. */
if
(
atomic_read
(
&
ni
->
count
)
>
2
)
{
ntfs_error
(
vol
->
sb
,
"Tried to free busy extent inode 0x%lx, "
"not freeing."
,
base_ni
->
mft_no
);
up
(
&
base_ni
->
extent_lock
);
return
-
EBUSY
;
}
/* Dissociate the ntfs inode from the base inode. */
extent_nis
=
base_ni
->
ext
.
extent_ntfs_inos
;
err
=
-
ENOENT
;
for
(
i
=
0
;
i
<
base_ni
->
nr_extents
;
i
++
)
{
if
(
ni
!=
extent_nis
[
i
])
continue
;
extent_nis
+=
i
;
base_ni
->
nr_extents
--
;
memmove
(
extent_nis
,
extent_nis
+
1
,
(
base_ni
->
nr_extents
-
i
)
*
sizeof
(
ntfs_inode
*
));
err
=
0
;
break
;
}
up
(
&
base_ni
->
extent_lock
);
if
(
unlikely
(
err
))
{
ntfs_error
(
vol
->
sb
,
"Extent inode 0x%lx is not attached to "
"its base inode 0x%lx."
,
mft_no
,
base_ni
->
mft_no
);
BUG
();
}
/*
* The extent inode is no longer attached to the base inode so no one
* can get a reference to it any more.
*/
/* Mark the mft record as not in use. */
m
->
flags
&=
const_cpu_to_le16
(
~
const_le16_to_cpu
(
MFT_RECORD_IN_USE
));
/* Increment the sequence number, skipping zero, if it is not zero. */
old_seq_no
=
m
->
sequence_number
;
seq_no
=
le16_to_cpu
(
old_seq_no
);
if
(
seq_no
==
0xffff
)
seq_no
=
1
;
else
if
(
seq_no
)
seq_no
++
;
m
->
sequence_number
=
cpu_to_le16
(
seq_no
);
/*
* Set the ntfs inode dirty and write it out. We do not need to worry
* about the base inode here since whatever caused the extent mft
* record to be freed is guaranteed to do it already.
*/
NInoSetDirty
(
ni
);
err
=
write_mft_record
(
ni
,
m
,
0
);
if
(
unlikely
(
err
))
{
ntfs_error
(
vol
->
sb
,
"Failed to write mft record 0x%lx, not "
"freeing."
,
mft_no
);
goto
rollback
;
}
rollback_error:
/* Unmap and throw away the now freed extent inode. */
unmap_extent_mft_record
(
ni
);
ntfs_clear_extent_inode
(
ni
);
/* Clear the bit in the $MFT/$BITMAP corresponding to this record. */
err
=
ntfs_bitmap_clear_bit
(
vol
->
mftbmp_ino
,
mft_no
);
if
(
unlikely
(
err
))
{
/*
* The extent inode is gone but we failed to deallocate it in
* the mft bitmap. Just emit a warning and leave the volume
* dirty on umount.
*/
ntfs_error
(
vol
->
sb
,
"Failed to clear bit in mft bitmap.%s"
,
es
);
NVolSetErrors
(
vol
);
}
return
0
;
rollback:
/* Rollback what we did... */
down
(
&
base_ni
->
extent_lock
);
extent_nis
=
base_ni
->
ext
.
extent_ntfs_inos
;
if
(
!
(
base_ni
->
nr_extents
&
3
))
{
int
new_size
=
(
base_ni
->
nr_extents
+
4
)
*
sizeof
(
ntfs_inode
*
);
extent_nis
=
(
ntfs_inode
**
)
kmalloc
(
new_size
,
GFP_NOFS
);
if
(
unlikely
(
!
extent_nis
))
{
ntfs_error
(
vol
->
sb
,
"Failed to allocate internal "
"buffer during rollback.%s"
,
es
);
up
(
&
base_ni
->
extent_lock
);
NVolSetErrors
(
vol
);
goto
rollback_error
;
}
if
(
base_ni
->
nr_extents
)
{
BUG_ON
(
!
base_ni
->
ext
.
extent_ntfs_inos
);
memcpy
(
extent_nis
,
base_ni
->
ext
.
extent_ntfs_inos
,
new_size
-
4
*
sizeof
(
ntfs_inode
*
));
kfree
(
base_ni
->
ext
.
extent_ntfs_inos
);
}
base_ni
->
ext
.
extent_ntfs_inos
=
extent_nis
;
}
m
->
flags
|=
MFT_RECORD_IN_USE
;
m
->
sequence_number
=
old_seq_no
;
extent_nis
[
base_ni
->
nr_extents
++
]
=
ni
;
up
(
&
base_ni
->
extent_lock
);
mark_mft_record_dirty
(
ni
);
return
err
;
}
#endif
/* NTFS_RW */
fs/ntfs/mft.h
View file @
30b44c02
...
...
@@ -111,6 +111,8 @@ static inline int write_mft_record(ntfs_inode *ni, MFT_RECORD *m, int sync)
return
err
;
}
extern
int
ntfs_extent_mft_record_free
(
ntfs_inode
*
ni
,
MFT_RECORD
*
m
);
#endif
/* NTFS_RW */
#endif
/* _LINUX_NTFS_MFT_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment