Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
Browse files Browse the repository at this point in the history
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (24 commits)
  Btrfs: don't use migrate page without CONFIG_MIGRATION
  Btrfs: deal with DIO bios that span more than one ordered extent
  Btrfs: setup blank root and fs_info for mount time
  Btrfs: fix fiemap
  Btrfs - fix race between btrfs_get_sb() and umount
  Btrfs: update inode ctime when using links
  Btrfs: make sure new inode size is ok in fallocate
  Btrfs: fix typo in fallocate to make it honor actual size
  Btrfs: avoid NULL pointer deref in try_release_extent_buffer
  Btrfs: make btrfs_add_nondir take parent inode as an argument
  Btrfs: hold i_mutex when calling btrfs_log_dentry_safe
  Btrfs: use dget_parent where we can UPDATED
  Btrfs: fix more ESTALE problems with NFS
  Btrfs: handle NFS lookups properly
  btrfs: make 1-bit signed fileds unsigned
  btrfs: Show device attr correctly for symlinks
  btrfs: Set file size correctly in file clone
  btrfs: Check if dest_offset is block-size aligned before cloning file
  Btrfs: handle the space_cache option properly
  btrfs: Fix early enospc because 'unused' calculated with wrong sign.
  ...
  • Loading branch information
Linus Torvalds committed Nov 29, 2010
2 parents 555bdae + 5a92bc8 commit aa3fc52
Show file tree
Hide file tree
Showing 15 changed files with 572 additions and 114 deletions.
15 changes: 1 addition & 14 deletions fs/btrfs/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,10 @@ static inline int compressed_bio_size(struct btrfs_root *root,
static struct bio *compressed_bio_alloc(struct block_device *bdev,
u64 first_byte, gfp_t gfp_flags)
{
struct bio *bio;
int nr_vecs;

nr_vecs = bio_get_nr_vecs(bdev);
bio = bio_alloc(gfp_flags, nr_vecs);

if (bio == NULL && (current->flags & PF_MEMALLOC)) {
while (!bio && (nr_vecs /= 2))
bio = bio_alloc(gfp_flags, nr_vecs);
}

if (bio) {
bio->bi_size = 0;
bio->bi_bdev = bdev;
bio->bi_sector = first_byte >> 9;
}
return bio;
return btrfs_bio_alloc(bdev, first_byte >> 9, nr_vecs, gfp_flags);
}

static int check_compressed_csum(struct inode *inode,
Expand Down
6 changes: 3 additions & 3 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -808,9 +808,9 @@ struct btrfs_block_group_cache {
int extents_thresh;
int free_extents;
int total_bitmaps;
int ro:1;
int dirty:1;
int iref:1;
unsigned int ro:1;
unsigned int dirty:1;
unsigned int iref:1;

int disk_cache_state;

Expand Down
38 changes: 32 additions & 6 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/freezer.h>
#include <linux/crc32c.h>
#include <linux/slab.h>
#include <linux/migrate.h>
#include "compat.h"
#include "ctree.h"
#include "disk-io.h"
Expand Down Expand Up @@ -355,6 +356,8 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page)
ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE,
btrfs_header_generation(eb));
BUG_ON(ret);
WARN_ON(!btrfs_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN));

found_start = btrfs_header_bytenr(eb);
if (found_start != start) {
WARN_ON(1);
Expand Down Expand Up @@ -693,6 +696,29 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
__btree_submit_bio_done);
}

static int btree_migratepage(struct address_space *mapping,
struct page *newpage, struct page *page)
{
/*
* we can't safely write a btree page from here,
* we haven't done the locking hook
*/
if (PageDirty(page))
return -EAGAIN;
/*
* Buffers may be managed in a filesystem specific way.
* We must have no buffers or drop them.
*/
if (page_has_private(page) &&
!try_to_release_page(page, GFP_KERNEL))
return -EAGAIN;
#ifdef CONFIG_MIGRATION
return migrate_page(mapping, newpage, page);
#else
return -ENOSYS;
#endif
}

