You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'master' of /Volumes/CaseSensitiveDisk/linux
This commit is contained in:
@@ -110,6 +110,7 @@ struct autofs_sb_info {
|
||||
int sub_version;
|
||||
int min_proto;
|
||||
int max_proto;
|
||||
int compat_daemon;
|
||||
unsigned long exp_timeout;
|
||||
unsigned int type;
|
||||
int reghost_enabled;
|
||||
|
||||
@@ -385,6 +385,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
|
||||
sbi->pipefd = pipefd;
|
||||
sbi->pipe = pipe;
|
||||
sbi->catatonic = 0;
|
||||
sbi->compat_daemon = is_compat_task();
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&sbi->wq_mutex);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <linux/parser.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/compat.h>
|
||||
#include "autofs_i.h"
|
||||
#include <linux/module.h>
|
||||
|
||||
@@ -224,6 +225,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
|
||||
set_autofs_type_indirect(&sbi->type);
|
||||
sbi->min_proto = 0;
|
||||
sbi->max_proto = 0;
|
||||
sbi->compat_daemon = is_compat_task();
|
||||
mutex_init(&sbi->wq_mutex);
|
||||
mutex_init(&sbi->pipe_mutex);
|
||||
spin_lock_init(&sbi->fs_lock);
|
||||
|
||||
+19
-3
@@ -91,7 +91,24 @@ static int autofs4_write(struct autofs_sb_info *sbi,
|
||||
|
||||
return (bytes > 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The autofs_v5 packet was misdesigned.
|
||||
*
|
||||
* The packets are identical on x86-32 and x86-64, but have different
|
||||
* alignment. Which means that 'sizeof()' will give different results.
|
||||
* Fix it up for the case of running 32-bit user mode on a 64-bit kernel.
|
||||
*/
|
||||
static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi)
|
||||
{
|
||||
size_t pktsz = sizeof(struct autofs_v5_packet);
|
||||
#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
|
||||
if (sbi->compat_daemon > 0)
|
||||
pktsz -= 4;
|
||||
#endif
|
||||
return pktsz;
|
||||
}
|
||||
|
||||
static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
|
||||
struct autofs_wait_queue *wq,
|
||||
int type)
|
||||
@@ -155,8 +172,7 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
|
||||
{
|
||||
struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
|
||||
|
||||
pktsz = sizeof(*packet);
|
||||
|
||||
pktsz = autofs_v5_packet_size(sbi);
|
||||
packet->wait_queue_token = wq->wait_queue_token;
|
||||
packet->len = wq->name.len;
|
||||
memcpy(packet->name, wq->name.name, wq->name.len);
|
||||
|
||||
@@ -892,6 +892,8 @@ static char *iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
|
||||
if (eb != eb_in)
|
||||
free_extent_buffer(eb);
|
||||
ret = inode_ref_info(parent, 0, fs_root, path, &found_key);
|
||||
if (ret > 0)
|
||||
ret = -ENOENT;
|
||||
if (ret)
|
||||
break;
|
||||
next_inum = found_key.offset;
|
||||
|
||||
@@ -644,7 +644,7 @@ static struct btrfsic_dev_state *btrfsic_dev_state_hashtable_lookup(
|
||||
static int btrfsic_process_superblock(struct btrfsic_state *state,
|
||||
struct btrfs_fs_devices *fs_devices)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct btrfs_super_block *selected_super;
|
||||
struct list_head *dev_head = &fs_devices->devices;
|
||||
struct btrfs_device *device;
|
||||
|
||||
@@ -588,6 +588,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
page_offset(bio->bi_io_vec->bv_page),
|
||||
PAGE_CACHE_SIZE);
|
||||
read_unlock(&em_tree->lock);
|
||||
if (!em)
|
||||
return -EIO;
|
||||
|
||||
compressed_len = em->block_len;
|
||||
cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS);
|
||||
|
||||
+1
-1
@@ -886,7 +886,7 @@ struct btrfs_block_rsv {
|
||||
u64 reserved;
|
||||
struct btrfs_space_info *space_info;
|
||||
spinlock_t lock;
|
||||
unsigned int full:1;
|
||||
unsigned int full;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -2260,6 +2260,12 @@ int open_ctree(struct super_block *sb,
|
||||
goto fail_sb_buffer;
|
||||
}
|
||||
|
||||
if (sectorsize < PAGE_SIZE) {
|
||||
printk(KERN_WARNING "btrfs: Incompatible sector size "
|
||||
"found on %s\n", sb->s_id);
|
||||
goto fail_sb_buffer;
|
||||
}
|
||||
|
||||
mutex_lock(&fs_info->chunk_mutex);
|
||||
ret = btrfs_read_sys_array(tree_root);
|
||||
mutex_unlock(&fs_info->chunk_mutex);
|
||||
@@ -2301,6 +2307,12 @@ int open_ctree(struct super_block *sb,
|
||||
|
||||
btrfs_close_extra_devices(fs_devices);
|
||||
|
||||
if (!fs_devices->latest_bdev) {
|
||||
printk(KERN_CRIT "btrfs: failed to read devices on %s\n",
|
||||
sb->s_id);
|
||||
goto fail_tree_roots;
|
||||
}
|
||||
|
||||
retry_root_backup:
|
||||
blocksize = btrfs_level_size(tree_root,
|
||||
btrfs_super_root_level(disk_super));
|
||||
|
||||
+32
-19
@@ -3312,7 +3312,8 @@ commit_trans:
|
||||
}
|
||||
data_sinfo->bytes_may_use += bytes;
|
||||
trace_btrfs_space_reservation(root->fs_info, "space_info",
|
||||
(u64)data_sinfo, bytes, 1);
|
||||
(u64)(unsigned long)data_sinfo,
|
||||
bytes, 1);
|
||||
spin_unlock(&data_sinfo->lock);
|
||||
|
||||
return 0;
|
||||
@@ -3333,7 +3334,8 @@ void btrfs_free_reserved_data_space(struct inode *inode, u64 bytes)
|
||||
spin_lock(&data_sinfo->lock);
|
||||
data_sinfo->bytes_may_use -= bytes;
|
||||
trace_btrfs_space_reservation(root->fs_info, "space_info",
|
||||
(u64)data_sinfo, bytes, 0);
|
||||
(u64)(unsigned long)data_sinfo,
|
||||
bytes, 0);
|
||||
spin_unlock(&data_sinfo->lock);
|
||||
}
|
||||
|
||||
@@ -3611,12 +3613,15 @@ static int may_commit_transaction(struct btrfs_root *root,
|
||||
if (space_info != delayed_rsv->space_info)
|
||||
return -ENOSPC;
|
||||
|
||||
spin_lock(&space_info->lock);
|
||||
spin_lock(&delayed_rsv->lock);
|
||||
if (delayed_rsv->size < bytes) {
|
||||
if (space_info->bytes_pinned + delayed_rsv->size < bytes) {
|
||||
spin_unlock(&delayed_rsv->lock);
|
||||
spin_unlock(&space_info->lock);
|
||||
return -ENOSPC;
|
||||
}
|
||||
spin_unlock(&delayed_rsv->lock);
|
||||
spin_unlock(&space_info->lock);
|
||||
|
||||
commit:
|
||||
trans = btrfs_join_transaction(root);
|
||||
@@ -3695,9 +3700,9 @@ again:
|
||||
if (used + orig_bytes <= space_info->total_bytes) {
|
||||
space_info->bytes_may_use += orig_bytes;
|
||||
trace_btrfs_space_reservation(root->fs_info,
|
||||
"space_info",
|
||||
(u64)space_info,
|
||||
orig_bytes, 1);
|
||||
"space_info",
|
||||
(u64)(unsigned long)space_info,
|
||||
orig_bytes, 1);
|
||||
ret = 0;
|
||||
} else {
|
||||
/*
|
||||
@@ -3766,9 +3771,9 @@ again:
|
||||
if (used + num_bytes < space_info->total_bytes + avail) {
|
||||
space_info->bytes_may_use += orig_bytes;
|
||||
trace_btrfs_space_reservation(root->fs_info,
|
||||
"space_info",
|
||||
(u64)space_info,
|
||||
orig_bytes, 1);
|
||||
"space_info",
|
||||
(u64)(unsigned long)space_info,
|
||||
orig_bytes, 1);
|
||||
ret = 0;
|
||||
} else {
|
||||
wait_ordered = true;
|
||||
@@ -3913,8 +3918,8 @@ static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
|
||||
spin_lock(&space_info->lock);
|
||||
space_info->bytes_may_use -= num_bytes;
|
||||
trace_btrfs_space_reservation(fs_info, "space_info",
|
||||
(u64)space_info,
|
||||
num_bytes, 0);
|
||||
(u64)(unsigned long)space_info,
|
||||
num_bytes, 0);
|
||||
space_info->reservation_progress++;
|
||||
spin_unlock(&space_info->lock);
|
||||
}
|
||||
@@ -4105,7 +4110,7 @@ static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
|
||||
num_bytes += div64_u64(data_used + meta_used, 50);
|
||||
|
||||
if (num_bytes * 3 > meta_used)
|
||||
num_bytes = div64_u64(meta_used, 3);
|
||||
num_bytes = div64_u64(meta_used, 3) * 2;
|
||||
|
||||
return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
|
||||
}
|
||||
@@ -4132,14 +4137,14 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
|
||||
block_rsv->reserved += num_bytes;
|
||||
sinfo->bytes_may_use += num_bytes;
|
||||
trace_btrfs_space_reservation(fs_info, "space_info",
|
||||
(u64)sinfo, num_bytes, 1);
|
||||
(u64)(unsigned long)sinfo, num_bytes, 1);
|
||||
}
|
||||
|
||||
if (block_rsv->reserved >= block_rsv->size) {
|
||||
num_bytes = block_rsv->reserved - block_rsv->size;
|
||||
sinfo->bytes_may_use -= num_bytes;
|
||||
trace_btrfs_space_reservation(fs_info, "space_info",
|
||||
(u64)sinfo, num_bytes, 0);
|
||||
(u64)(unsigned long)sinfo, num_bytes, 0);
|
||||
sinfo->reservation_progress++;
|
||||
block_rsv->reserved = block_rsv->size;
|
||||
block_rsv->full = 1;
|
||||
@@ -4192,7 +4197,8 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
|
||||
if (!trans->bytes_reserved)
|
||||
return;
|
||||
|
||||
trace_btrfs_space_reservation(root->fs_info, "transaction", (u64)trans,
|
||||
trace_btrfs_space_reservation(root->fs_info, "transaction",
|
||||
(u64)(unsigned long)trans,
|
||||
trans->bytes_reserved, 0);
|
||||
btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
|
||||
trans->bytes_reserved = 0;
|
||||
@@ -4710,9 +4716,9 @@ static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache,
|
||||
space_info->bytes_reserved += num_bytes;
|
||||
if (reserve == RESERVE_ALLOC) {
|
||||
trace_btrfs_space_reservation(cache->fs_info,
|
||||
"space_info",
|
||||
(u64)space_info,
|
||||
num_bytes, 0);
|
||||
"space_info",
|
||||
(u64)(unsigned long)space_info,
|
||||
num_bytes, 0);
|
||||
space_info->bytes_may_use -= num_bytes;
|
||||
}
|
||||
}
|
||||
@@ -7886,9 +7892,16 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range)
|
||||
u64 start;
|
||||
u64 end;
|
||||
u64 trimmed = 0;
|
||||
u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
|
||||
int ret = 0;
|
||||
|
||||
cache = btrfs_lookup_block_group(fs_info, range->start);
|
||||
/*
|
||||
* try to trim all FS space, our block group may start from non-zero.
|
||||
*/
|
||||
if (range->len == total_bytes)
|
||||
cache = btrfs_lookup_first_block_group(fs_info, range->start);
|
||||
else
|
||||
cache = btrfs_lookup_block_group(fs_info, range->start);
|
||||
|
||||
while (cache) {
|
||||
if (cache->key.objectid >= (range->start + range->len)) {
|
||||
|
||||
+65
-48
@@ -513,6 +513,15 @@ hit_next:
|
||||
WARN_ON(state->end < start);
|
||||
last_end = state->end;
|
||||
|
||||
if (state->end < end && !need_resched())
|
||||
next_node = rb_next(&state->rb_node);
|
||||
else
|
||||
next_node = NULL;
|
||||
|
||||
/* the state doesn't have the wanted bits, go ahead */
|
||||
if (!(state->state & bits))
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* | ---- desired range ---- |
|
||||
* | state | or
|
||||
@@ -565,20 +574,15 @@ hit_next:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (state->end < end && prealloc && !need_resched())
|
||||
next_node = rb_next(&state->rb_node);
|
||||
else
|
||||
next_node = NULL;
|
||||
|
||||
set |= clear_state_bit(tree, state, &bits, wake);
|
||||
next:
|
||||
if (last_end == (u64)-1)
|
||||
goto out;
|
||||
start = last_end + 1;
|
||||
if (start <= end && next_node) {
|
||||
state = rb_entry(next_node, struct extent_state,
|
||||
rb_node);
|
||||
if (state->start == start)
|
||||
goto hit_next;
|
||||
goto hit_next;
|
||||
}
|
||||
goto search_again;
|
||||
|
||||
@@ -961,8 +965,6 @@ hit_next:
|
||||
|
||||
set_state_bits(tree, state, &bits);
|
||||
clear_state_bit(tree, state, &clear_bits, 0);
|
||||
|
||||
merge_state(tree, state);
|
||||
if (last_end == (u64)-1)
|
||||
goto out;
|
||||
|
||||
@@ -1007,7 +1009,6 @@ hit_next:
|
||||
if (state->end <= end) {
|
||||
set_state_bits(tree, state, &bits);
|
||||
clear_state_bit(tree, state, &clear_bits, 0);
|
||||
merge_state(tree, state);
|
||||
if (last_end == (u64)-1)
|
||||
goto out;
|
||||
start = last_end + 1;
|
||||
@@ -1068,8 +1069,6 @@ hit_next:
|
||||
|
||||
set_state_bits(tree, prealloc, &bits);
|
||||
clear_state_bit(tree, prealloc, &clear_bits, 0);
|
||||
|
||||
merge_state(tree, prealloc);
|
||||
prealloc = NULL;
|
||||
goto out;
|
||||
}
|
||||
@@ -2154,13 +2153,46 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
|
||||
"this_mirror=%d, num_copies=%d, in_validation=%d\n", read_mode,
|
||||
failrec->this_mirror, num_copies, failrec->in_validation);
|
||||
|
||||
tree->ops->submit_bio_hook(inode, read_mode, bio, failrec->this_mirror,
|
||||
failrec->bio_flags, 0);
|
||||
return 0;
|
||||
ret = tree->ops->submit_bio_hook(inode, read_mode, bio,
|
||||
failrec->this_mirror,
|
||||
failrec->bio_flags, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* lots and lots of room for performance fixes in the end_bio funcs */
|
||||
|
||||
int end_extent_writepage(struct page *page, int err, u64 start, u64 end)
|
||||
{
|
||||
int uptodate = (err == 0);
|
||||
struct extent_io_tree *tree;
|
||||
int ret;
|
||||
|
||||
tree = &BTRFS_I(page->mapping->host)->io_tree;
|
||||
|
||||
if (tree->ops && tree->ops->writepage_end_io_hook) {
|
||||
ret = tree->ops->writepage_end_io_hook(page, start,
|
||||
end, NULL, uptodate);
|
||||
if (ret)
|
||||
uptodate = 0;
|
||||
}
|
||||
|
||||
if (!uptodate && tree->ops &&
|
||||
tree->ops->writepage_io_failed_hook) {
|
||||
ret = tree->ops->writepage_io_failed_hook(NULL, page,
|
||||
start, end, NULL);
|
||||
/* Writeback already completed */
|
||||
if (ret == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uptodate) {
|
||||
clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS);
|
||||
ClearPageUptodate(page);
|
||||
SetPageError(page);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* after a writepage IO is done, we need to:
|
||||
* clear the uptodate bits on error
|
||||
@@ -2172,13 +2204,11 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
|
||||
*/
|
||||
static void end_bio_extent_writepage(struct bio *bio, int err)
|
||||
{
|
||||
int uptodate = err == 0;
|
||||
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
|
||||
struct extent_io_tree *tree;
|
||||
u64 start;
|
||||
u64 end;
|
||||
int whole_page;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
struct page *page = bvec->bv_page;
|
||||
@@ -2195,28 +2225,9 @@ static void end_bio_extent_writepage(struct bio *bio, int err)
|
||||
|
||||
if (--bvec >= bio->bi_io_vec)
|
||||
prefetchw(&bvec->bv_page->flags);
|
||||
if (tree->ops && tree->ops->writepage_end_io_hook) {
|
||||
ret = tree->ops->writepage_end_io_hook(page, start,
|
||||
end, NULL, uptodate);
|
||||
if (ret)
|
||||
uptodate = 0;
|
||||
}
|
||||
|
||||
if (!uptodate && tree->ops &&
|
||||
tree->ops->writepage_io_failed_hook) {
|
||||
ret = tree->ops->writepage_io_failed_hook(bio, page,
|
||||
start, end, NULL);
|
||||
if (ret == 0) {
|
||||
uptodate = (err == 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uptodate) {
|
||||
clear_extent_uptodate(tree, start, end, NULL, GFP_NOFS);
|
||||
ClearPageUptodate(page);
|
||||
SetPageError(page);
|
||||
}
|
||||
if (end_extent_writepage(page, err, start, end))
|
||||
continue;
|
||||
|
||||
if (whole_page)
|
||||
end_page_writeback(page);
|
||||
@@ -2779,9 +2790,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
|
||||
delalloc_start = delalloc_end + 1;
|
||||
continue;
|
||||
}
|
||||
tree->ops->fill_delalloc(inode, page, delalloc_start,
|
||||
delalloc_end, &page_started,
|
||||
&nr_written);
|
||||
ret = tree->ops->fill_delalloc(inode, page,
|
||||
delalloc_start,
|
||||
delalloc_end,
|
||||
&page_started,
|
||||
&nr_written);
|
||||
BUG_ON(ret);
|
||||
/*
|
||||
* delalloc_end is already one less than the total
|
||||
* length, so we don't subtract one from
|
||||
@@ -2818,8 +2832,12 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
|
||||
if (tree->ops && tree->ops->writepage_start_hook) {
|
||||
ret = tree->ops->writepage_start_hook(page, start,
|
||||
page_end);
|
||||
if (ret == -EAGAIN) {
|
||||
redirty_page_for_writepage(wbc, page);
|
||||
if (ret) {
|
||||
/* Fixup worker will requeue */
|
||||
if (ret == -EBUSY)
|
||||
wbc->pages_skipped++;
|
||||
else
|
||||
redirty_page_for_writepage(wbc, page);
|
||||
update_nr_written(page, wbc, nr_written);
|
||||
unlock_page(page);
|
||||
ret = 0;
|
||||
@@ -3289,7 +3307,7 @@ int try_release_extent_mapping(struct extent_map_tree *map,
|
||||
len = end - start + 1;
|
||||
write_lock(&map->lock);
|
||||
em = lookup_extent_mapping(map, start, len);
|
||||
if (IS_ERR_OR_NULL(em)) {
|
||||
if (!em) {
|
||||
write_unlock(&map->lock);
|
||||
break;
|
||||
}
|
||||
@@ -3853,10 +3871,9 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||
num_pages = num_extent_pages(eb->start, eb->len);
|
||||
clear_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
|
||||
|
||||
if (eb_straddles_pages(eb)) {
|
||||
clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
|
||||
cached_state, GFP_NOFS);
|
||||
}
|
||||
clear_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
|
||||
cached_state, GFP_NOFS);
|
||||
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
page = extent_buffer_page(eb, i);
|
||||
if (page)
|
||||
|
||||
@@ -319,4 +319,5 @@ struct btrfs_mapping_tree;
|
||||
int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start,
|
||||
u64 length, u64 logical, struct page *page,
|
||||
int mirror_num);
|
||||
int end_extent_writepage(struct page *page, int err, u64 start, u64 end);
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,8 @@ struct extent_map {
|
||||
unsigned long flags;
|
||||
struct block_device *bdev;
|
||||
atomic_t refs;
|
||||
unsigned int in_tree:1;
|
||||
unsigned int compress_type:4;
|
||||
unsigned int in_tree;
|
||||
unsigned int compress_type;
|
||||
};
|
||||
|
||||
struct extent_map_tree {
|
||||
|
||||
+12
-17
@@ -1604,6 +1604,14 @@ static long btrfs_fallocate(struct file *file, int mode,
|
||||
if (mode & ~FALLOC_FL_KEEP_SIZE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* Make sure we have enough space before we do the
|
||||
* allocation.
|
||||
*/
|
||||
ret = btrfs_check_data_free_space(inode, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* wait for ordered IO before we have any locks. We'll loop again
|
||||
* below with the locks held.
|
||||
@@ -1667,27 +1675,12 @@ static long btrfs_fallocate(struct file *file, int mode,
|
||||
if (em->block_start == EXTENT_MAP_HOLE ||
|
||||
(cur_offset >= inode->i_size &&
|
||||
!test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
|
||||
|
||||
/*
|
||||
* Make sure we have enough space before we do the
|
||||
* allocation.
|
||||
*/
|
||||
ret = btrfs_check_data_free_space(inode, last_byte -
|
||||
cur_offset);
|
||||
if (ret) {
|
||||
free_extent_map(em);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
|
||||
last_byte - cur_offset,
|
||||
1 << inode->i_blkbits,
|
||||
offset + len,
|
||||
&alloc_hint);
|
||||
|
||||
/* Let go of our reservation. */
|
||||
btrfs_free_reserved_data_space(inode, last_byte -
|
||||
cur_offset);
|
||||
if (ret < 0) {
|
||||
free_extent_map(em);
|
||||
break;
|
||||
@@ -1715,6 +1708,8 @@ static long btrfs_fallocate(struct file *file, int mode,
|
||||
&cached_state, GFP_NOFS);
|
||||
out:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
/* Let go of our reservation. */
|
||||
btrfs_free_reserved_data_space(inode, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1761,7 +1756,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
|
||||
start - root->sectorsize,
|
||||
root->sectorsize, 0);
|
||||
if (IS_ERR(em)) {
|
||||
ret = -ENXIO;
|
||||
ret = PTR_ERR(em);
|
||||
goto out;
|
||||
}
|
||||
last_end = em->start + em->len;
|
||||
@@ -1773,7 +1768,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
|
||||
while (1) {
|
||||
em = btrfs_get_extent_fiemap(inode, NULL, 0, start, len, 0);
|
||||
if (IS_ERR(em)) {
|
||||
ret = -ENXIO;
|
||||
ret = PTR_ERR(em);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -777,6 +777,7 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info,
|
||||
spin_lock(&block_group->lock);
|
||||
if (block_group->disk_cache_state != BTRFS_DC_WRITTEN) {
|
||||
spin_unlock(&block_group->lock);
|
||||
btrfs_free_path(path);
|
||||
goto out;
|
||||
}
|
||||
spin_unlock(&block_group->lock);
|
||||
|
||||
@@ -438,7 +438,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
|
||||
trans->bytes_reserved);
|
||||
if (ret)
|
||||
goto out;
|
||||
trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans,
|
||||
trace_btrfs_space_reservation(root->fs_info, "ino_cache",
|
||||
(u64)(unsigned long)trans,
|
||||
trans->bytes_reserved, 1);
|
||||
again:
|
||||
inode = lookup_free_ino_inode(root, path);
|
||||
@@ -500,7 +501,8 @@ again:
|
||||
out_put:
|
||||
iput(inode);
|
||||
out_release:
|
||||
trace_btrfs_space_reservation(root->fs_info, "ino_cache", (u64)trans,
|
||||
trace_btrfs_space_reservation(root->fs_info, "ino_cache",
|
||||
(u64)(unsigned long)trans,
|
||||
trans->bytes_reserved, 0);
|
||||
btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
|
||||
out:
|
||||
|
||||
+35
-5
@@ -1555,6 +1555,7 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
|
||||
struct inode *inode;
|
||||
u64 page_start;
|
||||
u64 page_end;
|
||||
int ret;
|
||||
|
||||
fixup = container_of(work, struct btrfs_writepage_fixup, work);
|
||||
page = fixup->page;
|
||||
@@ -1582,12 +1583,21 @@ again:
|
||||
page_end, &cached_state, GFP_NOFS);
|
||||
unlock_page(page);
|
||||
btrfs_start_ordered_extent(inode, ordered, 1);
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
goto again;
|
||||
}
|
||||
|
||||
BUG();
|
||||
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
|
||||
if (ret) {
|
||||
mapping_set_error(page->mapping, ret);
|
||||
end_extent_writepage(page, ret, page_start, page_end);
|
||||
ClearPageChecked(page);
|
||||
goto out;
|
||||
}
|
||||
|
||||
btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state);
|
||||
ClearPageChecked(page);
|
||||
set_page_dirty(page);
|
||||
out:
|
||||
unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
|
||||
&cached_state, GFP_NOFS);
|
||||
@@ -1630,7 +1640,7 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end)
|
||||
fixup->work.func = btrfs_writepage_fixup_worker;
|
||||
fixup->page = page;
|
||||
btrfs_queue_worker(&root->fs_info->fixup_workers, &fixup->work);
|
||||
return -EAGAIN;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
@@ -4575,7 +4585,8 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
|
||||
ret = btrfs_insert_dir_item(trans, root, name, name_len,
|
||||
parent_inode, &key,
|
||||
btrfs_inode_type(inode), index);
|
||||
BUG_ON(ret);
|
||||
if (ret)
|
||||
goto fail_dir_item;
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size +
|
||||
name_len * 2);
|
||||
@@ -4583,6 +4594,23 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
|
||||
ret = btrfs_update_inode(trans, root, parent_inode);
|
||||
}
|
||||
return ret;
|
||||
|
||||
fail_dir_item:
|
||||
if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) {
|
||||
u64 local_index;
|
||||
int err;
|
||||
err = btrfs_del_root_ref(trans, root->fs_info->tree_root,
|
||||
key.objectid, root->root_key.objectid,
|
||||
parent_ino, &local_index, name, name_len);
|
||||
|
||||
} else if (add_backref) {
|
||||
u64 local_index;
|
||||
int err;
|
||||
|
||||
err = btrfs_del_inode_ref(trans, root, name, name_len,
|
||||
ino, parent_ino, &local_index);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
|
||||
@@ -6696,8 +6724,10 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
|
||||
int err;
|
||||
u64 index = 0;
|
||||
|
||||
inode = btrfs_new_inode(trans, new_root, NULL, "..", 2, new_dirid,
|
||||
new_dirid, S_IFDIR | 0700, &index);
|
||||
inode = btrfs_new_inode(trans, new_root, NULL, "..", 2,
|
||||
new_dirid, new_dirid,
|
||||
S_IFDIR | (~current_umask() & S_IRWXUGO),
|
||||
&index);
|
||||
if (IS_ERR(inode))
|
||||
return PTR_ERR(inode);
|
||||
inode->i_op = &btrfs_dir_inode_operations;
|
||||
|
||||
+35
-24
@@ -861,6 +861,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
|
||||
int i_done;
|
||||
struct btrfs_ordered_extent *ordered;
|
||||
struct extent_state *cached_state = NULL;
|
||||
struct extent_io_tree *tree;
|
||||
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
|
||||
|
||||
if (isize == 0)
|
||||
@@ -871,18 +872,34 @@ static int cluster_pages_for_defrag(struct inode *inode,
|
||||
num_pages << PAGE_CACHE_SHIFT);
|
||||
if (ret)
|
||||
return ret;
|
||||
again:
|
||||
ret = 0;
|
||||
i_done = 0;
|
||||
tree = &BTRFS_I(inode)->io_tree;
|
||||
|
||||
/* step one, lock all the pages */
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
struct page *page;
|
||||
again:
|
||||
page = find_or_create_page(inode->i_mapping,
|
||||
start_index + i, mask);
|
||||
start_index + i, mask);
|
||||
if (!page)
|
||||
break;
|
||||
|
||||
page_start = page_offset(page);
|
||||
page_end = page_start + PAGE_CACHE_SIZE - 1;
|
||||
while (1) {
|
||||
lock_extent(tree, page_start, page_end, GFP_NOFS);
|
||||
ordered = btrfs_lookup_ordered_extent(inode,
|
||||
page_start);
|
||||
unlock_extent(tree, page_start, page_end, GFP_NOFS);
|
||||
if (!ordered)
|
||||
break;
|
||||
|
||||
unlock_page(page);
|
||||
btrfs_start_ordered_extent(inode, ordered, 1);
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
lock_page(page);
|
||||
}
|
||||
|
||||
if (!PageUptodate(page)) {
|
||||
btrfs_readpage(NULL, page);
|
||||
lock_page(page);
|
||||
@@ -893,15 +910,22 @@ again:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
isize = i_size_read(inode);
|
||||
file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
|
||||
if (!isize || page->index > file_end ||
|
||||
page->mapping != inode->i_mapping) {
|
||||
if (!isize || page->index > file_end) {
|
||||
/* whoops, we blew past eof, skip this page */
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
break;
|
||||
}
|
||||
|
||||
if (page->mapping != inode->i_mapping) {
|
||||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
goto again;
|
||||
}
|
||||
|
||||
pages[i] = page;
|
||||
i_done++;
|
||||
}
|
||||
@@ -924,25 +948,6 @@ again:
|
||||
lock_extent_bits(&BTRFS_I(inode)->io_tree,
|
||||
page_start, page_end - 1, 0, &cached_state,
|
||||
GFP_NOFS);
|
||||
ordered = btrfs_lookup_first_ordered_extent(inode, page_end - 1);
|
||||
if (ordered &&
|
||||
ordered->file_offset + ordered->len > page_start &&
|
||||
ordered->file_offset < page_end) {
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
unlock_extent_cached(&BTRFS_I(inode)->io_tree,
|
||||
page_start, page_end - 1,
|
||||
&cached_state, GFP_NOFS);
|
||||
for (i = 0; i < i_done; i++) {
|
||||
unlock_page(pages[i]);
|
||||
page_cache_release(pages[i]);
|
||||
}
|
||||
btrfs_wait_ordered_range(inode, page_start,
|
||||
page_end - page_start);
|
||||
goto again;
|
||||
}
|
||||
if (ordered)
|
||||
btrfs_put_ordered_extent(ordered);
|
||||
|
||||
clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
|
||||
page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
|
||||
EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
|
||||
@@ -1327,6 +1332,12 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (name[0] == '.' &&
|
||||
(namelen == 1 || (name[1] == '.' && namelen == 2))) {
|
||||
ret = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (subvol) {
|
||||
ret = btrfs_mksubvol(&file->f_path, name, namelen,
|
||||
NULL, transid, readonly);
|
||||
|
||||
+5
-3
@@ -1367,7 +1367,8 @@ out:
|
||||
}
|
||||
|
||||
static noinline_for_stack int scrub_chunk(struct scrub_dev *sdev,
|
||||
u64 chunk_tree, u64 chunk_objectid, u64 chunk_offset, u64 length)
|
||||
u64 chunk_tree, u64 chunk_objectid, u64 chunk_offset, u64 length,
|
||||
u64 dev_offset)
|
||||
{
|
||||
struct btrfs_mapping_tree *map_tree =
|
||||
&sdev->dev->dev_root->fs_info->mapping_tree;
|
||||
@@ -1391,7 +1392,8 @@ static noinline_for_stack int scrub_chunk(struct scrub_dev *sdev,
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < map->num_stripes; ++i) {
|
||||
if (map->stripes[i].dev == sdev->dev) {
|
||||
if (map->stripes[i].dev == sdev->dev &&
|
||||
map->stripes[i].physical == dev_offset) {
|
||||
ret = scrub_stripe(sdev, map, i, chunk_offset, length);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -1487,7 +1489,7 @@ int scrub_enumerate_chunks(struct scrub_dev *sdev, u64 start, u64 end)
|
||||
break;
|
||||
}
|
||||
ret = scrub_chunk(sdev, chunk_tree, chunk_objectid,
|
||||
chunk_offset, length);
|
||||
chunk_offset, length, found_key.offset);
|
||||
btrfs_put_block_group(cache);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
@@ -327,7 +327,8 @@ again:
|
||||
|
||||
if (num_bytes) {
|
||||
trace_btrfs_space_reservation(root->fs_info, "transaction",
|
||||
(u64)h, num_bytes, 1);
|
||||
(u64)(unsigned long)h,
|
||||
num_bytes, 1);
|
||||
h->block_rsv = &root->fs_info->trans_block_rsv;
|
||||
h->bytes_reserved = num_bytes;
|
||||
}
|
||||
@@ -915,7 +916,11 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||
dentry->d_name.name, dentry->d_name.len,
|
||||
parent_inode, &key,
|
||||
BTRFS_FT_DIR, index);
|
||||
BUG_ON(ret);
|
||||
if (ret) {
|
||||
pending->error = -EEXIST;
|
||||
dput(parent);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
btrfs_i_size_write(parent_inode, parent_inode->i_size +
|
||||
dentry->d_name.len * 2);
|
||||
@@ -993,12 +998,9 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
struct btrfs_pending_snapshot *pending;
|
||||
struct list_head *head = &trans->transaction->pending_snapshots;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(pending, head, list) {
|
||||
ret = create_pending_snapshot(trans, fs_info, pending);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
list_for_each_entry(pending, head, list)
|
||||
create_pending_snapshot(trans, fs_info, pending);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user