Commit db05cffc authored by Anton Altaparmakov's avatar Anton Altaparmakov

NTFS: 2.0.15 - Fake inodes based attribute i/o via the pagecache, fixes, cleanups.

- Fix silly bug in fs/ntfs/super.c::parse_options() which was causing
  remounts to fail when the partition had an entry in /etc/fstab and
  the entry specified the nls= option.
- Apply same macro magic used in fs/ntfs/inode.h to fs/ntfs/volume.h to
  expand all the helper functions NVolFoo(), NVolSetFoo(), and
  NVolClearFoo().
- Move copyright statement from driver initialisation message to
  module description (fs/super.c). This makes the initialisation
  message fit on one line and fits in better with rest of kernel.
- Update fs/ntfs/attrib.c::map_run_list() to work on both real and
  attribute inodes, and both for files and directories.
- Implement fake attribute inodes allowing all attribute i/o to go via
  the page cache and to use all the normal vfs/mm functionality:
  - Add ntfs_attr_iget() and its helper ntfs_read_locked_attr_inode()
    to fs/ntfs/inode.c.
  - Add needed cleanup code to ntfs_clear_big_inode().
- Merge address space operations for files and directories (aops.c),
  now just have ntfs_aops:
  - Rename:
        end_buffer_read_attr_async() -> ntfs_end_buffer_read_async(),
        ntfs_attr_read_block()       -> ntfs_read_block(),
        ntfs_file_read_page()        -> ntfs_readpage().
  - Rewrite fs/ntfs/aops.c::ntfs_readpage() to work on both real and
    attribute inodes, and both for files and directories.
  - Remove obsolete fs/ntfs/aops.c::ntfs_mst_readpage().
