Commit ad71d86a authored by Anton Altaparmakov's avatar Anton Altaparmakov

Merge cantab.net:/home/aia21/bklinux-2.6

into cantab.net:/home/aia21/ntfs-2.6
parents 3dbdb149 cd090b6d
...@@ -20,6 +20,11 @@ ToDo: ...@@ -20,6 +20,11 @@ ToDo:
sufficient for synchronisation here. We then just need to make sure sufficient for synchronisation here. We then just need to make sure
ntfs_readpage/writepage/truncate interoperate properly with us. ntfs_readpage/writepage/truncate interoperate properly with us.
2.1.7 - WIP
- Set i_generation in the VFS inode from the seq_no of the NTFS inode.
- Make ntfs_lookup() NFS export safe, i.e. use d_splice_alias(), etc.
2.1.6 - Fix minor bug in handling of compressed directories. 2.1.6 - Fix minor bug in handling of compressed directories.
- Fix bug in handling of compressed directories. A compressed - Fix bug in handling of compressed directories. A compressed
......
...@@ -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.1.6\" EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.7-WIP\"
ifeq ($(CONFIG_NTFS_DEBUG),y) ifeq ($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
......
...@@ -533,7 +533,7 @@ static int ntfs_read_locked_inode(struct inode *vi) ...@@ -533,7 +533,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
} }
/* Transfer information from mft record into vfs and ntfs inodes. */ /* Transfer information from mft record into vfs and ntfs inodes. */
ni->seq_no = le16_to_cpu(m->sequence_number); vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number);
/* /*
* FIXME: Keep in mind that link_count is two for files which have both * FIXME: Keep in mind that link_count is two for files which have both
...@@ -1109,7 +1109,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) ...@@ -1109,7 +1109,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
vi->i_mtime = base_vi->i_mtime; vi->i_mtime = base_vi->i_mtime;
vi->i_ctime = base_vi->i_ctime; vi->i_ctime = base_vi->i_ctime;
vi->i_atime = base_vi->i_atime; vi->i_atime = base_vi->i_atime;
ni->seq_no = base_ni->seq_no; vi->i_generation = ni->seq_no = base_ni->seq_no;
/* Set inode type to zero but preserve permissions. */ /* Set inode type to zero but preserve permissions. */
vi->i_mode = base_vi->i_mode & ~S_IFMT; vi->i_mode = base_vi->i_mode & ~S_IFMT;
...@@ -1414,7 +1414,7 @@ void ntfs_read_inode_mount(struct inode *vi) ...@@ -1414,7 +1414,7 @@ void ntfs_read_inode_mount(struct inode *vi)
} }
/* Need this to sanity check attribute list references to $MFT. */ /* Need this to sanity check attribute list references to $MFT. */
ni->seq_no = le16_to_cpu(m->sequence_number); vi->i_generation = ni->seq_no = le16_to_cpu(m->sequence_number);
/* Provides readpage() and sync_page() for map_mft_record(). */ /* Provides readpage() and sync_page() for map_mft_record(). */
vi->i_mapping->a_ops = &ntfs_mft_aops; vi->i_mapping->a_ops = &ntfs_mft_aops;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* layout.h - All NTFS associated on-disk structures. Part of the Linux-NTFS * layout.h - All NTFS associated on-disk structures. Part of the Linux-NTFS
* project. * project.
* *
* Copyright (c) 2001-2003 Anton Altaparmakov * Copyright (c) 2001-2004 Anton Altaparmakov
* Copyright (c) 2002 Richard Russon * Copyright (c) 2002 Richard Russon
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
...@@ -941,7 +941,7 @@ typedef struct { ...@@ -941,7 +941,7 @@ typedef struct {
modified. */ modified. */
/* 18*/ s64 last_mft_change_time; /* Time this mft record was last /* 18*/ s64 last_mft_change_time; /* Time this mft record was last
modified. */ modified. */
/* 20*/ s64 last_access_time; /* Last time this mft record was /* 20*/ s64 last_access_time; /* Time this mft record was last
accessed. */ accessed. */
/* 28*/ s64 allocated_size; /* Byte size of allocated space for the /* 28*/ s64 allocated_size; /* Byte size of allocated space for the
data attribute. NOTE: Is a multiple data attribute. NOTE: Is a multiple
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS
* project. * project.
* *
* Copyright (c) 2001-2003 Anton Altaparmakov * Copyright (c) 2001-2004 Anton Altaparmakov
* *
* This program/include file is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License as published
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
*/ */
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/security.h>
#include "ntfs.h" #include "ntfs.h"
#include "dir.h" #include "dir.h"
...@@ -41,16 +42,17 @@ ...@@ -41,16 +42,17 @@
* @dir_ino looking for the converted Unicode name. If the name is found in the * @dir_ino looking for the converted Unicode name. If the name is found in the
* directory, the corresponding inode is loaded by calling ntfs_iget() on its * directory, the corresponding inode is loaded by calling ntfs_iget() on its
* inode number and the inode is associated with the dentry @dent via a call to * inode number and the inode is associated with the dentry @dent via a call to
* d_add(). * d_splice_alias().
* *
* If the name is not found in the directory, a NULL inode is inserted into the * If the name is not found in the directory, a NULL inode is inserted into the
* dentry @dent. The dentry is then termed a negative dentry. * dentry @dent via a call to d_add(). The dentry is then termed a negative
* dentry.
* *
* Only if an actual error occurs, do we return an error via ERR_PTR(). * Only if an actual error occurs, do we return an error via ERR_PTR().
* *
* In order to handle the case insensitivity issues of NTFS with regards to the * In order to handle the case insensitivity issues of NTFS with regards to the
* dcache and the dcache requiring only one dentry per directory, we deal with * dcache and the dcache requiring only one dentry per directory, we deal with
* dentry aliases that only differ in case in ->ntfs_lookup() while maintining * dentry aliases that only differ in case in ->ntfs_lookup() while maintaining
* a case sensitive dcache. This means that we get the full benefit of dcache * a case sensitive dcache. This means that we get the full benefit of dcache
* speed when the file/directory is looked up with the same case as returned by * speed when the file/directory is looked up with the same case as returned by
* ->ntfs_readdir() but that a lookup for any other case (or for the short file * ->ntfs_readdir() but that a lookup for any other case (or for the short file
...@@ -70,15 +72,18 @@ ...@@ -70,15 +72,18 @@
* 1) @dent perfectly matches (i.e. including case) a directory entry with a * 1) @dent perfectly matches (i.e. including case) a directory entry with a
* file name in the WIN32 or POSIX namespaces. In this case * file name in the WIN32 or POSIX namespaces. In this case
* ntfs_lookup_inode_by_name() will return with name set to NULL and we * ntfs_lookup_inode_by_name() will return with name set to NULL and we
* just d_add() @dent. * just d_splice_alias() @dent.
* 2) @dent matches (not including case) a directory entry with a file name in * 2) @dent matches (not including case) a directory entry with a file name in
* the WIN32 namespace. In this case ntfs_lookup_inode_by_name() will return * the WIN32 namespace. In this case ntfs_lookup_inode_by_name() will return
* with name set to point to a kmalloc()ed ntfs_name structure containing * with name set to point to a kmalloc()ed ntfs_name structure containing
* the properly cased little endian Unicode name. We convert the name to the * the properly cased little endian Unicode name. We convert the name to the
* current NLS code page, search if a dentry with this name already exists * current NLS code page, search if a dentry with this name already exists
* and if so return that instead of @dent. The VFS will then destroy the old * and if so return that instead of @dent. At this point things are
* @dent and use the one we returned. If a dentry is not found, we allocate * complicated by the possibility of 'disconnected' dentries due to NFS
* a new one, d_add() it, and return it as above. * which we deal with appropriately (see the code comments). The VFS will
* then destroy the old @dent and use the one we returned. If a dentry is
* not found, we allocate a new one, d_splice_alias() it, and return it as
* above.
* 3) @dent matches either perfectly or not (i.e. we don't care about case) a * 3) @dent matches either perfectly or not (i.e. we don't care about case) a
* directory entry with a file name in the DOS namespace. In this case * directory entry with a file name in the DOS namespace. In this case
* ntfs_lookup_inode_by_name() will return with name set to point to a * ntfs_lookup_inode_by_name() will return with name set to point to a
...@@ -120,7 +125,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -120,7 +125,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
dent_ino == FILE_MFT) { dent_ino == FILE_MFT) {
/* Perfect WIN32/POSIX match. -- Case 1. */ /* Perfect WIN32/POSIX match. -- Case 1. */
if (!name) { if (!name) {
d_add(dent, dent_inode); d_splice_alias(dent_inode, dent);
ntfs_debug("Done."); ntfs_debug("Done.");
return NULL; return NULL;
} }
...@@ -132,7 +137,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -132,7 +137,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
} }
ntfs_error(vol->sb, "Found stale reference to inode " ntfs_error(vol->sb, "Found stale reference to inode "
"0x%lx (reference sequence number = " "0x%lx (reference sequence number = "
"0x%x, inode sequence number = 0x%x, " "0x%x, inode sequence number = 0x%x), "
"returning -EIO. Run chkdsk.", "returning -EIO. Run chkdsk.",
dent_ino, MSEQNO(mref), dent_ino, MSEQNO(mref),
NTFS_I(dent_inode)->seq_no); NTFS_I(dent_inode)->seq_no);
...@@ -162,7 +167,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -162,7 +167,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
// TODO: Consider moving this lot to a separate function! (AIA) // TODO: Consider moving this lot to a separate function! (AIA)
handle_name: handle_name:
{ {
struct dentry *real_dent; struct dentry *real_dent, *new_dent;
MFT_RECORD *m; MFT_RECORD *m;
attr_search_context *ctx; attr_search_context *ctx;
ntfs_inode *ni = NTFS_I(dent_inode); ntfs_inode *ni = NTFS_I(dent_inode);
...@@ -173,8 +178,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -173,8 +178,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
if (name->type != FILE_NAME_DOS) { /* Case 2. */ if (name->type != FILE_NAME_DOS) { /* Case 2. */
nls_name.len = (unsigned)ntfs_ucstonls(vol, nls_name.len = (unsigned)ntfs_ucstonls(vol,
(uchar_t*)&name->name, name->len, (uchar_t*)&name->name, name->len,
(unsigned char**)&nls_name.name, (unsigned char**)&nls_name.name, 0);
name->len * 3 + 1);
kfree(name); kfree(name);
} else /* if (name->type == FILE_NAME_DOS) */ { /* Case 3. */ } else /* if (name->type == FILE_NAME_DOS) */ { /* Case 3. */
FILE_NAME_ATTR *fn; FILE_NAME_ATTR *fn;
...@@ -225,8 +229,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -225,8 +229,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
/* Convert the found WIN32 name to current NLS code page. */ /* Convert the found WIN32 name to current NLS code page. */
nls_name.len = (unsigned)ntfs_ucstonls(vol, nls_name.len = (unsigned)ntfs_ucstonls(vol,
(uchar_t*)&fn->file_name, fn->file_name_length, (uchar_t*)&fn->file_name, fn->file_name_length,
(unsigned char**)&nls_name.name, (unsigned char**)&nls_name.name, 0);
fn->file_name_length * 3 + 1);
put_attr_search_ctx(ctx); put_attr_search_ctx(ctx);
unmap_mft_record(ni); unmap_mft_record(ni);
...@@ -256,7 +259,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -256,7 +259,7 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
err = -ENOMEM; err = -ENOMEM;
goto err_out; goto err_out;
} }
d_add(real_dent, dent_inode); d_splice_alias(dent_inode, real_dent);
return real_dent; return real_dent;
} }
kfree(nls_name.name); kfree(nls_name.name);
...@@ -266,14 +269,54 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st ...@@ -266,14 +269,54 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
/* /*
* Already have the inode and the dentry attached, decrement * Already have the inode and the dentry attached, decrement
* the reference count to balance the ntfs_iget() we did * the reference count to balance the ntfs_iget() we did
* earlier on. * earlier on. We found the dentry using d_lookup() so it
* cannot be disconnected and thus we do not need to worry
* about any NFS/disconnectedness issues here.
*/ */
iput(dent_inode); iput(dent_inode);
return real_dent; return real_dent;
} }
/* Negative dentry: instantiate it. */ /*
d_instantiate(real_dent, dent_inode); * Negative dentry: instantiate it unless the inode is a directory and
return real_dent; * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED),
* in which case d_move() that in place of the found dentry.
*/
if (!S_ISDIR(dent_inode->i_mode)) {
/* Not a directory; everything is easy. */
d_instantiate(real_dent, dent_inode);
return real_dent;
}
spin_lock(&dcache_lock);
if (list_empty(&dent_inode->i_dentry)) {
/*
* Directory without a 'disconnected' dentry; we need to do
* d_instantiate() by hand because it takes dcache_lock which
* we already hold.
*/
list_add(&real_dent->d_alias, &dent_inode->i_dentry);
real_dent->d_inode = dent_inode;
spin_unlock(&dcache_lock);
security_d_instantiate(real_dent, dent_inode);
return real_dent;
}
/*
* Directory with a 'disconnected' dentry; get a reference to the
* 'disconnected' dentry.
*/
new_dent = list_entry(dent_inode->i_dentry.next, struct dentry,
d_alias);
dget_locked(new_dent);
spin_unlock(&dcache_lock);
/* Do security vodoo. */
security_d_instantiate(real_dent, dent_inode);
/* Move new_dent in place of real_dent. */
d_move(new_dent, real_dent);
/* Balance the ntfs_iget() we did above. */
iput(dent_inode);
/* Throw away real_dent. */
dput(real_dent);
/* Use new_dent as the actual dentry. */
return new_dent;
eio_err_out: eio_err_out:
ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk."); ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk.");
......
/* /*
* unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project. * unistr.c - NTFS Unicode string handling. Part of the Linux-NTFS project.
* *
* Copyright (c) 2001-2003 Anton Altaparmakov * Copyright (c) 2001-2004 Anton Altaparmakov
* *
* This program/include file is free software; you can redistribute it and/or * 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 * modify it under the terms of the GNU General Public License as published
...@@ -305,8 +305,9 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins, ...@@ -305,8 +305,9 @@ int ntfs_nlstoucs(const ntfs_volume *vol, const char *ins,
* Convert the input little endian, 2-byte Unicode string @ins, of length * Convert the input little endian, 2-byte Unicode string @ins, of length
* @ins_len into the string format dictated by the loaded NLS. * @ins_len into the string format dictated by the loaded NLS.
* *
* If @outs is NULL, this function allocates the string and the caller is * If *@outs is NULL, this function allocates the string and the caller is
* responsible for calling kfree(@outs); when finished with it. * responsible for calling kfree(*@outs); when finished with it. In this case
* @outs_len is ignored and can be 0.
* *
* On success the function returns the number of bytes written to the output * On success the function returns the number of bytes written to the output
* string *@outs (>= 0), not counting the terminating NULL byte. If the output * string *@outs (>= 0), not counting the terminating NULL byte. If the output
......
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