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
35b7e476
Commit
35b7e476
authored
May 02, 2007
by
Chris Mason
Committed by
David Woodhouse
May 02, 2007
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Btrfs: fix page cache memory leak
Signed-off-by:
Chris Mason
<
chris.mason@oracle.com
>
parent
090d1875
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
59 additions
and
45 deletions
+59
-45
fs/btrfs/bit-radix.c
fs/btrfs/bit-radix.c
+0
-2
fs/btrfs/ctree.h
fs/btrfs/ctree.h
+3
-0
fs/btrfs/dir-item.c
fs/btrfs/dir-item.c
+6
-5
fs/btrfs/disk-io.c
fs/btrfs/disk-io.c
+6
-2
fs/btrfs/disk-io.h
fs/btrfs/disk-io.h
+2
-0
fs/btrfs/extent-tree.c
fs/btrfs/extent-tree.c
+1
-11
fs/btrfs/hash.c
fs/btrfs/hash.c
+1
-0
fs/btrfs/print-tree.c
fs/btrfs/print-tree.c
+1
-0
fs/btrfs/super.c
fs/btrfs/super.c
+34
-22
fs/btrfs/transaction.c
fs/btrfs/transaction.c
+5
-3
No files found.
fs/btrfs/bit-radix.c
View file @
35b7e476
...
...
@@ -22,9 +22,7 @@ int set_radix_bit(struct radix_tree_root *radix, unsigned long bit)
return
-
ENOMEM
;
memset
(
bits
+
1
,
0
,
BIT_ARRAY_BYTES
-
sizeof
(
unsigned
long
));
bits
[
0
]
=
slot
;
radix_tree_preload
(
GFP_NOFS
);
ret
=
radix_tree_insert
(
radix
,
slot
,
bits
);
radix_tree_preload_end
();
if
(
ret
)
return
ret
;
}
...
...
fs/btrfs/ctree.h
View file @
35b7e476
...
...
@@ -8,6 +8,9 @@
struct
btrfs_trans_handle
;
struct
btrfs_transaction
;
extern
struct
kmem_cache
*
btrfs_trans_handle_cachep
;
extern
struct
kmem_cache
*
btrfs_transaction_cachep
;
extern
struct
kmem_cache
*
btrfs_bit_radix_cachep
;
extern
struct
kmem_cache
*
btrfs_path_cachep
;
#define BTRFS_MAGIC "_BtRfS_M"
...
...
fs/btrfs/dir-item.c
View file @
35b7e476
...
...
@@ -4,11 +4,12 @@
#include "hash.h"
#include "transaction.h"
struct
btrfs_dir_item
*
insert_with_overflow
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
cpu_key
,
u32
data_size
)
static
struct
btrfs_dir_item
*
insert_with_overflow
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
btrfs_path
*
path
,
struct
btrfs_key
*
cpu_key
,
u32
data_size
)
{
int
ret
;
char
*
ptr
;
...
...
fs/btrfs/disk-io.c
View file @
35b7e476
...
...
@@ -5,7 +5,7 @@
#include <linux/scatterlist.h>
#include <linux/swap.h>
#include <linux/radix-tree.h>
#include <linux/
file
.h>
#include <linux/
writeback
.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
...
...
@@ -694,7 +694,7 @@ static int free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
return
0
;
}
int
del_fs_roots
(
struct
btrfs_fs_info
*
fs_info
)
static
int
del_fs_roots
(
struct
btrfs_fs_info
*
fs_info
)
{
int
ret
;
struct
btrfs_root
*
gang
[
8
];
...
...
@@ -781,3 +781,7 @@ void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf)
brelse
(
buf
);
}
void
btrfs_btree_balance_dirty
(
struct
btrfs_root
*
root
)
{
balance_dirty_pages_ratelimited
(
root
->
fs_info
->
btree_inode
->
i_mapping
);
}
fs/btrfs/disk-io.h
View file @
35b7e476
...
...
@@ -55,4 +55,6 @@ int btrfs_insert_dev_radix(struct btrfs_root *root,
u64
num_blocks
);
int
btrfs_map_bh_to_logical
(
struct
btrfs_root
*
root
,
struct
buffer_head
*
bh
,
u64
logical
);
int
btrfs_releasepage
(
struct
page
*
page
,
gfp_t
flags
);
void
btrfs_btree_balance_dirty
(
struct
btrfs_root
*
root
);
#endif
fs/btrfs/extent-tree.c
View file @
35b7e476
...
...
@@ -322,18 +322,10 @@ static int update_block_group(struct btrfs_trans_handle *trans,
return
0
;
}
static
int
try_remove_page
(
struct
address_space
*
mapping
,
unsigned
long
index
)
{
int
ret
;
ret
=
invalidate_mapping_pages
(
mapping
,
index
,
index
);
return
ret
;
}
int
btrfs_finish_extent_commit
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
)
{
unsigned
long
gang
[
8
];
struct
inode
*
btree_inode
=
root
->
fs_info
->
btree_inode
;
u64
first
=
0
;
int
ret
;
int
i
;
...
...
@@ -348,9 +340,6 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
first
=
gang
[
0
];
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
clear_radix_bit
(
pinned_radix
,
gang
[
i
]);
try_remove_page
(
btree_inode
->
i_mapping
,
gang
[
i
]
<<
(
PAGE_CACHE_SHIFT
-
btree_inode
->
i_blkbits
));
}
}
return
0
;
...
...
@@ -983,6 +972,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
break
;
if
(
wret
<
0
)
ret
=
wret
;
btrfs_btree_balance_dirty
(
root
);
}
for
(
i
=
0
;
i
<=
orig_level
;
i
++
)
{
if
(
path
->
nodes
[
i
])
{
...
...
fs/btrfs/hash.c
View file @
35b7e476
...
...
@@ -11,6 +11,7 @@
*/
#include <linux/types.h>
#include "hash.h"
#define DELTA 0x9E3779B9
static
void
TEA_transform
(
__u32
buf
[
2
],
__u32
const
in
[])
...
...
fs/btrfs/print-tree.c
View file @
35b7e476
#include <linux/module.h>
#include "ctree.h"
#include "disk-io.h"
#include "print-tree.h"
void
btrfs_print_leaf
(
struct
btrfs_root
*
root
,
struct
btrfs_leaf
*
l
)
{
...
...
fs/btrfs/super.c
View file @
35b7e476
...
...
@@ -18,14 +18,14 @@
#include "btrfs_inode.h"
#include "ioctl.h"
void
btrfs_fsinfo_release
(
struct
kobject
*
obj
)
static
void
btrfs_fsinfo_release
(
struct
kobject
*
obj
)
{
struct
btrfs_fs_info
*
fsinfo
=
container_of
(
obj
,
struct
btrfs_fs_info
,
kobj
);
kfree
(
fsinfo
);
}
struct
kobj_type
btrfs_fsinfo_ktype
=
{
st
atic
st
ruct
kobj_type
btrfs_fsinfo_ktype
=
{
.
release
=
btrfs_fsinfo_release
,
};
...
...
@@ -148,7 +148,6 @@ static void fill_inode_item(struct btrfs_inode_item *item,
BTRFS_I
(
inode
)
->
block_group
->
key
.
objectid
);
}
static
int
btrfs_update_inode
(
struct
btrfs_trans_handle
*
trans
,
struct
btrfs_root
*
root
,
struct
inode
*
inode
)
...
...
@@ -251,6 +250,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
ret
=
btrfs_unlink_trans
(
trans
,
root
,
dir
,
dentry
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
return
ret
;
}
...
...
@@ -324,6 +324,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
btrfs_free_path
(
path
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
ret
=
btrfs_end_transaction
(
trans
,
root
);
btrfs_btree_balance_dirty
(
root
);
if
(
ret
&&
!
err
)
err
=
ret
;
return
err
;
...
...
@@ -449,6 +450,7 @@ static void btrfs_delete_inode(struct inode *inode)
btrfs_free_inode
(
trans
,
root
,
inode
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
return
;
no_delete:
clear_inode
(
inode
);
...
...
@@ -481,7 +483,7 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
return
ret
;
}
int
fixup_tree_root_location
(
struct
btrfs_root
*
root
,
static
int
fixup_tree_root_location
(
struct
btrfs_root
*
root
,
struct
btrfs_key
*
location
,
struct
btrfs_root
**
sub_root
)
{
...
...
@@ -512,7 +514,7 @@ int fixup_tree_root_location(struct btrfs_root *root,
return
0
;
}
int
btrfs_init_locked_inode
(
struct
inode
*
inode
,
void
*
p
)
static
int
btrfs_init_locked_inode
(
struct
inode
*
inode
,
void
*
p
)
{
struct
btrfs_iget_args
*
args
=
p
;
inode
->
i_ino
=
args
->
ino
;
...
...
@@ -520,15 +522,15 @@ int btrfs_init_locked_inode(struct inode *inode, void *p)
return
0
;
}
int
btrfs_find_actor
(
struct
inode
*
inode
,
void
*
opaque
)
static
int
btrfs_find_actor
(
struct
inode
*
inode
,
void
*
opaque
)
{
struct
btrfs_iget_args
*
args
=
opaque
;
return
(
args
->
ino
==
inode
->
i_ino
&&
args
->
root
==
BTRFS_I
(
inode
)
->
root
);
}
struct
inode
*
btrfs_iget_locked
(
struct
super_block
*
s
,
u64
objectid
,
struct
btrfs_root
*
root
)
st
atic
st
ruct
inode
*
btrfs_iget_locked
(
struct
super_block
*
s
,
u64
objectid
,
struct
btrfs_root
*
root
)
{
struct
inode
*
inode
;
struct
btrfs_iget_args
args
;
...
...
@@ -790,6 +792,7 @@ static void btrfs_dirty_inode(struct inode *inode)
btrfs_update_inode
(
trans
,
root
,
inode
);
btrfs_end_transaction
(
trans
,
root
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
}
static
struct
inode
*
btrfs_new_inode
(
struct
btrfs_trans_handle
*
trans
,
...
...
@@ -913,6 +916,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
inode_dec_link_count
(
inode
);
iput
(
inode
);
}
btrfs_btree_balance_dirty
(
root
);
return
err
;
}
...
...
@@ -1002,6 +1006,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
if
(
drop_on_err
)
iput
(
inode
);
btrfs_btree_balance_dirty
(
root
);
return
err
;
}
...
...
@@ -1099,7 +1104,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
found_type
!=
BTRFS_EXTENT_DATA_KEY
)
{
extent_end
=
0
;
extent_start
=
0
;
btrfs_release_path
(
root
,
path
);
goto
out
;
}
found_type
=
btrfs_file_extent_type
(
item
);
...
...
@@ -1135,7 +1139,6 @@ static int btrfs_get_block_lock(struct inode *inode, sector_t iblock,
btrfs_map_bh_to_logical
(
root
,
result
,
0
);
}
out:
btrfs_release_path
(
root
,
path
);
btrfs_free_path
(
path
);
return
err
;
}
...
...
@@ -1231,13 +1234,13 @@ static int __btrfs_write_full_page(struct inode *inode, struct page *page,
}
else
if
(
!
buffer_mapped
(
bh
)
&&
buffer_dirty
(
bh
))
{
WARN_ON
(
bh
->
b_size
!=
blocksize
);
err
=
btrfs_get_block
(
inode
,
block
,
bh
,
0
);
if
(
err
)
if
(
err
)
{
printk
(
"writepage going to recovery err %d
\n
"
,
err
);
goto
recover
;
}
if
(
buffer_new
(
bh
))
{
/* blockdev mappings never come here */
clear_buffer_new
(
bh
);
unmap_underlying_metadata
(
bh
->
b_bdev
,
bh
->
b_blocknr
);
}
}
bh
=
bh
->
b_this_page
;
...
...
@@ -1303,11 +1306,6 @@ static int __btrfs_write_full_page(struct inode *inode, struct page *page,
if
(
uptodate
)
SetPageUptodate
(
page
);
end_page_writeback
(
page
);
/*
* The page and buffer_heads can be released at any time from
* here on.
*/
wbc
->
pages_skipped
++
;
/* We didn't write this page */
}
return
err
;
...
...
@@ -1409,10 +1407,11 @@ static void btrfs_truncate(struct inode *inode)
btrfs_set_trans_block_group
(
trans
,
inode
);
ret
=
btrfs_truncate_in_trans
(
trans
,
root
,
inode
);
BUG_ON
(
ret
);
btrfs_update_inode
(
trans
,
root
,
inode
);
ret
=
btrfs_end_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
mark_inode_dirty
(
inode
);
btrfs_btree_balance_dirty
(
root
);
}
/*
...
...
@@ -1777,10 +1776,15 @@ static int prepare_pages(struct btrfs_root *root,
err
=
-
ENOMEM
;
goto
failed_release
;
}
cancel_dirty_page
(
pages
[
i
],
PAGE_CACHE_SIZE
);
wait_on_page_writeback
(
pages
[
i
]);
offset
=
pos
&
(
PAGE_CACHE_SIZE
-
1
);
this_write
=
min
(
PAGE_CACHE_SIZE
-
offset
,
write_bytes
);
create_empty_buffers
(
pages
[
i
],
root
->
fs_info
->
sb
->
s_blocksize
,
(
1
<<
BH_Uptodate
));
if
(
!
page_has_buffers
(
pages
[
i
]))
{
create_empty_buffers
(
pages
[
i
],
root
->
fs_info
->
sb
->
s_blocksize
,
(
1
<<
BH_Uptodate
));
}
head
=
page_buffers
(
pages
[
i
]);
bh
=
head
;
do
{
...
...
@@ -1820,7 +1824,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
btrfs_root
*
root
=
BTRFS_I
(
inode
)
->
root
;
struct
page
*
pages
[
8
];
struct
page
*
pinned
[
2
]
=
{
NULL
,
NULL
}
;
struct
page
*
pinned
[
2
];
unsigned
long
first_index
;
unsigned
long
last_index
;
u64
start_pos
;
...
...
@@ -1829,6 +1833,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
struct
btrfs_trans_handle
*
trans
;
struct
btrfs_key
ins
;
pinned
[
0
]
=
NULL
;
pinned
[
1
]
=
NULL
;
if
(
file
->
f_flags
&
O_DIRECT
)
return
-
EINVAL
;
pos
=
*
ppos
;
...
...
@@ -1858,6 +1864,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
if
(
!
PageUptodate
(
pinned
[
0
]))
{
ret
=
mpage_readpage
(
pinned
[
0
],
btrfs_get_block
);
BUG_ON
(
ret
);
wait_on_page_locked
(
pinned
[
0
]);
}
else
{
unlock_page
(
pinned
[
0
]);
}
...
...
@@ -1869,6 +1876,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
if
(
!
PageUptodate
(
pinned
[
1
]))
{
ret
=
mpage_readpage
(
pinned
[
1
],
btrfs_get_block
);
BUG_ON
(
ret
);
wait_on_page_locked
(
pinned
[
1
]);
}
else
{
unlock_page
(
pinned
[
1
]);
}
...
...
@@ -1940,6 +1948,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
num_written
+=
write_bytes
;
balance_dirty_pages_ratelimited
(
inode
->
i_mapping
);
btrfs_btree_balance_dirty
(
root
);
cond_resched
();
}
out_unlock:
...
...
@@ -2165,6 +2174,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
iput
(
inode
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
return
0
;
}
...
...
@@ -2220,6 +2230,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
ret
=
btrfs_commit_transaction
(
trans
,
root
);
BUG_ON
(
ret
);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
btrfs_btree_balance_dirty
(
root
);
return
0
;
}
...
...
@@ -2295,6 +2306,7 @@ printk("insert failed %d\n", ret);
mutex_unlock
(
&
root
->
fs_info
->
fs_mutex
);
out_nolock:
btrfs_free_path
(
path
);
btrfs_btree_balance_dirty
(
root
);
return
ret
;
}
...
...
fs/btrfs/transaction.c
View file @
35b7e476
...
...
@@ -199,8 +199,9 @@ struct dirty_root {
struct
btrfs_root
*
root
;
};
int
add_dirty_roots
(
struct
btrfs_trans_handle
*
trans
,
struct
radix_tree_root
*
radix
,
struct
list_head
*
list
)
static
int
add_dirty_roots
(
struct
btrfs_trans_handle
*
trans
,
struct
radix_tree_root
*
radix
,
struct
list_head
*
list
)
{
struct
dirty_root
*
dirty
;
struct
btrfs_root
*
gang
[
8
];
...
...
@@ -246,7 +247,8 @@ int add_dirty_roots(struct btrfs_trans_handle *trans,
return
0
;
}
int
drop_dirty_roots
(
struct
btrfs_root
*
tree_root
,
struct
list_head
*
list
)
static
int
drop_dirty_roots
(
struct
btrfs_root
*
tree_root
,
struct
list_head
*
list
)
{
struct
dirty_root
*
dirty
;
struct
btrfs_trans_handle
*
trans
;
...
...
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