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
3f7fc6f2
Commit
3f7fc6f2
authored
Oct 16, 2014
by
Anton Altaparmakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NTFS: Add bmap address space operation needed for FIBMAP ioctl.
Signed-off-by:
Anton Altaparmakov
<
anton@tuxera.com
>
parent
2b522cc1
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
124 additions
and
0 deletions
+124
-0
fs/ntfs/aops.c
fs/ntfs/aops.c
+124
-0
No files found.
fs/ntfs/aops.c
View file @
3f7fc6f2
...
...
@@ -1537,6 +1537,129 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc)
#endif
/* NTFS_RW */
/**
* ntfs_bmap - map logical file block to physical device block
* @mapping: address space mapping to which the block to be mapped belongs
* @block: logical block to map to its physical device block
*
* For regular, non-resident files (i.e. not compressed and not encrypted), map
* the logical @block belonging to the file described by the address space
* mapping @mapping to its physical device block.
*
* The size of the block is equal to the @s_blocksize field of the super block
* of the mounted file system which is guaranteed to be smaller than or equal
* to the cluster size thus the block is guaranteed to fit entirely inside the
* cluster which means we do not need to care how many contiguous bytes are
* available after the beginning of the block.
*
* Return the physical device block if the mapping succeeded or 0 if the block
* is sparse or there was an error.
*
* Note: This is a problem if someone tries to run bmap() on $Boot system file
* as that really is in block zero but there is nothing we can do. bmap() is
* just broken in that respect (just like it cannot distinguish sparse from
* not available or error).
*/
static
sector_t
ntfs_bmap
(
struct
address_space
*
mapping
,
sector_t
block
)
{
s64
ofs
,
size
;
loff_t
i_size
;
LCN
lcn
;
unsigned
long
blocksize
,
flags
;
ntfs_inode
*
ni
=
NTFS_I
(
mapping
->
host
);
ntfs_volume
*
vol
=
ni
->
vol
;
unsigned
delta
;
unsigned
char
blocksize_bits
,
cluster_size_shift
;
ntfs_debug
(
"Entering for mft_no 0x%lx, logical block 0x%llx."
,
ni
->
mft_no
,
(
unsigned
long
long
)
block
);
if
(
ni
->
type
!=
AT_DATA
||
!
NInoNonResident
(
ni
)
||
NInoEncrypted
(
ni
))
{
ntfs_error
(
vol
->
sb
,
"BMAP does not make sense for %s "
"attributes, returning 0."
,
(
ni
->
type
!=
AT_DATA
)
?
"non-data"
:
(
!
NInoNonResident
(
ni
)
?
"resident"
:
"encrypted"
));
return
0
;
}
/* None of these can happen. */
BUG_ON
(
NInoCompressed
(
ni
));
BUG_ON
(
NInoMstProtected
(
ni
));
blocksize
=
vol
->
sb
->
s_blocksize
;
blocksize_bits
=
vol
->
sb
->
s_blocksize_bits
;
ofs
=
(
s64
)
block
<<
blocksize_bits
;
read_lock_irqsave
(
&
ni
->
size_lock
,
flags
);
size
=
ni
->
initialized_size
;
i_size
=
i_size_read
(
VFS_I
(
ni
));
read_unlock_irqrestore
(
&
ni
->
size_lock
,
flags
);
/*
* If the offset is outside the initialized size or the block straddles
* the initialized size then pretend it is a hole unless the
* initialized size equals the file size.
*/
if
(
unlikely
(
ofs
>=
size
||
(
ofs
+
blocksize
>
size
&&
size
<
i_size
)))
goto
hole
;
cluster_size_shift
=
vol
->
cluster_size_bits
;
down_read
(
&
ni
->
runlist
.
lock
);
lcn
=
ntfs_attr_vcn_to_lcn_nolock
(
ni
,
ofs
>>
cluster_size_shift
,
false
);
up_read
(
&
ni
->
runlist
.
lock
);
if
(
unlikely
(
lcn
<
LCN_HOLE
))
{
/*
* Step down to an integer to avoid gcc doing a long long
* comparision in the switch when we know @lcn is between
* LCN_HOLE and LCN_EIO (i.e. -1 to -5).
*
* Otherwise older gcc (at least on some architectures) will
* try to use __cmpdi2() which is of course not available in
* the kernel.
*/
switch
((
int
)
lcn
)
{
case
LCN_ENOENT
:
/*
* If the offset is out of bounds then pretend it is a
* hole.
*/
goto
hole
;
case
LCN_ENOMEM
:
ntfs_error
(
vol
->
sb
,
"Not enough memory to complete "
"mapping for inode 0x%lx. "
"Returning 0."
,
ni
->
mft_no
);
break
;
default:
ntfs_error
(
vol
->
sb
,
"Failed to complete mapping for "
"inode 0x%lx. Run chkdsk. "
"Returning 0."
,
ni
->
mft_no
);
break
;
}
return
0
;
}
if
(
lcn
<
0
)
{
/* It is a hole. */
hole:
ntfs_debug
(
"Done (returning hole)."
);
return
0
;
}
/*
* The block is really allocated and fullfils all our criteria.
* Convert the cluster to units of block size and return the result.
*/
delta
=
ofs
&
vol
->
cluster_size_mask
;
if
(
unlikely
(
sizeof
(
block
)
<
sizeof
(
lcn
)))
{
block
=
lcn
=
((
lcn
<<
cluster_size_shift
)
+
delta
)
>>
blocksize_bits
;
/* If the block number was truncated return 0. */
if
(
unlikely
(
block
!=
lcn
))
{
ntfs_error
(
vol
->
sb
,
"Physical block 0x%llx is too "
"large to be returned, returning 0."
,
(
long
long
)
lcn
);
return
0
;
}
}
else
block
=
((
lcn
<<
cluster_size_shift
)
+
delta
)
>>
blocksize_bits
;
ntfs_debug
(
"Done (returning block 0x%llx)."
,
(
unsigned
long
long
)
lcn
);
return
block
;
}
/**
* ntfs_normal_aops - address space operations for normal inodes and attributes
*
...
...
@@ -1549,6 +1672,7 @@ const struct address_space_operations ntfs_normal_aops = {
.
writepage
=
ntfs_writepage
,
.
set_page_dirty
=
__set_page_dirty_buffers
,
#endif
/* NTFS_RW */
.
bmap
=
ntfs_bmap
,
.
migratepage
=
buffer_migrate_page
,
.
is_partially_uptodate
=
block_is_partially_uptodate
,
.
error_remove_page
=
generic_error_remove_page
,
...
...
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