Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
79c914d9
Commit
79c914d9
authored
Apr 25, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-ntfs.bkbits.net/ntfs-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
d9fd3c1c
7eebd09b
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
323 additions
and
66 deletions
+323
-66
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+2
-0
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+24
-1
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+13
-12
fs/ntfs/attrib.c
fs/ntfs/attrib.c
+6
-3
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
+200
-24
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 @
79c914d9
...
...
@@ -272,6 +272,8 @@ 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:
- Fix minor bug in handling of compressed directories that fixes the
erroneous "du" and "stat" output people reported.
...
...
fs/ntfs/ChangeLog
View file @
79c914d9
ToDo:
- Find and fix bugs.
- Enable NFS exporting of NTFS.
- Implement aops->set_page_dirty() in order to take control of buffer
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
...
...
@@ -20,6 +19,26 @@ ToDo:
sufficient for synchronisation here. We then just need to make sure
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.
- Move a few assignments in fs/ntfs/attrib.c::load_attribute_list() to
after a NULL check. Thanks to Dave Jones for pointing this out.
2.1.6 - Fix minor bug in handling of compressed directories.
- Fix bug in handling of compressed directories. A compressed
...
...
@@ -60,6 +79,10 @@ ToDo:
- Reduce function local stack usage from 0x3d4 bytes to just noise in
fs/ntfs/upcase.c. (Randy Dunlap <rddunlap@osdl.ord>)
- 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.
...
...
fs/ntfs/Makefile
View file @
79c914d9
...
...
@@ -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
\
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)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
79c914d9
/**
* 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
*
* This program/include file is free software; you can redistribute it and/or
...
...
@@ -10,13 +10,13 @@
* 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
* 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
* 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
*/
...
...
@@ -572,11 +572,11 @@ static int ntfs_write_block(struct writeback_control *wbc, struct page *page)
// Again for each page do:
// - wait_on_page_locked()
// - Check (PageUptodate(page) &&
//
!PageError(page))
// !PageError(page))
// Update initialized size in the attribute and
// in the inode.
// Again, for each page do:
//
__set_page_dirty_buffers();
// __set_page_dirty_buffers();
// page_cache_release()
// We don't need to wait on the writes.
// Update iblock.
...
...
@@ -1112,11 +1112,11 @@ static int ntfs_prepare_nonresident_write(struct page *page,
// Again for each page do:
// - wait_on_page_locked()
// - Check (PageUptodate(page) &&
//
!PageError(page))
// !PageError(page))
// Update initialized size in the attribute and
// in the inode.
// Again, for each page do:
//
__set_page_dirty_buffers();
// __set_page_dirty_buffers();
// page_cache_release()
// We don't need to wait on the writes.
// Update iblock.
...
...
@@ -1188,7 +1188,7 @@ static int ntfs_prepare_nonresident_write(struct page *page,
// TODO: Instantiate the hole.
// clear_buffer_new(bh);
// unmap_underlying_metadata(bh->b_bdev,
//
bh->b_blocknr);
// bh->b_blocknr);
// For non-uptodate buffers, need to
// zero out the region outside the
// request in this bh or all bhs,
...
...
@@ -1279,7 +1279,7 @@ static int ntfs_prepare_nonresident_write(struct page *page,
if
(
PageUptodate
(
page
))
{
if
(
!
buffer_uptodate
(
bh
))
set_buffer_uptodate
(
bh
);
continue
;
continue
;
}
/*
* The page is not uptodate. The buffer is mapped. If it is not
...
...
@@ -1525,6 +1525,7 @@ static int ntfs_commit_nonresident_write(struct page *page,
if
(
pos
>
vi
->
i_size
)
{
ntfs_error
(
vi
->
i_sb
,
"Writing beyond the existing file size is "
"not supported yet. Sorry."
);
return
-
EOPNOTSUPP
;
// vi->i_size = pos;
// mark_inode_dirty(vi);
}
...
...
@@ -1708,7 +1709,7 @@ static int ntfs_commit_write(struct file *file, struct page *page,
/*
* Bring the out of bounds area(s) uptodate by copying data
* from the mft record to the page.
*/
*/
if
(
from
>
0
)
memcpy
(
kaddr
,
kattr
,
from
);
if
(
to
<
bytes
)
...
...
fs/ntfs/attrib.c
View file @
79c914d9
...
...
@@ -1235,11 +1235,11 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
u8
*
al_end
=
al
+
initialized_size
;
run_list_element
*
rl
;
struct
buffer_head
*
bh
;
struct
super_block
*
sb
=
vol
->
sb
;
unsigned
long
block_size
=
sb
->
s_blocksize
;
struct
super_block
*
sb
;
unsigned
long
block_size
;
unsigned
long
block
,
max_block
;
int
err
=
0
;
unsigned
char
block_size_bits
=
sb
->
s_blocksize_bits
;
unsigned
char
block_size_bits
;
ntfs_debug
(
"Entering."
);
if
(
!
vol
||
!
run_list
||
!
al
||
size
<=
0
||
initialized_size
<
0
||
...
...
@@ -1249,6 +1249,9 @@ int load_attribute_list(ntfs_volume *vol, run_list *run_list, u8 *al_start,
memset
(
al
,
0
,
size
);
return
0
;
}
sb
=
vol
->
sb
;
block_size
=
sb
->
s_blocksize
;
block_size_bits
=
sb
->
s_blocksize_bits
;
down_read
(
&
run_list
->
lock
);
rl
=
run_list
->
rl
;
/* Read all clusters specified by the run list one run at a time. */
...
...
fs/ntfs/dir.c
View file @
79c914d9
/**
* 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
*
* 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,
"and if that doesn't find any "
"errors please report you saw "
"this message to "
"linux-ntfs-dev@lists.sf.net."
);
"linux-ntfs-dev@lists."
"sourceforge.net."
);
goto
dir_err_out
;
}
...
...
@@ -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 "
"errors please report you saw "
"this message to "
"linux-ntfs-dev@lists.sf.net."
);
"linux-ntfs-dev@lists."
"sourceforge.net."
);
ntfs_unmap_page
(
page
);
goto
dir_err_out
;
}
...
...
fs/ntfs/inode.c
View file @
79c914d9
...
...
@@ -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
* 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
)
{
iput
(
vi
);
...
...
@@ -533,7 +533,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
}
/* 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
...
...
@@ -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_ctime
=
base_vi
->
i_ctime
;
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. */
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)
"the attribute is resident (mft_no "
"0x%lx, type 0x%x, name_len %i). "
"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
);
goto
unm_err_out
;
}
...
...
@@ -1157,8 +1158,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"Please report you saw this "
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
"lists.sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
}
NInoSetCompressed
(
ni
);
...
...
@@ -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, "
"name_len %i). Please report "
"you saw this message to "
"linux-ntfs-dev@lists.sf.net"
,
"linux-ntfs-dev@lists."
"sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
...
...
@@ -1224,8 +1227,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"Please report you saw this "
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
"lists.sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
}
NInoSetEncrypted
(
ni
);
...
...
@@ -1238,8 +1242,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
"type 0x%x, name_len %i). "
"Please report you saw this "
"message to linux-ntfs-dev@"
"lists.sf.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
"lists.sourceforge.net"
,
vi
->
i_ino
,
ni
->
type
,
ni
->
name_len
);
goto
unm_err_out
;
}
NInoSetSparse
(
ni
);
...
...
@@ -1414,7 +1419,7 @@ void ntfs_read_inode_mount(struct inode *vi)
}
/* 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(). */
vi
->
i_mapping
->
a_ops
=
&
ntfs_mft_aops
;
...
...
@@ -1541,7 +1546,8 @@ void ntfs_read_inode_mount(struct inode *vi)
"of $MFT is not in the base "
"mft record. Please report "
"you saw this message to "
"linux-ntfs-dev@lists.sf.net"
);
"linux-ntfs-dev@lists."
"sourceforge.net"
);
goto
put_err_out
;
}
else
{
/* Sequence numbers must match. */
...
...
@@ -1662,7 +1668,8 @@ void ntfs_read_inode_mount(struct inode *vi)
"Run chkdsk and if no errors "
"are found, please report you "
"saw this message to "
"linux-ntfs-dev@lists.sf.net"
);
"linux-ntfs-dev@lists."
"sourceforge.net"
);
put_attr_search_ctx
(
ctx
);
/* Revert to the safe super operations. */
sb
->
s_op
=
&
ntfs_mount_sops
;
...
...
fs/ntfs/layout.h
View file @
79c914d9
...
...
@@ -2,7 +2,7 @@
* layout.h - All NTFS associated on-disk structures. 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
*
* This program/include file is free software; you can redistribute it and/or
...
...
@@ -941,7 +941,7 @@ typedef struct {
modified. */
/* 18*/
s64
last_mft_change_time
;
/* Time this mft record was last
modified. */
/* 20*/
s64
last_access_time
;
/*
Last time this mft record was
/* 20*/
s64
last_access_time
;
/*
Time this mft record was last
accessed. */
/* 28*/
s64
allocated_size
;
/* Byte size of allocated space for the
data attribute. NOTE: Is a multiple
...
...
fs/ntfs/namei.c
View file @
79c914d9
...
...
@@ -2,7 +2,7 @@
* namei.c - NTFS kernel directory inode operations. 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
* modify it under the terms of the GNU General Public License as published
...
...
@@ -21,6 +21,7 @@
*/
#include <linux/dcache.h>
#include <linux/security.h>
#include "ntfs.h"
#include "dir.h"
...
...
@@ -41,16 +42,17 @@
* @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
* 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
* 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().
*
* 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
* 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
* 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
...
...
@@ -70,15 +72,18 @@
* 1) @dent perfectly matches (i.e. including case) a directory entry with a
* 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
* just d_
add
() @dent.
* just d_
splice_alias
() @dent.
* 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
* 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
* 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
* @dent and use the one we returned. If a dentry is not found, we allocate
* a new one, d_add() it, and return it as above.
* and if so return that instead of @dent. At this point things are
* complicated by the possibility of 'disconnected' dentries due to NFS
* 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
* 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
...
...
@@ -88,7 +93,8 @@
* name. We then convert the name to the current NLS code page, and proceed
* searching for a dentry with this name, etc, as in case 2), above.
*/
static
struct
dentry
*
ntfs_lookup
(
struct
inode
*
dir_ino
,
struct
dentry
*
dent
,
struct
nameidata
*
nd
)
static
struct
dentry
*
ntfs_lookup
(
struct
inode
*
dir_ino
,
struct
dentry
*
dent
,
struct
nameidata
*
nd
)
{
ntfs_volume
*
vol
=
NTFS_SB
(
dir_ino
->
i_sb
);
struct
inode
*
dent_inode
;
...
...
@@ -120,9 +126,8 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
dent_ino
==
FILE_MFT
)
{
/* Perfect WIN32/POSIX match. -- Case 1. */
if
(
!
name
)
{
d_add
(
dent
,
dent_inode
);
ntfs_debug
(
"Done."
);
return
NULL
;
return
d_splice_alias
(
dent_inode
,
dent
)
;
}
/*
* We are too indented. Handle imperfect
...
...
@@ -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 "
"0x%lx (reference sequence number = "
"0x%x, inode sequence number = 0x%x, "
"0x%x, inode sequence number = 0x%x
)
, "
"returning -EIO. Run chkdsk."
,
dent_ino
,
MSEQNO
(
mref
),
NTFS_I
(
dent_inode
)
->
seq_no
);
...
...
@@ -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)
handle_name:
{
struct
dentry
*
real_dent
;
struct
dentry
*
real_dent
,
*
new_dent
;
MFT_RECORD
*
m
;
attr_search_context
*
ctx
;
ntfs_inode
*
ni
=
NTFS_I
(
dent_inode
);
...
...
@@ -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. */
nls_name
.
len
=
(
unsigned
)
ntfs_ucstonls
(
vol
,
(
uchar_t
*
)
&
name
->
name
,
name
->
len
,
(
unsigned
char
**
)
&
nls_name
.
name
,
name
->
len
*
3
+
1
);
(
unsigned
char
**
)
&
nls_name
.
name
,
0
);
kfree
(
name
);
}
else
/* if (name->type == FILE_NAME_DOS) */
{
/* Case 3. */
FILE_NAME_ATTR
*
fn
;
...
...
@@ -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. */
nls_name
.
len
=
(
unsigned
)
ntfs_ucstonls
(
vol
,
(
uchar_t
*
)
&
fn
->
file_name
,
fn
->
file_name_length
,
(
unsigned
char
**
)
&
nls_name
.
name
,
fn
->
file_name_length
*
3
+
1
);
(
unsigned
char
**
)
&
nls_name
.
name
,
0
);
put_attr_search_ctx
(
ctx
);
unmap_mft_record
(
ni
);
...
...
@@ -256,8 +259,12 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
err
=
-
ENOMEM
;
goto
err_out
;
}
d_add
(
real_dent
,
dent_inode
);
return
real_dent
;
new_dent
=
d_splice_alias
(
dent_inode
,
real_dent
);
if
(
new_dent
)
dput
(
real_dent
);
else
new_dent
=
real_dent
;
return
new_dent
;
}
kfree
(
nls_name
.
name
);
/* Matching dentry exists, check if it is negative. */
...
...
@@ -266,14 +273,54 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
/*
* Already have the inode and the dentry attached, decrement
* 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
);
return
real_dent
;
}
/* Negative dentry: instantiate it. */
d_instantiate
(
real_dent
,
dent_inode
);
return
real_dent
;
/*
* 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
);
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:
ntfs_error
(
vol
->
sb
,
"Illegal file name attribute. Run chkdsk."
);
...
...
@@ -288,10 +335,139 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, st
}
}
/*
/*
*
* Inode operations for directories.
*/
struct
inode_operations
ntfs_dir_inode_ops
=
{
.
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 0x%lx."
,
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
);
ntfs_error
(
vi
->
i_sb
,
"Inode 0x%lx does not have a file name "
"attribute. Run chkdsk."
,
vi
->
i_ino
);
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
);
ntfs_error
(
vi
->
i_sb
,
"Failed to get parent directory inode "
"0x%lx of child inode 0x%lx."
,
parent_ino
,
vi
->
i_ino
);
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 0x%lx."
,
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 0x%lx, generation 0x%x."
,
ino
,
gen
);
vi
=
ntfs_iget
(
sb
,
ino
);
if
(
unlikely
(
IS_ERR
(
vi
)))
{
ntfs_error
(
sb
,
"Failed to get inode 0x%lx."
,
ino
);
return
(
struct
dentry
*
)
vi
;
}
if
(
unlikely
(
is_bad_inode
(
vi
)
||
vi
->
i_generation
!=
gen
))
{
/* We didn't find the right inode. */
ntfs_error
(
sb
,
"Inode 0x%lx, bad count: %d %d or version 0x%x "
"0x%x."
,
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 0x%lx, generation 0x%x."
,
ino
,
gen
);
return
dent
;
}
fs/ntfs/super.c
View file @
79c914d9
/*
* 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
*
* 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)
return
-
EROFS
;
}
}
// TODO: For now we enforce no atime and dir atime updates as they are
// not implemented.
*
flags
|=
MS_NOATIME
|
MS_NODIRATIME
;
#endif
// FIXME/TODO: If left like this we will have problems with rw->ro and
...
...
@@ -1338,6 +1341,40 @@ struct super_operations ntfs_sops = {
.
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
* @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)
ntfs_debug
(
"Entering."
);
#ifndef NTFS_RW
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
/* Allocate a new ntfs_volume and place it in sb->s_fs_info. */
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)
default_upcase
=
NULL
;
}
up
(
&
ntfs_lock
);
sb
->
s_export_op
=
&
ntfs_export_ops
;
return
0
;
}
ntfs_error
(
sb
,
"Failed to allocate root directory."
);
...
...
@@ -1788,13 +1830,13 @@ static void __exit exit_ntfs_fs(void)
printk
(
KERN_CRIT
"NTFS: This causes memory to leak! There is "
"probably a BUG in the driver! Please report "
"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. */
ntfs_sysctl
(
0
);
}
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"
);
#ifdef DEBUG
MODULE_PARM
(
debug_msgs
,
"i"
);
...
...
fs/ntfs/unistr.c
View file @
79c914d9
/*
* 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
* 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,
* Convert the input little endian, 2-byte Unicode string @ins, of length
* @ins_len into the string format dictated by the loaded NLS.
*
* If @outs is NULL, this function allocates the string and the caller is
* responsible for calling kfree(@outs); when finished with it.
* If *@outs is NULL, this function allocates the string and the caller is
* 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
* 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