parent 5a597e77
...@@ -247,6 +247,11 @@ ChangeLog ...@@ -247,6 +247,11 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.15:
- Bug fix in parsing of remount options.
- Internal changes implementing attribute (fake) inodes allowing all
attribute i/o to go via the page cache and to use all the normal
vfs/mm functionality.
2.0.14: 2.0.14:
- Internal changes improving run list merging code and minor locking - Internal changes improving run list merging code and minor locking
change to not rely on BKL in ntfs_statfs(). change to not rely on BKL in ntfs_statfs().
......
...@@ -26,7 +26,34 @@ ToDo: ...@@ -26,7 +26,34 @@ ToDo:
callers, i.e. ntfs_iget(), to pass that error code up instead of just callers, i.e. ntfs_iget(), to pass that error code up instead of just
using -EIO. using -EIO.
- Enable NFS exporting of NTFS. - Enable NFS exporting of NTFS.
- Use fake inodes for address space i/o.
2.0.15 - Fake inodes based attribute i/o via the pagecache, fixes and cleanups.
- Fix silly bug in fs/ntfs/super.c::parse_options() which was causing
remounts to fail when the partition had an entry in /etc/fstab and
the entry specified the nls= option.
- Apply same macro magic used in fs/ntfs/inode.h to fs/ntfs/volume.h to
expand all the helper functions NVolFoo(), NVolSetFoo(), and
NVolClearFoo().
- Move copyright statement from driver initialisation message to
module description (fs/super.c). This makes the initialisation
message fit on one line and fits in better with rest of kernel.
- Update fs/ntfs/attrib.c::map_run_list() to work on both real and
attribute inodes, and both for files and directories.
- Implement fake attribute inodes allowing all attribute i/o to go via
the page cache and to use all the normal vfs/mm functionality:
- Add ntfs_attr_iget() and its helper ntfs_read_locked_attr_inode()
to fs/ntfs/inode.c.
- Add needed cleanup code to ntfs_clear_big_inode().
- Merge address space operations for files and directories (aops.c),
now just have ntfs_aops:
- Rename:
end_buffer_read_attr_async() -> ntfs_end_buffer_read_async(),
ntfs_attr_read_block() -> ntfs_read_block(),
ntfs_file_read_page() -> ntfs_readpage().
- Rewrite fs/ntfs/aops.c::ntfs_readpage() to work on both real and
attribute inodes, and both for files and directories.
- Remove obsolete fs/ntfs/aops.c::ntfs_mst_readpage().
2.0.14 - Run list merging code cleanup, minor locking changes, typo fixes. 2.0.14 - Run list merging code cleanup, minor locking changes, typo fixes.
......
...@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o ...@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \ ntfs-objs := aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o \
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.14\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.0.15\"
ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "ntfs.h" #include "ntfs.h"
/** /**
* end_buffer_read_attr_async - async io completion for reading attributes * ntfs_end_buffer_read_async - async io completion for reading attributes
* @bh: buffer head on which io is completed * @bh: buffer head on which io is completed
* @uptodate: whether @bh is now uptodate or not * @uptodate: whether @bh is now uptodate or not
* *
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
* record size, and index_block_size_bits, to the log(base 2) of the ntfs * record size, and index_block_size_bits, to the log(base 2) of the ntfs
* record size. * record size.
*/ */
static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate) static void ntfs_end_buffer_read_async(struct buffer_head *bh, int uptodate)
{ {
static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED; static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags; unsigned long flags;
...@@ -143,12 +143,12 @@ static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate) ...@@ -143,12 +143,12 @@ static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate)
} }
/** /**
* ntfs_attr_read_block - fill a @page of an address space with data * ntfs_read_block - fill a @page of an address space with data
* @page: page cache page to fill with data * @page: page cache page to fill with data
* *
* Fill the page @page of the address space belonging to the @page->host inode. * Fill the page @page of the address space belonging to the @page->host inode.
* We read each buffer asynchronously and when all buffers are read in, our io * We read each buffer asynchronously and when all buffers are read in, our io
* completion handler end_buffer_read_attr_async(), if required, automatically * completion handler ntfs_end_buffer_read_async(), if required, automatically
* applies the mst fixups to the page before finally marking it uptodate and * applies the mst fixups to the page before finally marking it uptodate and
* unlocking it. * unlocking it.
* *
...@@ -156,7 +156,7 @@ static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate) ...@@ -156,7 +156,7 @@ static void end_buffer_read_attr_async(struct buffer_head *bh, int uptodate)
* *
* Contains an adapted version of fs/buffer.c::block_read_full_page(). * Contains an adapted version of fs/buffer.c::block_read_full_page().
*/ */
static int ntfs_attr_read_block(struct page *page) static int ntfs_read_block(struct page *page)
{ {
VCN vcn; VCN vcn;
LCN lcn; LCN lcn;
...@@ -267,7 +267,7 @@ static int ntfs_attr_read_block(struct page *page) ...@@ -267,7 +267,7 @@ static int ntfs_attr_read_block(struct page *page)
for (i = 0; i < nr; i++) { for (i = 0; i < nr; i++) {
struct buffer_head *tbh = arr[i]; struct buffer_head *tbh = arr[i];
lock_buffer(tbh); lock_buffer(tbh);
tbh->b_end_io = end_buffer_read_attr_async; tbh->b_end_io = ntfs_end_buffer_read_async;
set_buffer_async_read(tbh); set_buffer_async_read(tbh);
} }
/* Finally, start i/o on the buffers. */ /* Finally, start i/o on the buffers. */
...@@ -285,27 +285,27 @@ static int ntfs_attr_read_block(struct page *page) ...@@ -285,27 +285,27 @@ static int ntfs_attr_read_block(struct page *page)
} }
/** /**
* ntfs_file_readpage - fill a @page of a @file with data from the device * ntfs_readpage - fill a @page of a @file with data from the device
* @file: open file to which the page @page belongs or NULL * @file: open file to which the page @page belongs or NULL
* @page: page cache page to fill with data * @page: page cache page to fill with data
* *
* For non-resident attributes, ntfs_file_readpage() fills the @page of the open * For non-resident attributes, ntfs_readpage() fills the @page of the open
* file @file by calling the ntfs version of the generic block_read_full_page() * file @file by calling the ntfs version of the generic block_read_full_page()
* function provided by the kernel, ntfs_attr_read_block(), which in turn * function, ntfs_read_block(), which in turn creates and reads in the buffers
* creates and reads in the buffers associated with the page asynchronously. * associated with the page asynchronously.
* *
* For resident attributes, OTOH, ntfs_file_readpage() fills @page by copying * For resident attributes, OTOH, ntfs_readpage() fills @page by copying the
* the data from the mft record (which at this stage is most likely in memory) * data from the mft record (which at this stage is most likely in memory) and
* and fills the remainder with zeroes. Thus, in this case, I/O is synchronous, * fills the remainder with zeroes. Thus, in this case, I/O is synchronous, as
* as even if the mft record is not cached at this point in time, we need to * even if the mft record is not cached at this point in time, we need to wait
* wait for it to be read in before we can do the copy. * for it to be read in before we can do the copy.
* *
* Return 0 on success or -errno on error. * Return 0 on success and -errno on error.
*/ */
static int ntfs_file_readpage(struct file *file, struct page *page) int ntfs_readpage(struct file *file, struct page *page)
{ {
s64 attr_pos; s64 attr_pos;
ntfs_inode *ni; ntfs_inode *ni, *base_ni;
char *addr; char *addr;
attr_search_context *ctx; attr_search_context *ctx;
MFT_RECORD *mrec; MFT_RECORD *mrec;
...@@ -317,40 +317,45 @@ static int ntfs_file_readpage(struct file *file, struct page *page) ...@@ -317,40 +317,45 @@ static int ntfs_file_readpage(struct file *file, struct page *page)
ni = NTFS_I(page->mapping->host); ni = NTFS_I(page->mapping->host);
/* Is the unnamed $DATA attribute resident? */
if (NInoNonResident(ni)) { if (NInoNonResident(ni)) {
/* Attribute is not resident. */ /*
* Only unnamed $DATA attributes can be compressed or
/* If the file is encrypted, we deny access, just like NT4. */ * encrypted.
if (NInoEncrypted(ni)) { */
err = -EACCES; if (ni->type == AT_DATA && !ni->name_len) {
goto unl_err_out; /* If file is encrypted, deny access, just like NT4. */
if (NInoEncrypted(ni)) {
err = -EACCES;
goto err_out;
}
/* Compressed data streams are handled in compress.c. */
if (NInoCompressed(ni))
return ntfs_file_read_compressed_block(page);
} }
/* Compressed data stream. Handled in compress.c. */
if (NInoCompressed(ni))
return ntfs_file_read_compressed_block(page);
/* Normal data stream. */ /* Normal data stream. */
return ntfs_attr_read_block(page); return ntfs_read_block(page);
} }
/* Attribute is resident, implying it is not compressed or encrypted. */ /* Attribute is resident, implying it is not compressed or encrypted. */
if (!NInoAttr(ni))
base_ni = ni;
else
base_ni = ni->_INE(base_ntfs_ino);
/* Map, pin and lock the mft record for reading. */ /* Map, pin and lock the mft record for reading. */
mrec = map_mft_record(READ, ni); mrec = map_mft_record(READ, base_ni);
if (unlikely(IS_ERR(mrec))) { if (unlikely(IS_ERR(mrec))) {
err = PTR_ERR(mrec); err = PTR_ERR(mrec);
goto unl_err_out; goto err_out;
} }
ctx = get_attr_search_ctx(base_ni, mrec);
ctx = get_attr_search_ctx(ni, mrec);
if (unlikely(!ctx)) { if (unlikely(!ctx)) {
err = -ENOMEM; err = -ENOMEM;
goto unm_unl_err_out; goto unm_err_out;
} }
if (unlikely(!lookup_attr(ni->type, ni->name, ni->name_len,
/* Find the data attribute in the mft record. */ IGNORE_CASE, 0, NULL, 0, ctx))) {
if (unlikely(!lookup_attr(AT_DATA, NULL, 0, 0, 0, NULL, 0, ctx))) {
err = -ENOENT; err = -ENOENT;
goto put_unm_unl_err_out; goto put_unm_err_out;
} }
/* Starting position of the page within the attribute value. */ /* Starting position of the page within the attribute value. */
...@@ -377,34 +382,15 @@ static int ntfs_file_readpage(struct file *file, struct page *page) ...@@ -377,34 +382,15 @@ static int ntfs_file_readpage(struct file *file, struct page *page)
kunmap(page); kunmap(page);
SetPageUptodate(page); SetPageUptodate(page);
put_unm_unl_err_out: put_unm_err_out:
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
unm_unl_err_out: unm_err_out:
unmap_mft_record(READ, ni); unmap_mft_record(READ, base_ni);
unl_err_out: err_out:
unlock_page(page); unlock_page(page);
return err; return err;
} }
/**
* ntfs_mst_readpage - fill a @page of the mft or a directory with data
* @file: open file/directory to which the @page belongs or NULL
* @page: page cache page to fill with data
*
* Readpage method for the VFS address space operations of directory inodes
* and the $MFT/$DATA attribute.
*
* We just call ntfs_attr_read_block() here, in fact we only need this wrapper
* because of the difference in function parameters.
*/
int ntfs_mst_readpage(struct file *file, struct page *page)
{
if (unlikely(!PageLocked(page)))
PAGE_BUG(page);
return ntfs_attr_read_block(page);
}
/** /**
* end_buffer_read_mftbmp_async - * end_buffer_read_mftbmp_async -
* *
...@@ -473,7 +459,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate) ...@@ -473,7 +459,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate)
/** /**
* ntfs_mftbmp_readpage - * ntfs_mftbmp_readpage -
* *
* Readpage for accessing mft bitmap. Adapted from ntfs_mst_readpage(). * Readpage for accessing mft bitmap.
*/ */
static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page) static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
{ {
...@@ -587,11 +573,11 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page) ...@@ -587,11 +573,11 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
} }
/** /**
* ntfs_file_aops - address space operations for accessing normal file data * ntfs_aops - general address space operations for inodes and attributes
*/ */
struct address_space_operations ntfs_file_aops = { struct address_space_operations ntfs_aops = {
writepage: NULL, /* Write dirty page to disk. */ writepage: NULL, /* Write dirty page to disk. */
readpage: ntfs_file_readpage, /* Fill page with data. */ readpage: ntfs_readpage, /* Fill page with data. */
sync_page: block_sync_page, /* Currently, just unplugs the sync_page: block_sync_page, /* Currently, just unplugs the
disk request queue. */ disk request queue. */
prepare_write: NULL, /* . */ prepare_write: NULL, /* . */
...@@ -613,20 +599,3 @@ struct address_space_operations ntfs_mftbmp_aops = { ...@@ -613,20 +599,3 @@ struct address_space_operations ntfs_mftbmp_aops = {
commit_write: NULL, /* . */ commit_write: NULL, /* . */
}; };
/**
* ntfs_dir_aops -
*
* Address space operations for accessing normal directory data (i.e. index
* allocation attribute). We can't just use the same operations as for files
* because 1) the attribute is different and even more importantly 2) the index
* records have to be multi sector transfer deprotected (i.e. fixed-up).
*/
struct address_space_operations ntfs_dir_aops = {
writepage: NULL, /* Write dirty page to disk. */
readpage: ntfs_mst_readpage, /* Fill page with data. */
sync_page: block_sync_page, /* Currently, just unplugs the
disk request queue. */
prepare_write: NULL, /* . */
commit_write: NULL, /* . */
};
...@@ -935,78 +935,51 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol, ...@@ -935,78 +935,51 @@ run_list_element *decompress_mapping_pairs(const ntfs_volume *vol,
*/ */
int map_run_list(ntfs_inode *ni, VCN vcn) int map_run_list(ntfs_inode *ni, VCN vcn)
{ {
ntfs_inode *base_ni;
attr_search_context *ctx; attr_search_context *ctx;
MFT_RECORD *mrec; MFT_RECORD *mrec;
const uchar_t *name;
u32 name_len;
ATTR_TYPES at;
int err = 0; int err = 0;
ntfs_debug("Mapping run list part containing vcn 0x%Lx.", ntfs_debug("Mapping run list part containing vcn 0x%Lx.",
(long long)vcn); (long long)vcn);
/* Map, pin and lock the mft record for reading. */ if (!NInoAttr(ni))
mrec = map_mft_record(READ, ni); base_ni = ni;
else
base_ni = ni->_INE(base_ntfs_ino);
mrec = map_mft_record(READ, base_ni);
if (IS_ERR(mrec)) if (IS_ERR(mrec))
return PTR_ERR(mrec); return PTR_ERR(mrec);
ctx = get_attr_search_ctx(base_ni, mrec);
ctx = get_attr_search_ctx(ni, mrec);
if (!ctx) { if (!ctx) {
err = -ENOMEM; err = -ENOMEM;
goto unm_err_out; goto err_out;
}
/* The attribute type is determined from the inode type. */
if (S_ISDIR(VFS_I(ni)->i_mode)) {
at = AT_INDEX_ALLOCATION;
name = I30;
name_len = 4;
} else {
at = AT_DATA;
name = NULL;
name_len = 0;
} }
if (!lookup_attr(ni->type, ni->name, ni->name_len, IGNORE_CASE, vcn,
/* Find the attribute in the mft record. */ NULL, 0, ctx)) {
if (!lookup_attr(at, name, name_len, CASE_SENSITIVE, vcn, NULL, 0,
ctx)) {
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
err = -ENOENT; err = -ENOENT;
goto unm_err_out; goto err_out;
} }
/* Lock the run list. */
down_write(&ni->run_list.lock); down_write(&ni->run_list.lock);
/* Make sure someone else didn't do the work while we were spinning. */ /* Make sure someone else didn't do the work while we were spinning. */
if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) { if (likely(vcn_to_lcn(ni->run_list.rl, vcn) <= LCN_RL_NOT_MAPPED)) {
run_list_element *rl; run_list_element *rl;
/* Decode the run list. */
rl = decompress_mapping_pairs(ni->vol, ctx->attr, rl = decompress_mapping_pairs(ni->vol, ctx->attr,
ni->run_list.rl); ni->run_list.rl);
/* Flag any errors or set the run list if successful. */
if (unlikely(IS_ERR(rl))) if (unlikely(IS_ERR(rl)))
err = PTR_ERR(rl); err = PTR_ERR(rl);
else else
ni->run_list.rl = rl; ni->run_list.rl = rl;
} }
/* Unlock the run list. */
up_write(&ni->run_list.lock); up_write(&ni->run_list.lock);
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
err_out:
/* Unlock, unpin and release the mft record. */ unmap_mft_record(READ, base_ni);
unmap_mft_record(READ, ni);
/* If an error occured, return it. */
ntfs_debug("Done.");
return err;
unm_err_out:
unmap_mft_record(READ, ni);
return err; return err;
} }
......
...@@ -462,6 +462,11 @@ int ntfs_file_read_compressed_block(struct page *page) ...@@ -462,6 +462,11 @@ int ntfs_file_read_compressed_block(struct page *page)
ntfs_debug("Entering, page->index = 0x%lx, cb_size = 0x%x, nr_pages = " ntfs_debug("Entering, page->index = 0x%lx, cb_size = 0x%x, nr_pages = "
"%i.", index, cb_size, nr_pages); "%i.", index, cb_size, nr_pages);
/*
* Bad things happen if we get here for anything that is not an
* unnamed $DATA attribute.
*/
BUG_ON(ni->type != AT_DATA || ni->name_len);
pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS); pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS);
......
This diff is collapsed.
...@@ -95,8 +95,10 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec) ...@@ -95,8 +95,10 @@ int format_mft_record(ntfs_inode *ni, MFT_RECORD *mft_rec)
return 0; return 0;
} }
/* From fs/ntfs/aops.c */ /**
extern int ntfs_mst_readpage(struct file *, struct page *); * From fs/ntfs/aops.c
*/
extern int ntfs_readpage(struct file *, struct page *);
/** /**
* ntfs_mft_aops - address space operations for access to $MFT * ntfs_mft_aops - address space operations for access to $MFT
...@@ -106,7 +108,7 @@ extern int ntfs_mst_readpage(struct file *, struct page *); ...@@ -106,7 +108,7 @@ extern int ntfs_mst_readpage(struct file *, struct page *);
*/ */
struct address_space_operations ntfs_mft_aops = { struct address_space_operations ntfs_mft_aops = {
writepage: NULL, /* Write dirty page to disk. */ writepage: NULL, /* Write dirty page to disk. */
readpage: ntfs_mst_readpage, /* Fill page with data. */ readpage: ntfs_readpage, /* Fill page with data. */
sync_page: block_sync_page, /* Currently, just unplugs the sync_page: block_sync_page, /* Currently, just unplugs the
disk request queue. */ disk request queue. */
prepare_write: NULL, /* . */ prepare_write: NULL, /* . */
...@@ -214,11 +216,11 @@ static inline void unmap_mft_record_page(ntfs_inode *ni) ...@@ -214,11 +216,11 @@ static inline void unmap_mft_record_page(ntfs_inode *ni)
* necessary, increments the use count on the page so that it cannot disappear * necessary, increments the use count on the page so that it cannot disappear
* under us and returns a reference to the page cache page). * under us and returns a reference to the page cache page).
* *
* If read_cache_page() invokes ntfs_mst_readpage() to load the page from disk, * If read_cache_page() invokes ntfs_readpage() to load the page from disk, it
* it sets PG_locked and clears PG_uptodate on the page. Once I/O has * sets PG_locked and clears PG_uptodate on the page. Once I/O has completed
* completed and the post-read mst fixups on each mft record in the page have * and the post-read mst fixups on each mft record in the page have been
* been performed, the page gets PG_uptodate set and PG_locked cleared (this is * performed, the page gets PG_uptodate set and PG_locked cleared (this is done
* done in our asynchronous I/O completion handler end_buffer_read_mft_async()). * in our asynchronous I/O completion handler end_buffer_read_mft_async()).
* ntfs_map_page() waits for PG_locked to become clear and checks if * ntfs_map_page() waits for PG_locked to become clear and checks if
* PG_uptodate is set and returns an error code if not. This provides * PG_uptodate is set and returns an error code if not. This provides
* sufficient protection against races when reading/using the page. * sufficient protection against races when reading/using the page.
......
...@@ -62,18 +62,21 @@ extern kmem_cache_t *ntfs_big_inode_cache; ...@@ -62,18 +62,21 @@ extern kmem_cache_t *ntfs_big_inode_cache;
extern kmem_cache_t *ntfs_attr_ctx_cache; extern kmem_cache_t *ntfs_attr_ctx_cache;
/* The various operations structs defined throughout the driver files. */ /* The various operations structs defined throughout the driver files. */
extern struct super_operations ntfs_mount_sops;
extern struct super_operations ntfs_sops; extern struct super_operations ntfs_sops;
extern struct file_operations ntfs_file_ops; extern struct super_operations ntfs_mount_sops;
extern struct address_space_operations ntfs_aops;
extern struct address_space_operations ntfs_mft_aops;
extern struct address_space_operations ntfs_mftbmp_aops;
extern struct file_operations ntfs_file_ops;
extern struct inode_operations ntfs_file_inode_ops; extern struct inode_operations ntfs_file_inode_ops;
extern struct address_space_operations ntfs_file_aops;
extern struct file_operations ntfs_dir_ops; extern struct file_operations ntfs_dir_ops;
extern struct inode_operations ntfs_dir_inode_ops; extern struct inode_operations ntfs_dir_inode_ops;
extern struct address_space_operations ntfs_dir_aops;
extern struct file_operations ntfs_empty_file_ops; extern struct file_operations ntfs_empty_file_ops;
extern struct inode_operations ntfs_empty_inode_ops; extern struct inode_operations ntfs_empty_inode_ops;
extern struct address_space_operations ntfs_mft_aops;
extern struct address_space_operations ntfs_mftbmp_aops;
/* Generic macro to convert pointers to values for comparison purposes. */ /* Generic macro to convert pointers to values for comparison purposes. */
#ifndef p2n #ifndef p2n
......
...@@ -135,6 +135,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt) ...@@ -135,6 +135,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
} }
if (!opt || !*opt) if (!opt || !*opt)
goto no_mount_options; goto no_mount_options;
ntfs_debug("Entering with mount options string: %s", opt);
while ((p = strsep(&opt, ","))) { while ((p = strsep(&opt, ","))) {
if ((v = strchr(p, '='))) if ((v = strchr(p, '=')))
*v++ = '\0'; *v++ = '\0';
...@@ -217,7 +218,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt) ...@@ -217,7 +218,7 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
} }
} }
if (nls_map) { if (nls_map) {
if (vol->nls_map) { if (vol->nls_map && vol->nls_map != nls_map) {
ntfs_error(vol->sb, "Cannot change NLS character set " ntfs_error(vol->sb, "Cannot change NLS character set "
"on remount."); "on remount.");
return FALSE; return FALSE;
...@@ -249,8 +250,8 @@ static BOOL parse_options(ntfs_volume *vol, char *opt) ...@@ -249,8 +250,8 @@ static BOOL parse_options(ntfs_volume *vol, char *opt)
mft_zone_multiplier = 1; mft_zone_multiplier = 1;
} }
vol->mft_zone_multiplier = mft_zone_multiplier; vol->mft_zone_multiplier = mft_zone_multiplier;
} if (!vol->mft_zone_multiplier) }
/* Not specified and it is the first mount, so set default. */ if (!vol->mft_zone_multiplier)
vol->mft_zone_multiplier = 1; vol->mft_zone_multiplier = 1;
if (on_errors != -1) if (on_errors != -1)
vol->on_errors = on_errors; vol->on_errors = on_errors;
...@@ -304,7 +305,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt) ...@@ -304,7 +305,7 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
{ {
ntfs_volume *vol = NTFS_SB(sb); ntfs_volume *vol = NTFS_SB(sb);
ntfs_debug("Entering."); ntfs_debug("Entering with remount options string: %s", opt);
// FIXME/TODO: If left like this we will have problems with rw->ro and // 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. // ro->rw, as well as with sync->async and vice versa remounts.
...@@ -1799,7 +1800,7 @@ static int __init init_ntfs_fs(void) ...@@ -1799,7 +1800,7 @@ static int __init init_ntfs_fs(void)
#ifdef MODULE #ifdef MODULE
" MODULE" " MODULE"
#endif #endif
"]. Copyright (c) 2001,2002 Anton Altaparmakov.\n"); "].\n");
ntfs_debug("Debug messages are enabled."); ntfs_debug("Debug messages are enabled.");
...@@ -1899,7 +1900,7 @@ static void __exit exit_ntfs_fs(void) ...@@ -1899,7 +1900,7 @@ static void __exit exit_ntfs_fs(void)
} }
MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>"); MODULE_AUTHOR("Anton Altaparmakov <aia21@cantab.net>");
MODULE_DESCRIPTION("NTFS 1.2/3.x driver"); MODULE_DESCRIPTION("NTFS 1.2/3.x driver - Copyright (c) 2001-2002 Anton Altaparmakov");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef DEBUG #ifdef DEBUG
MODULE_PARM(debug_msgs, "i"); MODULE_PARM(debug_msgs, "i");
......
...@@ -26,31 +26,6 @@ ...@@ -26,31 +26,6 @@
#include "types.h" #include "types.h"
/*
* Defined bits for the flags field in the ntfs_volume structure.
*/
typedef enum {
NV_ShowSystemFiles, /* 1: Return system files in ntfs_readdir(). */
NV_CaseSensitive, /* 1: Treat file names as case sensitive and
create filenames in the POSIX namespace.
Otherwise be case insensitive and create
file names in WIN32 namespace. */
} ntfs_volume_flags;
#define NVolShowSystemFiles(n_vol) test_bit(NV_ShowSystemFiles, \
&(n_vol)->flags)
#define NVolSetShowSystemFiles(n_vol) set_bit(NV_ShowSystemFiles, \
&(n_vol)->flags)
#define NVolClearShowSystemFiles(n_vol) clear_bit(NV_ShowSystemFiles, \
&(n_vol)->flags)
#define NVolCaseSensitive(n_vol) test_bit(NV_CaseSensitive, \
&(n_vol)->flags)
#define NVolSetCaseSensitive(n_vol) set_bit(NV_CaseSensitive, \
&(n_vol)->flags)
#define NVolClearCaseSensitive(n_vol) clear_bit(NV_CaseSensitive, \
&(n_vol)->flags)
/* /*
* The NTFS in memory super block structure. * The NTFS in memory super block structure.
*/ */
...@@ -124,5 +99,38 @@ typedef struct { ...@@ -124,5 +99,38 @@ typedef struct {
struct nls_table *nls_map; struct nls_table *nls_map;
} ntfs_volume; } ntfs_volume;
/*
* Defined bits for the flags field in the ntfs_volume structure.
*/
typedef enum {
NV_ShowSystemFiles, /* 1: Return system files in ntfs_readdir(). */
NV_CaseSensitive, /* 1: Treat file names as case sensitive and
create filenames in the POSIX namespace.
Otherwise be case insensitive and create
file names in WIN32 namespace. */
} ntfs_volume_flags;
/*
* Macro tricks to expand the NVolFoo(), NVolSetFoo(), and NVolClearFoo()
* functions.
*/
#define NVOL_FNS(flag) \
static inline int NVol##flag(ntfs_volume *vol) \
{ \
return test_bit(NV_##flag, &(vol)->flags); \
} \
static inline void NVolSet##flag(ntfs_volume *vol) \
{ \
set_bit(NV_##flag, &(vol)->flags); \
} \
static inline void NVolClear##flag(ntfs_volume *vol) \
{ \
clear_bit(NV_##flag, &(vol)->flags); \
}
/* Emit the ntfs volume bitops functions. */
NVOL_FNS(ShowSystemFiles)
NVOL_FNS(CaseSensitive)
#endif /* _LINUX_NTFS_VOLUME_H */ #endif /* _LINUX_NTFS_VOLUME_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment