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
2b8d99a7
Commit
2b8d99a7
authored
May 24, 2007
by
Chris Mason
Committed by
David Woodhouse
May 24, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: symlinks and hard links
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
e06afa83
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
147 additions
and
16 deletions
+147
-16
fs/btrfs/super.c
fs/btrfs/super.c
+147
-16
No files found.
fs/btrfs/super.c
View file @
2b8d99a7
...
@@ -26,11 +26,13 @@ struct btrfs_iget_args {
...
@@ -26,11 +26,13 @@ struct btrfs_iget_args {
#define BTRFS_SUPER_MAGIC 0x9123682E
#define BTRFS_SUPER_MAGIC 0x9123682E
static
struct
inode_operations
btrfs_dir_inode_operations
;
static
struct
inode_operations
btrfs_dir_inode_operations
;
static
struct
inode_operations
btrfs_symlink_inode_operations
;
static
struct
inode_operations
btrfs_dir_ro_inode_operations
;
static
struct
inode_operations
btrfs_dir_ro_inode_operations
;
static
struct
super_operations
btrfs_super_ops
;
static
struct
super_operations
btrfs_super_ops
;
static
struct
file_operations
btrfs_dir_file_operations
;
static
struct
file_operations
btrfs_dir_file_operations
;
static
struct
inode_operations
btrfs_file_inode_operations
;
static
struct
inode_operations
btrfs_file_inode_operations
;
static
struct
address_space_operations
btrfs_aops
;
static
struct
address_space_operations
btrfs_aops
;
static
struct
address_space_operations
btrfs_symlink_aops
;
static
struct
file_operations
btrfs_file_operations
;
static
struct
file_operations
btrfs_file_operations
;
static
void
btrfs_read_locked_inode
(
struct
inode
*
inode
)
static
void
btrfs_read_locked_inode
(
struct
inode
*
inode
)
...
@@ -103,7 +105,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
...
@@ -103,7 +105,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
inode
->
i_op
=
&
btrfs_dir_inode_operations
;
inode
->
i_op
=
&
btrfs_dir_inode_operations
;
break
;
break
;
case
S_IFLNK
:
case
S_IFLNK
:
// inode->i_op = &page_symlink_inode_operations;
inode
->
i_op
=
&
btrfs_symlink_inode_operations
;
inode
->
i_mapping
->
a_ops
=
&
btrfs_symlink_aops
;
break
;
break
;
}
}
return
;
return
;
...
@@ -940,6 +943,41 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
...
@@ -940,6 +943,41 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
return
err
;
return
err
;
}
}
static
int
btrfs_link
(
struct
dentry
*
old_dentry
,
struct
inode
*
dir
,
struct
dentry
*
dentry
)
{
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_root
*
root
=
BTRFS_I
(
dir
)
->
root
;
struct
inode
*
inode
=
old_dentry
->
d_inode
;
int
err
;
int
drop_inode
=
0
;
if
(
inode
->
i_nlink
==
0
)
return
-
ENOENT
;
inc_nlink
(
inode
);
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
btrfs_set_trans_block_group
(
trans
,
dir
);
atomic_inc
(
&
inode
->
i_count
);
err
=
btrfs_add_nondir
(
trans
,
dentry
,
inode
);
if
(
err
)
drop_inode
=
1
;
dir
->
i_sb
->
s_dirt
=
1
;
btrfs_update_inode_block_group
(
trans
,
dir
);
btrfs_update_inode
(
trans
,
root
,
inode
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
drop_inode
)
{
inode_dec_link_count
(
inode
);
iput
(
inode
);
}
btrfs_btree_balance_dirty
(
root
);
return
err
;
}
static
int
btrfs_make_empty_dir
(
struct
btrfs_trans_handle
*
trans
,
static
int
btrfs_make_empty_dir
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_root
*
root
,
u64
objectid
,
u64
dirid
)
u64
objectid
,
u64
dirid
)
...
@@ -2577,33 +2615,25 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
...
@@ -2577,33 +2615,25 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
}
}
ret
=
btrfs_add_link
(
trans
,
new_dentry
,
old_inode
);
if
(
ret
==
-
EEXIST
&&
new_inode
)
ret
=
0
;
else
if
(
ret
)
goto
out_fail
;
ret
=
btrfs_unlink_trans
(
trans
,
root
,
old_dir
,
old_dentry
);
ret
=
btrfs_unlink_trans
(
trans
,
root
,
old_dir
,
old_dentry
);
if
(
ret
)
if
(
ret
)
goto
out_fail
;
goto
out_fail
;
if
(
new_inode
)
{
if
(
new_inode
)
{
new_inode
->
i_ctime
=
CURRENT_TIME
;
new_inode
->
i_ctime
=
CURRENT_TIME
;
di
=
btrfs_lookup_dir_index_item
(
trans
,
root
,
path
,
ret
=
btrfs_unlink_trans
(
trans
,
root
,
new_dir
,
new_dentry
);
new_dir
->
i_ino
,
if
(
ret
)
new_inode
->
i_ino
,
goto
out_fail
;
new_dentry
->
d_name
.
name
,
new_dentry
->
d_name
.
len
,
-
1
);
if
(
di
&&
!
IS_ERR
(
di
))
{
btrfs_del_item
(
trans
,
root
,
path
);
btrfs_release_path
(
root
,
path
);
}
if
(
S_ISDIR
(
new_inode
->
i_mode
))
if
(
S_ISDIR
(
new_inode
->
i_mode
))
clear_nlink
(
new_inode
);
clear_nlink
(
new_inode
);
else
else
drop_nlink
(
new_inode
);
drop_nlink
(
new_inode
);
btrfs_update_inode
(
trans
,
root
,
new_inode
);
btrfs_update_inode
(
trans
,
root
,
new_inode
);
}
}
ret
=
btrfs_add_link
(
trans
,
new_dentry
,
old_inode
);
if
(
ret
)
goto
out_fail
;
out_fail:
out_fail:
btrfs_free_path
(
path
);
btrfs_free_path
(
path
);
btrfs_end_transaction
(
trans
,
root
);
btrfs_end_transaction
(
trans
,
root
);
...
@@ -2611,6 +2641,94 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
...
@@ -2611,6 +2641,94 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
return
ret
;
return
ret
;
}
}
static
int
btrfs_symlink
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
const
char
*
symname
)
{
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_root
*
root
=
BTRFS_I
(
dir
)
->
root
;
struct
btrfs_path
*
path
;
struct
btrfs_key
key
;
struct
inode
*
inode
;
int
err
;
int
drop_inode
=
0
;
u64
objectid
;
int
name_len
;
int
datasize
;
char
*
ptr
;
struct
btrfs_file_extent_item
*
ei
;
name_len
=
strlen
(
symname
)
+
1
;
if
(
name_len
>
BTRFS_MAX_INLINE_DATA_SIZE
(
root
))
return
-
ENAMETOOLONG
;
mutex_lock
(
&
root
->
fs_info
->
fs_mutex
);
trans
=
btrfs_start_transaction
(
root
,
1
);
btrfs_set_trans_block_group
(
trans
,
dir
);
err
=
btrfs_find_free_objectid
(
trans
,
root
,
dir
->
i_ino
,
&
objectid
);
if
(
err
)
{
err
=
-
ENOSPC
;
goto
out_unlock
;
}
inode
=
btrfs_new_inode
(
trans
,
root
,
objectid
,
BTRFS_I
(
dir
)
->
block_group
,
S_IFLNK
|
S_IRWXUGO
);
err
=
PTR_ERR
(
inode
);
if
(
IS_ERR
(
inode
))
goto
out_unlock
;
btrfs_set_trans_block_group
(
trans
,
inode
);
err
=
btrfs_add_nondir
(
trans
,
dentry
,
inode
);
if
(
err
)
drop_inode
=
1
;
else
{
inode
->
i_mapping
->
a_ops
=
&
btrfs_aops
;
inode
->
i_fop
=
&
btrfs_file_operations
;
inode
->
i_op
=
&
btrfs_file_inode_operations
;
}
dir
->
i_sb
->
s_dirt
=
1
;
btrfs_update_inode_block_group
(
trans
,
inode
);
btrfs_update_inode_block_group
(
trans
,
dir
);
if
(
drop_inode
)
goto
out_unlock
;
path
=
btrfs_alloc_path
();
BUG_ON
(
!
path
);
key
.
objectid
=
inode
->
i_ino
;
key
.
offset
=
0
;
key
.
flags
=
0
;
btrfs_set_key_type
(
&
key
,
BTRFS_EXTENT_DATA_KEY
);
datasize
=
btrfs_file_extent_calc_inline_size
(
name_len
);
err
=
btrfs_insert_empty_item
(
trans
,
root
,
path
,
&
key
,
datasize
);
BUG_ON
(
err
);
ei
=
btrfs_item_ptr
(
btrfs_buffer_leaf
(
path
->
nodes
[
0
]),
path
->
slots
[
0
],
struct
btrfs_file_extent_item
);
btrfs_set_file_extent_generation
(
ei
,
trans
->
transid
);
btrfs_set_file_extent_type
(
ei
,
BTRFS_FILE_EXTENT_INLINE
);
ptr
=
btrfs_file_extent_inline_start
(
ei
);
btrfs_memcpy
(
root
,
path
->
nodes
[
0
]
->
b_data
,
ptr
,
symname
,
name_len
);
mark_buffer_dirty
(
path
->
nodes
[
0
]);
btrfs_free_path
(
path
);
inode
->
i_op
=
&
btrfs_symlink_inode_operations
;
inode
->
i_mapping
->
a_ops
=
&
btrfs_symlink_aops
;
inode
->
i_size
=
name_len
-
1
;
btrfs_update_inode
(
trans
,
root
,
inode
);
err
=
0
;
out_unlock:
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
drop_inode
)
{
inode_dec_link_count
(
inode
);
iput
(
inode
);
}
btrfs_btree_balance_dirty
(
root
);
return
err
;
}
static
struct
file_system_type
btrfs_fs_type
=
{
static
struct
file_system_type
btrfs_fs_type
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"btrfs"
,
.
name
=
"btrfs"
,
...
@@ -2636,9 +2754,11 @@ static struct inode_operations btrfs_dir_inode_operations = {
...
@@ -2636,9 +2754,11 @@ static struct inode_operations btrfs_dir_inode_operations = {
.
lookup
=
btrfs_lookup
,
.
lookup
=
btrfs_lookup
,
.
create
=
btrfs_create
,
.
create
=
btrfs_create
,
.
unlink
=
btrfs_unlink
,
.
unlink
=
btrfs_unlink
,
.
link
=
btrfs_link
,
.
mkdir
=
btrfs_mkdir
,
.
mkdir
=
btrfs_mkdir
,
.
rmdir
=
btrfs_rmdir
,
.
rmdir
=
btrfs_rmdir
,
.
rename
=
btrfs_rename
,
.
rename
=
btrfs_rename
,
.
symlink
=
btrfs_symlink
,
};
};
static
struct
inode_operations
btrfs_dir_ro_inode_operations
=
{
static
struct
inode_operations
btrfs_dir_ro_inode_operations
=
{
...
@@ -2660,6 +2780,11 @@ static struct address_space_operations btrfs_aops = {
...
@@ -2660,6 +2780,11 @@ static struct address_space_operations btrfs_aops = {
.
commit_write
=
btrfs_commit_write
,
.
commit_write
=
btrfs_commit_write
,
};
};
static
struct
address_space_operations
btrfs_symlink_aops
=
{
.
readpage
=
btrfs_readpage
,
.
writepage
=
btrfs_writepage
,
};
static
struct
inode_operations
btrfs_file_inode_operations
=
{
static
struct
inode_operations
btrfs_file_inode_operations
=
{
.
truncate
=
btrfs_truncate
,
.
truncate
=
btrfs_truncate
,
.
getattr
=
btrfs_getattr
,
.
getattr
=
btrfs_getattr
,
...
@@ -2676,6 +2801,12 @@ static struct file_operations btrfs_file_operations = {
...
@@ -2676,6 +2801,12 @@ static struct file_operations btrfs_file_operations = {
.
fsync
=
btrfs_sync_file
,
.
fsync
=
btrfs_sync_file
,
};
};
static
struct
inode_operations
btrfs_symlink_inode_operations
=
{
.
readlink
=
generic_readlink
,
.
follow_link
=
page_follow_link_light
,
.
put_link
=
page_put_link
,
};
static
int
__init
init_btrfs_fs
(
void
)
static
int
__init
init_btrfs_fs
(
void
)
{
{
int
err
;
int
err
;
...
...
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