static int btree_writepage(struct page *page, struct writeback_control *wbc)
{
struct extent_io_tree *tree;
Expand All @@ -707,8 +733,7 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc)
}

redirty_page_for_writepage(wbc, page);
eb = btrfs_find_tree_block(root, page_offset(page),
PAGE_CACHE_SIZE);
eb = btrfs_find_tree_block(root, page_offset(page), PAGE_CACHE_SIZE);
WARN_ON(!eb);

was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags);
Expand Down Expand Up @@ -799,6 +824,9 @@ static const struct address_space_operations btree_aops = {
.releasepage = btree_releasepage,
.invalidatepage = btree_invalidatepage,
.sync_page = block_sync_page,
#ifdef CONFIG_MIGRATION
.migratepage = btree_migratepage,
#endif
};

int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
Expand Down Expand Up @@ -1538,10 +1566,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
GFP_NOFS);
struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info),
GFP_NOFS);
struct btrfs_root *tree_root = btrfs_sb(sb);
struct btrfs_fs_info *fs_info = tree_root->fs_info;
struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
Expand Down
76 changes: 76 additions & 0 deletions fs/btrfs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,85 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
return ERR_PTR(ret);
}

static int btrfs_get_name(struct dentry *parent, char *name,
struct dentry *child)
{
struct inode *inode = child->d_inode;
struct inode *dir = parent->d_inode;
struct btrfs_path *path;
struct btrfs_root *root = BTRFS_I(dir)->root;
struct btrfs_inode_ref *iref;
struct btrfs_root_ref *rref;
struct extent_buffer *leaf;
unsigned long name_ptr;
struct btrfs_key key;
int name_len;
int ret;

if (!dir || !inode)
return -EINVAL;

if (!S_ISDIR(dir->i_mode))
return -EINVAL;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
path->leave_spinning = 1;

if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
key.objectid = BTRFS_I(inode)->root->root_key.objectid;
key.type = BTRFS_ROOT_BACKREF_KEY;
key.offset = (u64)-1;
root = root->fs_info->tree_root;
} else {
key.objectid = inode->i_ino;
key.offset = dir->i_ino;
key.type = BTRFS_INODE_REF_KEY;
}

ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0) {
btrfs_free_path(path);
return ret;
} else if (ret > 0) {
if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
path->slots[0]--;
} else {
btrfs_free_path(path);
return -ENOENT;
}
}
leaf = path->nodes[0];

if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) {
rref = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_root_ref);
name_ptr = (unsigned long)(rref + 1);
name_len = btrfs_root_ref_name_len(leaf, rref);
} else {
iref = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_inode_ref);
name_ptr = (unsigned long)(iref + 1);
name_len = btrfs_inode_ref_name_len(leaf, iref);
}

read_extent_buffer(leaf, name, name_ptr, name_len);
btrfs_free_path(path);

/*
* have to add the null termination to make sure that reconnect_path
* gets the right len for strlen
*/
name[name_len] = '\0';

return 0;
}

const struct export_operations btrfs_export_ops = {
.encode_fh = btrfs_encode_fh,
.fh_to_dentry = btrfs_fh_to_dentry,
.fh_to_parent = btrfs_fh_to_parent,
.get_parent = btrfs_get_parent,
.get_name = btrfs_get_name,
};
2 changes: 1 addition & 1 deletion fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3412,7 +3412,7 @@ static int reserve_metadata_bytes(struct btrfs_trans_handle *trans,
* our reservation.
*/
if (unused <= space_info->total_bytes) {
unused -= space_info->total_bytes;
unused = space_info->total_bytes - unused;
if (unused >= num_bytes) {
if (!reserved)
space_info->bytes_reserved += orig_bytes;
Expand Down
77 changes: 62 additions & 15 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -1828,9 +1828,9 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err)
bio_put(bio);
}

static struct bio *
extent_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
gfp_t gfp_flags)
struct bio *
btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
gfp_t gfp_flags)
{
struct bio *bio;

Expand Down Expand Up @@ -1919,7 +1919,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
else
nr = bio_get_nr_vecs(bdev);

bio = extent_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);
bio = btrfs_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH);

