Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
3ddbbf30
Commit
3ddbbf30
authored
Apr 05, 2004
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Plain Diff
Merge cantab.net:/home/src/bklinux-2.6
into cantab.net:/home/src/ntfs-2.6
parents
196c4ebd
f1ca09a6
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
302 additions
and
60 deletions
+302
-60
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+2
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+22
-1
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+13
-12
fs/ntfs/dir.c
fs/ntfs/dir.c
+5
-3
fs/ntfs/inode.c
fs/ntfs/inode.c
+21
-14
fs/ntfs/layout.h
fs/ntfs/layout.h
+2
-2
fs/ntfs/namei.c
fs/ntfs/namei.c
+187
-21
fs/ntfs/super.c
fs/ntfs/super.c
+45
-3
fs/ntfs/unistr.c
fs/ntfs/unistr.c
+4
-3
No files found.
Documentation/filesystems/ntfs.txt
View file @
3ddbbf30
...
@@ -272,6 +272,8 @@ ChangeLog
...
@@ -272,6 +272,8 @@ 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.1.7:
- Enable NFS exporting of mounted NTFS volumes.
2.1.6:
2.1.6:
- Fix minor bug in handling of compressed directories that fixes the
- Fix minor bug in handling of compressed directories that fixes the
erroneous "du" and "stat" output people reported.
erroneous "du" and "stat" output people reported.
...
...
fs/ntfs/ChangeLog
View file @
3ddbbf30
ToDo:
ToDo:
- Find and fix bugs.
- Find and fix bugs.
- Enable NFS exporting of NTFS.
- Implement aops->set_page_dirty() in order to take control of buffer
- Implement aops->set_page_dirty() in order to take control of buffer
dirtying. Not having it means if page_has_buffers(), all buffers
dirtying. Not having it means if page_has_buffers(), all buffers
will be dirtied with the page. And if not they won't be. That is
will be dirtied with the page. And if not they won't be. That is
...
@@ -20,6 +19,24 @@ ToDo:
...
@@ -20,6 +19,24 @@ 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 - Enable NFS exporting of mounted NTFS volumes.
- 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.
- Implement ->get_dentry() in fs/ntfs/namei.c::ntfs_get_dentry() as the
default doesn't allow inode number 0 which is a valid inode on NTFS
and even if it did allow that it uses iget() instead of ntfs_iget()
which makes it useless for us.
- Implement ->get_parent() in fs/ntfs/namei.c::ntfs_get_parent() as the
default just returns -EACCES which is not very useful.
- Define export operations (->s_export_op) for NTFS (ntfs_export_ops)
and set them up in the super block at mount time (super.c) this
allows mounted NTFS volumes to be exported via NFS.
- Add missing return -EOPNOTSUPP; in
fs/ntfs/aops.c::ntfs_commit_nonresident_write().
- Enforce no atime and no dir atime updates at mount/remount time as
they are not implemented yet anyway.
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
...
@@ -60,6 +77,10 @@ ToDo:
...
@@ -60,6 +77,10 @@ ToDo:
- Reduce function local stack usage from 0x3d4 bytes to just noise in
- Reduce function local stack usage from 0x3d4 bytes to just noise in
fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>)
fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>)
- Remove compiler warnings for newer gcc.
- Remove compiler warnings for newer gcc.
- Pages are no longer kmapped by mm/filemap.c::generic_file_write()
around calls to ->{prepare,commit}_write. Adapt NTFS appropriately
in fs/ntfs/aops.c::ntfs_prepare_nonresident_write() by using
kmap_atomic(KM_USER0).
2.1.0 - First steps towards write support: implement file overwrite.
2.1.0 - First steps towards write support: implement file overwrite.
...
...
fs/ntfs/Makefile
View file @
3ddbbf30
...
@@ -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
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
3ddbbf30
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
* aops.c - NTFS kernel address space operations and page cache handling.
* aops.c - NTFS kernel address space operations and page cache handling.
* Part of the Linux-NTFS project.
* Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
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
...
@@ -1536,6 +1536,7 @@ static int ntfs_commit_nonresident_write(struct page *page,
...
@@ -1536,6 +1536,7 @@ static int ntfs_commit_nonresident_write(struct page *page,
if
(
pos
>
vi
->
i_size
)
{
if
(
pos
>
vi
->
i_size
)
{
ntfs_error
(
vi
->
i_sb
,
"Writing beyond the existing file size is "
ntfs_error
(
vi
->
i_sb
,
"Writing beyond the existing file size is "
"not supported yet. Sorry."
);
"not supported yet. Sorry."
);
return
-
EOPNOTSUPP
;
// vi->i_size = pos;
// vi->i_size = pos;
// mark_inode_dirty(vi);
// mark_inode_dirty(vi);
}
}
...
...
fs/ntfs/dir.c
View file @
3ddbbf30
/**
/**
* dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
* dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
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
...
@@ -200,7 +200,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -200,7 +200,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"and if that doesn't find any "
"and if that doesn't find any "
"errors please report you saw "
"errors please report you saw "
"this message to "
"this message to "
"linux-ntfs-dev@lists.sf.net."
);
"linux-ntfs-dev@lists."
"sourceforge.net."
);
goto
dir_err_out
;
goto
dir_err_out
;
}
}
...
@@ -457,7 +458,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
...
@@ -457,7 +458,8 @@ MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const uchar_t *uname,
"and if that doesn't find any "
"and if that doesn't find any "
"errors please report you saw "
"errors please report you saw "
"this message to "
"this message to "
"linux-ntfs-dev@lists.sf.net."
);
"linux-ntfs-dev@lists."
"sourceforge.net."
);
ntfs_unmap_page
(
page
);
ntfs_unmap_page
(
page
);
goto
dir_err_out
;
goto
dir_err_out
;
}
}
...
...
fs/ntfs/inode.c
View file @
3ddbbf30
...
@@ -196,7 +196,7 @@ struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
...
@@ -196,7 +196,7 @@ struct inode *ntfs_iget(struct super_block *sb, unsigned long mft_no)
}
}
/*
/*
* There is no point in keeping bad inodes around if the failure was
* There is no point in keeping bad inodes around if the failure was
* due to ENOMEM. We want to be able to retry again la
y
er.
* due to ENOMEM. We want to be able to retry again la
t
er.
*/
*/
if
(
err
==
-
ENOMEM
)
{
if
(
err
==
-
ENOMEM
)
{
iput
(
vi
);
iput
(
vi
);
...
@@ -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
;
...
@@ -1137,7 +1137,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1137,7 +1137,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"the attribute is resident (mft_no "
"the attribute is resident (mft_no "
"0x%lx, type 0x%x, name_len %i). "
"0x%lx, type 0x%x, name_len %i). "
"Please report you saw this message "
"Please report you saw this message "
"to linux-ntfs-dev@lists.sf.net"
,
"to linux-ntfs-dev@lists."
"sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
goto
unm_err_out
;
}
}
...
@@ -1157,8 +1158,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1157,8 +1158,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"type 0x%x, name_len %i). "
"Please report you saw this "
"Please report you saw this "
"message to linux-ntfs-dev@"
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
"lists.sourceforge.net"
,
ni
->
type
,
ni
->
name_len
);
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
goto
unm_err_out
;
}
}
NInoSetCompressed
(
ni
);
NInoSetCompressed
(
ni
);
...
@@ -1169,7 +1171,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1169,7 +1171,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"(mft_no 0x%lx, type 0x%x, "
"(mft_no 0x%lx, type 0x%x, "
"name_len %i). Please report "
"name_len %i). Please report "
"you saw this message to "
"you saw this message to "
"linux-ntfs-dev@lists.sf.net"
,
"linux-ntfs-dev@lists."
"sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
ni
->
name_len
);
goto
unm_err_out
;
goto
unm_err_out
;
...
@@ -1224,8 +1227,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1224,8 +1227,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"type 0x%x, name_len %i). "
"Please report you saw this "
"Please report you saw this "
"message to linux-ntfs-dev@"
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
"lists.sourceforge.net"
,
ni
->
type
,
ni
->
name_len
);
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
goto
unm_err_out
;
}
}
NInoSetEncrypted
(
ni
);
NInoSetEncrypted
(
ni
);
...
@@ -1238,8 +1242,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
...
@@ -1238,8 +1242,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"type 0x%x, name_len %i). "
"Please report you saw this "
"Please report you saw this "
"message to linux-ntfs-dev@"
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
"lists.sourceforge.net"
,
ni
->
type
,
ni
->
name_len
);
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
goto
unm_err_out
;
}
}
NInoSetSparse
(
ni
);
NInoSetSparse
(
ni
);
...
@@ -1414,7 +1419,7 @@ void ntfs_read_inode_mount(struct inode *vi)
...
@@ -1414,7 +1419,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
;
...
@@ -1541,7 +1546,8 @@ void ntfs_read_inode_mount(struct inode *vi)
...
@@ -1541,7 +1546,8 @@ void ntfs_read_inode_mount(struct inode *vi)
"of $MFT is not in the base "
"of $MFT is not in the base "
"mft record. Please report "
"mft record. Please report "
"you saw this message to "
"you saw this message to "
"linux-ntfs-dev@lists.sf.net"
);
"linux-ntfs-dev@lists."
"sourceforge.net"
);
goto
put_err_out
;
goto
put_err_out
;
}
else
{
}
else
{
/* Sequence numbers must match. */
/* Sequence numbers must match. */
...
@@ -1662,7 +1668,8 @@ void ntfs_read_inode_mount(struct inode *vi)
...
@@ -1662,7 +1668,8 @@ void ntfs_read_inode_mount(struct inode *vi)
"Run chkdsk and if no errors "
"Run chkdsk and if no errors "
"are found, please report you "
"are found, please report you "
"saw this message to "
"saw this message to "
"linux-ntfs-dev@lists.sf.net"
);
"linux-ntfs-dev@lists."
"sourceforge.net"
);
put_attr_search_ctx
(
ctx
);
put_attr_search_ctx
(
ctx
);
/* Revert to the safe super operations. */
/* Revert to the safe super operations. */
sb
->
s_op
=
&
ntfs_mount_sops
;
sb
->
s_op
=
&
ntfs_mount_sops
;
...
...
fs/ntfs/layout.h
View file @
3ddbbf30
...
@@ -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-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
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
...
...
fs/ntfs/namei.c
View file @
3ddbbf30
...
@@ -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-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
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 maint
a
ining
* 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. */
/*
* Negative dentry: instantiate it unless the inode is a directory and
* 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
);
d_instantiate
(
real_dent
,
dent_inode
);
return
real_dent
;
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."
);
...
@@ -288,10 +331,133 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
...
@@ -288,10 +331,133 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
}
}
}
}
/*
/*
*
* Inode operations for directories.
* Inode operations for directories.
*/
*/
struct
inode_operations
ntfs_dir_inode_ops
=
{
struct
inode_operations
ntfs_dir_inode_ops
=
{
.
lookup
=
ntfs_lookup
,
/* VFS: Lookup directory. */
.
lookup
=
ntfs_lookup
,
/* VFS: Lookup directory. */
};
};
/**
* ntfs_get_parent - find the dentry of the parent of a given directory dentry
* @child_dent: dentry of the directory whose parent directory to find
*
* Find the dentry for the parent directory of the directory specified by the
* dentry @child_dent. This function is called from
* fs/exportfs/expfs.c::find_exported_dentry() which in turn is called from the
* default ->decode_fh() which is export_decode_fh() in the same file.
*
* The code is based on the ext3 ->get_parent() implementation found in
* fs/ext3/namei.c::ext3_get_parent().
*
* Note: ntfs_get_parent() is called with @child_dent->d_inode->i_sem down.
*
* Return the dentry of the parent directory on success or the error code on
* error (IS_ERR() is true).
*/
struct
dentry
*
ntfs_get_parent
(
struct
dentry
*
child_dent
)
{
struct
inode
*
vi
=
child_dent
->
d_inode
;
ntfs_inode
*
ni
=
NTFS_I
(
vi
);
MFT_RECORD
*
mrec
;
attr_search_context
*
ctx
;
ATTR_RECORD
*
attr
;
FILE_NAME_ATTR
*
fn
;
struct
inode
*
parent_vi
;
struct
dentry
*
parent_dent
;
unsigned
long
parent_ino
;
ntfs_debug
(
"Entering for inode %lu."
,
vi
->
i_ino
);
/* Get the mft record of the inode belonging to the child dentry. */
mrec
=
map_mft_record
(
ni
);
if
(
unlikely
(
IS_ERR
(
mrec
)))
return
(
struct
dentry
*
)
mrec
;
/* Find the first file name attribute in the mft record. */
ctx
=
get_attr_search_ctx
(
ni
,
mrec
);
if
(
unlikely
(
!
ctx
))
{
unmap_mft_record
(
ni
);
return
ERR_PTR
(
-
ENOMEM
);
}
try_next:
if
(
unlikely
(
!
lookup_attr
(
AT_FILE_NAME
,
NULL
,
0
,
IGNORE_CASE
,
0
,
NULL
,
0
,
ctx
)))
{
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
return
ERR_PTR
(
-
ENOENT
);
}
attr
=
ctx
->
attr
;
if
(
unlikely
(
attr
->
non_resident
))
goto
try_next
;
fn
=
(
FILE_NAME_ATTR
*
)((
u8
*
)
attr
+
le16_to_cpu
(
attr
->
data
.
resident
.
value_offset
));
if
(
unlikely
((
u8
*
)
fn
+
le32_to_cpu
(
attr
->
data
.
resident
.
value_length
)
>
(
u8
*
)
attr
+
le32_to_cpu
(
attr
->
length
)))
goto
try_next
;
/* Get the inode number of the parent directory. */
parent_ino
=
MREF_LE
(
fn
->
parent_directory
);
/* Release the search context and the mft record of the child. */
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
/* Get the inode of the parent directory. */
parent_vi
=
ntfs_iget
(
vi
->
i_sb
,
parent_ino
);
if
(
unlikely
(
IS_ERR
(
parent_vi
)
||
is_bad_inode
(
parent_vi
)))
{
if
(
!
IS_ERR
(
parent_vi
))
iput
(
parent_vi
);
return
ERR_PTR
(
-
EACCES
);
}
/* Finally get a dentry for the parent directory and return it. */
parent_dent
=
d_alloc_anon
(
parent_vi
);
if
(
unlikely
(
!
parent_dent
))
{
iput
(
parent_vi
);
return
ERR_PTR
(
-
ENOMEM
);
}
ntfs_debug
(
"Done for inode %lu."
,
vi
->
i_ino
);
return
parent_dent
;
}
/**
* ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment
* @sb: super block identifying the mounted ntfs volume
* @fh: the file handle sub-fragment
*
* Find a dentry for the inode given a file handle sub-fragment. This function
* is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is
* called from the default ->decode_fh() which is export_decode_fh() in the
* same file. The code is closely based on the default ->get_dentry() helper
* fs/exportfs/expfs.c::get_object().
*
* The @fh contains two 32-bit unsigned values, the first one is the inode
* number and the second one is the inode generation.
*
* Return the dentry on success or the error code on error (IS_ERR() is true).
*/
struct
dentry
*
ntfs_get_dentry
(
struct
super_block
*
sb
,
void
*
fh
)
{
struct
inode
*
vi
;
struct
dentry
*
dent
;
unsigned
long
ino
=
((
u32
*
)
fh
)[
0
];
u32
gen
=
((
u32
*
)
fh
)[
1
];
ntfs_debug
(
"Entering for inode %lu, generation %u."
,
ino
,
gen
);
vi
=
ntfs_iget
(
sb
,
ino
);
if
(
unlikely
(
IS_ERR
(
vi
)))
return
(
struct
dentry
*
)
vi
;
if
(
unlikely
(
is_bad_inode
(
vi
)
||
vi
->
i_generation
!=
gen
))
{
/* We didn't find the right inode. */
ntfs_debug
(
"Inode %lu, bad count: %d %d or version %u %u."
,
vi
->
i_ino
,
vi
->
i_nlink
,
atomic_read
(
&
vi
->
i_count
),
vi
->
i_generation
,
gen
);
iput
(
vi
);
return
ERR_PTR
(
-
ESTALE
);
}
/* Now find a dentry. If possible, get a well-connected one. */
dent
=
d_alloc_anon
(
vi
);
if
(
unlikely
(
!
dent
))
{
iput
(
vi
);
return
ERR_PTR
(
-
ENOMEM
);
}
ntfs_debug
(
"Done for inode %lu, generation %u."
,
ino
,
gen
);
return
dent
;
}
fs/ntfs/super.c
View file @
3ddbbf30
/*
/*
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
* super.c - NTFS kernel super block handling. Part of the Linux-NTFS project.
*
*
* Copyright (c) 2001-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
Anton Altaparmakov
* Copyright (c) 2001,2002 Richard Russon
* Copyright (c) 2001,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
...
@@ -323,6 +323,9 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
...
@@ -323,6 +323,9 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
return
-
EROFS
;
return
-
EROFS
;
}
}
}
}
// TODO: For now we enforce no atime and dir atime updates as they are
// not implemented.
*
flags
|=
MS_NOATIME
|
MS_NODIRATIME
;
#endif
#endif
// 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
...
@@ -1338,6 +1341,40 @@ struct super_operations ntfs_sops = {
...
@@ -1338,6 +1341,40 @@ struct super_operations ntfs_sops = {
.
show_options
=
ntfs_show_options
,
/* Show mount options in proc. */
.
show_options
=
ntfs_show_options
,
/* Show mount options in proc. */
};
};
/**
* Declarations for NTFS specific export operations (fs/ntfs/namei.c).
*/
extern
struct
dentry
*
ntfs_get_parent
(
struct
dentry
*
child_dent
);
extern
struct
dentry
*
ntfs_get_dentry
(
struct
super_block
*
sb
,
void
*
fh
);
/**
* Export operations allowing NFS exporting of mounted NTFS partitions.
*
* We use the default ->decode_fh() and ->encode_fh() for now. Note that they
* use 32 bits to store the inode number which is an unsigned long so on 64-bit
* architectures is usually 64 bits so it would all fail horribly on huge
* volumes. I guess we need to define our own encode and decode fh functions
* that store 64-bit inode numbers at some point but for now we will ignore the
* problem...
*
* We also use the default ->get_name() helper (used by ->decode_fh() via
* fs/exportfs/expfs.c::find_exported_dentry()) as that is completely fs
* independent.
*
* The default ->get_parent() just returns -EACCES so we have to provide our
* own and the default ->get_dentry() is incompatible with NTFS due to not
* allowing the inode number 0 which is used in NTFS for the system file $MFT
* and due to using iget() whereas NTFS needs ntfs_iget().
*/
static
struct
export_operations
ntfs_export_ops
=
{
.
get_parent
=
ntfs_get_parent
,
/* Find the parent of a given
directory. */
.
get_dentry
=
ntfs_get_dentry
,
/* Find a dentry for the inode
given a file handle
sub-fragment. */
};
/**
/**
* ntfs_fill_super - mount an ntfs files system
* ntfs_fill_super - mount an ntfs files system
* @sb: super block of ntfs file system to mount
* @sb: super block of ntfs file system to mount
...
@@ -1366,6 +1403,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
...
@@ -1366,6 +1403,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_debug
(
"Entering."
);
ntfs_debug
(
"Entering."
);
#ifndef NTFS_RW
#ifndef NTFS_RW
sb
->
s_flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
sb
->
s_flags
|=
MS_RDONLY
|
MS_NOATIME
|
MS_NODIRATIME
;
#else
// TODO: For now we enforce no atime and dir atime updates as they are
// not implemented.
sb
->
s_flags
|=
MS_NOATIME
|
MS_NODIRATIME
;
#endif
#endif
/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
sb
->
s_fs_info
=
kmalloc
(
sizeof
(
ntfs_volume
),
GFP_NOFS
);
sb
->
s_fs_info
=
kmalloc
(
sizeof
(
ntfs_volume
),
GFP_NOFS
);
...
@@ -1544,6 +1585,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
...
@@ -1544,6 +1585,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
default_upcase
=
NULL
;
default_upcase
=
NULL
;
}
}
up
(
&
ntfs_lock
);
up
(
&
ntfs_lock
);
sb
->
s_export_op
=
&
ntfs_export_ops
;
return
0
;
return
0
;
}
}
ntfs_error
(
sb
,
"Failed to allocate root directory."
);
ntfs_error
(
sb
,
"Failed to allocate root directory."
);
...
@@ -1788,13 +1830,13 @@ static void __exit exit_ntfs_fs(void)
...
@@ -1788,13 +1830,13 @@ static void __exit exit_ntfs_fs(void)
printk
(
KERN_CRIT
"NTFS: This causes memory to leak! There is "
printk
(
KERN_CRIT
"NTFS: This causes memory to leak! There is "
"probably a BUG in the driver! Please report "
"probably a BUG in the driver! Please report "
"you saw this message to "
"you saw this message to "
"linux-ntfs-dev@lists.s
f
.net
\n
"
);
"linux-ntfs-dev@lists.s
ourceforge
.net
\n
"
);
/* Unregister the ntfs sysctls. */
/* Unregister the ntfs sysctls. */
ntfs_sysctl
(
0
);
ntfs_sysctl
(
0
);
}
}
MODULE_AUTHOR
(
"Anton Altaparmakov <aia21@cantab.net>"
);
MODULE_AUTHOR
(
"Anton Altaparmakov <aia21@cantab.net>"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
3
Anton Altaparmakov"
);
MODULE_DESCRIPTION
(
"NTFS 1.2/3.x driver - Copyright (c) 2001-200
4
Anton Altaparmakov"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
#ifdef DEBUG
#ifdef DEBUG
MODULE_PARM
(
debug_msgs
,
"i"
);
MODULE_PARM
(
debug_msgs
,
"i"
);
...
...
fs/ntfs/unistr.c
View file @
3ddbbf30
/*
/*
* 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-200
3
Anton Altaparmakov
* Copyright (c) 2001-200
4
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment