* [2.6-BK-URL] NTFS 2.1.17 release
@ 2004-08-23 10:25 Anton Altaparmakov
2004-08-23 10:28 ` [PATCH 1/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:25 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
Hi Andrew, Hi Linus, please do a
bk pull bk://linux-ntfs.bkbits.net/ntfs-2.6
This is quite a big update and all of it has been in -mm kernels for a
while. I have been holding off until 2.6.8 had been released before
submitting so any problems would have time to get to me. I haven't had
any problem reports so here it is. The most important points are that
NTFS now provides most of the facilities provided by other Linux fs, e.g.:
- fsync/fdatasync/msync
- access {a/m/c}time updates
- readv/writev
- aio_read/aio_write
Also several bugs in the mount code error paths were fixed and a global
variable got eliminated as a result. See below for details ChangeSet
comemnts.
Please apply. Thanks!
For the benefit of non-BK users and to make code review easier, I am
sending each ChangeSet in a separate email as a diff -u style patch.
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
This will update the following files:
Documentation/filesystems/ntfs.txt | 22
fs/ntfs/ChangeLog | 70 +-
fs/ntfs/Makefile | 12
fs/ntfs/aops.c | 78 +-
fs/ntfs/attrib.c | 539 +++++++++++--------
fs/ntfs/attrib.h | 20
fs/ntfs/bitmap.c | 203 ++++++-
fs/ntfs/bitmap.h | 118 ++++
fs/ntfs/compress.c | 34 -
fs/ntfs/debug.c | 17
fs/ntfs/debug.h | 2
fs/ntfs/dir.c | 61 ++
fs/ntfs/file.c | 105 +++
fs/ntfs/inode.c | 140 +++-
fs/ntfs/inode.h | 15
fs/ntfs/layout.h | 14
fs/ntfs/lcnalloc.c | 1043 ++++++++++++++++++++++++++++++++++++-
fs/ntfs/lcnalloc.h | 83 ++
fs/ntfs/ntfs.h | 1
fs/ntfs/super.c | 298 +++++++---
fs/ntfs/types.h | 12
fs/ntfs/volume.h | 15
22 files changed, 2368 insertions(+), 534 deletions(-)
through these ChangeSets:
<aia21@cantab.net> (04/07/07 1.1784.14.1)
NTFS: Add support for readv/writev and aio_read/aio_write.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/08 1.1784.14.2)
NTFS: Change ntfs_write_inode to return 0 on success and -errno on error
and create a wrapper ntfs_write_inode_vfs that does not have a
return value and use the wrapper for the VFS super_operations
write_inode function.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/08 1.1784.14.3)
NTFS: Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
and directories (fs/ntfs/dir.c).
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/14 1.1784.3.21)
NTFS: 2.1.16 - Implement access time updates in fs/ntfs/inode.c::ntfs_write_inode.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/21 1.1808)
NTFS: Implement bitmap modification code (fs/ntfs/bitmap.[hc]). This
includes functions to set/clear a single bit or a run of bits.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/21 1.1809)
NTFS: Wrap the new bitmap.[hc] code in #ifdef NTFS_RW / #endif.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/21 1.1810)
NTFS: Rename run_list to runlist everywhere to bring in line with libntfs.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/21 1.1811)
NTFS: Rename map_runlist() to ntfs_map_runlist().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/21 1.1812)
NTFS: Rename vcn_to_lcn() to ntfs_vcn_to_lcn().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/22 1.1813)
NTFS: Complete "run list" to "runlist" renaming.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/22 1.1814)
NTFS: Move a NULL check to before the first use of the pointer.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/22 1.1815)
NTFS: Add fs/ntfs/attrib.[hc]::ntfs_find_vcn().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/07/30 1.1816)
NTFS: Fix compilation with gcc-2.95 in attrib.c::ntfs_find_vcn(). (Adrian Bunk)
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
<aia21@cantab.net> (04/08/16 1.1820)
NTFS: Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/17 1.1821)
NTFS: Minor update to fs/ntfs/bitmap.c to only perform rollback if at
least one bit has actually been changed.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/17 1.1822)
NTFS: Fix fs/ntfs/lcnalloc.c::ntfs_cluster_alloc() to use LCN_RL_NOT_MAPPED
rather than LCN_ENOENT as runlist terminator. Also, make it not create a
LCN_RL_NOT_MAPPED element at the beginning.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/17 1.1823)
NTFS: Fix fs/ntfs/debug.c::ntfs_debug_dump_runlist() for the previous
removal of LCN_EINVAL which was not used in the kernel NTFS driver.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/17 1.1824)
NTFS: Only need two spare runlist elements when reallocating memory in
fs/ntfs/lcnalloc.c::ntfs_cluster_alloc(), not three since we no longer
add a starting element.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/18 1.1825)
NTFS: - Load attribute definition table from $AttrDef at mount time.
- Fix bugs in mount time error code paths involving (de)allocation of
the default and volume upcase tables.
- Remove ntfs_nr_mounts as it is no longer used.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
<aia21@cantab.net> (04/08/18 1.1826)
NTFS: 2.1.17 - Fix bugs in mount time error code paths.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:25 [2.6-BK-URL] NTFS 2.1.17 release Anton Altaparmakov
@ 2004-08-23 10:28 ` Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 2/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:28 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 1/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/07 1.1784.14.1)
NTFS: Add support for readv/writev and aio_read/aio_write.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:49:46 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:49:46 +01:00
@@ -26,6 +26,12 @@
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
+2.1.16 - WIP.
+
+ - Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
+ This is done by setting the appropriate file operations pointers to
+ the generic helper functions provided by mm/filemap.c.
+
2.1.15 - Invalidate quotas when (re)mounting read-write.
- Add new element itype.index.collation_rule to the ntfs inode
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile 2004-08-18 20:49:46 +01:00
+++ b/fs/ntfs/Makefile 2004-08-18 20:49:46 +01:00
@@ -6,7 +6,7 @@
index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.15\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.16-WIP\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
diff -Nru a/fs/ntfs/file.c b/fs/ntfs/file.c
--- a/fs/ntfs/file.c 2004-08-18 20:49:46 +01:00
+++ b/fs/ntfs/file.c 2004-08-18 20:49:46 +01:00
@@ -49,25 +49,48 @@
}
struct file_operations ntfs_file_ops = {
- .llseek = generic_file_llseek, /* Seek inside file. */
- .read = generic_file_read, /* Read from file. */
+ .llseek = generic_file_llseek, /* Seek inside file. */
+ .read = generic_file_read, /* Read from file. */
+ .aio_read = generic_file_aio_read, /* Async read from file. */
+ .readv = generic_file_readv, /* Read from file. */
#ifdef NTFS_RW
- .write = generic_file_write, /* Write to a file. */
-#endif
- .mmap = generic_file_mmap, /* Mmap file. */
- .sendfile = generic_file_sendfile,/* Zero-copy data send with the
- data source being on the
- ntfs partition. We don't
- need to care about the data
- destination. */
- .open = ntfs_file_open, /* Open file. */
+ .write = generic_file_write, /* Write to file. */
+ .aio_write = generic_file_aio_write, /* Async write to file. */
+ .writev = generic_file_writev, /* Write to file. */
+ /*.release = ,*/ /* Last file is closed. See
+ fs/ext2/file.c::
+ ext2_release_file() for
+ how to use this to discard
+ preallocated space for
+ write opened files. */
+ /*.fsync = ,*/ /* Sync a file to disk. See
+ fs/buffer.c::sys_fsync()
+ and file_fsync(). */
+ /*.aio_fsync = ,*/ /* Sync all outstanding async
+ i/o operations on a
+ kiocb. */
+#endif /* NTFS_RW */
+ /*.ioctl = ,*/ /* Perform function on the
+ mounted filesystem. */
+ .mmap = generic_file_mmap, /* Mmap file. */
+ .open = ntfs_file_open, /* Open file. */
+ .sendfile = generic_file_sendfile, /* Zero-copy data send with
+ the data source being on
+ the ntfs partition. We
+ do not need to care about
+ the data destination. */
+ /*.sendpage = ,*/ /* Zero-copy data send with
+ the data destination being
+ on the ntfs partition. We
+ do not need to care about
+ the data source. */
};
struct inode_operations ntfs_file_inode_ops = {
#ifdef NTFS_RW
.truncate = ntfs_truncate,
.setattr = ntfs_setattr,
-#endif
+#endif /* NTFS_RW */
};
struct file_operations ntfs_empty_file_ops = {};
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:28 ` [PATCH 1/20] " Anton Altaparmakov
@ 2004-08-23 10:29 ` Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 3/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:29 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 2/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/08 1.1784.14.2)
NTFS: Change ntfs_write_inode to return 0 on success and -errno on error
and create a wrapper ntfs_write_inode_vfs that does not have a
return value and use the wrapper for the VFS super_operations
write_inode function.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c 2004-08-18 20:49:49 +01:00
+++ b/fs/ntfs/inode.c 2004-08-18 20:49:49 +01:00
@@ -2314,8 +2314,10 @@
* marking the page (and in this case mft record) dirty but we do not implement
* this yet as write_mft_record() largely ignores the @sync parameter and
* always performs synchronous writes.
+ *
+ * Return 0 on success and -errno on error.
*/
-void ntfs_write_inode(struct inode *vi, int sync)
+int ntfs_write_inode(struct inode *vi, int sync)
{
ntfs_inode *ni = NTFS_I(vi);
#if 0
@@ -2332,7 +2334,7 @@
*/
if (NInoAttr(ni)) {
NInoClearDirty(ni);
- return;
+ return 0;
}
/* Map, pin, and lock the mft record belonging to the inode. */
m = map_mft_record(ni);
@@ -2410,7 +2412,7 @@
if (unlikely(err))
goto err_out;
ntfs_debug("Done.");
- return;
+ return 0;
#if 0
unm_err_out:
unmap_mft_record(ni);
@@ -2426,7 +2428,31 @@
"as bad. You should run chkdsk.", -err);
make_bad_inode(vi);
}
- return;
+ return err;
+}
+
+/**
+ * ntfs_write_inode_vfs - write out a dirty inode
+ * @vi: inode to write out
+ * @sync: if true, write out synchronously
+ *
+ * Write out a dirty inode to disk including any extent inodes if present.
+ *
+ * If @sync is true, commit the inode to disk and wait for io completion. This
+ * is done using write_mft_record().
+ *
+ * If @sync is false, just schedule the write to happen but do not wait for i/o
+ * completion. In 2.6 kernels, scheduling usually happens just by virtue of
+ * marking the page (and in this case mft record) dirty but we do not implement
+ * this yet as write_mft_record() largely ignores the @sync parameter and
+ * always performs synchronous writes.
+ *
+ * This functions does not have a return value which is the required behaviour
+ * for the VFS super_operations ->dirty_inode function.
+ */
+void ntfs_write_inode_vfs(struct inode *vi, int sync)
+{
+ ntfs_write_inode(vi, sync);
}
#endif /* NTFS_RW */
diff -Nru a/fs/ntfs/inode.h b/fs/ntfs/inode.h
--- a/fs/ntfs/inode.h 2004-08-18 20:49:49 +01:00
+++ b/fs/ntfs/inode.h 2004-08-18 20:49:49 +01:00
@@ -285,7 +285,8 @@
extern int ntfs_setattr(struct dentry *dentry, struct iattr *attr);
-extern void ntfs_write_inode(struct inode *vi, int sync);
+extern int ntfs_write_inode(struct inode *vi, int sync);
+extern void ntfs_write_inode_vfs(struct inode *vi, int sync);
static inline void ntfs_commit_inode(struct inode *vi)
{
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:49:49 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:49:49 +01:00
@@ -2050,7 +2050,7 @@
#ifdef NTFS_RW
//.dirty_inode = NULL, /* VFS: Called from
// __mark_inode_dirty(). */
- .write_inode = ntfs_write_inode, /* VFS: Write dirty inode to
+ .write_inode = ntfs_write_inode_vfs, /* VFS: Write dirty inode to
disk. */
//.drop_inode = NULL, /* VFS: Called just after the
// inode reference count has
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:29 ` [PATCH 2/20] " Anton Altaparmakov
@ 2004-08-23 10:29 ` Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 4/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:29 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 3/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/08 1.1784.14.3)
NTFS: Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
and directories (fs/ntfs/dir.c).
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:49:53 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:49:53 +01:00
@@ -31,6 +31,8 @@
- Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
This is done by setting the appropriate file operations pointers to
the generic helper functions provided by mm/filemap.c.
+ - Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
+ and directories (fs/ntfs/dir.c).
2.1.15 - Invalidate quotas when (re)mounting read-write.
diff -Nru a/fs/ntfs/dir.c b/fs/ntfs/dir.c
--- a/fs/ntfs/dir.c 2004-08-18 20:49:53 +01:00
+++ b/fs/ntfs/dir.c 2004-08-18 20:49:53 +01:00
@@ -1495,10 +1495,69 @@
return 0;
}
+#ifdef NTFS_RW
+
+/**
+ * ntfs_dir_fsync - sync a directory to disk
+ * @filp: directory to be synced
+ * @dentry: dentry describing the directory to sync
+ * @datasync: if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a directory to disk. Used for fsync, fdatasync, and
+ * msync system calls. This function is based on file.c::ntfs_file_fsync().
+ *
+ * Write the mft record and all associated extent mft records as well as the
+ * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device.
+ *
+ * If @datasync is true, we do not wait on the inode(s) to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now. We do write the $BITMAP attribute if it is present
+ * which is the important one for a directory so things are not too bad.
+ */
+static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry,
+ int datasync)
+{
+ struct inode *vi = dentry->d_inode;
+ ntfs_inode *ni = NTFS_I(vi);
+ int err, ret;
+
+ ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+ BUG_ON(!S_ISDIR(vi->i_mode));
+ if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino)
+ write_inode_now(ni->itype.index.bmp_ino, !datasync);
+ ret = ntfs_write_inode(vi, 1);
+ write_inode_now(vi, !datasync);
+ err = sync_blockdev(vi->i_sb->s_bdev);
+ if (unlikely(err && !ret))
+ ret = err;
+ if (likely(!ret))
+ ntfs_debug("Done.");
+ else
+ ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx. Error "
+ "%u.", datasync ? "data" : "", vi->i_ino, -ret);
+ return ret;
+}
+
+#endif /* NTFS_RW */
+
struct file_operations ntfs_dir_ops = {
.llseek = generic_file_llseek, /* Seek inside directory. */
.read = generic_read_dir, /* Return -EISDIR. */
.readdir = ntfs_readdir, /* Read directory contents. */
+#ifdef NTFS_RW
+ .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */
+ /*.aio_fsync = ,*/ /* Sync all outstanding async
+ i/o operations on a kiocb. */
+#endif /* NTFS_RW */
+ /*.ioctl = ,*/ /* Perform function on the
+ mounted filesystem. */
.open = ntfs_dir_open, /* Open directory. */
};
-
diff -Nru a/fs/ntfs/file.c b/fs/ntfs/file.c
--- a/fs/ntfs/file.c 2004-08-18 20:49:53 +01:00
+++ b/fs/ntfs/file.c 2004-08-18 20:49:53 +01:00
@@ -48,6 +48,60 @@
return generic_file_open(vi, filp);
}
+#ifdef NTFS_RW
+
+/**
+ * ntfs_file_fsync - sync a file to disk
+ * @filp: file to be synced
+ * @dentry: dentry describing the file to sync
+ * @datasync: if non-zero only flush user data and not metadata
+ *
+ * Data integrity sync of a file to disk. Used for fsync, fdatasync, and msync
+ * system calls. This function is inspired by fs/buffer.c::file_fsync().
+ *
+ * If @datasync is false, write the mft record and all associated extent mft
+ * records as well as the $DATA attribute and then sync the block device.
+ *
+ * If @datasync is true and the attribute is non-resident, we skip the writing
+ * of the mft record and all associated extent mft records (this might still
+ * happen due to the write_inode_now() call).
+ *
+ * Also, if @datasync is true, we do not wait on the inode to be written out
+ * but we always wait on the page cache pages to be written out.
+ *
+ * Note: In the past @filp could be NULL so we ignore it as we don't need it
+ * anyway.
+ *
+ * Locking: Caller must hold i_sem on the inode.
+ *
+ * TODO: We should probably also write all attribute/index inodes associated
+ * with this inode but since we have no simple way of getting to them we ignore
+ * this problem for now.
+ */
+static int ntfs_file_fsync(struct file *filp, struct dentry *dentry,
+ int datasync)
+{
+ struct inode *vi = dentry->d_inode;
+ int err, ret = 0;
+
+ ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
+ BUG_ON(S_ISDIR(vi->i_mode));
+ if (!datasync || !NInoNonResident(NTFS_I(vi)))
+ ret = ntfs_write_inode(vi, 1);
+ write_inode_now(vi, !datasync);
+ err = sync_blockdev(vi->i_sb->s_bdev);
+ if (unlikely(err && !ret))
+ ret = err;
+ if (likely(!ret))
+ ntfs_debug("Done.");
+ else
+ ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx. Error "
+ "%u.", datasync ? "data" : "", vi->i_ino, -ret);
+ return ret;
+}
+
+#endif /* NTFS_RW */
+
struct file_operations ntfs_file_ops = {
.llseek = generic_file_llseek, /* Seek inside file. */
.read = generic_file_read, /* Read from file. */
@@ -63,9 +117,7 @@
how to use this to discard
preallocated space for
write opened files. */
- /*.fsync = ,*/ /* Sync a file to disk. See
- fs/buffer.c::sys_fsync()
- and file_fsync(). */
+ .fsync = ntfs_file_fsync, /* Sync a file to disk. */
/*.aio_fsync = ,*/ /* Sync all outstanding async
i/o operations on a
kiocb. */
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 4/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:29 ` [PATCH 3/20] " Anton Altaparmakov
@ 2004-08-23 10:29 ` Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 5/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:29 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 4/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/14 1.1784.3.21)
NTFS: 2.1.16 - Implement access time updates in fs/ntfs/inode.c::ntfs_write_inode.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
--- a/Documentation/filesystems/ntfs.txt 2004-08-18 20:49:56 +01:00
+++ b/Documentation/filesystems/ntfs.txt 2004-08-18 20:49:56 +01:00
@@ -273,6 +273,12 @@
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
+2.1.16:
+ - Implement access time updates (including mtime and ctime).
+ - Implement fsync(2), fdatasync(2), and msync(2) system calls.
+ - Enable the readv(2) and writev(2) system calls.
+ - Enable access via the asynchronous io (aio) API by adding support for
+ the aio_read(3) and aio_write(3) functions.
2.1.15:
- Invalidate quotas when (re)mounting read-write.
NOTE: This now only leave user space journalling on the side. (See
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:49:56 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:49:56 +01:00
@@ -26,13 +26,19 @@
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
-2.1.16 - WIP.
+2.1.16 - Implement access time updates, file sync, async io, and read/writev.
- Add support for readv/writev and aio_read/aio_write (fs/ntfs/file.c).
This is done by setting the appropriate file operations pointers to
the generic helper functions provided by mm/filemap.c.
- Implement fsync, fdatasync, and msync both for files (fs/ntfs/file.c)
and directories (fs/ntfs/dir.c).
+ - Add support for {a,m,c}time updates to inode.c::ntfs_write_inode().
+ Note, except for the root directory and any other system files opened
+ by the user, the system files will not have their access times
+ updated as they are only accessed at the inode level an hence the
+ file level functions which cause the times to be updated are never
+ invoked.
2.1.15 - Invalidate quotas when (re)mounting read-write.
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile 2004-08-18 20:49:56 +01:00
+++ b/fs/ntfs/Makefile 2004-08-18 20:49:56 +01:00
@@ -6,7 +6,7 @@
index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.16-WIP\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.16\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c 2004-08-18 20:49:56 +01:00
+++ b/fs/ntfs/inode.c 2004-08-18 20:49:56 +01:00
@@ -622,7 +622,7 @@
si = (STANDARD_INFORMATION*)((char*)ctx->attr +
le16_to_cpu(ctx->attr->data.resident.value_offset));
- /* Transfer information from the standard information into vfs_ino. */
+ /* Transfer information from the standard information into vi. */
/*
* Note: The i_?times do not quite map perfectly onto the NTFS times,
* but they are close enough, and in the end it doesn't really matter
@@ -2319,21 +2319,24 @@
*/
int ntfs_write_inode(struct inode *vi, int sync)
{
+ s64 nt;
ntfs_inode *ni = NTFS_I(vi);
-#if 0
attr_search_context *ctx;
-#endif
MFT_RECORD *m;
+ STANDARD_INFORMATION *si;
int err = 0;
+ BOOL modified = FALSE;
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. TODO: Take care of access time updates.
+ * clean them here. Access time updates are taken care off when the
+ * real inode is written.
*/
if (NInoAttr(ni)) {
NInoClearDirty(ni);
+ ntfs_debug("Done.");
return 0;
}
/* Map, pin, and lock the mft record belonging to the inode. */
@@ -2342,8 +2345,7 @@
err = PTR_ERR(m);
goto err_out;
}
-#if 0
- /* Obtain the standard information attribute. */
+ /* Update the access times in the standard information attribute. */
ctx = get_attr_search_ctx(ni, m);
if (unlikely(!ctx)) {
err = -ENOMEM;
@@ -2355,28 +2357,50 @@
err = -ENOENT;
goto unm_err_out;
}
- // TODO: Update the access times in the standard information attribute
- // which is now in ctx->attr.
- // - Probably want to have use sops->dirty_inode() to set a flag that
- // we need to update the times here rather than having to blindly do
- // it every time. Or even don't do it here at all and do it in
- // sops->dirty_inode() instead. Problem with this would be that
- // sops->dirty_inode() must be atomic under certain circumstances
- // and mapping mft records and such like is not atomic.
- // - For atime updates also need to check whether they are enabled in
- // the superblock flags.
- ntfs_warning(vi->i_sb, "Access time updates not implement yet.");
+ si = (STANDARD_INFORMATION*)((u8*)ctx->attr +
+ le16_to_cpu(ctx->attr->data.resident.value_offset));
+ /* Update the access times if they have changed. */
+ nt = utc2ntfs(vi->i_mtime);
+ if (si->last_data_change_time != nt) {
+ ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, "
+ "new = 0x%llx", vi->i_ino,
+ sle64_to_cpu(si->last_data_change_time),
+ sle64_to_cpu(nt));
+ si->last_data_change_time = nt;
+ modified = TRUE;
+ }
+ nt = utc2ntfs(vi->i_ctime);
+ if (si->last_mft_change_time != nt) {
+ ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, "
+ "new = 0x%llx", vi->i_ino,
+ sle64_to_cpu(si->last_mft_change_time),
+ sle64_to_cpu(nt));
+ si->last_mft_change_time = nt;
+ modified = TRUE;
+ }
+ nt = utc2ntfs(vi->i_atime);
+ if (si->last_access_time != nt) {
+ ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, "
+ "new = 0x%llx", vi->i_ino,
+ sle64_to_cpu(si->last_access_time),
+ sle64_to_cpu(nt));
+ si->last_access_time = nt;
+ modified = TRUE;
+ }
/*
- * We just modified the mft record containing the standard information
- * attribute. So need to mark the mft record dirty, too, but we do it
- * manually so that mark_inode_dirty() is not called again.
- * TODO: Only do this if there was a change in any of the times!
+ * If we just modified the standard information attribute we need to
+ * mark the mft record it is in dirty. We do this manually so that
+ * mark_inode_dirty() is not called which would redirty the inode and
+ * hence result in an infinite loop of trying to write the inode.
+ * There is no need to mark the base inode nor the base mft record
+ * dirty, since we are going to write this mft record below in any case
+ * and the base mft record may actually not have been modified so it
+ * might not need to be written out.
*/
- if (!NInoTestSetDirty(ctx->ntfs_ino))
+ if (modified && !NInoTestSetDirty(ctx->ntfs_ino))
__set_page_dirty_nobuffers(ctx->ntfs_ino->page);
put_attr_search_ctx(ctx);
-#endif
- /* Write this base mft record. */
+ /* Now the access times are updated, write the base mft record. */
if (NInoDirty(ni))
err = write_mft_record(ni, m, sync);
/* Write all attached extent mft records. */
@@ -2413,10 +2437,8 @@
goto err_out;
ntfs_debug("Done.");
return 0;
-#if 0
unm_err_out:
unmap_mft_record(ni);
-#endif
err_out:
if (err == -ENOMEM) {
ntfs_warning(vi->i_sb, "Not enough memory to write inode. "
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:49:56 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:49:56 +01:00
@@ -409,7 +409,7 @@
#ifndef NTFS_RW
/* For read-only compiled driver, enforce all read-only flags. */
*flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else /* ! NTFS_RW */
+#else /* NTFS_RW */
/*
* For the read-write compiled driver, if we are remounting read-write,
* make sure there are no volume errors and that no unsupported volume
@@ -479,28 +479,7 @@
"flags. Run chkdsk.");
}
}
- // TODO: For now we enforce no atime and dir atime updates as they are
- // not implemented.
- if ((sb->s_flags & MS_NOATIME) && !(*flags & MS_NOATIME))
- ntfs_warning(sb, "Atime updates are not implemented yet. "
- "Leaving them disabled.");
- else if ((sb->s_flags & MS_NODIRATIME) && !(*flags & MS_NODIRATIME))
- ntfs_warning(sb, "Directory atime updates are not implemented "
- "yet. Leaving them disabled.");
- *flags |= MS_NOATIME | MS_NODIRATIME;
-#endif /* ! NTFS_RW */
-
- // FIXME/TODO: If left like this we will have problems with rw->ro and
- // ro->rw, as well as with sync->async and vice versa remounts.
- // Note: The VFS already checks that there are no pending deletes and
- // no open files for writing. So we only need to worry about dirty
- // inode pages and dirty system files (which include dirty inodes).
- // Either handle by flushing the whole volume NOW or by having the
- // write routines work on MS_RDONLY fs and guarantee we don't mark
- // anything as dirty if MS_RDONLY is set. That way the dirty data
- // would get flushed but no new dirty data would appear. This is
- // probably best but we need to be careful not to mark anything dirty
- // or the MS_RDONLY will be leaking writes.
+#endif /* NTFS_RW */
// TODO: Deal with *flags.
@@ -2139,15 +2118,7 @@
ntfs_debug("Entering.");
#ifndef NTFS_RW
sb->s_flags |= MS_RDONLY | MS_NOATIME | MS_NODIRATIME;
-#else
- if (!(sb->s_flags & MS_NOATIME))
- ntfs_warning(sb, "Atime updates are not implemented yet. "
- "Disabling them.");
- else if (!(sb->s_flags & MS_NODIRATIME))
- ntfs_warning(sb, "Directory atime updates are not implemented "
- "yet. Disabling them.");
- sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
-#endif
+#endif /* ! NTFS_RW */
/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
sb->s_fs_info = kmalloc(sizeof(ntfs_volume), GFP_NOFS);
vol = NTFS_SB(sb);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 5/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:29 ` [PATCH 4/20] " Anton Altaparmakov
@ 2004-08-23 10:30 ` Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 6/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:30 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 5/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/21 1.1808)
NTFS: Implement bitmap modification code (fs/ntfs/bitmap.[hc]). This
includes functions to set/clear a single bit or a run of bits.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:50:00 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:50:00 +01:00
@@ -1,11 +1,6 @@
ToDo/Notes:
- Find and fix bugs.
- Checkpoint or disable the user space journal ($UsnJrnl).
- - Implement sops->dirty_inode() to implement {a,m,c}time updates and
- such things. This should probably just flag the ntfs inode such that
- sops->write_inode(), i.e. ntfs_write_inode(), will copy the times
- when it is invoked rather than having to update the mft record
- every time.
- In between ntfs_prepare/commit_write, need exclusion between
simultaneous file extensions. Need perhaps an NInoResizeUnderway()
flag which we can set in ntfs_prepare_write() and clear again in
@@ -25,6 +20,11 @@
the problem.
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
+
+2.1.17 - WIP.
+
+ - Implement bitmap modification code (fs/ntfs/bitmap.[hc]). This
+ includes functions to set/clear a single bit or a run of bits.
2.1.16 - Implement access time updates, file sync, async io, and read/writev.
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile 2004-08-18 20:50:00 +01:00
+++ b/fs/ntfs/Makefile 2004-08-18 20:50:00 +01:00
@@ -6,7 +6,7 @@
index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.16\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.17-WIP\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
@@ -15,5 +15,5 @@
ifeq ($(CONFIG_NTFS_RW),y)
EXTRA_CFLAGS += -DNTFS_RW
-ntfs-objs += logfile.o quota.o
+ntfs-objs += bitmap.o logfile.o quota.o
endif
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/bitmap.c 2004-08-18 20:50:00 +01:00
@@ -0,0 +1,183 @@
+/*
+ * bitmap.c - NTFS kernel bitmap handling. Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/pagemap.h>
+
+#include "bitmap.h"
+#include "debug.h"
+#include "ntfs.h"
+
+/**
+ * __ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi: vfs inode describing the bitmap
+ * @start_bit: first bit to set
+ * @count: number of bits to set
+ * @value: value to set the bits to (i.e. 0 or 1)
+ * @is_rollback: if TRUE this is a rollback operation
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors. You probably want to use ntfs_bitmap_set_bits_in_run() instead.
+ *
+ * Return 0 on success and -errno on error.
+ */
+int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+ const s64 count, const u8 value, const BOOL is_rollback)
+{
+ s64 cnt = count;
+ pgoff_t index, end_index;
+ struct address_space *mapping;
+ struct page *page;
+ u8 *kaddr;
+ int pos, len;
+ u8 bit;
+
+ ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
+ "value %u.", vi->i_ino, (unsigned long long)start_bit,
+ (unsigned long long)cnt, (unsigned int)value);
+ BUG_ON(!vi);
+ BUG_ON(start_bit < 0);
+ BUG_ON(cnt < 0);
+ BUG_ON(value > 1);
+ /*
+ * Calculate the indices for the pages containing the first and last
+ * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively.
+ */
+ index = start_bit >> (3 + PAGE_CACHE_SHIFT);
+ end_index = (start_bit + cnt - 1) >> (3 + PAGE_CACHE_SHIFT);
+
+ /* Get the page containing the first bit (@start_bit). */
+ mapping = vi->i_mapping;
+ page = ntfs_map_page(mapping, index);
+ if (IS_ERR(page)) {
+ if (!is_rollback)
+ ntfs_error(vi->i_sb, "Failed to map first page (error "
+ "%li), aborting.", PTR_ERR(page));
+ return PTR_ERR(page);
+ }
+ kaddr = page_address(page);
+
+ /* Set @pos to the position of the byte containing @start_bit. */
+ pos = (start_bit >> 3) & ~PAGE_CACHE_MASK;
+
+ /* Calculate the position of @start_bit in the first byte. */
+ bit = start_bit & 7;
+
+ /* If the first byte is partial, modify the appropriate bits in it. */
+ if (bit) {
+ u8 *byte = kaddr + pos;
+ while ((bit & 7) && cnt--) {
+ if (value)
+ *byte |= 1 << bit++;
+ else
+ *byte &= ~(1 << bit++);
+ }
+ /* If we are done, unmap the page and return success. */
+ if (!cnt)
+ goto done;
+
+ /* Update @pos to the new position. */
+ pos++;
+ }
+ /*
+ * Depending on @value, modify all remaining whole bytes in the page up
+ * to @cnt.
+ */
+ len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE - pos);
+ memset(kaddr + pos, value ? 0xff : 0, len);
+ cnt -= len << 3;
+
+ /* Update @len to point to the first not-done byte in the page. */
+ if (cnt < 8)
+ len += pos;
+
+ /* If we are not in the last page, deal with all subsequent pages. */
+ while (end_index > index) {
+ BUG_ON(cnt <= 0);
+
+ /* Update @index and get the next page. */
+ flush_dcache_page(page);
+ set_page_dirty(page);
+ ntfs_unmap_page(page);
+ page = ntfs_map_page(mapping, ++index);
+ if (IS_ERR(page))
+ goto rollback;
+ kaddr = page_address(page);
+ /*
+ * Depending on @value, modify all remaining whole bytes in the
+ * page up to @cnt.
+ */
+ len = min_t(s64, cnt >> 3, PAGE_CACHE_SIZE);
+ memset(kaddr, value ? 0xff : 0, len);
+ cnt -= len << 3;
+ }
+ /*
+ * The currently mapped page is the last one. If the last byte is
+ * partial, modify the appropriate bits in it. Note, @len is the
+ * position of the last byte inside the page.
+ */
+ if (cnt) {
+ u8 *byte;
+
+ BUG_ON(cnt > 7);
+
+ bit = cnt;
+ byte = kaddr + len;
+ while (bit--) {
+ if (value)
+ *byte |= 1 << bit;
+ else
+ *byte &= ~(1 << bit);
+ }
+ }
+done:
+ /* We are done. Unmap the page and return success. */
+ flush_dcache_page(page);
+ set_page_dirty(page);
+ ntfs_unmap_page(page);
+ ntfs_debug("Done.");
+ return 0;
+rollback:
+ /*
+ * Current state:
+ * - no pages are mapped
+ * - @count - @cnt is the number of bits that have been modified
+ */
+ if (is_rollback)
+ return PTR_ERR(page);
+ pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
+ value ? 0 : 1, TRUE);
+ if (!pos) {
+ /* Rollback was successful. */
+ ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+ "%li), aborting.", PTR_ERR(page));
+ } else {
+ /* Rollback failed. */
+ ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
+ "%li) and rollback failed (error %i). "
+ "Aborting and leaving inconsistent metadata. "
+ "Unmount and run chkdsk.", PTR_ERR(page), pos);
+ NVolSetErrors(NTFS_SB(vi->i_sb));
+ }
+ return PTR_ERR(page);
+}
diff -Nru a/fs/ntfs/bitmap.h b/fs/ntfs/bitmap.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/bitmap.h 2004-08-18 20:50:00 +01:00
@@ -0,0 +1,114 @@
+/*
+ * bitmap.h - Defines for NTFS kernel bitmap handling. Part of the Linux-NTFS
+ * project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_NTFS_BITMAP_H
+#define _LINUX_NTFS_BITMAP_H
+
+#include <linux/fs.h>
+
+#include "types.h"
+
+extern int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
+ const s64 count, const u8 value, const BOOL is_rollback);
+
+/**
+ * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
+ * @vi: vfs inode describing the bitmap
+ * @start_bit: first bit to set
+ * @count: number of bits to set
+ * @value: value to set the bits to (i.e. 0 or 1)
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi to @value, where @value is either 0 or 1.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bits_in_run(struct inode *vi,
+ const s64 start_bit, const s64 count, const u8 value)
+{
+ return __ntfs_bitmap_set_bits_in_run(vi, start_bit, count, value,
+ FALSE);
+}
+
+/**
+ * ntfs_bitmap_set_run - set a run of bits in a bitmap
+ * @vi: vfs inode describing the bitmap
+ * @start_bit: first bit to set
+ * @count: number of bits to set
+ *
+ * Set @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_run(struct inode *vi, const s64 start_bit,
+ const s64 count)
+{
+ return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
+ * @vi: vfs inode describing the bitmap
+ * @start_bit: first bit to clear
+ * @count: number of bits to clear
+ *
+ * Clear @count bits starting at bit @start_bit in the bitmap described by the
+ * vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_run(struct inode *vi, const s64 start_bit,
+ const s64 count)
+{
+ return ntfs_bitmap_set_bits_in_run(vi, start_bit, count, 0);
+}
+
+/**
+ * ntfs_bitmap_set_bit - set a bit in a bitmap
+ * @vi: vfs inode describing the bitmap
+ * @bit: bit to set
+ *
+ * Set bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_set_bit(struct inode *vi, const s64 bit)
+{
+ return ntfs_bitmap_set_run(vi, bit, 1);
+}
+
+/**
+ * ntfs_bitmap_clear_bit - clear a bit in a bitmap
+ * @vi: vfs inode describing the bitmap
+ * @bit: bit to clear
+ *
+ * Clear bit @bit in the bitmap described by the vfs inode @vi.
+ *
+ * Return 0 on success and -errno on error.
+ */
+static inline int ntfs_bitmap_clear_bit(struct inode *vi, const s64 bit)
+{
+ return ntfs_bitmap_clear_run(vi, bit, 1);
+}
+
+#endif /* defined _LINUX_NTFS_BITMAP_H */
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 6/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:30 ` [PATCH 5/20] " Anton Altaparmakov
@ 2004-08-23 10:30 ` Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 7/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:30 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 6/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/21 1.1809)
NTFS: Wrap the new bitmap.[hc] code in #ifdef NTFS_RW / #endif.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- a/fs/ntfs/bitmap.c 2004-08-18 20:50:03 +01:00
+++ b/fs/ntfs/bitmap.c 2004-08-18 20:50:03 +01:00
@@ -19,6 +19,8 @@
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#ifdef NTFS_RW
+
#include <linux/pagemap.h>
#include "bitmap.h"
@@ -181,3 +183,5 @@
}
return PTR_ERR(page);
}
+
+#endif /* NTFS_RW */
diff -Nru a/fs/ntfs/bitmap.h b/fs/ntfs/bitmap.h
--- a/fs/ntfs/bitmap.h 2004-08-18 20:50:03 +01:00
+++ b/fs/ntfs/bitmap.h 2004-08-18 20:50:03 +01:00
@@ -23,6 +23,8 @@
#ifndef _LINUX_NTFS_BITMAP_H
#define _LINUX_NTFS_BITMAP_H
+#ifdef NTFS_RW
+
#include <linux/fs.h>
#include "types.h"
@@ -110,5 +112,7 @@
{
return ntfs_bitmap_clear_run(vi, bit, 1);
}
+
+#endif /* NTFS_RW */
#endif /* defined _LINUX_NTFS_BITMAP_H */
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 7/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:30 ` [PATCH 6/20] " Anton Altaparmakov
@ 2004-08-23 10:30 ` Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 8/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:30 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 7/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/21 1.1810)
NTFS: Rename run_list to runlist everywhere to bring in line with libntfs.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c
--- a/fs/ntfs/aops.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/aops.c 2004-08-18 20:50:07 +01:00
@@ -170,7 +170,7 @@
LCN lcn;
ntfs_inode *ni;
ntfs_volume *vol;
- run_list_element *rl;
+ runlist_element *rl;
struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
sector_t iblock, lblock, zblock;
unsigned int blocksize, vcn_ofs;
@@ -196,7 +196,7 @@
zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits;
#ifdef DEBUG
- if (unlikely(!ni->run_list.rl && !ni->mft_no && !NInoAttr(ni)))
+ if (unlikely(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)))
panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
"very serious bug! Cannot continue...");
#endif
@@ -225,8 +225,8 @@
vol->cluster_size_mask;
if (!rl) {
lock_retry_remap:
- down_read(&ni->run_list.lock);
- rl = ni->run_list.rl;
+ down_read(&ni->runlist.lock);
+ rl = ni->runlist.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
@@ -259,8 +259,8 @@
* Attempt to map run list, dropping lock for
* the duration.
*/
- up_read(&ni->run_list.lock);
- if (!map_run_list(ni, vcn))
+ up_read(&ni->runlist.lock);
+ if (!map_runlist(ni, vcn))
goto lock_retry_remap;
rl = NULL;
}
@@ -291,7 +291,7 @@
/* Release the lock if we took it. */
if (rl)
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
/* Check we have at least one buffer ready for i/o. */
if (nr) {
@@ -473,7 +473,7 @@
struct inode *vi;
ntfs_inode *ni;
ntfs_volume *vol;
- run_list_element *rl;
+ runlist_element *rl;
struct buffer_head *bh, *head;
unsigned int blocksize, vcn_ofs;
int err;
@@ -631,8 +631,8 @@
vol->cluster_size_mask;
if (!rl) {
lock_retry_remap:
- down_read(&ni->run_list.lock);
- rl = ni->run_list.rl;
+ down_read(&ni->runlist.lock);
+ rl = ni->runlist.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
@@ -666,8 +666,8 @@
* Attempt to map run list, dropping lock for
* the duration.
*/
- up_read(&ni->run_list.lock);
- err = map_run_list(ni, vcn);
+ up_read(&ni->runlist.lock);
+ err = map_runlist(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
@@ -687,7 +687,7 @@
/* Release the lock if we took it. */
if (rl)
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
/* For the error case, need to reset bh to the beginning. */
bh = head;
@@ -1240,7 +1240,7 @@
struct inode *vi;
ntfs_inode *ni;
ntfs_volume *vol;
- run_list_element *rl;
+ runlist_element *rl;
struct buffer_head *bh, *head, *wait[2], **wait_bh = wait;
unsigned int vcn_ofs, block_start, block_end, blocksize;
int err;
@@ -1397,8 +1397,8 @@
is_retry = FALSE;
if (!rl) {
lock_retry_remap:
- down_read(&ni->run_list.lock);
- rl = ni->run_list.rl;
+ down_read(&ni->runlist.lock);
+ rl = ni->runlist.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
@@ -1442,8 +1442,8 @@
* Attempt to map run list, dropping
* lock for the duration.
*/
- up_read(&ni->run_list.lock);
- err = map_run_list(ni, vcn);
+ up_read(&ni->runlist.lock);
+ err = map_runlist(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
@@ -1530,7 +1530,7 @@
/* Release the lock if we took it. */
if (rl) {
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
rl = NULL;
}
@@ -1576,7 +1576,7 @@
if (is_retry)
flush_dcache_page(page);
if (rl)
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
return err;
}
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:07 +01:00
@@ -27,11 +27,11 @@
/* Temporary helper functions -- might become macros */
/**
- * ntfs_rl_mm - run_list memmove
+ * ntfs_rl_mm - runlist memmove
*
* It is up to the caller to serialize access to the run list @base.
*/
-static inline void ntfs_rl_mm(run_list_element *base, int dst, int src,
+static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
int size)
{
if (likely((dst != src) && (size > 0)))
@@ -39,25 +39,25 @@
}
/**
- * ntfs_rl_mc - run_list memory copy
+ * ntfs_rl_mc - runlist memory copy
*
* It is up to the caller to serialize access to the run lists @dstbase and
* @srcbase.
*/
-static inline void ntfs_rl_mc(run_list_element *dstbase, int dst,
- run_list_element *srcbase, int src, int size)
+static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
+ runlist_element *srcbase, int src, int size)
{
if (likely(size > 0))
memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
}
/**
- * ntfs_rl_realloc - Reallocate memory for run_lists
+ * ntfs_rl_realloc - Reallocate memory for runlists
* @rl: original run list
* @old_size: number of run list elements in the original run list @rl
* @new_size: number of run list elements we need space for
*
- * As the run_lists grow, more memory will be required. To prevent the
+ * As the runlists grow, more memory will be required. To prevent the
* kernel having to allocate and reallocate large numbers of small bits of
* memory, this function returns and entire page of memory.
*
@@ -71,10 +71,10 @@
* -ENOMEM - Not enough memory to allocate run list array.
* -EINVAL - Invalid parameters were passed in.
*/
-static inline run_list_element *ntfs_rl_realloc(run_list_element *rl,
+static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
int old_size, int new_size)
{
- run_list_element *new_rl;
+ runlist_element *new_rl;
old_size = PAGE_ALIGN(old_size * sizeof(*rl));
new_size = PAGE_ALIGN(new_size * sizeof(*rl));
@@ -107,8 +107,8 @@
* Return: TRUE Success, the run lists can be merged.
* FALSE Failure, the run lists cannot be merged.
*/
-static inline BOOL ntfs_are_rl_mergeable(run_list_element *dst,
- run_list_element *src)
+static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
+ runlist_element *src)
{
BUG_ON(!dst);
BUG_ON(!src);
@@ -134,7 +134,7 @@
*
* It is up to the caller to serialize access to the run lists @dst and @src.
*/
-static inline void __ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
{
dst->length += src->length;
}
@@ -154,7 +154,7 @@
* FALSE Failure, the run lists cannot be merged and have not been
* modified.
*/
-static inline BOOL ntfs_rl_merge(run_list_element *dst, run_list_element *src)
+static inline BOOL ntfs_rl_merge(runlist_element *dst, runlist_element *src)
{
BOOL merge = ntfs_are_rl_mergeable(dst, src);
@@ -187,8 +187,8 @@
* -ENOMEM - Not enough memory to allocate run list array.
* -EINVAL - Invalid parameters were passed in.
*/
-static inline run_list_element *ntfs_rl_append(run_list_element *dst,
- int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_append(runlist_element *dst,
+ int dsize, runlist_element *src, int ssize, int loc)
{
BOOL right;
int magic;
@@ -252,8 +252,8 @@
* -ENOMEM - Not enough memory to allocate run list array.
* -EINVAL - Invalid parameters were passed in.
*/
-static inline run_list_element *ntfs_rl_insert(run_list_element *dst,
- int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
+ int dsize, runlist_element *src, int ssize, int loc)
{
BOOL left = FALSE;
BOOL disc = FALSE; /* Discontinuity */
@@ -336,7 +336,7 @@
}
/**
- * ntfs_rl_replace - overwrite a run_list element with another run list
+ * ntfs_rl_replace - overwrite a runlist element with another run list
* @dst: original run list to be worked on
* @dsize: number of elements in @dst (including end marker)
* @src: new run list to be inserted
@@ -358,8 +358,8 @@
* -ENOMEM - Not enough memory to allocate run list array.
* -EINVAL - Invalid parameters were passed in.
*/
-static inline run_list_element *ntfs_rl_replace(run_list_element *dst,
- int dsize, run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
+ int dsize, runlist_element *src, int ssize, int loc)
{
BOOL left = FALSE;
BOOL right;
@@ -424,8 +424,8 @@
* -ENOMEM - Not enough memory to allocate run list array.
* -EINVAL - Invalid parameters were passed in.
*/
-static inline run_list_element *ntfs_rl_split(run_list_element *dst, int dsize,
- run_list_element *src, int ssize, int loc)
+static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
+ runlist_element *src, int ssize, int loc)
{
BUG_ON(!dst);
BUG_ON(!src);
@@ -452,7 +452,7 @@
}
/**
- * ntfs_merge_run_lists - merge two run_lists into one
+ * ntfs_merge_runlists - merge two runlists into one
* @drl: original run list to be worked on
* @srl: new run list to be merged into @drl
*
@@ -485,8 +485,8 @@
* -EINVAL - Invalid parameters were passed in.
* -ERANGE - The run lists overlap and cannot be merged.
*/
-run_list_element *ntfs_merge_run_lists(run_list_element *drl,
- run_list_element *srl)
+runlist_element *ntfs_merge_runlists(runlist_element *drl,
+ runlist_element *srl)
{
int di, si; /* Current index into @[ds]rl. */
int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */
@@ -532,7 +532,7 @@
si = di = 0;
- /* Skip any unmapped start element(s) in the source run_list. */
+ /* Skip any unmapped start element(s) in the source runlist. */
while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
si++;
@@ -715,18 +715,18 @@
* two into one, if that is possible (we check for overlap and discard the new
* run list if overlap present before returning ERR_PTR(-ERANGE)).
*/
-run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
- const ATTR_RECORD *attr, run_list_element *old_rl)
+runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+ const ATTR_RECORD *attr, runlist_element *old_rl)
{
VCN vcn; /* Current vcn. */
LCN lcn; /* Current lcn. */
s64 deltaxcn; /* Change in [vl]cn. */
- run_list_element *rl; /* The output run list. */
+ runlist_element *rl; /* The output run list. */
u8 *buf; /* Current position in mapping pairs array. */
u8 *attr_end; /* End of attribute. */
int rlsize; /* Size of run list buffer. */
u16 rlpos; /* Current run list position in units of
- run_list_elements. */
+ runlist_elements. */
u8 b; /* Current byte offset in buf. */
#ifdef DEBUG
@@ -768,7 +768,7 @@
* operates on whole pages only.
*/
if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
- run_list_element *rl2;
+ runlist_element *rl2;
rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
if (unlikely(!rl2)) {
@@ -780,7 +780,7 @@
rl = rl2;
rlsize += PAGE_SIZE;
}
- /* Enter the current vcn into the current run_list element. */
+ /* Enter the current vcn into the current runlist element. */
rl[rlpos].vcn = vcn;
/*
* Get the change in vcn, i.e. the run length in clusters.
@@ -854,10 +854,10 @@
"mapping pairs array.");
goto err_out;
}
- /* Enter the current lcn into the run_list element. */
+ /* Enter the current lcn into the runlist element. */
rl[rlpos].lcn = lcn;
}
- /* Get to the next run_list element. */
+ /* Get to the next runlist element. */
rlpos++;
/* Increment the buffer position to the next mapping pair. */
buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
@@ -908,7 +908,7 @@
} else /* Not the base extent. There may be more extents to follow. */
rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
- /* Setup terminating run_list element. */
+ /* Setup terminating runlist element. */
rl[rlpos].vcn = vcn;
rl[rlpos].length = (s64)0;
/* If no existing run list was specified, we are done. */
@@ -918,7 +918,7 @@
return rl;
}
/* Now combine the new and old run lists checking for overlaps. */
- old_rl = ntfs_merge_run_lists(old_rl, rl);
+ old_rl = ntfs_merge_runlists(old_rl, rl);
if (likely(!IS_ERR(old_rl)))
return old_rl;
ntfs_free(rl);
@@ -932,15 +932,15 @@
}
/**
- * map_run_list - map (a part of) a run list of an ntfs inode
+ * map_runlist - map (a part of) a run list of an ntfs inode
* @ni: ntfs inode for which to map (part of) a run list
* @vcn: map run list part containing this vcn
*
- * Map the part of a run list containing the @vcn of an the ntfs inode @ni.
+ * Map the part of a run list containing the @vcn of the ntfs inode @ni.
*
* Return 0 on success and -errno on error.
*/
-int map_run_list(ntfs_inode *ni, VCN vcn)
+int map_runlist(ntfs_inode *ni, VCN vcn)
{
ntfs_inode *base_ni;
attr_search_context *ctx;
@@ -970,19 +970,19 @@
goto err_out;
}
- down_write(&ni->run_list.lock);
+ down_write(&ni->runlist.lock);
/* Make sure someone else didn't do the work while we were sleeping. */
- if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
- run_list_element *rl;
+ if (likely(vcn_to_lcn(ni->runlist.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
+ runlist_element *rl;
rl = decompress_mapping_pairs(ni->vol, ctx->attr,
- ni->run_list.rl);
+ ni->runlist.rl);
if (unlikely(IS_ERR(rl)))
err = PTR_ERR(rl);
else
- ni->run_list.rl = rl;
+ ni->runlist.rl = rl;
}
- up_write(&ni->run_list.lock);
+ up_write(&ni->runlist.lock);
put_attr_search_ctx(ctx);
err_out:
@@ -1011,14 +1011,11 @@
* -3 = LCN_ENOENT There is no such vcn in the attribute.
* -4 = LCN_EINVAL Input parameter error (if debug enabled).
*/
-LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn)
+LCN vcn_to_lcn(const runlist_element *rl, const VCN vcn)
{
int i;
-#ifdef DEBUG
- if (vcn < (VCN)0)
- return (LCN)LCN_EINVAL;
-#endif
+ BUG_ON(vcn < 0);
/*
* If rl is NULL, assume that we have found an unmapped run list. The
* caller can then attempt to map it and fail appropriately if
@@ -1214,12 +1211,12 @@
/**
* load_attribute_list - load an attribute list into memory
* @vol: ntfs volume from which to read
- * @run_list: run list of the attribute list
+ * @runlist: run list of the attribute list
* @al_start: destination buffer
* @size: size of the destination buffer in bytes
* @initialized_size: initialized size of the attribute list
*
- * Walk the run list @run_list and load all clusters from it copying them into
+ * Walk the run list @runlist and load all clusters from it copying them into
* the linear buffer @al. The maximum number of bytes copied to @al is @size
* bytes. Note, @size does not need to be a multiple of the cluster size. If
* @initialized_size is less than @size, the region in @al between
@@ -1227,13 +1224,13 @@
*
* Return 0 on success or -errno on error.
*/
-int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
+int load_attribute_list(ntfs_volume *vol, runlist *runlist, u8 *al_start,
const s64 size, const s64 initialized_size)
{
LCN lcn;
u8 *al = al_start;
u8 *al_end = al + initialized_size;
- run_list_element *rl;
+ runlist_element *rl;
struct buffer_head *bh;
struct super_block *sb;
unsigned long block_size;
@@ -1242,7 +1239,7 @@
unsigned char block_size_bits;
ntfs_debug("Entering.");
- if (!vol || !run_list || !al || size <= 0 || initialized_size < 0 ||
+ if (!vol || !runlist || !al || size <= 0 || initialized_size < 0 ||
initialized_size > size)
return -EINVAL;
if (!initialized_size) {
@@ -1252,8 +1249,8 @@
sb = vol->sb;
block_size = sb->s_blocksize;
block_size_bits = sb->s_blocksize_bits;
- down_read(&run_list->lock);
- rl = run_list->rl;
+ down_read(&runlist->lock);
+ rl = runlist->rl;
/* Read all clusters specified by the run list one run at a time. */
while (rl->length) {
lcn = vcn_to_lcn(rl, rl->vcn);
@@ -1292,7 +1289,7 @@
memset(al_start + initialized_size, 0, size - initialized_size);
}
done:
- up_read(&run_list->lock);
+ up_read(&runlist->lock);
return err;
do_final:
if (al < al_end) {
diff -Nru a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
--- a/fs/ntfs/attrib.h 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/attrib.h 2004-08-18 20:50:07 +01:00
@@ -30,7 +30,7 @@
#include "types.h"
#include "layout.h"
-static inline void init_run_list(run_list *rl)
+static inline void init_runlist(runlist *rl)
{
rl->rl = NULL;
init_rwsem(&rl->lock);
@@ -72,12 +72,12 @@
ATTR_RECORD *base_attr;
} attr_search_context;
-extern run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
- const ATTR_RECORD *attr, run_list_element *old_rl);
+extern runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
+ const ATTR_RECORD *attr, runlist_element *old_rl);
-extern int map_run_list(ntfs_inode *ni, VCN vcn);
+extern int map_runlist(ntfs_inode *ni, VCN vcn);
-extern LCN vcn_to_lcn(const run_list_element *rl, const VCN vcn);
+extern LCN vcn_to_lcn(const runlist_element *rl, const VCN vcn);
extern BOOL find_attr(const ATTR_TYPES type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic, const u8 *val,
@@ -88,7 +88,7 @@
const VCN lowest_vcn, const u8 *val, const u32 val_len,
attr_search_context *ctx);
-extern int load_attribute_list(ntfs_volume *vol, run_list *rl, u8 *al_start,
+extern int load_attribute_list(ntfs_volume *vol, runlist *rl, u8 *al_start,
const s64 size, const s64 initialized_size);
static inline s64 attribute_value_length(const ATTR_RECORD *a)
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/compress.c 2004-08-18 20:50:07 +01:00
@@ -478,7 +478,7 @@
ntfs_inode *ni = NTFS_I(mapping->host);
ntfs_volume *vol = ni->vol;
struct super_block *sb = vol->sb;
- run_list_element *rl;
+ runlist_element *rl;
unsigned long block_size = sb->s_blocksize;
unsigned char block_size_bits = sb->s_blocksize_bits;
u8 *cb, *cb_pos, *cb_end;
@@ -593,8 +593,8 @@
if (!rl) {
lock_retry_remap:
- down_read(&ni->run_list.lock);
- rl = ni->run_list.rl;
+ down_read(&ni->runlist.lock);
+ rl = ni->runlist.rl;
}
if (likely(rl != NULL)) {
/* Seek to element containing target vcn. */
@@ -620,8 +620,8 @@
* Attempt to map run list, dropping lock for the
* duration.
*/
- up_read(&ni->run_list.lock);
- if (!map_run_list(ni, vcn))
+ up_read(&ni->runlist.lock);
+ if (!map_runlist(ni, vcn))
goto lock_retry_remap;
goto map_rl_err;
}
@@ -638,7 +638,7 @@
/* Release the lock if we took it. */
if (rl)
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
/* Setup and initiate io on all buffer heads. */
for (i = 0; i < nr_bhs; i++) {
@@ -920,18 +920,18 @@
goto err_out;
map_rl_err:
- ntfs_error(vol->sb, "map_run_list() failed. Cannot read compression "
+ ntfs_error(vol->sb, "map_runlist() failed. Cannot read compression "
"block.");
goto err_out;
rl_err:
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
ntfs_error(vol->sb, "vcn_to_lcn() failed. Cannot read compression "
"block.");
goto err_out;
getblk_err:
- up_read(&ni->run_list.lock);
+ up_read(&ni->runlist.lock);
ntfs_error(vol->sb, "getblk() failed. Cannot read compression block.");
err_out:
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/debug.c 2004-08-18 20:50:07 +01:00
@@ -133,7 +133,7 @@
}
/* Dump a run list. Caller has to provide synchronisation for @rl. */
-void ntfs_debug_dump_runlist(const run_list_element *rl)
+void ntfs_debug_dump_runlist(const runlist_element *rl)
{
int i;
const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED",
diff -Nru a/fs/ntfs/debug.h b/fs/ntfs/debug.h
--- a/fs/ntfs/debug.h 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/debug.h 2004-08-18 20:50:07 +01:00
@@ -51,7 +51,7 @@
#define ntfs_debug(f, a...) \
__ntfs_debug(__FILE__, __LINE__, __FUNCTION__, f, ##a)
-extern void ntfs_debug_dump_runlist(const run_list_element *rl);
+extern void ntfs_debug_dump_runlist(const runlist_element *rl);
#else /* !DEBUG */
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/inode.c 2004-08-18 20:50:07 +01:00
@@ -372,13 +372,13 @@
ni->seq_no = 0;
atomic_set(&ni->count, 1);
ni->vol = NTFS_SB(sb);
- init_run_list(&ni->run_list);
+ init_runlist(&ni->runlist);
init_MUTEX(&ni->mrec_lock);
ni->page = NULL;
ni->page_ofs = 0;
ni->attr_list_size = 0;
ni->attr_list = NULL;
- init_run_list(&ni->attr_list_rl);
+ init_runlist(&ni->attr_list_rl);
ni->itype.index.bmp_ino = NULL;
ni->itype.index.block_size = 0;
ni->itype.index.vcn_size = 0;
@@ -1628,7 +1628,7 @@
* We solve these problems by starting with the $DATA attribute before anything
* else and iterating using lookup_attr($DATA) over all extents. As each extent
* is found, we decompress_mapping_pairs() including the implied
- * merge_run_lists(). Each step of the iteration necessarily provides
+ * merge_runlists(). Each step of the iteration necessarily provides
* sufficient information for the next step to complete.
*
* This should work but there are two possible pit falls (see inline comments
@@ -1861,7 +1861,7 @@
attr = NULL;
next_vcn = last_vcn = highest_vcn = 0;
while (lookup_attr(AT_DATA, NULL, 0, 0, next_vcn, NULL, 0, ctx)) {
- run_list_element *nrl;
+ runlist_element *nrl;
/* Cache the current attribute. */
attr = ctx->attr;
@@ -1889,14 +1889,14 @@
* as we have exclusive access to the inode at this time and we
* are a mount in progress task, too.
*/
- nrl = decompress_mapping_pairs(vol, attr, ni->run_list.rl);
+ nrl = decompress_mapping_pairs(vol, attr, ni->runlist.rl);
if (IS_ERR(nrl)) {
ntfs_error(sb, "decompress_mapping_pairs() failed with "
"error code %ld. $MFT is corrupt.",
PTR_ERR(nrl));
goto put_err_out;
}
- ni->run_list.rl = nrl;
+ ni->runlist.rl = nrl;
/* Are we in the first extent? */
if (!next_vcn) {
@@ -1932,7 +1932,7 @@
}
vol->nr_mft_records = ll;
/*
- * We have got the first extent of the run_list for
+ * We have got the first extent of the runlist for
* $MFT which means it is now relatively safe to call
* the normal ntfs_read_inode() function.
* Complete reading the inode, this will actually
@@ -2073,12 +2073,12 @@
void __ntfs_clear_inode(ntfs_inode *ni)
{
/* Free all alocated memory. */
- down_write(&ni->run_list.lock);
- if (ni->run_list.rl) {
- ntfs_free(ni->run_list.rl);
- ni->run_list.rl = NULL;
+ down_write(&ni->runlist.lock);
+ if (ni->runlist.rl) {
+ ntfs_free(ni->runlist.rl);
+ ni->runlist.rl = NULL;
}
- up_write(&ni->run_list.lock);
+ up_write(&ni->runlist.lock);
if (ni->attr_list) {
ntfs_free(ni->attr_list);
diff -Nru a/fs/ntfs/inode.h b/fs/ntfs/inode.h
--- a/fs/ntfs/inode.h 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/inode.h 2004-08-18 20:50:07 +01:00
@@ -56,18 +56,18 @@
ATTR_TYPES type; /* Attribute type of this fake inode. */
ntfschar *name; /* Attribute name of this fake inode. */
u32 name_len; /* Attribute name length of this fake inode. */
- run_list run_list; /* If state has the NI_NonResident bit set,
+ runlist runlist; /* If state has the NI_NonResident bit set,
the run list of the unnamed data attribute
(if a file) or of the index allocation
attribute (directory) or of the attribute
described by the fake inode (if NInoAttr()).
- If run_list.rl is NULL, the run list has not
+ If runlist.rl is NULL, the run list has not
been read in yet or has been unmapped. If
NI_NonResident is clear, the attribute is
resident (file and fake inode) or there is
no $I30 index allocation attribute
(small directory). In the latter case
- run_list.rl is always NULL.*/
+ runlist.rl is always NULL.*/
/*
* The following fields are only valid for real inodes and extent
* inodes.
@@ -88,7 +88,7 @@
*/
u32 attr_list_size; /* Length of attribute list value in bytes. */
u8 *attr_list; /* Attribute list value itself. */
- run_list attr_list_rl; /* Run list for the attribute list value. */
+ runlist attr_list_rl; /* Run list for the attribute list value. */
union {
struct { /* It is a directory, $MFT, or an index inode. */
struct inode *bmp_ino; /* Attribute inode for the
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:50:07 +01:00
@@ -913,7 +913,7 @@
ntfs_inode *mirr_ni;
struct page *mft_page, *mirr_page;
u8 *kmft, *kmirr;
- run_list_element *rl, rl2[2];
+ runlist_element *rl, rl2[2];
int mrecs_per_page, i;
ntfs_debug("Entering.");
@@ -999,8 +999,8 @@
* mapped the full run list for it.
*/
mirr_ni = NTFS_I(vol->mftmirr_ino);
- down_read(&mirr_ni->run_list.lock);
- rl = mirr_ni->run_list.rl;
+ down_read(&mirr_ni->runlist.lock);
+ rl = mirr_ni->runlist.rl;
/* Compare the two run lists. They must be identical. */
i = 0;
do {
@@ -1008,11 +1008,11 @@
rl2[i].length != rl[i].length) {
ntfs_error(sb, "$MFTMirr location mismatch. "
"Run chkdsk.");
- up_read(&mirr_ni->run_list.lock);
+ up_read(&mirr_ni->runlist.lock);
return FALSE;
}
} while (rl2[i++].length);
- up_read(&mirr_ni->run_list.lock);
+ up_read(&mirr_ni->runlist.lock);
ntfs_debug("Done.");
return TRUE;
}
diff -Nru a/fs/ntfs/types.h b/fs/ntfs/types.h
--- a/fs/ntfs/types.h 2004-08-18 20:50:07 +01:00
+++ b/fs/ntfs/types.h 2004-08-18 20:50:07 +01:00
@@ -42,7 +42,7 @@
typedef s64 LSN;
/**
- * run_list_element - in memory vcn to lcn mapping array element
+ * runlist_element - in memory vcn to lcn mapping array element
* @vcn: starting vcn of the current array element
* @lcn: starting lcn of the current array element
* @length: length in clusters of the current array element
@@ -56,18 +56,18 @@
VCN vcn; /* vcn = Starting virtual cluster number. */
LCN lcn; /* lcn = Starting logical cluster number. */
s64 length; /* Run length in clusters. */
-} run_list_element;
+} runlist_element;
/**
- * run_list - in memory vcn to lcn mapping array including a read/write lock
+ * runlist - in memory vcn to lcn mapping array including a read/write lock
* @rl: pointer to an array of run list elements
* @lock: read/write spinlock for serializing access to @rl
*
*/
typedef struct {
- run_list_element *rl;
+ runlist_element *rl;
struct rw_semaphore lock;
-} run_list;
+} runlist;
typedef enum {
FALSE = 0,
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 8/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:30 ` [PATCH 7/20] " Anton Altaparmakov
@ 2004-08-23 10:30 ` Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 9/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:30 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 8/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/21 1.1811)
NTFS: Rename map_runlist() to ntfs_map_runlist().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c
--- a/fs/ntfs/aops.c 2004-08-18 20:50:10 +01:00
+++ b/fs/ntfs/aops.c 2004-08-18 20:50:10 +01:00
@@ -260,7 +260,7 @@
* the duration.
*/
up_read(&ni->runlist.lock);
- if (!map_runlist(ni, vcn))
+ if (!ntfs_map_runlist(ni, vcn))
goto lock_retry_remap;
rl = NULL;
}
@@ -667,7 +667,7 @@
* the duration.
*/
up_read(&ni->runlist.lock);
- err = map_runlist(ni, vcn);
+ err = ntfs_map_runlist(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
@@ -1443,7 +1443,7 @@
* lock for the duration.
*/
up_read(&ni->runlist.lock);
- err = map_runlist(ni, vcn);
+ err = ntfs_map_runlist(ni, vcn);
if (likely(!err))
goto lock_retry_remap;
rl = NULL;
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:10 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:10 +01:00
@@ -932,7 +932,7 @@
}
/**
- * map_runlist - map (a part of) a run list of an ntfs inode
+ * ntfs_map_runlist - map (a part of) a run list of an ntfs inode
* @ni: ntfs inode for which to map (part of) a run list
* @vcn: map run list part containing this vcn
*
@@ -940,7 +940,7 @@
*
* Return 0 on success and -errno on error.
*/
-int map_runlist(ntfs_inode *ni, VCN vcn)
+int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
{
ntfs_inode *base_ni;
attr_search_context *ctx;
diff -Nru a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
--- a/fs/ntfs/attrib.h 2004-08-18 20:50:10 +01:00
+++ b/fs/ntfs/attrib.h 2004-08-18 20:50:10 +01:00
@@ -75,7 +75,7 @@
extern runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
const ATTR_RECORD *attr, runlist_element *old_rl);
-extern int map_runlist(ntfs_inode *ni, VCN vcn);
+extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
extern LCN vcn_to_lcn(const runlist_element *rl, const VCN vcn);
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c 2004-08-18 20:50:10 +01:00
+++ b/fs/ntfs/compress.c 2004-08-18 20:50:10 +01:00
@@ -621,7 +621,7 @@
* duration.
*/
up_read(&ni->runlist.lock);
- if (!map_runlist(ni, vcn))
+ if (!ntfs_map_runlist(ni, vcn))
goto lock_retry_remap;
goto map_rl_err;
}
@@ -920,8 +920,8 @@
goto err_out;
map_rl_err:
- ntfs_error(vol->sb, "map_runlist() failed. Cannot read compression "
- "block.");
+ ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read "
+ "compression block.");
goto err_out;
rl_err:
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 9/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:30 ` [PATCH 8/20] " Anton Altaparmakov
@ 2004-08-23 10:31 ` Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 10/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:31 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 9/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/21 1.1812)
NTFS: Rename vcn_to_lcn() to ntfs_vcn_to_lcn().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c
--- a/fs/ntfs/aops.c 2004-08-18 20:50:13 +01:00
+++ b/fs/ntfs/aops.c 2004-08-18 20:50:13 +01:00
@@ -232,7 +232,7 @@
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
- lcn = vcn_to_lcn(rl, vcn);
+ lcn = ntfs_vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
/* Successful remap. */
@@ -266,15 +266,15 @@
}
/* Hard error, zero out region. */
SetPageError(page);
- ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
- "with error code 0x%llx%s.",
+ ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) "
+ "failed with error code 0x%llx%s.",
(unsigned long long)vcn,
(unsigned long long)-lcn,
is_retry ? " even after retrying" : "");
// FIXME: Depending on vol->on_errors, do something.
}
/*
- * Either iblock was outside lblock limits or vcn_to_lcn()
+ * Either iblock was outside lblock limits or ntfs_vcn_to_lcn()
* returned error. Just zero that portion of the page and set
* the buffer uptodate.
*/
@@ -638,7 +638,7 @@
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
- lcn = vcn_to_lcn(rl, vcn);
+ lcn = ntfs_vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
/* Successful remap. */
@@ -674,7 +674,7 @@
}
/* Failed to map the buffer, even after retrying. */
bh->b_blocknr = -1UL;
- ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) failed "
+ ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = 0x%llx) failed "
"with error code 0x%llx%s.",
(unsigned long long)vcn,
(unsigned long long)-lcn,
@@ -1404,7 +1404,7 @@
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
- lcn = vcn_to_lcn(rl, vcn);
+ lcn = ntfs_vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
if (unlikely(lcn < 0)) {
@@ -1453,9 +1453,9 @@
* retrying.
*/
bh->b_blocknr = -1UL;
- ntfs_error(vol->sb, "vcn_to_lcn(vcn = 0x%llx) "
- "failed with error code "
- "0x%llx%s.",
+ ntfs_error(vol->sb, "ntfs_vcn_to_lcn(vcn = "
+ "0x%llx) failed with error "
+ "code 0x%llx%s.",
(unsigned long long)vcn,
(unsigned long long)-lcn,
is_retry ? " even after "
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:13 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:13 +01:00
@@ -939,6 +939,9 @@
* Map the part of a run list containing the @vcn of the ntfs inode @ni.
*
* Return 0 on success and -errno on error.
+ *
+ * Locking: - The runlist must be unlocked on entry and is unlocked on return.
+ * - This function takes the lock for writing and modifies the runlist.
*/
int ntfs_map_runlist(ntfs_inode *ni, VCN vcn)
{
@@ -972,7 +975,7 @@
down_write(&ni->runlist.lock);
/* Make sure someone else didn't do the work while we were sleeping. */
- if (likely(vcn_to_lcn(ni->runlist.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
+ if (likely(ntfs_vcn_to_lcn(ni->runlist.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
runlist_element *rl;
rl = decompress_mapping_pairs(ni->vol, ctx->attr,
@@ -991,7 +994,7 @@
}
/**
- * vcn_to_lcn - convert a vcn into a lcn given a run list
+ * ntfs_vcn_to_lcn - convert a vcn into a lcn given a run list
* @rl: run list to use for conversion
* @vcn: vcn to convert
*
@@ -1009,9 +1012,11 @@
* -2 = LCN_RL_NOT_MAPPED This is part of the run list which has not been
* inserted into the run list yet.
* -3 = LCN_ENOENT There is no such vcn in the attribute.
- * -4 = LCN_EINVAL Input parameter error (if debug enabled).
+ *
+ * Locking: - The caller must have locked the runlist (for reading or writing).
+ * - This function does not touch the lock.
*/
-LCN vcn_to_lcn(const runlist_element *rl, const VCN vcn)
+LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
{
int i;
@@ -1253,13 +1258,13 @@
rl = runlist->rl;
/* Read all clusters specified by the run list one run at a time. */
while (rl->length) {
- lcn = vcn_to_lcn(rl, rl->vcn);
+ lcn = ntfs_vcn_to_lcn(rl, rl->vcn);
ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
(unsigned long long)rl->vcn,
(unsigned long long)lcn);
/* The attribute list cannot be sparse. */
if (lcn < 0) {
- ntfs_error(sb, "vcn_to_lcn() failed. Cannot read "
+ ntfs_error(sb, "ntfs_vcn_to_lcn() failed. Cannot read "
"attribute list.");
goto err_out;
}
diff -Nru a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
--- a/fs/ntfs/attrib.h 2004-08-18 20:50:13 +01:00
+++ b/fs/ntfs/attrib.h 2004-08-18 20:50:13 +01:00
@@ -40,7 +40,6 @@
LCN_HOLE = -1, /* Keep this as highest value or die! */
LCN_RL_NOT_MAPPED = -2,
LCN_ENOENT = -3,
- LCN_EINVAL = -4,
} LCN_SPECIAL_VALUES;
/**
@@ -77,7 +76,7 @@
extern int ntfs_map_runlist(ntfs_inode *ni, VCN vcn);
-extern LCN vcn_to_lcn(const runlist_element *rl, const VCN vcn);
+extern LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
extern BOOL find_attr(const ATTR_TYPES type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic, const u8 *val,
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c 2004-08-18 20:50:13 +01:00
+++ b/fs/ntfs/compress.c 2004-08-18 20:50:13 +01:00
@@ -600,7 +600,7 @@
/* Seek to element containing target vcn. */
while (rl->length && rl[1].vcn <= vcn)
rl++;
- lcn = vcn_to_lcn(rl, vcn);
+ lcn = ntfs_vcn_to_lcn(rl, vcn);
} else
lcn = (LCN)LCN_RL_NOT_MAPPED;
ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
@@ -926,8 +926,8 @@
rl_err:
up_read(&ni->runlist.lock);
- ntfs_error(vol->sb, "vcn_to_lcn() failed. Cannot read compression "
- "block.");
+ ntfs_error(vol->sb, "ntfs_vcn_to_lcn() failed. Cannot read "
+ "compression block.");
goto err_out;
getblk_err:
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c 2004-08-18 20:50:13 +01:00
+++ b/fs/ntfs/debug.c 2004-08-18 20:50:13 +01:00
@@ -137,8 +137,7 @@
{
int i;
const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED",
- "LCN_ENOENT ", "LCN_EINVAL ",
- "LCN_unknown " };
+ "LCN_ENOENT ", "LCN_unknown " };
if (!debug_msgs)
return;
@@ -155,7 +154,7 @@
if (lcn < (LCN)0) {
int index = -lcn - 1;
- if (index > -LCN_EINVAL - 1)
+ if (index > -LCN_ENOENT - 1)
index = 4;
printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
(rl + i)->vcn, lcn_str[index],
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 10/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:31 ` [PATCH 9/20] " Anton Altaparmakov
@ 2004-08-23 10:31 ` Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 11/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:31 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 10/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/22 1.1813)
NTFS: Complete "run list" to "runlist" renaming.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/aops.c b/fs/ntfs/aops.c
--- a/fs/ntfs/aops.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/aops.c 2004-08-18 20:50:17 +01:00
@@ -197,7 +197,7 @@
#ifdef DEBUG
if (unlikely(!ni->runlist.rl && !ni->mft_no && !NInoAttr(ni)))
- panic("NTFS: $MFT/$DATA run list has been unmapped! This is a "
+ panic("NTFS: $MFT/$DATA runlist has been unmapped! This is a "
"very serious bug! Cannot continue...");
#endif
@@ -252,11 +252,11 @@
/* It is a hole, need to zero it. */
if (lcn == LCN_HOLE)
goto handle_hole;
- /* If first try and run list unmapped, map and retry. */
+ /* If first try and runlist unmapped, map and retry. */
if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
is_retry = TRUE;
/*
- * Attempt to map run list, dropping lock for
+ * Attempt to map runlist, dropping lock for
* the duration.
*/
up_read(&ni->runlist.lock);
@@ -659,11 +659,11 @@
err = -EOPNOTSUPP;
break;
}
- /* If first try and run list unmapped, map and retry. */
+ /* If first try and runlist unmapped, map and retry. */
if (!is_retry && lcn == LCN_RL_NOT_MAPPED) {
is_retry = TRUE;
/*
- * Attempt to map run list, dropping lock for
+ * Attempt to map runlist, dropping lock for
* the duration.
*/
up_read(&ni->runlist.lock);
@@ -1439,7 +1439,7 @@
lcn == LCN_RL_NOT_MAPPED) {
is_retry = TRUE;
/*
- * Attempt to map run list, dropping
+ * Attempt to map runlist, dropping
* lock for the duration.
*/
up_read(&ni->runlist.lock);
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:17 +01:00
@@ -29,7 +29,7 @@
/**
* ntfs_rl_mm - runlist memmove
*
- * It is up to the caller to serialize access to the run list @base.
+ * It is up to the caller to serialize access to the runlist @base.
*/
static inline void ntfs_rl_mm(runlist_element *base, int dst, int src,
int size)
@@ -41,7 +41,7 @@
/**
* ntfs_rl_mc - runlist memory copy
*
- * It is up to the caller to serialize access to the run lists @dstbase and
+ * It is up to the caller to serialize access to the runlists @dstbase and
* @srcbase.
*/
static inline void ntfs_rl_mc(runlist_element *dstbase, int dst,
@@ -53,22 +53,22 @@
/**
* ntfs_rl_realloc - Reallocate memory for runlists
- * @rl: original run list
- * @old_size: number of run list elements in the original run list @rl
- * @new_size: number of run list elements we need space for
+ * @rl: original runlist
+ * @old_size: number of runlist elements in the original runlist @rl
+ * @new_size: number of runlist elements we need space for
*
* As the runlists grow, more memory will be required. To prevent the
* kernel having to allocate and reallocate large numbers of small bits of
* memory, this function returns and entire page of memory.
*
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
*
* N.B. If the new allocation doesn't require a different number of pages in
* memory, the function will return the original pointer.
*
* On success, return a pointer to the newly allocated, or recycled, memory.
* On error, return -errno. The following error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_realloc(runlist_element *rl,
@@ -95,17 +95,17 @@
}
/**
- * ntfs_are_rl_mergeable - test if two run lists can be joined together
- * @dst: original run list
- * @src: new run list to test for mergeability with @dst
+ * ntfs_are_rl_mergeable - test if two runlists can be joined together
+ * @dst: original runlist
+ * @src: new runlist to test for mergeability with @dst
*
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
* must be adjacent.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * Return: TRUE Success, the run lists can be merged.
- * FALSE Failure, the run lists cannot be merged.
+ * Return: TRUE Success, the runlists can be merged.
+ * FALSE Failure, the runlists cannot be merged.
*/
static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst,
runlist_element *src)
@@ -124,15 +124,15 @@
}
/**
- * __ntfs_rl_merge - merge two run lists without testing if they can be merged
- * @dst: original, destination run list
- * @src: new run list to merge with @dst
- *
- * Merge the two run lists, writing into the destination run list @dst. The
- * caller must make sure the run lists can be merged or this will corrupt the
- * destination run list.
+ * __ntfs_rl_merge - merge two runlists without testing if they can be merged
+ * @dst: original, destination runlist
+ * @src: new runlist to merge with @dst
+ *
+ * Merge the two runlists, writing into the destination runlist @dst. The
+ * caller must make sure the runlists can be merged or this will corrupt the
+ * destination runlist.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*/
static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src)
{
@@ -140,18 +140,18 @@
}
/**
- * ntfs_rl_merge - test if two run lists can be joined together and merge them
- * @dst: original, destination run list
- * @src: new run list to merge with @dst
+ * ntfs_rl_merge - test if two runlists can be joined together and merge them
+ * @dst: original, destination runlist
+ * @src: new runlist to merge with @dst
*
- * Test if two run lists can be joined together. For this, their VCNs and LCNs
+ * Test if two runlists can be joined together. For this, their VCNs and LCNs
* must be adjacent. If they can be merged, perform the merge, writing into
- * the destination run list @dst.
+ * the destination runlist @dst.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * Return: TRUE Success, the run lists have been merged.
- * FALSE Failure, the run lists cannot be merged and have not been
+ * Return: TRUE Success, the runlists have been merged.
+ * FALSE Failure, the runlists cannot be merged and have not been
* modified.
*/
static inline BOOL ntfs_rl_merge(runlist_element *dst, runlist_element *src)
@@ -164,27 +164,27 @@
}
/**
- * ntfs_rl_append - append a run list after a given element
- * @dst: original run list to be worked on
+ * ntfs_rl_append - append a runlist after a given element
+ * @dst: original runlist to be worked on
* @dsize: number of elements in @dst (including end marker)
- * @src: run list to be inserted into @dst
+ * @src: runlist to be inserted into @dst
* @ssize: number of elements in @src (excluding end marker)
- * @loc: append the new run list @src after this element in @dst
+ * @loc: append the new runlist @src after this element in @dst
*
- * Append the run list @src after element @loc in @dst. Merge the right end of
- * the new run list, if necessary. Adjust the size of the hole before the
- * appended run list.
+ * Append the runlist @src after element @loc in @dst. Merge the right end of
+ * the new runlist, if necessary. Adjust the size of the hole before the
+ * appended runlist.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
* may be the same as @dst but this is irrelevant.)
*
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
* error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_append(runlist_element *dst,
@@ -205,7 +205,7 @@
return dst;
/*
* We are guaranteed to succeed from here so can start modifying the
- * original run lists.
+ * original runlists.
*/
/* First, merge the right hand end, if necessary. */
@@ -229,27 +229,27 @@
}
/**
- * ntfs_rl_insert - insert a run list into another
- * @dst: original run list to be worked on
+ * ntfs_rl_insert - insert a runlist into another
+ * @dst: original runlist to be worked on
* @dsize: number of elements in @dst (including end marker)
- * @src: new run list to be inserted
+ * @src: new runlist to be inserted
* @ssize: number of elements in @src (excluding end marker)
- * @loc: insert the new run list @src before this element in @dst
+ * @loc: insert the new runlist @src before this element in @dst
*
- * Insert the run list @src before element @loc in the run list @dst. Merge the
- * left end of the new run list, if necessary. Adjust the size of the hole
- * after the inserted run list.
+ * Insert the runlist @src before element @loc in the runlist @dst. Merge the
+ * left end of the new runlist, if necessary. Adjust the size of the hole
+ * after the inserted runlist.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
* may be the same as @dst but this is irrelevant.)
*
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
* error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_insert(runlist_element *dst,
@@ -290,7 +290,7 @@
return dst;
/*
* We are guaranteed to succeed from here so can start modifying the
- * original run list.
+ * original runlist.
*/
if (left)
@@ -336,26 +336,26 @@
}
/**
- * ntfs_rl_replace - overwrite a runlist element with another run list
- * @dst: original run list to be worked on
+ * ntfs_rl_replace - overwrite a runlist element with another runlist
+ * @dst: original runlist to be worked on
* @dsize: number of elements in @dst (including end marker)
- * @src: new run list to be inserted
+ * @src: new runlist to be inserted
* @ssize: number of elements in @src (excluding end marker)
- * @loc: index in run list @dst to overwrite with @src
+ * @loc: index in runlist @dst to overwrite with @src
*
- * Replace the run list element @dst at @loc with @src. Merge the left and
- * right ends of the inserted run list, if necessary.
+ * Replace the runlist element @dst at @loc with @src. Merge the left and
+ * right ends of the inserted runlist, if necessary.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
* may be the same as @dst but this is irrelevant.)
*
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
* error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_replace(runlist_element *dst,
@@ -380,7 +380,7 @@
return dst;
/*
* We are guaranteed to succeed from here so can start modifying the
- * original run lists.
+ * original runlists.
*/
if (right)
__ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
@@ -401,27 +401,27 @@
}
/**
- * ntfs_rl_split - insert a run list into the centre of a hole
- * @dst: original run list to be worked on
+ * ntfs_rl_split - insert a runlist into the centre of a hole
+ * @dst: original runlist to be worked on
* @dsize: number of elements in @dst (including end marker)
- * @src: new run list to be inserted
+ * @src: new runlist to be inserted
* @ssize: number of elements in @src (excluding end marker)
- * @loc: index in run list @dst at which to split and insert @src
+ * @loc: index in runlist @dst at which to split and insert @src
*
- * Split the run list @dst at @loc into two and insert @new in between the two
- * fragments. No merging of run lists is necessary. Adjust the size of the
+ * Split the runlist @dst at @loc into two and insert @new in between the two
+ * fragments. No merging of runlists is necessary. Adjust the size of the
* holes either side.
*
- * It is up to the caller to serialize access to the run lists @dst and @src.
+ * It is up to the caller to serialize access to the runlists @dst and @src.
*
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @dst and @src are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @dst and @src are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
* may be the same as @dst but this is irrelevant.)
*
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
* error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
*/
static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
@@ -436,7 +436,7 @@
return dst;
/*
* We are guaranteed to succeed from here so can start modifying the
- * original run lists.
+ * original runlists.
*/
/* Move the tail of @dst out of the way, then copy in @src. */
@@ -453,16 +453,16 @@
/**
* ntfs_merge_runlists - merge two runlists into one
- * @drl: original run list to be worked on
- * @srl: new run list to be merged into @drl
+ * @drl: original runlist to be worked on
+ * @srl: new runlist to be merged into @drl
*
- * First we sanity check the two run lists @srl and @drl to make sure that they
- * are sensible and can be merged. The run list @srl must be either after the
- * run list @drl or completely within a hole (or unmapped region) in @drl.
+ * First we sanity check the two runlists @srl and @drl to make sure that they
+ * are sensible and can be merged. The runlist @srl must be either after the
+ * runlist @drl or completely within a hole (or unmapped region) in @drl.
*
- * It is up to the caller to serialize access to the run lists @drl and @srl.
+ * It is up to the caller to serialize access to the runlists @drl and @srl.
*
- * Merging of run lists is necessary in two cases:
+ * Merging of runlists is necessary in two cases:
* 1. When attribute lists are used and a further extent is being mapped.
* 2. When new clusters are allocated to fill a hole or extend a file.
*
@@ -471,19 +471,19 @@
* - split the hole in two and be inserted between the two fragments,
* - be appended at the end of a hole, or it can
* - replace the whole hole.
- * It can also be appended to the end of the run list, which is just a variant
+ * It can also be appended to the end of the runlist, which is just a variant
* of the insert case.
*
- * On success, return a pointer to the new, combined, run list. Note, both
- * run lists @drl and @srl are deallocated before returning so you cannot use
- * the pointers for anything any more. (Strictly speaking the returned run list
+ * On success, return a pointer to the new, combined, runlist. Note, both
+ * runlists @drl and @srl are deallocated before returning so you cannot use
+ * the pointers for anything any more. (Strictly speaking the returned runlist
* may be the same as @dst but this is irrelevant.)
*
- * On error, return -errno. Both run lists are left unmodified. The following
+ * On error, return -errno. Both runlists are left unmodified. The following
* error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
+ * -ENOMEM - Not enough memory to allocate runlist array.
* -EINVAL - Invalid parameters were passed in.
- * -ERANGE - The run lists overlap and cannot be merged.
+ * -ERANGE - The runlists overlap and cannot be merged.
*/
runlist_element *ntfs_merge_runlists(runlist_element *drl,
runlist_element *srl)
@@ -513,15 +513,15 @@
/* Check for the case where the first mapping is being done now. */
if (unlikely(!drl)) {
drl = srl;
- /* Complete the source run list if necessary. */
+ /* Complete the source runlist if necessary. */
if (unlikely(drl[0].vcn)) {
- /* Scan to the end of the source run list. */
+ /* Scan to the end of the source runlist. */
for (dend = 0; likely(drl[dend].length); dend++)
;
drl = ntfs_rl_realloc(drl, dend, dend + 1);
if (IS_ERR(drl))
return drl;
- /* Insert start element at the front of the run list. */
+ /* Insert start element at the front of the runlist. */
ntfs_rl_mm(drl, 1, 0, dend);
drl[0].vcn = 0;
drl[0].lcn = LCN_RL_NOT_MAPPED;
@@ -536,7 +536,7 @@
while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
si++;
- /* Can't have an entirely unmapped source run list. */
+ /* Can't have an entirely unmapped source runlist. */
BUG_ON(!srl[si].length);
/* Record the starting points. */
@@ -560,7 +560,7 @@
return ERR_PTR(-ERANGE);
}
- /* Scan to the end of both run lists in order to know their sizes. */
+ /* Scan to the end of both runlists in order to know their sizes. */
for (send = si; srl[send].length; send++)
;
for (dend = di; drl[dend].length; dend++)
@@ -631,7 +631,7 @@
goto finished;
}
/*
- * We need to create an unmapped run list element in
+ * We need to create an unmapped runlist element in
* @drl or extend an existing one before adding the
* ENOENT terminator.
*/
@@ -640,7 +640,7 @@
slots = 1;
}
if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
- /* Add an unmapped run list element. */
+ /* Add an unmapped runlist element. */
if (!slots) {
/* FIXME/TODO: We need to have the
* extra memory already! (AIA) */
@@ -677,7 +677,7 @@
finished:
/* The merge was completed successfully. */
- ntfs_debug("Merged run list:");
+ ntfs_debug("Merged runlist:");
ntfs_debug_dump_runlist(drl);
return drl;
@@ -688,32 +688,32 @@
}
/**
- * decompress_mapping_pairs - convert mapping pairs array to run list
+ * decompress_mapping_pairs - convert mapping pairs array to runlist
* @vol: ntfs volume on which the attribute resides
* @attr: attribute record whose mapping pairs array to decompress
- * @old_rl: optional run list in which to insert @attr's run list
+ * @old_rl: optional runlist in which to insert @attr's runlist
*
- * It is up to the caller to serialize access to the run list @old_rl.
+ * It is up to the caller to serialize access to the runlist @old_rl.
*
- * Decompress the attribute @attr's mapping pairs array into a run list. On
- * success, return the decompressed run list.
+ * Decompress the attribute @attr's mapping pairs array into a runlist. On
+ * success, return the decompressed runlist.
*
- * If @old_rl is not NULL, decompressed run list is inserted into the
- * appropriate place in @old_rl and the resultant, combined run list is
+ * If @old_rl is not NULL, decompressed runlist is inserted into the
+ * appropriate place in @old_rl and the resultant, combined runlist is
* returned. The original @old_rl is deallocated.
*
* On error, return -errno. @old_rl is left unmodified in that case.
*
* The following error codes are defined:
- * -ENOMEM - Not enough memory to allocate run list array.
- * -EIO - Corrupt run list.
+ * -ENOMEM - Not enough memory to allocate runlist array.
+ * -EIO - Corrupt runlist.
* -EINVAL - Invalid parameters were passed in.
- * -ERANGE - The two run lists overlap.
+ * -ERANGE - The two runlists overlap.
*
* FIXME: For now we take the conceptionally simplest approach of creating the
- * new run list disregarding the already existing one and then splicing the
+ * new runlist disregarding the already existing one and then splicing the
* two into one, if that is possible (we check for overlap and discard the new
- * run list if overlap present before returning ERR_PTR(-ERANGE)).
+ * runlist if overlap present before returning ERR_PTR(-ERANGE)).
*/
runlist_element *decompress_mapping_pairs(const ntfs_volume *vol,
const ATTR_RECORD *attr, runlist_element *old_rl)
@@ -721,11 +721,11 @@
VCN vcn; /* Current vcn. */
LCN lcn; /* Current lcn. */
s64 deltaxcn; /* Change in [vl]cn. */
- runlist_element *rl; /* The output run list. */
+ runlist_element *rl; /* The output runlist. */
u8 *buf; /* Current position in mapping pairs array. */
u8 *attr_end; /* End of attribute. */
- int rlsize; /* Size of run list buffer. */
- u16 rlpos; /* Current run list position in units of
+ int rlsize; /* Size of runlist buffer. */
+ u16 rlpos; /* Current runlist position in units of
runlist_elements. */
u8 b; /* Current byte offset in buf. */
@@ -748,9 +748,9 @@
ntfs_error(vol->sb, "Corrupt attribute.");
return ERR_PTR(-EIO);
}
- /* Current position in run list array. */
+ /* Current position in runlist array. */
rlpos = 0;
- /* Allocate first page and set current run list size to one page. */
+ /* Allocate first page and set current runlist size to one page. */
rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE);
if (unlikely(!rl))
return ERR_PTR(-ENOMEM);
@@ -810,7 +810,7 @@
goto err_out;
}
/*
- * Enter the current run length into the current run list
+ * Enter the current run length into the current runlist
* element.
*/
rl[rlpos].length = deltaxcn;
@@ -866,7 +866,7 @@
goto io_error;
/*
* If there is a highest_vcn specified, it must be equal to the final
- * vcn in the run list - 1, or something has gone badly wrong.
+ * vcn in the runlist - 1, or something has gone badly wrong.
*/
deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn);
if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) {
@@ -875,7 +875,7 @@
"non-resident attribute.");
goto err_out;
}
- /* Setup not mapped run list element if this is the base extent. */
+ /* Setup not mapped runlist element if this is the base extent. */
if (!attr->data.non_resident.lowest_vcn) {
VCN max_cluster;
@@ -885,7 +885,7 @@
vol->cluster_size_bits;
/*
* If there is a difference between the highest_vcn and the
- * highest cluster, the run list is either corrupt or, more
+ * highest cluster, the runlist is either corrupt or, more
* likely, there are more extents following this one.
*/
if (deltaxcn < --max_cluster) {
@@ -911,18 +911,18 @@
/* Setup terminating runlist element. */
rl[rlpos].vcn = vcn;
rl[rlpos].length = (s64)0;
- /* If no existing run list was specified, we are done. */
+ /* If no existing runlist was specified, we are done. */
if (!old_rl) {
ntfs_debug("Mapping pairs array successfully decompressed:");
ntfs_debug_dump_runlist(rl);
return rl;
}
- /* Now combine the new and old run lists checking for overlaps. */
+ /* Now combine the new and old runlists checking for overlaps. */
old_rl = ntfs_merge_runlists(old_rl, rl);
if (likely(!IS_ERR(old_rl)))
return old_rl;
ntfs_free(rl);
- ntfs_error(vol->sb, "Failed to merge run lists.");
+ ntfs_error(vol->sb, "Failed to merge runlists.");
return old_rl;
io_error:
ntfs_error(vol->sb, "Corrupt attribute.");
@@ -932,11 +932,11 @@
}
/**
- * ntfs_map_runlist - map (a part of) a run list of an ntfs inode
- * @ni: ntfs inode for which to map (part of) a run list
- * @vcn: map run list part containing this vcn
+ * ntfs_map_runlist - map (a part of) a runlist of an ntfs inode
+ * @ni: ntfs inode for which to map (part of) a runlist
+ * @vcn: map runlist part containing this vcn
*
- * Map the part of a run list containing the @vcn of the ntfs inode @ni.
+ * Map the part of a runlist containing the @vcn of the ntfs inode @ni.
*
* Return 0 on success and -errno on error.
*
@@ -950,7 +950,7 @@
MFT_RECORD *mrec;
int err = 0;
- ntfs_debug("Mapping run list part containing vcn 0x%llx.",
+ ntfs_debug("Mapping runlist part containing vcn 0x%llx.",
(unsigned long long)vcn);
if (!NInoAttr(ni))
@@ -994,23 +994,23 @@
}
/**
- * ntfs_vcn_to_lcn - convert a vcn into a lcn given a run list
- * @rl: run list to use for conversion
+ * ntfs_vcn_to_lcn - convert a vcn into a lcn given a runlist
+ * @rl: runlist to use for conversion
* @vcn: vcn to convert
*
* Convert the virtual cluster number @vcn of an attribute into a logical
- * cluster number (lcn) of a device using the run list @rl to map vcns to their
+ * cluster number (lcn) of a device using the runlist @rl to map vcns to their
* corresponding lcns.
*
- * It is up to the caller to serialize access to the run list @rl.
+ * It is up to the caller to serialize access to the runlist @rl.
*
* Since lcns must be >= 0, we use negative return values with special meaning:
*
* Return value Meaning / Description
* ==================================================
* -1 = LCN_HOLE Hole / not allocated on disk.
- * -2 = LCN_RL_NOT_MAPPED This is part of the run list which has not been
- * inserted into the run list yet.
+ * -2 = LCN_RL_NOT_MAPPED This is part of the runlist which has not been
+ * inserted into the runlist yet.
* -3 = LCN_ENOENT There is no such vcn in the attribute.
*
* Locking: - The caller must have locked the runlist (for reading or writing).
@@ -1022,7 +1022,7 @@
BUG_ON(vcn < 0);
/*
- * If rl is NULL, assume that we have found an unmapped run list. The
+ * If rl is NULL, assume that we have found an unmapped runlist. The
* caller can then attempt to map it and fail appropriately if
* necessary.
*/
@@ -1216,12 +1216,12 @@
/**
* load_attribute_list - load an attribute list into memory
* @vol: ntfs volume from which to read
- * @runlist: run list of the attribute list
+ * @runlist: runlist of the attribute list
* @al_start: destination buffer
* @size: size of the destination buffer in bytes
* @initialized_size: initialized size of the attribute list
*
- * Walk the run list @runlist and load all clusters from it copying them into
+ * Walk the runlist @runlist and load all clusters from it copying them into
* the linear buffer @al. The maximum number of bytes copied to @al is @size
* bytes. Note, @size does not need to be a multiple of the cluster size. If
* @initialized_size is less than @size, the region in @al between
@@ -1256,7 +1256,7 @@
block_size_bits = sb->s_blocksize_bits;
down_read(&runlist->lock);
rl = runlist->rl;
- /* Read all clusters specified by the run list one run at a time. */
+ /* Read all clusters specified by the runlist one run at a time. */
while (rl->length) {
lcn = ntfs_vcn_to_lcn(rl, rl->vcn);
ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.",
diff -Nru a/fs/ntfs/compress.c b/fs/ntfs/compress.c
--- a/fs/ntfs/compress.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/compress.c 2004-08-18 20:50:17 +01:00
@@ -575,7 +575,7 @@
}
/*
- * We have the run list, and all the destination pages we need to fill.
+ * We have the runlist, and all the destination pages we need to fill.
* Now read the first compression block.
*/
cur_page = 0;
@@ -617,7 +617,7 @@
goto rl_err;
is_retry = TRUE;
/*
- * Attempt to map run list, dropping lock for the
+ * Attempt to map runlist, dropping lock for the
* duration.
*/
up_read(&ni->runlist.lock);
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/debug.c 2004-08-18 20:50:17 +01:00
@@ -132,7 +132,7 @@
spin_unlock(&err_buf_lock);
}
-/* Dump a run list. Caller has to provide synchronisation for @rl. */
+/* Dump a runlist. Caller has to provide synchronisation for @rl. */
void ntfs_debug_dump_runlist(const runlist_element *rl)
{
int i;
@@ -141,7 +141,7 @@
if (!debug_msgs)
return;
- printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping run list (values "
+ printk(KERN_DEBUG "NTFS-fs DEBUG: Dumping runlist (values "
"in hex):\n");
if (!rl) {
printk(KERN_DEBUG "Run list not present.\n");
@@ -159,12 +159,12 @@
printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
(rl + i)->vcn, lcn_str[index],
(rl + i)->length, (rl + i)->length ?
- "" : " (run list end)");
+ "" : " (runlist end)");
} else
printk(KERN_DEBUG "%-16Lx %-16Lx %-16Lx%s\n",
(rl + i)->vcn, (rl + i)->lcn,
(rl + i)->length, (rl + i)->length ?
- "" : " (run list end)");
+ "" : " (runlist end)");
if (!(rl + i)->length)
break;
}
diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c
--- a/fs/ntfs/inode.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/inode.c 2004-08-18 20:50:17 +01:00
@@ -680,7 +680,7 @@
goto unm_err_out;
}
/*
- * Setup the run list. No need for locking as we have
+ * Setup the runlist. No need for locking as we have
* exclusive access to the inode at this time.
*/
ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
@@ -1757,7 +1757,7 @@
"You should run chkdsk.");
goto put_err_out;
}
- /* Setup the run list. */
+ /* Setup the runlist. */
ni->attr_list_rl.rl = decompress_mapping_pairs(vol,
ctx->attr, NULL);
if (IS_ERR(ni->attr_list_rl.rl)) {
@@ -1885,7 +1885,7 @@
}
/*
* Decompress the mapping pairs array of this extent and merge
- * the result into the existing run list. No need for locking
+ * the result into the existing runlist. No need for locking
* as we have exclusive access to the inode at this time and we
* are a mount in progress task, too.
*/
@@ -2001,7 +2001,7 @@
goto put_err_out;
}
if (highest_vcn && highest_vcn != last_vcn - 1) {
- ntfs_error(sb, "Failed to load the complete run list "
+ ntfs_error(sb, "Failed to load the complete runlist "
"for $MFT/$DATA. Driver bug or "
"corrupt $MFT. Run chkdsk.");
ntfs_debug("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx",
diff -Nru a/fs/ntfs/inode.h b/fs/ntfs/inode.h
--- a/fs/ntfs/inode.h 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/inode.h 2004-08-18 20:50:17 +01:00
@@ -57,11 +57,11 @@
ntfschar *name; /* Attribute name of this fake inode. */
u32 name_len; /* Attribute name length of this fake inode. */
runlist runlist; /* If state has the NI_NonResident bit set,
- the run list of the unnamed data attribute
+ the runlist of the unnamed data attribute
(if a file) or of the index allocation
attribute (directory) or of the attribute
described by the fake inode (if NInoAttr()).
- If runlist.rl is NULL, the run list has not
+ If runlist.rl is NULL, the runlist has not
been read in yet or has been unmapped. If
NI_NonResident is clear, the attribute is
resident (file and fake inode) or there is
diff -Nru a/fs/ntfs/layout.h b/fs/ntfs/layout.h
--- a/fs/ntfs/layout.h 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/layout.h 2004-08-18 20:50:17 +01:00
@@ -545,7 +545,7 @@
* can be stored:
*
* 1) The data in the block is all zero (a sparse block):
- * This is stored as a sparse block in the run list, i.e. the run list
+ * This is stored as a sparse block in the runlist, i.e. the runlist
* entry has length = X and lcn = -1. The mapping pairs array actually
* uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
* all, which is then interpreted by the driver as lcn = -1.
@@ -558,7 +558,7 @@
* in clusters. I.e. if compression has a small effect so that the
* compressed data still occupies X clusters, then the uncompressed data
* is stored in the block.
- * This case is recognised by the fact that the run list entry has
+ * This case is recognised by the fact that the runlist entry has
* length = X and lcn >= 0. The mapping pairs array stores this as
* normal with a run length of X and some specific delta_lcn, i.e.
* delta_lcn has to be present.
@@ -567,7 +567,7 @@
* The common case. This case is recognised by the fact that the run
* list entry has length L < X and lcn >= 0. The mapping pairs array
* stores this as normal with a run length of X and some specific
- * delta_lcn, i.e. delta_lcn has to be present. This run list entry is
+ * delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
* immediately followed by a sparse entry with length = X - L and
* lcn = -1. The latter entry is to make up the vcn counting to the
* full compression block size X.
@@ -575,15 +575,15 @@
* In fact, life is more complicated because adjacent entries of the same type
* can be coalesced. This means that one has to keep track of the number of
* clusters handled and work on a basis of X clusters at a time being one
- * block. An example: if length L > X this means that this particular run list
+ * block. An example: if length L > X this means that this particular runlist
* entry contains a block of length X and part of one or more blocks of length
* L - X. Another example: if length L < X, this does not necessarily mean that
* the block is compressed as it might be that the lcn changes inside the block
- * and hence the following run list entry describes the continuation of the
+ * and hence the following runlist entry describes the continuation of the
* potentially compressed block. The block would be compressed if the
- * following run list entry describes at least X - L sparse clusters, thus
+ * following runlist entry describes at least X - L sparse clusters, thus
* making up the compression block length as described in point 3 above. (Of
- * course, there can be several run list entries with small lengths so that the
+ * course, there can be several runlist entries with small lengths so that the
* sparse entry does not follow the first data containing entry with
* length < X.)
*
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:50:17 +01:00
@@ -986,7 +986,7 @@
ntfs_unmap_page(mft_page);
ntfs_unmap_page(mirr_page);
- /* Construct the mft mirror run list by hand. */
+ /* Construct the mft mirror runlist by hand. */
rl2[0].vcn = 0;
rl2[0].lcn = vol->mftmirr_lcn;
rl2[0].length = (vol->mftmirr_size * vol->mft_record_size +
@@ -996,12 +996,12 @@
rl2[1].length = 0;
/*
* Because we have just read all of the mft mirror, we know we have
- * mapped the full run list for it.
+ * mapped the full runlist for it.
*/
mirr_ni = NTFS_I(vol->mftmirr_ino);
down_read(&mirr_ni->runlist.lock);
rl = mirr_ni->runlist.rl;
- /* Compare the two run lists. They must be identical. */
+ /* Compare the two runlists. They must be identical. */
i = 0;
do {
if (rl2[i].vcn != rl[i].vcn || rl2[i].lcn != rl[i].lcn ||
diff -Nru a/fs/ntfs/types.h b/fs/ntfs/types.h
--- a/fs/ntfs/types.h 2004-08-18 20:50:17 +01:00
+++ b/fs/ntfs/types.h 2004-08-18 20:50:17 +01:00
@@ -60,7 +60,7 @@
/**
* runlist - in memory vcn to lcn mapping array including a read/write lock
- * @rl: pointer to an array of run list elements
+ * @rl: pointer to an array of runlist elements
* @lock: read/write spinlock for serializing access to @rl
*
*/
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 11/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:31 ` [PATCH 10/20] " Anton Altaparmakov
@ 2004-08-23 10:31 ` Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 12/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:31 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 11/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/22 1.1814)
NTFS: Move a NULL check to before the first use of the pointer.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- a/fs/ntfs/bitmap.c 2004-08-18 20:50:20 +01:00
+++ b/fs/ntfs/bitmap.c 2004-08-18 20:50:20 +01:00
@@ -54,10 +54,10 @@
int pos, len;
u8 bit;
+ BUG_ON(!vi);
ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
"value %u.", vi->i_ino, (unsigned long long)start_bit,
(unsigned long long)cnt, (unsigned int)value);
- BUG_ON(!vi);
BUG_ON(start_bit < 0);
BUG_ON(cnt < 0);
BUG_ON(value > 1);
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 12/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:31 ` [PATCH 11/20] " Anton Altaparmakov
@ 2004-08-23 10:31 ` Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 13/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:31 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 12/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/22 1.1815)
NTFS: Add fs/ntfs/attrib.[hc]::ntfs_find_vcn().
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:50:24 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:50:24 +01:00
@@ -25,6 +25,9 @@
- Implement bitmap modification code (fs/ntfs/bitmap.[hc]). This
includes functions to set/clear a single bit or a run of bits.
+ - Add fs/ntfs/attrib.[hc]::ntfs_find_vcn() which returns the locked
+ runlist element containing a particular vcn. It also takes care of
+ mapping any needed runlist fragments.
2.1.16 - Implement access time updates, file sync, async io, and read/writev.
@@ -448,7 +451,7 @@
cannot set any write related options when the driver is compiled
read-only.
- Optimize block resolution in fs/ntfs/aops.c::ntfs_read_block() to
- cache the current run list element. This should improve performance
+ cache the current runlist element. This should improve performance
when reading very large and/or very fragmented data.
2.0.16 - Convert access to $MFT/$BITMAP to attribute inode API.
@@ -496,9 +499,9 @@
- Change fs/ntfs/super.c::ntfs_statfs() to not rely on BKL by moving
the locking out of super.c::get_nr_free_mft_records() and taking and
dropping the mftbmp_lock rw_semaphore in ntfs_statfs() itself.
- - Bring attribute run list merging code (fs/ntfs/attrib.c) in sync with
+ - Bring attribute runlist merging code (fs/ntfs/attrib.c) in sync with
current userspace ntfs library code. This means that if a merge
- fails the original run lists are always left unmodified instead of
+ fails the original runlists are always left unmodified instead of
being silently corrupted.
- Misc typo fixes.
@@ -690,7 +693,7 @@
appropriately.
- Update to 2.5.9 kernel (preserving backwards compatibility) by
replacing all occurences of page->buffers with page_buffers(page).
- - Fix minor bugs in run list merging, also minor cleanup.
+ - Fix minor bugs in runlist merging, also minor cleanup.
- Updates to bootsector layout and mft mirror contents descriptions.
- Small bug fix in error detection in unistr.c and some cleanups.
- Grow name buffer allocations in unistr.c in aligned mutlipled of 64
@@ -713,12 +716,12 @@
initialized_size vs data_size (i.e. i_size). Done are
mft.c::ntfs_mft_readpage(), aops.c::end_buffer_read_index_async(),
and attrib.c::load_attribute_list().
- - Lock the run list in attrib.c::load_attribute_list() while using it.
+ - Lock the runlist in attrib.c::load_attribute_list() while using it.
- Fix memory leak in ntfs_file_read_compressed_block() and generally
clean up compress.c a little, removing some uncommented/unused debug
code.
- Tidy up dir.c a little bit.
- - Don't bother getting the run list in inode.c::ntfs_read_inode().
+ - Don't bother getting the runlist in inode.c::ntfs_read_inode().
- Merge mft.c::ntfs_mft_readpage() and aops.c::ntfs_index_readpage()
creating aops.c::ntfs_mst_readpage(), improving the handling of
holes and overflow in the process and implementing the correct
@@ -748,7 +751,7 @@
- Apply kludge in ntfs_read_inode(), setting i_nlink to 1 for
directories. Without this the "find" utility gets very upset which is
fair enough as Linux/Unix do not support directory hard links.
- - Further run list merging work. (Richard Russon)
+ - Further runlist merging work. (Richard Russon)
- Backwards compatibility for gcc-2.95. (Richard Russon)
- Update to kernel 2.5.5-pre1 and rediff the now tiny patch.
- Convert to new file system declaration using ->ntfs_get_sb() and
@@ -803,7 +806,7 @@
which is then referenced but not copied.
- Rename run_list structure to run_list_element and create a new
run_list structure containing a pointer to a run_list_element
- structure and a read/write semaphore. Adapt all users of run lists
+ structure and a read/write semaphore. Adapt all users of runlists
to new scheme and take and release the lock as needed. This fixes a
nasty race as the run_list changes even when inodes are locked for
reading and even when the inode isn't locked at all, so we really
@@ -834,7 +837,7 @@
- Cleanup mft.c and it's debug/error output in particular. Fix a minor
bug in mapping of extent inodes. Update all the comments to fit all
the recent code changes.
- - Modify vcn_to_lcn() to cope with entirely unmapped run lists.
+ - Modify vcn_to_lcn() to cope with entirely unmapped runlists.
- Cleanups in compress.c, mostly comments and folding help.
- Implement attrib.c::map_run_list() as a generic helper.
- Make compress.c::ntfs_file_read_compressed_block() use map_run_list()
@@ -860,11 +863,11 @@
pass in the upcase table and its length. These can be gotten from
ctx->ntfs_ino->vol->upcase{_len}. Update all callers.
- Cleanups in attrib.c.
- - Implement merging of run lists, attrib.c::merge_run_lists() and its
+ - Implement merging of runlists, attrib.c::merge_run_lists() and its
helpers. (Richard Russon)
- - Attribute lists part 2, attribute extents and multi part run lists:
+ - Attribute lists part 2, attribute extents and multi part runlists:
enable proper support for LCN_RL_NOT_MAPPED and automatic mapping of
- further run list parts via attrib.c::map_run_list().
+ further runlist parts via attrib.c::map_run_list().
- Tiny endianness bug fix in decompress_mapping_pairs().
tng-0.0.6 - Encrypted directories, bug fixes, cleanups, debugging enhancements.
@@ -896,7 +899,7 @@
support dollar signs in the names of variables/constants. Attribute
types now start with AT_ instead of $ and $I30 is now just I30.
- Cleanup ntfs_lookup() and add consistency check of sequence numbers.
- - Load complete run list for $MFT/$BITMAP during mount and cleanup
+ - Load complete runlist for $MFT/$BITMAP during mount and cleanup
access functions. This means we now cope with $MFT/$BITMAP being
spread accross several mft records.
- Disable modification of mft_zone_multiplier on remount. We can always
@@ -929,11 +932,11 @@
parameter list. Pass either READ or WRITE to this, each has the
obvious meaning.
- General cleanups to allow for easier folding in vi.
- - attrib.c::decompress_mapping_pairs() now accepts the old run list
+ - attrib.c::decompress_mapping_pairs() now accepts the old runlist
argument, and invokes attrib.c::merge_run_lists() to merge the old
- and the new run lists.
+ and the new runlists.
- Removed attrib.c::find_first_attr().
- - Implemented loading of attribute list and complete run list for $MFT.
+ - Implemented loading of attribute list and complete runlist for $MFT.
This means we now cope with $MFT being spread across several mft
records.
- Adapt to 2.5.2-pre9 and the changed create_empty_buffers() syntax.
@@ -971,7 +974,7 @@
tng-0.0.3 - Cleanups, enhancements, bug fixes.
- Work on attrib.c::decompress_mapping_pairs() to detect base extents
- and setup the run list appropriately using knowledge provided by the
+ and setup the runlist appropriately using knowledge provided by the
sizes in the base attribute record.
- Balance the get_/put_attr_search_ctx() calls so we don't leak memory
any more.
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:24 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:24 +01:00
@@ -1051,6 +1051,107 @@
}
/**
+ * ntfs_find_vcn - find a vcn in the runlist described by an ntfs inode
+ * @ni: ntfs inode describing the runlist to search
+ * @vcn: vcn to find
+ * @need_write: if false, lock for reading and if true, lock for writing
+ *
+ * Find the virtual cluster number @vcn in the runlist described by the ntfs
+ * inode @ni and return the address of the runlist element containing the @vcn.
+ * The runlist is left locked and the caller has to unlock it. If @need_write
+ * is true, the runlist is locked for writing and if @need_write is false, the
+ * runlist is locked for reading. In the error case, the runlist is not left
+ * locked.
+ *
+ * Note you need to distinguish between the lcn of the returned runlist element
+ * being >= 0 and LCN_HOLE. In the later case you have to return zeroes on
+ * read and allocate clusters on write.
+ *
+ * Return the runlist element containing the @vcn on success and
+ * ERR_PTR(-errno) on error. You need to test the return value with IS_ERR()
+ * to decide if the return is success or failure and PTR_ERR() to get to the
+ * error code if IS_ERR() is true.
+ *
+ * The possible error return codes are:
+ * -ENOENT - No such vcn in the runlist, i.e. @vcn is out of bounds.
+ * -ENOMEM - Not enough memory to map runlist.
+ * -EIO - Critical error (runlist/file is corrupt, i/o error, etc).
+ *
+ * Locking: - The runlist must be unlocked on entry.
+ * - On failing return, the runlist is unlocked.
+ * - On successful return, the runlist is locked. If @need_write us
+ * true, it is locked for writing. Otherwise is is locked for
+ * reading.
+ */
+runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+ const BOOL need_write)
+{
+ runlist_element *rl;
+ int err = 0;
+ BOOL is_retry = FALSE;
+
+ ntfs_debug("Entering for i_ino 0x%lx, vcn 0x%llx, lock for %sing.",
+ ni->mft_no, (unsigned long long)vcn,
+ !need_write ? "read" : "writ");
+ BUG_ON(!ni);
+ BUG_ON(!NInoNonResident(ni));
+ BUG_ON(vcn < 0);
+lock_retry_remap:
+ if (!need_write)
+ down_read(&ni->runlist.lock);
+ else
+ down_write(&ni->runlist.lock);
+ rl = ni->runlist.rl;
+ if (likely(rl && vcn >= rl[0].vcn)) {
+ while (likely(rl->length)) {
+ if (likely(vcn < rl[1].vcn)) {
+ if (likely(rl->lcn >= (LCN)LCN_HOLE)) {
+ ntfs_debug("Done.");
+ return rl;
+ }
+ break;
+ }
+ rl++;
+ }
+ switch (rl->lcn) {
+ case (LCN)LCN_RL_NOT_MAPPED:
+ break;
+ case (LCN)LCN_ENOENT:
+ err = -ENOENT;
+ break;
+ default:
+ err = -EIO;
+ break;
+ }
+ }
+ if (!need_write)
+ up_read(&ni->runlist.lock);
+ else
+ up_write(&ni->runlist.lock);
+ if (!err && !is_retry) {
+ /*
+ * The @vcn is in an unmapped region, map the runlist and
+ * retry.
+ */
+ err = ntfs_map_runlist(ni, vcn);
+ if (likely(!err)) {
+ is_retry = TRUE;
+ goto lock_retry_remap;
+ }
+ /*
+ * -EINVAL and -ENOENT coming from a failed mapping attempt are
+ * equivalent to i/o errors for us as they should not happen in
+ * our code paths.
+ */
+ if (err == -EINVAL || err == -ENOENT)
+ err = -EIO;
+ } else if (!err)
+ err = -EIO;
+ ntfs_error(ni->vol->sb, "Failed with error code %i.", err);
+ return ERR_PTR(err);
+}
+
+/**
* find_attr - find (next) attribute in mft record
* @type: attribute type to find
* @name: attribute name to find (optional, i.e. NULL means don't care)
diff -Nru a/fs/ntfs/attrib.h b/fs/ntfs/attrib.h
--- a/fs/ntfs/attrib.h 2004-08-18 20:50:24 +01:00
+++ b/fs/ntfs/attrib.h 2004-08-18 20:50:24 +01:00
@@ -78,6 +78,9 @@
extern LCN ntfs_vcn_to_lcn(const runlist_element *rl, const VCN vcn);
+extern runlist_element *ntfs_find_vcn(ntfs_inode *ni, const VCN vcn,
+ const BOOL need_write);
+
extern BOOL find_attr(const ATTR_TYPES type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic, const u8 *val,
const u32 val_len, attr_search_context *ctx);
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 13/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:31 ` [PATCH 12/20] " Anton Altaparmakov
@ 2004-08-23 10:32 ` Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 14/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:32 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 13/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/07/30 1.1816)
NTFS: Fix compilation with gcc-2.95 in attrib.c::ntfs_find_vcn(). (Adrian Bunk)
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
--- a/fs/ntfs/attrib.c 2004-08-18 20:50:27 +01:00
+++ b/fs/ntfs/attrib.c 2004-08-18 20:50:27 +01:00
@@ -1113,15 +1113,11 @@
}
rl++;
}
- switch (rl->lcn) {
- case (LCN)LCN_RL_NOT_MAPPED:
- break;
- case (LCN)LCN_ENOENT:
- err = -ENOENT;
- break;
- default:
- err = -EIO;
- break;
+ if (likely(rl->lcn != (LCN)LCN_RL_NOT_MAPPED)) {
+ if (likely(rl->lcn == (LCN)LCN_ENOENT))
+ err = -ENOENT;
+ else
+ err = -EIO;
}
}
if (!need_write)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 14/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:32 ` [PATCH 13/20] " Anton Altaparmakov
@ 2004-08-23 10:32 ` Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 15/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:32 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 14/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/16 1.1820)
NTFS: Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:50:30 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:50:30 +01:00
@@ -28,6 +28,7 @@
- Add fs/ntfs/attrib.[hc]::ntfs_find_vcn() which returns the locked
runlist element containing a particular vcn. It also takes care of
mapping any needed runlist fragments.
+ - Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
2.1.16 - Implement access time updates, file sync, async io, and read/writev.
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile 2004-08-18 20:50:30 +01:00
+++ b/fs/ntfs/Makefile 2004-08-18 20:50:30 +01:00
@@ -15,5 +15,5 @@
ifeq ($(CONFIG_NTFS_RW),y)
EXTRA_CFLAGS += -DNTFS_RW
-ntfs-objs += bitmap.o logfile.o quota.o
+ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o
endif
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- a/fs/ntfs/bitmap.c 2004-08-18 20:50:30 +01:00
+++ b/fs/ntfs/bitmap.c 2004-08-18 20:50:30 +01:00
@@ -56,8 +56,9 @@
BUG_ON(!vi);
ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, "
- "value %u.", vi->i_ino, (unsigned long long)start_bit,
- (unsigned long long)cnt, (unsigned int)value);
+ "value %u.%s", vi->i_ino, (unsigned long long)start_bit,
+ (unsigned long long)cnt, (unsigned int)value,
+ is_rollback ? " (rollback)" : "");
BUG_ON(start_bit < 0);
BUG_ON(cnt < 0);
BUG_ON(value > 1);
diff -Nru a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/lcnalloc.c 2004-08-18 20:50:30 +01:00
@@ -0,0 +1,1015 @@
+/*
+ * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef NTFS_RW
+
+#include <linux/pagemap.h>
+
+#include "lcnalloc.h"
+#include "debug.h"
+#include "bitmap.h"
+#include "inode.h"
+#include "volume.h"
+#include "attrib.h"
+#include "malloc.h"
+#include "ntfs.h"
+
+/**
+ * ntfs_cluster_free_from_rl_nolock - free clusters from runlist
+ * @vol: mounted ntfs volume on which to free the clusters
+ * @rl: runlist describing the clusters to free
+ *
+ * Free all the clusters described by the runlist @rl on the volume @vol. In
+ * the case of an error being returned, at least some of the clusters were not
+ * freed.
+ *
+ * Return 0 on success and -errno on error.
+ *
+ * Locking: - The volume lcn bitmap must be locked for writing on entry and is
+ * left locked on return.
+ */
+static int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol,
+ const runlist_element *rl)
+{
+ struct inode *lcnbmp_vi = vol->lcnbmp_ino;
+ int ret = 0;
+
+ ntfs_debug("Entering.");
+ for (; rl->length; rl++) {
+ int err;
+
+ if (rl->lcn < 0)
+ continue;
+ err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length);
+ if (unlikely(err && (!ret || ret == ENOMEM) && ret != err))
+ ret = err;
+ }
+ ntfs_debug("Done.");
+ return ret;
+}
+
+/**
+ * ntfs_cluster_alloc - allocate clusters on an ntfs volume
+ * @vol: mounted ntfs volume on which to allocate the clusters
+ * @start_vcn: vcn to use for the first allocated cluster
+ * @count: number of clusters to allocate
+ * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none)
+ * @zone: zone from which to allocate the clusters
+ *
+ * Allocate @count clusters preferably starting at cluster @start_lcn or at the
+ * current allocator position if @start_lcn is -1, on the mounted ntfs volume
+ * @vol. @zone is either DATA_ZONE for allocation of normal clusters or
+ * MFT_ZONE for allocation of clusters for the master file table, i.e. the
+ * $MFT/$DATA attribute.
+ *
+ * @start_vcn specifies the vcn of the first allocated cluster. This makes
+ * merging the resulting runlist with the old runlist easier.
+ *
+ * You need to check the return value with IS_ERR(). If this is false, the
+ * function was successful and the return value is a runlist describing the
+ * allocated cluster(s). If IS_ERR() is true, the function failed and
+ * PTR_ERR() gives you the error code.
+ *
+ * Notes on the allocation algorithm
+ * =================================
+ *
+ * There are two data zones. First is the area between the end of the mft zone
+ * and the end of the volume, and second is the area between the start of the
+ * volume and the start of the mft zone. On unmodified/standard NTFS 1.x
+ * volumes, the second data zone does not exist due to the mft zone being
+ * expanded to cover the start of the volume in order to reserve space for the
+ * mft bitmap attribute.
+ *
+ * This is not the prettiest function but the complexity stems from the need of
+ * implementing the mft vs data zoned approach and from the fact that we have
+ * access to the lcn bitmap in portions of up to 8192 bytes at a time, so we
+ * need to cope with crossing over boundaries of two buffers. Further, the
+ * fact that the allocator allows for caller supplied hints as to the location
+ * of where allocation should begin and the fact that the allocator keeps track
+ * of where in the data zones the next natural allocation should occur,
+ * contribute to the complexity of the function. But it should all be
+ * worthwhile, because this allocator should: 1) be a full implementation of
+ * the MFT zone approach used by Windows NT, 2) cause reduction in
+ * fragmentation, and 3) be speedy in allocations (the code is not optimized
+ * for speed, but the algorithm is, so further speed improvements are probably
+ * possible).
+ *
+ * FIXME: We should be monitoring cluster allocation and increment the MFT zone
+ * size dynamically but this is something for the future. We will just cause
+ * heavier fragmentation by not doing it and I am not even sure Windows would
+ * grow the MFT zone dynamically, so it might even be correct not to do this.
+ * The overhead in doing dynamic MFT zone expansion would be very large and
+ * unlikely worth the effort. (AIA)
+ *
+ * TODO: I have added in double the required zone position pointer wrap around
+ * logic which can be optimized to having only one of the two logic sets.
+ * However, having the double logic will work fine, but if we have only one of
+ * the sets and we get it wrong somewhere, then we get into trouble, so
+ * removing the duplicate logic requires _very_ careful consideration of _all_
+ * possible code paths. So at least for now, I am leaving the double logic -
+ * better safe than sorry... (AIA)
+ *
+ * Locking: - The volume lcn bitmap must be unlocked on entry and is unlocked
+ * on return.
+ * - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
+ */
+runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn,
+ const s64 count, const LCN start_lcn,
+ const NTFS_CLUSTER_ALLOCATION_ZONES zone)
+{
+ LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn;
+ LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size;
+ s64 clusters;
+ struct inode *lcnbmp_vi;
+ runlist_element *rl = NULL;
+ struct address_space *mapping;
+ struct page *page = NULL;
+ u8 *buf, *byte;
+ int err = 0, rlpos, rlsize, buf_size;
+ u8 pass, done_zones, search_zone, need_writeback = 0, bit;
+
+ ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn "
+ "0x%llx, zone %s_ZONE.", (unsigned long long)start_vcn,
+ (unsigned long long)count,
+ (unsigned long long)start_lcn,
+ zone == MFT_ZONE ? "MFT" : "DATA");
+ BUG_ON(!vol);
+ lcnbmp_vi = vol->lcnbmp_ino;
+ BUG_ON(!lcnbmp_vi);
+ BUG_ON(start_vcn < 0);
+ BUG_ON(count < 0);
+ BUG_ON(start_lcn < -1);
+ BUG_ON(zone < FIRST_ZONE);
+ BUG_ON(zone > LAST_ZONE);
+
+ /* Return empty runlist if @count == 0 */
+ // FIXME: Do we want to just return NULL instead? (AIA)
+ if (!count) {
+ rl = ntfs_malloc_nofs(PAGE_SIZE);
+ if (!rl)
+ return ERR_PTR(-ENOMEM);
+ rlpos = 0;
+ if (start_vcn) {
+ rl[0].vcn = 0;
+ rl[0].lcn = LCN_RL_NOT_MAPPED;
+ rl[0].length = start_vcn;
+ rlpos++;
+ }
+ rl[rlpos].vcn = start_vcn;
+ rl[rlpos].lcn = LCN_ENOENT;
+ rl[rlpos].length = 0;
+ return rl;
+ }
+ /* Take the lcnbmp lock for writing. */
+ down_write(&vol->lcnbmp_lock);
+ /*
+ * If no specific @start_lcn was requested, use the current data zone
+ * position, otherwise use the requested @start_lcn but make sure it
+ * lies outside the mft zone. Also set done_zones to 0 (no zones done)
+ * and pass depending on whether we are starting inside a zone (1) or
+ * at the beginning of a zone (2). If requesting from the MFT_ZONE,
+ * we either start at the current position within the mft zone or at
+ * the specified position. If the latter is out of bounds then we start
+ * at the beginning of the MFT_ZONE.
+ */
+ done_zones = 0;
+ pass = 1;
+ /*
+ * zone_start and zone_end are the current search range. search_zone
+ * is 1 for mft zone, 2 for data zone 1 (end of mft zone till end of
+ * volume) and 4 for data zone 2 (start of volume till start of mft
+ * zone).
+ */
+ zone_start = start_lcn;
+ if (zone_start < 0) {
+ if (zone == DATA_ZONE)
+ zone_start = vol->data1_zone_pos;
+ else
+ zone_start = vol->mft_zone_pos;
+ if (!zone_start) {
+ /*
+ * Zone starts at beginning of volume which means a
+ * single pass is sufficient.
+ */
+ pass = 2;
+ }
+ } else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start &&
+ zone_start < vol->mft_zone_end) {
+ zone_start = vol->mft_zone_end;
+ /*
+ * Starting at beginning of data1_zone which means a single
+ * pass in this zone is sufficient.
+ */
+ pass = 2;
+ } else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start ||
+ zone_start >= vol->mft_zone_end)) {
+ zone_start = vol->mft_lcn;
+ if (!vol->mft_zone_end)
+ zone_start = 0;
+ /*
+ * Starting at beginning of volume which means a single pass
+ * is sufficient.
+ */
+ pass = 2;
+ }
+ if (zone == MFT_ZONE) {
+ zone_end = vol->mft_zone_end;
+ search_zone = 1;
+ } else /* if (zone == DATA_ZONE) */ {
+ /* Skip searching the mft zone. */
+ done_zones |= 1;
+ if (zone_start >= vol->mft_zone_end) {
+ zone_end = vol->nr_clusters;
+ search_zone = 2;
+ } else {
+ zone_end = vol->mft_zone_start;
+ search_zone = 4;
+ }
+ }
+ /*
+ * bmp_pos is the current bit position inside the bitmap. We use
+ * bmp_initial_pos to determine whether or not to do a zone switch.
+ */
+ bmp_pos = bmp_initial_pos = zone_start;
+
+ /* Loop until all clusters are allocated, i.e. clusters == 0. */
+ clusters = count;
+ rlpos = rlsize = 0;
+ mapping = lcnbmp_vi->i_mapping;
+ while (1) {
+ ntfs_debug("Start of outer while loop: done_zones 0x%x, "
+ "search_zone %i, pass %i, zone_start 0x%llx, "
+ "zone_end 0x%llx, bmp_initial_pos 0x%llx, "
+ "bmp_pos 0x%llx, rlpos %i, rlsize %i.",
+ done_zones, search_zone, pass,
+ (unsigned long long)zone_start,
+ (unsigned long long)zone_end,
+ (unsigned long long)bmp_initial_pos,
+ (unsigned long long)bmp_pos, rlpos, rlsize);
+ /* Loop until we run out of free clusters. */
+ last_read_pos = bmp_pos >> 3;
+ ntfs_debug("last_read_pos 0x%llx.",
+ (unsigned long long)last_read_pos);
+ if (last_read_pos > lcnbmp_vi->i_size) {
+ ntfs_debug("End of attribute reached. "
+ "Skipping to zone_pass_done.");
+ goto zone_pass_done;
+ }
+ if (likely(page)) {
+ if (need_writeback) {
+ ntfs_debug("Marking page dirty.");
+ flush_dcache_page(page);
+ set_page_dirty(page);
+ need_writeback = 0;
+ }
+ ntfs_unmap_page(page);
+ }
+ page = ntfs_map_page(mapping, last_read_pos >>
+ PAGE_CACHE_SHIFT);
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ ntfs_error(vol->sb, "Failed to map page.");
+ goto out;
+ }
+ buf_size = last_read_pos & ~PAGE_CACHE_MASK;
+ buf = page_address(page) + buf_size;
+ buf_size = PAGE_CACHE_SIZE - buf_size;
+ if (unlikely(last_read_pos + buf_size > lcnbmp_vi->i_size))
+ buf_size = lcnbmp_vi->i_size - last_read_pos;
+ buf_size <<= 3;
+ lcn = bmp_pos & 7;
+ bmp_pos &= ~7;
+ ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, "
+ "bmp_pos 0x%llx, need_writeback %i.", buf_size,
+ (unsigned long long)lcn,
+ (unsigned long long)bmp_pos, need_writeback);
+ while (lcn < buf_size && lcn + bmp_pos < zone_end) {
+ byte = buf + (lcn >> 3);
+ ntfs_debug("In inner while loop: buf_size %i, "
+ "lcn 0x%llx, bmp_pos 0x%llx, "
+ "need_writeback %i, byte ofs 0x%x, "
+ "*byte 0x%x.", buf_size,
+ (unsigned long long)lcn,
+ (unsigned long long)bmp_pos,
+ need_writeback,
+ (unsigned int)(lcn >> 3),
+ (unsigned int)*byte);
+ /* Skip full bytes. */
+ if (*byte == 0xff) {
+ lcn = (lcn + 8) & ~7;
+ ntfs_debug("Continuing while loop 1.");
+ continue;
+ }
+ bit = 1 << (lcn & 7);
+ ntfs_debug("bit %i.", bit);
+ /* If the bit is already set, go onto the next one. */
+ if (*byte & bit) {
+ lcn++;
+ ntfs_debug("Continuing while loop 2.");
+ continue;
+ }
+ /*
+ * Allocate more memory if needed, including space for
+ * the not-mapped and terminator elements.
+ * ntfs_malloc_nofs() operates on whole pages only.
+ */
+ if ((rlpos + 3) * sizeof(*rl) > rlsize) {
+ runlist_element *rl2;
+
+ ntfs_debug("Reallocating memory.");
+ if (!rl)
+ ntfs_debug("First free bit is at LCN "
+ "0x%llx.",
+ (unsigned long long)
+ (lcn + bmp_pos));
+ rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE);
+ if (unlikely(!rl2)) {
+ err = -ENOMEM;
+ ntfs_error(vol->sb, "Failed to "
+ "allocate memory.");
+ goto out;
+ }
+ memcpy(rl2, rl, rlsize);
+ ntfs_free(rl);
+ rl = rl2;
+ rlsize += PAGE_SIZE;
+ ntfs_debug("Reallocated memory, rlsize 0x%x.",
+ rlsize);
+ }
+ /* Allocate the bitmap bit. */
+ *byte |= bit;
+ /* We need to write this bitmap page to disk. */
+ need_writeback = 1;
+ ntfs_debug("*byte 0x%x, need_writeback is set.",
+ (unsigned int)*byte);
+ /*
+ * Coalesce with previous run if adjacent LCNs.
+ * Otherwise, append a new run.
+ */
+ ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), "
+ "prev_lcn 0x%llx, lcn 0x%llx, "
+ "bmp_pos 0x%llx, prev_run_len 0x%llx, "
+ "rlpos %i.",
+ (unsigned long long)(lcn + bmp_pos),
+ 1ULL, (unsigned long long)prev_lcn,
+ (unsigned long long)lcn,
+ (unsigned long long)bmp_pos,
+ (unsigned long long)prev_run_len,
+ rlpos);
+ if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
+ ntfs_debug("Coalescing to run (lcn 0x%llx, "
+ "len 0x%llx).",
+ (unsigned long long)
+ rl[rlpos - 1].lcn,
+ (unsigned long long)
+ rl[rlpos - 1].length);
+ rl[rlpos - 1].length = ++prev_run_len;
+ ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), "
+ "prev_run_len 0x%llx.",
+ (unsigned long long)
+ rl[rlpos - 1].lcn,
+ (unsigned long long)
+ rl[rlpos - 1].length,
+ (unsigned long long)
+ prev_run_len);
+ } else {
+ if (likely(rlpos)) {
+ ntfs_debug("Adding new run, (previous "
+ "run lcn 0x%llx, "
+ "len 0x%llx).",
+ (unsigned long long)
+ rl[rlpos - 1].lcn,
+ (unsigned long long)
+ rl[rlpos - 1].length);
+ rl[rlpos].vcn = rl[rlpos - 1].vcn +
+ prev_run_len;
+ } else {
+ ntfs_debug("Adding new run, is first "
+ "run.");
+ rl[rlpos].vcn = 0;
+ if (start_vcn) {
+ rl[rlpos].lcn =
+ LCN_RL_NOT_MAPPED;
+ rl[rlpos].length = start_vcn;
+ rlpos++;
+ rl[rlpos].vcn = start_vcn;
+ }
+ }
+ rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
+ rl[rlpos].length = prev_run_len = 1;
+ rlpos++;
+ }
+ /* Done? */
+ if (!--clusters) {
+ LCN tc;
+ /*
+ * Update the current zone position. Positions
+ * of already scanned zones have been updated
+ * during the respective zone switches.
+ */
+ tc = lcn + bmp_pos + 1;
+ ntfs_debug("Done. Updating current zone "
+ "position, tc 0x%llx, "
+ "search_zone %i.",
+ (unsigned long long)tc,
+ search_zone);
+ switch (search_zone) {
+ case 1:
+ ntfs_debug("Before checks, "
+ "vol->mft_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->mft_zone_pos);
+ if (tc >= vol->mft_zone_end) {
+ vol->mft_zone_pos =
+ vol->mft_lcn;
+ if (!vol->mft_zone_end)
+ vol->mft_zone_pos = 0;
+ } else if ((bmp_initial_pos >=
+ vol->mft_zone_pos ||
+ tc > vol->mft_zone_pos)
+ && tc >= vol->mft_lcn)
+ vol->mft_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->mft_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->mft_zone_pos);
+ break;
+ case 2:
+ ntfs_debug("Before checks, "
+ "vol->data1_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data1_zone_pos);
+ if (tc >= vol->nr_clusters)
+ vol->data1_zone_pos =
+ vol->mft_zone_end;
+ else if ((bmp_initial_pos >=
+ vol->data1_zone_pos ||
+ tc > vol->data1_zone_pos)
+ && tc >= vol->mft_zone_end)
+ vol->data1_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->data1_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data1_zone_pos);
+ break;
+ case 4:
+ ntfs_debug("Before checks, "
+ "vol->data2_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data2_zone_pos);
+ if (tc >= vol->mft_zone_start)
+ vol->data2_zone_pos = 0;
+ else if (bmp_initial_pos >=
+ vol->data2_zone_pos ||
+ tc > vol->data2_zone_pos)
+ vol->data2_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->data2_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data2_zone_pos);
+ break;
+ default:
+ BUG();
+ }
+ ntfs_debug("Finished. Going to out.");
+ goto out;
+ }
+ lcn++;
+ }
+ bmp_pos += buf_size;
+ ntfs_debug("After inner while loop: buf_size 0x%x, lcn "
+ "0x%llx, bmp_pos 0x%llx, need_writeback %i.",
+ buf_size, (unsigned long long)lcn,
+ (unsigned long long)bmp_pos, need_writeback);
+ if (bmp_pos < zone_end) {
+ ntfs_debug("Continuing outer while loop, "
+ "bmp_pos 0x%llx, zone_end 0x%llx.",
+ (unsigned long long)bmp_pos,
+ (unsigned long long)zone_end);
+ continue;
+ }
+zone_pass_done: /* Finished with the current zone pass. */
+ ntfs_debug("At zone_pass_done, pass %i.", pass);
+ if (pass == 1) {
+ /*
+ * Now do pass 2, scanning the first part of the zone
+ * we omitted in pass 1.
+ */
+ pass = 2;
+ zone_end = zone_start;
+ switch (search_zone) {
+ case 1: /* mft_zone */
+ zone_start = vol->mft_zone_start;
+ break;
+ case 2: /* data1_zone */
+ zone_start = vol->mft_zone_end;
+ break;
+ case 4: /* data2_zone */
+ zone_start = 0;
+ break;
+ default:
+ BUG();
+ }
+ /* Sanity check. */
+ if (zone_end < zone_start)
+ zone_end = zone_start;
+ bmp_pos = zone_start;
+ ntfs_debug("Continuing outer while loop, pass 2, "
+ "zone_start 0x%llx, zone_end 0x%llx, "
+ "bmp_pos 0x%llx.",
+ (unsigned long long)zone_start,
+ (unsigned long long)zone_end,
+ (unsigned long long)bmp_pos);
+ continue;
+ } /* pass == 2 */
+done_zones_check:
+ ntfs_debug("At done_zones_check, search_zone %i, done_zones "
+ "before 0x%x, done_zones after 0x%x.",
+ search_zone, done_zones,
+ done_zones | search_zone);
+ done_zones |= search_zone;
+ if (done_zones < 7) {
+ ntfs_debug("Switching zone.");
+ /* Now switch to the next zone we haven't done yet. */
+ pass = 1;
+ switch (search_zone) {
+ case 1:
+ ntfs_debug("Switching from mft zone to data1 "
+ "zone.");
+ /* Update mft zone position. */
+ if (rlpos) {
+ LCN tc;
+
+ ntfs_debug("Before checks, "
+ "vol->mft_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->mft_zone_pos);
+ tc = rl[rlpos - 1].lcn +
+ rl[rlpos - 1].length;
+ if (tc >= vol->mft_zone_end) {
+ vol->mft_zone_pos =
+ vol->mft_lcn;
+ if (!vol->mft_zone_end)
+ vol->mft_zone_pos = 0;
+ } else if ((bmp_initial_pos >=
+ vol->mft_zone_pos ||
+ tc > vol->mft_zone_pos)
+ && tc >= vol->mft_lcn)
+ vol->mft_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->mft_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->mft_zone_pos);
+ }
+ /* Switch from mft zone to data1 zone. */
+switch_to_data1_zone: search_zone = 2;
+ zone_start = bmp_initial_pos =
+ vol->data1_zone_pos;
+ zone_end = vol->nr_clusters;
+ if (zone_start == vol->mft_zone_end)
+ pass = 2;
+ if (zone_start >= zone_end) {
+ vol->data1_zone_pos = zone_start =
+ vol->mft_zone_end;
+ pass = 2;
+ }
+ break;
+ case 2:
+ ntfs_debug("Switching from data1 zone to "
+ "data2 zone.");
+ /* Update data1 zone position. */
+ if (rlpos) {
+ LCN tc;
+
+ ntfs_debug("Before checks, "
+ "vol->data1_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data1_zone_pos);
+ tc = rl[rlpos - 1].lcn +
+ rl[rlpos - 1].length;
+ if (tc >= vol->nr_clusters)
+ vol->data1_zone_pos =
+ vol->mft_zone_end;
+ else if ((bmp_initial_pos >=
+ vol->data1_zone_pos ||
+ tc > vol->data1_zone_pos)
+ && tc >= vol->mft_zone_end)
+ vol->data1_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->data1_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data1_zone_pos);
+ }
+ /* Switch from data1 zone to data2 zone. */
+ search_zone = 4;
+ zone_start = bmp_initial_pos =
+ vol->data2_zone_pos;
+ zone_end = vol->mft_zone_start;
+ if (!zone_start)
+ pass = 2;
+ if (zone_start >= zone_end) {
+ vol->data2_zone_pos = zone_start =
+ bmp_initial_pos = 0;
+ pass = 2;
+ }
+ break;
+ case 4:
+ ntfs_debug("Switching from data2 zone to "
+ "data1 zone.");
+ /* Update data2 zone position. */
+ if (rlpos) {
+ LCN tc;
+
+ ntfs_debug("Before checks, "
+ "vol->data2_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data2_zone_pos);
+ tc = rl[rlpos - 1].lcn +
+ rl[rlpos - 1].length;
+ if (tc >= vol->mft_zone_start)
+ vol->data2_zone_pos = 0;
+ else if (bmp_initial_pos >=
+ vol->data2_zone_pos ||
+ tc > vol->data2_zone_pos)
+ vol->data2_zone_pos = tc;
+ ntfs_debug("After checks, "
+ "vol->data2_zone_pos "
+ "0x%llx.",
+ (unsigned long long)
+ vol->data2_zone_pos);
+ }
+ /* Switch from data2 zone to data1 zone. */
+ goto switch_to_data1_zone;
+ default:
+ BUG();
+ }
+ ntfs_debug("After zone switch, search_zone %i, "
+ "pass %i, bmp_initial_pos 0x%llx, "
+ "zone_start 0x%llx, zone_end 0x%llx.",
+ search_zone, pass,
+ (unsigned long long)bmp_initial_pos,
+ (unsigned long long)zone_start,
+ (unsigned long long)zone_end);
+ bmp_pos = zone_start;
+ if (zone_start == zone_end) {
+ ntfs_debug("Empty zone, going to "
+ "done_zones_check.");
+ /* Empty zone. Don't bother searching it. */
+ goto done_zones_check;
+ }
+ ntfs_debug("Continuing outer while loop.");
+ continue;
+ } /* done_zones == 7 */
+ ntfs_debug("All zones are finished.");
+ /*
+ * All zones are finished! If DATA_ZONE, shrink mft zone. If
+ * MFT_ZONE, we have really run out of space.
+ */
+ mft_zone_size = vol->mft_zone_end - vol->mft_zone_start;
+ ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end "
+ "0x%llx, mft_zone_size 0x%llx.",
+ (unsigned long long)vol->mft_zone_start,
+ (unsigned long long)vol->mft_zone_end,
+ (unsigned long long)mft_zone_size);
+ if (zone == MFT_ZONE || mft_zone_size <= 0) {
+ ntfs_debug("No free clusters left, going to out.");
+ /* Really no more space left on device. */
+ err = ENOSPC;
+ goto out;
+ } /* zone == DATA_ZONE && mft_zone_size > 0 */
+ ntfs_debug("Shrinking mft zone.");
+ zone_end = vol->mft_zone_end;
+ mft_zone_size >>= 1;
+ if (mft_zone_size > 0)
+ vol->mft_zone_end = vol->mft_zone_start + mft_zone_size;
+ else /* mft zone and data2 zone no longer exist. */
+ vol->data2_zone_pos = vol->mft_zone_start =
+ vol->mft_zone_end = 0;
+ if (vol->mft_zone_pos >= vol->mft_zone_end) {
+ vol->mft_zone_pos = vol->mft_lcn;
+ if (!vol->mft_zone_end)
+ vol->mft_zone_pos = 0;
+ }
+ bmp_pos = zone_start = bmp_initial_pos =
+ vol->data1_zone_pos = vol->mft_zone_end;
+ search_zone = 2;
+ pass = 2;
+ done_zones &= ~2;
+ ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, "
+ "vol->mft_zone_start 0x%llx, "
+ "vol->mft_zone_end 0x%llx, "
+ "vol->mft_zone_pos 0x%llx, search_zone 2, "
+ "pass 2, dones_zones 0x%x, zone_start 0x%llx, "
+ "zone_end 0x%llx, vol->data1_zone_pos 0x%llx, "
+ "continuing outer while loop.",
+ (unsigned long long)mft_zone_size,
+ (unsigned long long)vol->mft_zone_start,
+ (unsigned long long)vol->mft_zone_end,
+ (unsigned long long)vol->mft_zone_pos,
+ done_zones, (unsigned long long)zone_start,
+ (unsigned long long)zone_end,
+ (unsigned long long)vol->data1_zone_pos);
+ }
+ ntfs_debug("After outer while loop.");
+out:
+ ntfs_debug("At out.");
+ /* Add runlist terminator element. */
+ if (likely(rl)) {
+ rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
+ rl[rlpos].lcn = LCN_ENOENT;
+ rl[rlpos].length = 0;
+ }
+ if (likely(page && !IS_ERR(page))) {
+ if (need_writeback) {
+ ntfs_debug("Marking page dirty.");
+ flush_dcache_page(page);
+ set_page_dirty(page);
+ need_writeback = 0;
+ }
+ ntfs_unmap_page(page);
+ }
+ if (likely(!err)) {
+ up_write(&vol->lcnbmp_lock);
+ ntfs_debug("Done.");
+ return rl;
+ }
+ ntfs_error(vol->sb, "Failed to allocate clusters, aborting "
+ "(error %i).", err);
+ if (rl) {
+ int err2;
+
+ if (err == ENOSPC)
+ ntfs_debug("Not enough space to complete allocation, "
+ "err ENOSPC, first free lcn 0x%llx, "
+ "could allocate up to 0x%llx "
+ "clusters.",
+ (unsigned long long)rl[0].lcn,
+ (unsigned long long)count - clusters);
+ /* Deallocate all allocated clusters. */
+ ntfs_debug("Attempting rollback...");
+ err2 = ntfs_cluster_free_from_rl_nolock(vol, rl);
+ if (err2) {
+ ntfs_error(vol->sb, "Failed to rollback (error %i). "
+ "Leaving inconsistent metadata! "
+ "Unmount and run chkdsk.", err2);
+ NVolSetErrors(vol);
+ }
+ /* Free the runlist. */
+ ntfs_free(rl);
+ } else if (err == ENOSPC)
+ ntfs_debug("No space left at all, err = ENOSPC, "
+ "first free lcn = 0x%llx.",
+ (unsigned long long)vol->data1_zone_pos);
+ up_write(&vol->lcnbmp_lock);
+ return ERR_PTR(err);
+}
+
+/**
+ * __ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi: vfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @count: number of clusters to free or -1 for all clusters
+ * @is_rollback: if TRUE this is a rollback operation
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated. Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * @is_rollback should always be FALSE, it is for internal use to rollback
+ * errors. You probably want to use ntfs_cluster_free() instead.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ * unlocked on return.
+ * - This function takes the runlist lock of @vi for reading and
+ * sometimes for writing and sometimes modifies the runlist.
+ * - The volume lcn bitmap must be unlocked on entry and is unlocked
+ * on return.
+ * - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
+ */
+s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn, s64 count,
+ const BOOL is_rollback)
+{
+ s64 delta, to_free, total_freed, real_freed;
+ ntfs_inode *ni;
+ ntfs_volume *vol;
+ struct inode *lcnbmp_vi;
+ runlist_element *rl;
+ int err;
+
+ BUG_ON(!vi);
+ ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count "
+ "0x%llx.%s", vi->i_ino, (unsigned long long)start_vcn,
+ (unsigned long long)count,
+ is_rollback ? " (rollback)" : "");
+ ni = NTFS_I(vi);
+ vol = ni->vol;
+ lcnbmp_vi = vol->lcnbmp_ino;
+ BUG_ON(!lcnbmp_vi);
+ BUG_ON(start_vcn < 0);
+ BUG_ON(count < -1);
+ /*
+ * Lock the lcn bitmap for writing but only if not rolling back. We
+ * must hold the lock all the way including through rollback otherwise
+ * rollback is not possible because once we have cleared a bit and
+ * dropped the lock, anyone could have set the bit again, thus
+ * allocating the cluster for another use.
+ */
+ if (likely(!is_rollback))
+ down_write(&vol->lcnbmp_lock);
+
+ total_freed = real_freed = 0;
+
+ /* This returns with ni->runlist locked for reading on success. */
+ rl = ntfs_find_vcn(ni, start_vcn, FALSE);
+ if (IS_ERR(rl)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to find first runlist "
+ "element (error %li), aborting.",
+ PTR_ERR(rl));
+ err = PTR_ERR(rl);
+ goto err_out;
+ }
+ if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "First runlist element has "
+ "invalid lcn, aborting.");
+ err = -EIO;
+ goto unl_err_out;
+ }
+ /* Find the starting cluster inside the run that needs freeing. */
+ delta = start_vcn - rl->vcn;
+
+ /* The number of clusters in this run that need freeing. */
+ to_free = rl->length - delta;
+ if (count >= 0 && to_free > count)
+ to_free = count;
+
+ if (likely(rl->lcn >= 0)) {
+ /* Do the actual freeing of the clusters in this run. */
+ err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn + delta,
+ to_free, likely(!is_rollback) ? 0 : 1);
+ if (unlikely(err)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to clear first run "
+ "(error %i), aborting.", err);
+ goto unl_err_out;
+ }
+ /* We have freed @to_free real clusters. */
+ real_freed = to_free;
+ };
+ /* Go to the next run and adjust the number of clusters left to free. */
+ ++rl;
+ if (count >= 0)
+ count -= to_free;
+
+ /* Keep track of the total "freed" clusters, including sparse ones. */
+ total_freed = to_free;
+ /*
+ * Loop over the remaining runs, using @count as a capping value, and
+ * free them.
+ */
+ for (; rl->length && count != 0; ++rl) {
+ if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+ VCN vcn;
+
+ /*
+ * Attempt to map runlist, dropping runlist lock for
+ * the duration.
+ */
+ up_read(&ni->runlist.lock);
+ vcn = rl->vcn;
+ err = ntfs_map_runlist(ni, vcn);
+ if (err) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to map "
+ "runlist fragment.");
+ if (err == -EINVAL || err == -ENOENT)
+ err = -EIO;
+ goto err_out;
+ }
+ /*
+ * This returns with ni->runlist locked for reading on
+ * success.
+ */
+ rl = ntfs_find_vcn(ni, vcn, FALSE);
+ if (IS_ERR(rl)) {
+ err = PTR_ERR(rl);
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to find "
+ "subsequent runlist "
+ "element.");
+ goto err_out;
+ }
+ if (unlikely(rl->lcn < (LCN)LCN_HOLE)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Runlist element "
+ "has invalid lcn "
+ "(0x%llx).",
+ (unsigned long long)
+ rl->lcn);
+ err = -EIO;
+ goto unl_err_out;
+ }
+ }
+ /* The number of clusters in this run that need freeing. */
+ to_free = rl->length;
+ if (count >= 0 && to_free > count)
+ to_free = count;
+
+ if (likely(rl->lcn >= 0)) {
+ /* Do the actual freeing of the clusters in the run. */
+ err = ntfs_bitmap_set_bits_in_run(lcnbmp_vi, rl->lcn,
+ to_free, likely(!is_rollback) ? 0 : 1);
+ if (unlikely(err)) {
+ if (!is_rollback)
+ ntfs_error(vol->sb, "Failed to clear "
+ "subsequent run.");
+ goto unl_err_out;
+ }
+ /* We have freed @to_free real clusters. */
+ real_freed += to_free;
+ }
+ /* Adjust the number of clusters left to free. */
+ if (count >= 0)
+ count -= to_free;
+
+ /* Update the total done clusters. */
+ total_freed += to_free;
+ }
+ up_read(&ni->runlist.lock);
+ if (likely(!is_rollback))
+ up_write(&vol->lcnbmp_lock);
+
+ BUG_ON(count > 0);
+
+ /* We are done. Return the number of actually freed clusters. */
+ ntfs_debug("Done.");
+ return real_freed;
+unl_err_out:
+ up_read(&ni->runlist.lock);
+err_out:
+ if (is_rollback)
+ return err;
+ /* If no real clusters were freed, no need to rollback. */
+ if (!real_freed) {
+ up_write(&vol->lcnbmp_lock);
+ return err;
+ }
+ /*
+ * Attempt to rollback and if that succeeds just return the error code.
+ * If rollback fails, set the volume errors flag, emit an error
+ * message, and return the error code.
+ */
+ delta = __ntfs_cluster_free(vi, start_vcn, total_freed, TRUE);
+ if (delta < 0) {
+ ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving "
+ "inconsistent metadata! Unmount and run "
+ "chkdsk.", (int)delta);
+ NVolSetErrors(vol);
+ }
+ up_write(&vol->lcnbmp_lock);
+ ntfs_error(vol->sb, "Aborting (error %i).", err);
+ return err;
+}
+
+#endif /* NTFS_RW */
diff -Nru a/fs/ntfs/lcnalloc.h b/fs/ntfs/lcnalloc.h
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/fs/ntfs/lcnalloc.h 2004-08-18 20:50:30 +01:00
@@ -0,0 +1,83 @@
+/*
+ * lcnalloc.h - Exports for NTFS kernel cluster (de)allocation. Part of the
+ * Linux-NTFS project.
+ *
+ * Copyright (c) 2004 Anton Altaparmakov
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_NTFS_LCNALLOC_H
+#define _LINUX_NTFS_LCNALLOC_H
+
+#ifdef NTFS_RW
+
+#include <linux/fs.h>
+
+#include "types.h"
+#include "volume.h"
+
+typedef enum {
+ FIRST_ZONE = 0, /* For sanity checking. */
+ MFT_ZONE = 0, /* Allocate from $MFT zone. */
+ DATA_ZONE = 1, /* Allocate from $DATA zone. */
+ LAST_ZONE = 1, /* For sanity checking. */
+} NTFS_CLUSTER_ALLOCATION_ZONES;
+
+extern runlist_element *ntfs_cluster_alloc(ntfs_volume *vol,
+ const VCN start_vcn, const s64 count, const LCN start_lcn,
+ const NTFS_CLUSTER_ALLOCATION_ZONES zone);
+
+extern s64 __ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+ s64 count, const BOOL is_rollback);
+
+/**
+ * ntfs_cluster_free - free clusters on an ntfs volume
+ * @vi: vfs inode whose runlist describes the clusters to free
+ * @start_vcn: vcn in the runlist of @vi at which to start freeing clusters
+ * @count: number of clusters to free or -1 for all clusters
+ *
+ * Free @count clusters starting at the cluster @start_vcn in the runlist
+ * described by the vfs inode @vi.
+ *
+ * If @count is -1, all clusters from @start_vcn to the end of the runlist are
+ * deallocated. Thus, to completely free all clusters in a runlist, use
+ * @start_vcn = 0 and @count = -1.
+ *
+ * Note, ntfs_cluster_free() does not modify the runlist at all, so the caller
+ * has to deal with it later.
+ *
+ * Return the number of deallocated clusters (not counting sparse ones) on
+ * success and -errno on error.
+ *
+ * Locking: - The runlist described by @vi must be unlocked on entry and is
+ * unlocked on return.
+ * - This function takes the runlist lock of @vi for reading and
+ * sometimes for writing and sometimes modifies the runlist.
+ * - The volume lcn bitmap must be unlocked on entry and is unlocked
+ * on return.
+ * - This function takes the volume lcn bitmap lock for writing and
+ * modifies the bitmap contents.
+ */
+static inline s64 ntfs_cluster_free(struct inode *vi, const VCN start_vcn,
+ s64 count)
+{
+ return __ntfs_cluster_free(vi, start_vcn, count, FALSE);
+}
+
+#endif /* NTFS_RW */
+
+#endif /* defined _LINUX_NTFS_LCNALLOC_H */
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:50:30 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:50:30 +01:00
@@ -818,37 +818,86 @@
vol->serial_no = le64_to_cpu(b->volume_serial_number);
ntfs_debug("vol->serial_no = 0x%llx",
(unsigned long long)vol->serial_no);
- /*
- * Determine MFT zone size. This is not strictly the right place to do
- * this, but I am too lazy to create a function especially for it...
- */
- vol->mft_zone_end = vol->nr_clusters;
+ return TRUE;
+}
+
+/**
+ * setup_lcn_allocator - initialize the cluster allocator
+ * @vol: volume structure for which to setup the lcn allocator
+ *
+ * Setup the cluster (lcn) allocator to the starting values.
+ */
+static void setup_lcn_allocator(ntfs_volume *vol)
+{
+#ifdef NTFS_RW
+ LCN mft_zone_size, mft_lcn;
+#endif /* NTFS_RW */
+
+ ntfs_debug("vol->mft_zone_multiplier = 0x%x",
+ vol->mft_zone_multiplier);
+#ifdef NTFS_RW
+ /* Determine the size of the MFT zone. */
+ mft_zone_size = vol->nr_clusters;
switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */
case 4:
- vol->mft_zone_end = vol->mft_zone_end >> 1; /* 50% */
+ mft_zone_size >>= 1; /* 50% */
break;
case 3:
- vol->mft_zone_end = (vol->mft_zone_end +
- (vol->mft_zone_end >> 1)) >> 2; /* 37.5% */
+ mft_zone_size = (mft_zone_size +
+ (mft_zone_size >> 1)) >> 2; /* 37.5% */
break;
case 2:
- vol->mft_zone_end = vol->mft_zone_end >> 2; /* 25% */
+ mft_zone_size >>= 2; /* 25% */
break;
+ /* case 1: */
default:
- vol->mft_zone_multiplier = 1;
- /* Fall through into case 1. */
- case 1:
- vol->mft_zone_end = vol->mft_zone_end >> 3; /* 12.5% */
+ mft_zone_size >>= 3; /* 12.5% */
break;
}
- ntfs_debug("vol->mft_zone_multiplier = 0x%x",
- vol->mft_zone_multiplier);
- vol->mft_zone_start = vol->mft_lcn;
- vol->mft_zone_end += vol->mft_lcn;
+ /* Setup the mft zone. */
+ vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
+ ntfs_debug("vol->mft_zone_pos = 0x%llx",
+ (unsigned long long)vol->mft_zone_pos);
+ /*
+ * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
+ * source) and if the actual mft_lcn is in the expected place or even
+ * further to the front of the volume, extend the mft_zone to cover the
+ * beginning of the volume as well. This is in order to protect the
+ * area reserved for the mft bitmap as well within the mft_zone itself.
+ * On non-standard volumes we do not protect it as the overhead would
+ * be higher than the speed increase we would get by doing it.
+ */
+ mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
+ if (mft_lcn * vol->cluster_size < 16 * 1024)
+ mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
+ vol->cluster_size;
+ if (vol->mft_zone_start <= mft_lcn)
+ vol->mft_zone_start = 0;
ntfs_debug("vol->mft_zone_start = 0x%llx",
- (long long)vol->mft_zone_start);
- ntfs_debug("vol->mft_zone_end = 0x%llx", (long long)vol->mft_zone_end);
- return TRUE;
+ (unsigned long long)vol->mft_zone_start);
+ /*
+ * Need to cap the mft zone on non-standard volumes so that it does
+ * not point outside the boundaries of the volume. We do this by
+ * halving the zone size until we are inside the volume.
+ */
+ vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+ while (vol->mft_zone_end >= vol->nr_clusters) {
+ mft_zone_size >>= 1;
+ vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
+ }
+ ntfs_debug("vol->mft_zone_end = 0x%llx",
+ (unsigned long long)vol->mft_zone_end);
+ /*
+ * Set the current position within each data zone to the start of the
+ * respective zone.
+ */
+ vol->data1_zone_pos = vol->mft_zone_end;
+ ntfs_debug("vol->data1_zone_pos = 0x%llx",
+ (unsigned long long)vol->data1_zone_pos);
+ vol->data2_zone_pos = 0;
+ ntfs_debug("vol->data2_zone_pos = 0x%llx",
+ (unsigned long long)vol->data2_zone_pos);
+#endif /* NTFS_RW */
}
#ifdef NTFS_RW
@@ -2195,6 +2244,9 @@
* using it.
*/
result = parse_ntfs_boot_sector(vol, (NTFS_BOOT_SECTOR*)bh->b_data);
+
+ /* Initialize the cluster allocator. */
+ setup_lcn_allocator(vol);
brelse(bh);
diff -Nru a/fs/ntfs/volume.h b/fs/ntfs/volume.h
--- a/fs/ntfs/volume.h 2004-08-18 20:50:30 +01:00
+++ b/fs/ntfs/volume.h 2004-08-18 20:50:30 +01:00
@@ -73,8 +73,18 @@
/* Mount specific NTFS information. */
u32 upcase_len; /* Number of entries in upcase[]. */
ntfschar *upcase; /* The upcase table. */
+
+#ifdef NTFS_RW
+ /* Variables used by the cluster and mft allocators. */
LCN mft_zone_start; /* First cluster of the mft zone. */
LCN mft_zone_end; /* First cluster beyond the mft zone. */
+ LCN mft_zone_pos; /* Current position in the mft zone. */
+ LCN data1_zone_pos; /* Current position in the first data
+ zone. */
+ LCN data2_zone_pos; /* Current position in the second data
+ zone. */
+#endif /* NTFS_RW */
+
struct inode *mft_ino; /* The VFS inode of $MFT. */
struct inode *mftbmp_ino; /* Attribute inode for $MFT/$BITMAP. */
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 15/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:32 ` [PATCH 14/20] " Anton Altaparmakov
@ 2004-08-23 10:32 ` Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 16/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:32 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 15/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/17 1.1821)
NTFS: Minor update to fs/ntfs/bitmap.c to only perform rollback if at
least one bit has actually been changed.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
--- a/fs/ntfs/bitmap.c 2004-08-18 20:50:34 +01:00
+++ b/fs/ntfs/bitmap.c 2004-08-18 20:50:34 +01:00
@@ -115,7 +115,7 @@
len += pos;
/* If we are not in the last page, deal with all subsequent pages. */
- while (end_index > index) {
+ while (index < end_index) {
BUG_ON(cnt <= 0);
/* Update @index and get the next page. */
@@ -168,8 +168,11 @@
*/
if (is_rollback)
return PTR_ERR(page);
- pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
- value ? 0 : 1, TRUE);
+ if (count != cnt)
+ pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt,
+ value ? 0 : 1, TRUE);
+ else
+ pos = 0;
if (!pos) {
/* Rollback was successful. */
ntfs_error(vi->i_sb, "Failed to map subsequent page (error "
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 16/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:32 ` [PATCH 15/20] " Anton Altaparmakov
@ 2004-08-23 10:33 ` Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 17/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:33 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 16/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/17 1.1822)
NTFS: Fix fs/ntfs/lcnalloc.c::ntfs_cluster_alloc() to use LCN_RL_NOT_MAPPED
rather than LCN_ENOENT as runlist terminator. Also, make it not create a
LCN_RL_NOT_MAPPED element at the beginning.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
--- a/fs/ntfs/lcnalloc.c 2004-08-18 20:50:37 +01:00
+++ b/fs/ntfs/lcnalloc.c 2004-08-18 20:50:37 +01:00
@@ -167,16 +167,9 @@
rl = ntfs_malloc_nofs(PAGE_SIZE);
if (!rl)
return ERR_PTR(-ENOMEM);
- rlpos = 0;
- if (start_vcn) {
- rl[0].vcn = 0;
- rl[0].lcn = LCN_RL_NOT_MAPPED;
- rl[0].length = start_vcn;
- rlpos++;
- }
- rl[rlpos].vcn = start_vcn;
- rl[rlpos].lcn = LCN_ENOENT;
- rl[rlpos].length = 0;
+ rl[0].vcn = start_vcn;
+ rl[0].lcn = LCN_RL_NOT_MAPPED;
+ rl[0].length = 0;
return rl;
}
/* Take the lcnbmp lock for writing. */
@@ -405,14 +398,7 @@
} else {
ntfs_debug("Adding new run, is first "
"run.");
- rl[rlpos].vcn = 0;
- if (start_vcn) {
- rl[rlpos].lcn =
- LCN_RL_NOT_MAPPED;
- rl[rlpos].length = start_vcn;
- rlpos++;
- rl[rlpos].vcn = start_vcn;
- }
+ rl[rlpos].vcn = start_vcn;
}
rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
rl[rlpos].length = prev_run_len = 1;
@@ -746,7 +732,7 @@
/* Add runlist terminator element. */
if (likely(rl)) {
rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length;
- rl[rlpos].lcn = LCN_ENOENT;
+ rl[rlpos].lcn = LCN_RL_NOT_MAPPED;
rl[rlpos].length = 0;
}
if (likely(page && !IS_ERR(page))) {
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 17/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:33 ` [PATCH 16/20] " Anton Altaparmakov
@ 2004-08-23 10:33 ` Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 18/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:33 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 17/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/17 1.1823)
NTFS: Fix fs/ntfs/debug.c::ntfs_debug_dump_runlist() for the previous
removal of LCN_EINVAL which was not used in the kernel NTFS driver.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/debug.c b/fs/ntfs/debug.c
--- a/fs/ntfs/debug.c 2004-08-18 20:50:41 +01:00
+++ b/fs/ntfs/debug.c 2004-08-18 20:50:41 +01:00
@@ -155,7 +155,7 @@
int index = -lcn - 1;
if (index > -LCN_ENOENT - 1)
- index = 4;
+ index = 3;
printk(KERN_DEBUG "%-16Lx %s %-16Lx%s\n",
(rl + i)->vcn, lcn_str[index],
(rl + i)->length, (rl + i)->length ?
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 18/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:33 ` [PATCH 17/20] " Anton Altaparmakov
@ 2004-08-23 10:33 ` Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 19/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:33 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 18/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/17 1.1824)
NTFS: Only need two spare runlist elements when reallocating memory in
fs/ntfs/lcnalloc.c::ntfs_cluster_alloc(), not three since we no longer
add a starting element.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
--- a/fs/ntfs/lcnalloc.c 2004-08-18 20:50:44 +01:00
+++ b/fs/ntfs/lcnalloc.c 2004-08-18 20:50:44 +01:00
@@ -322,10 +322,10 @@
}
/*
* Allocate more memory if needed, including space for
- * the not-mapped and terminator elements.
+ * the terminator element.
* ntfs_malloc_nofs() operates on whole pages only.
*/
- if ((rlpos + 3) * sizeof(*rl) > rlsize) {
+ if ((rlpos + 2) * sizeof(*rl) > rlsize) {
runlist_element *rl2;
ntfs_debug("Reallocating memory.");
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 19/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:33 ` [PATCH 18/20] " Anton Altaparmakov
@ 2004-08-23 10:33 ` Anton Altaparmakov
2004-08-23 10:34 ` [PATCH 20/20] " Anton Altaparmakov
0 siblings, 1 reply; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:33 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 19/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/18 1.1825)
NTFS: - Load attribute definition table from $AttrDef at mount time.
- Fix bugs in mount time error code paths involving (de)allocation of
the default and volume upcase tables.
- Remove ntfs_nr_mounts as it is no longer used.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:50:47 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:50:47 +01:00
@@ -29,6 +29,10 @@
runlist element containing a particular vcn. It also takes care of
mapping any needed runlist fragments.
- Implement cluster (de-)allocation code (fs/ntfs/lcnalloc.[hc]).
+ - Load attribute definition table from $AttrDef at mount time.
+ - Fix bugs in mount time error code paths involving (de)allocation of
+ the default and volume upcase tables.
+ - Remove ntfs_nr_mounts as it is no longer used.
2.1.16 - Implement access time updates, file sync, async io, and read/writev.
diff -Nru a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
--- a/fs/ntfs/ntfs.h 2004-08-18 20:50:47 +01:00
+++ b/fs/ntfs/ntfs.h 2004-08-18 20:50:47 +01:00
@@ -158,7 +158,6 @@
#define default_upcase_len 0x10000
extern wchar_t *default_upcase;
extern unsigned long ntfs_nr_upcase_users;
-extern unsigned long ntfs_nr_mounts;
extern struct semaphore ntfs_lock;
typedef struct {
diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c
--- a/fs/ntfs/super.c 2004-08-18 20:50:47 +01:00
+++ b/fs/ntfs/super.c 2004-08-18 20:50:47 +01:00
@@ -1164,6 +1164,66 @@
return TRUE;
}
+/**
+ * load_and_init_attrdef - load the attribute definitions table for a volume
+ * @vol: ntfs super block describing device whose attrdef to load
+ *
+ * Return TRUE on success or FALSE on error.
+ */
+static BOOL load_and_init_attrdef(ntfs_volume *vol)
+{
+ struct super_block *sb = vol->sb;
+ struct inode *ino;
+ struct page *page;
+ unsigned long index, max_index;
+ unsigned int size;
+
+ ntfs_debug("Entering.");
+ /* Read attrdef table and setup vol->attrdef and vol->attrdef_size. */
+ ino = ntfs_iget(sb, FILE_AttrDef);
+ if (IS_ERR(ino) || is_bad_inode(ino)) {
+ if (!IS_ERR(ino))
+ iput(ino);
+ goto failed;
+ }
+ /* The size of FILE_AttrDef must be above 0 and fit inside 31 bits. */
+ if (!ino->i_size || ino->i_size > 0x7fffffff)
+ goto iput_failed;
+ vol->attrdef = (ATTR_DEF*)ntfs_malloc_nofs(ino->i_size);
+ if (!vol->attrdef)
+ goto iput_failed;
+ index = 0;
+ max_index = ino->i_size >> PAGE_CACHE_SHIFT;
+ size = PAGE_CACHE_SIZE;
+ while (index < max_index) {
+ /* Read the attrdef table and copy it into the linear buffer. */
+read_partial_attrdef_page:
+ page = ntfs_map_page(ino->i_mapping, index);
+ if (IS_ERR(page))
+ goto free_iput_failed;
+ memcpy((u8*)vol->attrdef + (index++ << PAGE_CACHE_SHIFT),
+ page_address(page), size);
+ ntfs_unmap_page(page);
+ };
+ if (size == PAGE_CACHE_SIZE) {
+ size = ino->i_size & ~PAGE_CACHE_MASK;
+ if (size)
+ goto read_partial_attrdef_page;
+ }
+ vol->attrdef_size = ino->i_size;
+ ntfs_debug("Read %llu bytes from $AttrDef.", ino->i_size);
+ iput(ino);
+ return TRUE;
+free_iput_failed:
+ ntfs_free(vol->attrdef);
+ vol->attrdef = NULL;
+iput_failed:
+ iput(ino);
+failed:
+ ntfs_error(sb, "Failed to initialize attribute definition table.");
+ return FALSE;
+}
+
#endif /* NTFS_RW */
/**
@@ -1264,7 +1324,7 @@
return TRUE;
}
up(&ntfs_lock);
- ntfs_error(sb, "Failed to initialized upcase table.");
+ ntfs_error(sb, "Failed to initialize upcase table.");
return FALSE;
}
@@ -1280,7 +1340,6 @@
static BOOL load_system_files(ntfs_volume *vol)
{
struct super_block *sb = vol->sb;
- struct inode *tmp_ino;
MFT_RECORD *m;
VOLUME_INFORMATION *vi;
attr_search_context *ctx;
@@ -1324,6 +1383,14 @@
/* Read upcase table and setup @vol->upcase and @vol->upcase_len. */
if (!load_and_init_upcase(vol))
goto iput_mftbmp_err_out;
+#ifdef NTFS_RW
+ /*
+ * Read attribute definitions table and setup @vol->attrdef and
+ * @vol->attrdef_size.
+ */
+ if (!load_and_init_attrdef(vol))
+ goto iput_upcase_err_out;
+#endif /* NTFS_RW */
/*
* Get the cluster allocation bitmap inode and verify the size, no
* need for any locking at this stage as we are already running
@@ -1339,7 +1406,7 @@
iput(vol->lcnbmp_ino);
bitmap_failed:
ntfs_error(sb, "Failed to load $Bitmap.");
- goto iput_mirr_err_out;
+ goto iput_attrdef_err_out;
}
/*
* Get the volume inode and setup our cache of the volume flags and
@@ -1511,19 +1578,6 @@
NVolSetErrors(vol);
}
#endif /* NTFS_RW */
- /*
- * Get the inode for the attribute definitions file and parse the
- * attribute definitions.
- */
- tmp_ino = ntfs_iget(sb, FILE_AttrDef);
- if (IS_ERR(tmp_ino) || is_bad_inode(tmp_ino)) {
- if (!IS_ERR(tmp_ino))
- iput(tmp_ino);
- ntfs_error(sb, "Failed to load $AttrDef.");
- goto iput_logfile_err_out;
- }
- // FIXME: Parse the attribute definitions.
- iput(tmp_ino);
/* Get the root directory inode. */
vol->root_ino = ntfs_iget(sb, FILE_root);
if (IS_ERR(vol->root_ino) || is_bad_inode(vol->root_ino)) {
@@ -1619,6 +1673,26 @@
iput(vol->vol_ino);
iput_lcnbmp_err_out:
iput(vol->lcnbmp_ino);
+iput_attrdef_err_out:
+ vol->attrdef_size = 0;
+ if (vol->attrdef) {
+ ntfs_free(vol->attrdef);
+ vol->attrdef = NULL;
+ }
+#ifdef NTFS_RW
+iput_upcase_err_out:
+#endif /* NTFS_RW */
+ vol->upcase_len = 0;
+ down(&ntfs_lock);
+ if (vol->upcase == default_upcase) {
+ ntfs_nr_upcase_users--;
+ vol->upcase = NULL;
+ }
+ up(&ntfs_lock);
+ if (vol->upcase) {
+ ntfs_free(vol->upcase);
+ vol->upcase = NULL;
+ }
iput_mftbmp_err_out:
iput(vol->mftbmp_ino);
iput_mirr_err_out:
@@ -1790,14 +1864,18 @@
iput(vol->mft_ino);
vol->mft_ino = NULL;
+ /* Throw away the table of attribute definitions. */
+ vol->attrdef_size = 0;
+ if (vol->attrdef) {
+ ntfs_free(vol->attrdef);
+ vol->attrdef = NULL;
+ }
vol->upcase_len = 0;
/*
- * Decrease the number of mounts and destroy the global default upcase
- * table if necessary. Also decrease the number of upcase users if we
- * are a user.
+ * Destroy the global default upcase table if necessary. Also decrease
+ * the number of upcase users if we are a user.
*/
down(&ntfs_lock);
- ntfs_nr_mounts--;
if (vol->upcase == default_upcase) {
ntfs_nr_upcase_users--;
vol->upcase = NULL;
@@ -2181,6 +2259,7 @@
memset(vol, 0, sizeof(ntfs_volume));
vol->sb = sb;
vol->upcase = NULL;
+ vol->attrdef = NULL;
vol->mft_ino = NULL;
vol->mftbmp_ino = NULL;
init_rwsem(&vol->mftbmp_lock);
@@ -2312,14 +2391,13 @@
}
}
/*
- * Increment the number of mounts and generate the global default
- * upcase table if necessary. Also temporarily increment the number of
- * upcase users to avoid race conditions with concurrent (u)mounts.
+ * Generate the global default upcase table if necessary. Also
+ * temporarily increment the number of upcase users to avoid race
+ * conditions with concurrent (u)mounts.
*/
- if (!ntfs_nr_mounts++)
+ if (!default_upcase)
default_upcase = generate_default_upcase();
ntfs_nr_upcase_users++;
-
up(&ntfs_lock);
/*
* From now on, ignore @silent parameter. If we fail below this line,
@@ -2391,10 +2469,23 @@
vol->mftmirr_ino = NULL;
}
#endif /* NTFS_RW */
+ /* Throw away the table of attribute definitions. */
+ vol->attrdef_size = 0;
+ if (vol->attrdef) {
+ ntfs_free(vol->attrdef);
+ vol->attrdef = NULL;
+ }
vol->upcase_len = 0;
- if (vol->upcase != default_upcase)
+ down(&ntfs_lock);
+ if (vol->upcase == default_upcase) {
+ ntfs_nr_upcase_users--;
+ vol->upcase = NULL;
+ }
+ up(&ntfs_lock);
+ if (vol->upcase) {
ntfs_free(vol->upcase);
- vol->upcase = NULL;
+ vol->upcase = NULL;
+ }
if (vol->nls_map) {
unload_nls(vol->nls_map);
vol->nls_map = NULL;
@@ -2402,11 +2493,10 @@
/* Error exit code path. */
unl_upcase_iput_tmp_ino_err_out_now:
/*
- * Decrease the number of mounts and destroy the global default upcase
- * table if necessary.
+ * Decrease the number of upcase users and destroy the global default
+ * upcase table if necessary.
*/
down(&ntfs_lock);
- ntfs_nr_mounts--;
if (!--ntfs_nr_upcase_users && default_upcase) {
ntfs_free(default_upcase);
default_upcase = NULL;
@@ -2474,9 +2564,6 @@
/* A global default upcase table and a corresponding reference count. */
wchar_t *default_upcase = NULL;
unsigned long ntfs_nr_upcase_users = 0;
-
-/* The number of mounted filesystems. */
-unsigned long ntfs_nr_mounts = 0;
/* Driver wide semaphore. */
DECLARE_MUTEX(ntfs_lock);
diff -Nru a/fs/ntfs/volume.h b/fs/ntfs/volume.h
--- a/fs/ntfs/volume.h 2004-08-18 20:50:47 +01:00
+++ b/fs/ntfs/volume.h 2004-08-18 20:50:47 +01:00
@@ -74,6 +74,11 @@
u32 upcase_len; /* Number of entries in upcase[]. */
ntfschar *upcase; /* The upcase table. */
+ s32 attrdef_size; /* Size of the attribute definition
+ table in bytes. */
+ ATTR_DEF *attrdef; /* Table of attribute definitions.
+ Obtained from FILE_AttrDef. */
+
#ifdef NTFS_RW
/* Variables used by the cluster and mft allocators. */
LCN mft_zone_start; /* First cluster of the mft zone. */
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 20/20] Re: [2.6-BK-URL] NTFS 2.1.17 release
2004-08-23 10:33 ` [PATCH 19/20] " Anton Altaparmakov
@ 2004-08-23 10:34 ` Anton Altaparmakov
0 siblings, 0 replies; 21+ messages in thread
From: Anton Altaparmakov @ 2004-08-23 10:34 UTC (permalink / raw)
To: Andrew Morton, Linus Torvalds; +Cc: linux-kernel
This is patch 20/20 in the series. It contains the following ChangeSet:
<aia21@cantab.net> (04/08/18 1.1826)
NTFS: 2.1.17 - Fix bugs in mount time error code paths.
Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Best regards,
Anton
--
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Unix Support, Computing Service, University of Cambridge, CB2 3QH, UK
Linux NTFS maintainer / IRC: #ntfs on irc.freenode.net
WWW: http://linux-ntfs.sf.net/, http://www-stu.christs.cam.ac.uk/~aia21/
===================================================================
diff -Nru a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt
--- a/Documentation/filesystems/ntfs.txt 2004-08-18 20:50:51 +01:00
+++ b/Documentation/filesystems/ntfs.txt 2004-08-18 20:50:51 +01:00
@@ -30,7 +30,7 @@
support.
For fault tolerance and raid support (i.e. volume and stripe sets), you can
-use the kernel's Software RAID / MD driver. See section "Using Software RAID
+use the kernel's Software RAID / MD driver. See section "Using Software RAID
with NTFS" for details.
@@ -64,14 +64,18 @@
time find . -type f -exec md5sum "{}" \;
run three times in sequence with each driver (after a reboot) on a 1.4GiB
NTFS partition, showed the new driver to be 20% faster in total time elapsed
- (from 9:43 minutes on average down to 7:53). The time spent in user space
+ (from 9:43 minutes on average down to 7:53). The time spent in user space
was unchanged but the time spent in the kernel was decreased by a factor of
2.5 (from 85 CPU seconds down to 33).
-- The driver does not support short file names in general. For backwards
+- The driver does not support short file names in general. For backwards
compatibility, we implement access to files using their short file names if
- they exist. The driver will not create short file names however, and a rename
- will discard any existing short file name.
+ they exist. The driver will not create short file names however, and a
+ rename will discard any existing short file name.
- The new driver supports exporting of mounted NTFS volumes via NFS.
+- The new driver supports async io (aio).
+- The new driver supports fsync(2), fdatasync(2), and msync(2).
+- The new driver supports readv(2) and writev(2).
+- The new driver supports access time updates (including mtime and ctime).
Supported mount options
@@ -273,6 +277,8 @@
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
+2.1.17:
+ - Fix bugs in mount time error code paths.
2.1.16:
- Implement access time updates (including mtime and ctime).
- Implement fsync(2), fdatasync(2), and msync(2) system calls.
diff -Nru a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog
--- a/fs/ntfs/ChangeLog 2004-08-18 20:50:51 +01:00
+++ b/fs/ntfs/ChangeLog 2004-08-18 20:50:51 +01:00
@@ -21,7 +21,7 @@
- Enable the code for setting the NT4 compatibility flag when we start
making NTFS 1.2 specific modifications.
-2.1.17 - WIP.
+2.1.17 - Fix bugs in mount time error code paths and other updates.
- Implement bitmap modification code (fs/ntfs/bitmap.[hc]). This
includes functions to set/clear a single bit or a run of bits.
diff -Nru a/fs/ntfs/Makefile b/fs/ntfs/Makefile
--- a/fs/ntfs/Makefile 2004-08-18 20:50:51 +01:00
+++ b/fs/ntfs/Makefile 2004-08-18 20:50:51 +01:00
@@ -6,7 +6,7 @@
index.o inode.o mft.o mst.o namei.o super.o sysctl.o unistr.o \
upcase.o
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.17-WIP\"
+EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.17\"
ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2004-08-23 11:11 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-23 10:25 [2.6-BK-URL] NTFS 2.1.17 release Anton Altaparmakov
2004-08-23 10:28 ` [PATCH 1/20] " Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 2/20] " Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 3/20] " Anton Altaparmakov
2004-08-23 10:29 ` [PATCH 4/20] " Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 5/20] " Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 6/20] " Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 7/20] " Anton Altaparmakov
2004-08-23 10:30 ` [PATCH 8/20] " Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 9/20] " Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 10/20] " Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 11/20] " Anton Altaparmakov
2004-08-23 10:31 ` [PATCH 12/20] " Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 13/20] " Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 14/20] " Anton Altaparmakov
2004-08-23 10:32 ` [PATCH 15/20] " Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 16/20] " Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 17/20] " Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 18/20] " Anton Altaparmakov
2004-08-23 10:33 ` [PATCH 19/20] " Anton Altaparmakov
2004-08-23 10:34 ` [PATCH 20/20] " Anton Altaparmakov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).