bio_add_page(bio, page, page_size, offset);
bio->bi_end_io = end_io_func;
Expand Down Expand Up @@ -2901,21 +2901,53 @@ sector_t extent_bmap(struct address_space *mapping, sector_t iblock,
int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len, get_extent_t *get_extent)
{
int ret;
int ret = 0;
u64 off = start;
u64 max = start + len;
u32 flags = 0;
u32 found_type;
u64 last;
u64 disko = 0;
struct btrfs_key found_key;
struct extent_map *em = NULL;
struct extent_state *cached_state = NULL;
struct btrfs_path *path;
struct btrfs_file_extent_item *item;
int end = 0;
u64 em_start = 0, em_len = 0;
unsigned long emflags;
ret = 0;
int hole = 0;

if (len == 0)
return -EINVAL;

path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
path->leave_spinning = 1;

ret = btrfs_lookup_file_extent(NULL, BTRFS_I(inode)->root,
path, inode->i_ino, -1, 0);
if (ret < 0) {
btrfs_free_path(path);
return ret;
}
WARN_ON(!ret);
path->slots[0]--;
item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_file_extent_item);
btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
found_type = btrfs_key_type(&found_key);

/* No extents, just return */
if (found_key.objectid != inode->i_ino ||
found_type != BTRFS_EXTENT_DATA_KEY) {
btrfs_free_path(path);
return 0;
}
last = found_key.offset;
btrfs_free_path(path);

lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
&cached_state, GFP_NOFS);
em = get_extent(inode, NULL, 0, off, max - off, 0);
Expand All @@ -2925,11 +2957,18 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
ret = PTR_ERR(em);
goto out;
}

while (!end) {
hole = 0;
off = em->start + em->len;
if (off >= max)
end = 1;

if (em->block_start == EXTENT_MAP_HOLE) {
hole = 1;
goto next;
}

em_start = em->start;
em_len = em->len;

Expand All @@ -2939,8 +2978,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
if (em->block_start == EXTENT_MAP_LAST_BYTE) {
end = 1;
flags |= FIEMAP_EXTENT_LAST;
} else if (em->block_start == EXTENT_MAP_HOLE) {
flags |= FIEMAP_EXTENT_UNWRITTEN;
} else if (em->block_start == EXTENT_MAP_INLINE) {
flags |= (FIEMAP_EXTENT_DATA_INLINE |
FIEMAP_EXTENT_NOT_ALIGNED);
Expand All @@ -2953,10 +2990,10 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
flags |= FIEMAP_EXTENT_ENCODED;

next:
emflags = em->flags;
free_extent_map(em);
em = NULL;

if (!end) {
em = get_extent(inode, NULL, 0, off, max - off, 0);
if (!em)
Expand All @@ -2967,15 +3004,23 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
}
emflags = em->flags;
}

if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) {
flags |= FIEMAP_EXTENT_LAST;
end = 1;
}

ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
em_len, flags);
if (ret)
goto out_free;
if (em_start == last) {
flags |= FIEMAP_EXTENT_LAST;
end = 1;
}

if (!hole) {
ret = fiemap_fill_next_extent(fieinfo, em_start, disko,
em_len, flags);
if (ret)
goto out_free;
}
}
out_free:
free_extent_map(em);
Expand Down Expand Up @@ -3836,8 +3881,10 @@ int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page)

spin_lock(&tree->buffer_lock);
eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT);
if (!eb)
goto out;
if (!eb) {
spin_unlock(&tree->buffer_lock);
return ret;
}

if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
ret = 0;
Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/extent_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,7 @@ int extent_clear_unlock_delalloc(struct inode *inode,
struct extent_io_tree *tree,
u64 start, u64 end, struct page *locked_page,
unsigned long op);
struct bio *
btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
gfp_t gfp_flags);
#endif
Loading

0 comments on commit aa3fc52

Please sign in to comment.