From: Linus Torvalds Date: Fri, 16 Dec 2011 20:15:50 +0000 (-0800) Subject: Merge branches 'for-linus' and 'for-linus-3.2' of git://git.kernel.org/pub/scm/linux... X-Git-Tag: upstream/snapshot3+hdmi~8556 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9a7fe9672612c0b595633d2945f52257ad92b20;hp=-c;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git Merge branches 'for-linus' and 'for-linus-3.2' of git://git./linux/kernel/git/mason/linux-btrfs * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: Btrfs: unplug every once and a while Btrfs: deal with NULL srv_rsv in the delalloc inode reservation code Btrfs: only set cache_generation if we setup the block group Btrfs: don't panic if orphan item already exists Btrfs: fix leaked space in truncate Btrfs: fix how we do delalloc reservations and how we free reservations on error Btrfs: deal with enospc from dirtying inodes properly Btrfs: fix num_workers_starting bug and other bugs in async thread BTRFS: Establish i_ops before calling d_instantiate Btrfs: add a cond_resched() into the worker loop Btrfs: fix ctime update of on-disk inode btrfs: keep orphans for subvolume deletion Btrfs: fix inaccurate available space on raid0 profile Btrfs: fix wrong disk space information of the files Btrfs: fix wrong i_size when truncating a file to a larger size Btrfs: fix btrfs_end_bio to deal with write errors to a single mirror * 'for-linus-3.2' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: btrfs: lower the dirty balance poll interval --- c9a7fe9672612c0b595633d2945f52257ad92b20 diff --combined fs/btrfs/delayed-inode.c index 5b16357,c7ddf8a,5b16357..9c1eccc --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@@@ -640,8 -640,8 -640,8 +640,8 @@@@ static int btrfs_delayed_inode_reserve_ * Now if src_rsv == delalloc_block_rsv we'll let it just steal since * we're accounted for. */ - - if (!trans->bytes_reserved && - - src_rsv != &root->fs_info->delalloc_block_rsv) { + + if (!src_rsv || (!trans->bytes_reserved && + + src_rsv != &root->fs_info->delalloc_block_rsv)) { ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes); /* * Since we're under a transaction reserve_metadata_bytes could @@@@ -1719,7 -1719,7 -1719,7 +1719,7 @@@@ int btrfs_fill_inode(struct inode *inod inode->i_gid = btrfs_stack_inode_gid(inode_item); btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); inode->i_mode = btrfs_stack_inode_mode(inode_item); - inode->i_nlink = btrfs_stack_inode_nlink(inode_item); + set_nlink(inode, btrfs_stack_inode_nlink(inode_item)); inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item); diff --combined fs/btrfs/disk-io.c index 632f8f3,3f9d555,632f8f3..f44b392 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@@@ -2007,7 -2007,7 -2007,7 +2007,7 @@@@ struct btrfs_root *open_ctree(struct su sb->s_bdi = &fs_info->bdi; fs_info->btree_inode->i_ino = BTRFS_BTREE_INODE_OBJECTID; - fs_info->btree_inode->i_nlink = 1; + set_nlink(fs_info->btree_inode, 1); /* * we set the i_size on the btree inode to the max possible int. * the real end of the address space is determined by all of @@@@ -2194,19 -2194,27 -2194,19 +2194,27 @@@@ fs_info->endio_meta_write_workers.idle_thresh = 2; fs_info->readahead_workers.idle_thresh = 2; - - btrfs_start_workers(&fs_info->workers, 1); - - btrfs_start_workers(&fs_info->generic_worker, 1); - - btrfs_start_workers(&fs_info->submit_workers, 1); - - btrfs_start_workers(&fs_info->delalloc_workers, 1); - - btrfs_start_workers(&fs_info->fixup_workers, 1); - - btrfs_start_workers(&fs_info->endio_workers, 1); - - btrfs_start_workers(&fs_info->endio_meta_workers, 1); - - btrfs_start_workers(&fs_info->endio_meta_write_workers, 1); - - btrfs_start_workers(&fs_info->endio_write_workers, 1); - - btrfs_start_workers(&fs_info->endio_freespace_worker, 1); - - btrfs_start_workers(&fs_info->delayed_workers, 1); - - btrfs_start_workers(&fs_info->caching_workers, 1); - - btrfs_start_workers(&fs_info->readahead_workers, 1); + + /* + + * btrfs_start_workers can really only fail because of ENOMEM so just + + * return -ENOMEM if any of these fail. + + */ + + ret = btrfs_start_workers(&fs_info->workers); + + ret |= btrfs_start_workers(&fs_info->generic_worker); + + ret |= btrfs_start_workers(&fs_info->submit_workers); + + ret |= btrfs_start_workers(&fs_info->delalloc_workers); + + ret |= btrfs_start_workers(&fs_info->fixup_workers); + + ret |= btrfs_start_workers(&fs_info->endio_workers); + + ret |= btrfs_start_workers(&fs_info->endio_meta_workers); + + ret |= btrfs_start_workers(&fs_info->endio_meta_write_workers); + + ret |= btrfs_start_workers(&fs_info->endio_write_workers); + + ret |= btrfs_start_workers(&fs_info->endio_freespace_worker); + + ret |= btrfs_start_workers(&fs_info->delayed_workers); + + ret |= btrfs_start_workers(&fs_info->caching_workers); + + ret |= btrfs_start_workers(&fs_info->readahead_workers); + + if (ret) { + + ret = -ENOMEM; + + goto fail_sb_buffer; + + } fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, diff --combined fs/btrfs/extent-tree.c index 2ad8136,8603ee4,2ad8136..f5fbe57 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@@@ -2822,7 -2822,7 -2822,7 +2822,7 @@@@ out_free btrfs_release_path(path); out: spin_lock(&block_group->lock); - - if (!ret) + + if (!ret && dcs == BTRFS_DC_SETUP) block_group->cache_generation = trans->transid; block_group->disk_cache_state = dcs; spin_unlock(&block_group->lock); @@@@ -3416,8 -3416,7 -3416,8 +3416,8 @@@@ static int shrink_delalloc(struct btrfs smp_mb(); nr_pages = min_t(unsigned long, nr_pages, root->fs_info->delalloc_bytes >> PAGE_CACHE_SHIFT); - writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages); + writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages, + WB_REASON_FS_FREE_SPACE); spin_lock(&space_info->lock); if (reserved > space_info->bytes_may_use) @@@@ -4204,12 -4203,17 -4204,12 +4204,17 @@@@ int btrfs_delalloc_reserve_metadata(str struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv; u64 to_reserve = 0; + + u64 csum_bytes; unsigned nr_extents = 0; + + int extra_reserve = 0; int flush = 1; int ret; + + /* Need to be holding the i_mutex here if we aren't free space cache */ if (btrfs_is_free_space_inode(root, inode)) flush = 0; + + else + + WARN_ON(!mutex_is_locked(&inode->i_mutex)); if (flush && btrfs_transaction_in_commit(root->fs_info)) schedule_timeout(1); @@@@ -4220,11 -4224,9 -4220,11 +4225,9 @@@@ BTRFS_I(inode)->outstanding_extents++; if (BTRFS_I(inode)->outstanding_extents > - - BTRFS_I(inode)->reserved_extents) { + + BTRFS_I(inode)->reserved_extents) nr_extents = BTRFS_I(inode)->outstanding_extents - BTRFS_I(inode)->reserved_extents; - - BTRFS_I(inode)->reserved_extents += nr_extents; - - } /* * Add an item to reserve for updating the inode when we complete the @@@@ -4232,11 -4234,12 -4232,11 +4235,12 @@@@ */ if (!BTRFS_I(inode)->delalloc_meta_reserved) { nr_extents++; - - BTRFS_I(inode)->delalloc_meta_reserved = 1; + + extra_reserve = 1; } to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); + + csum_bytes = BTRFS_I(inode)->csum_bytes; spin_unlock(&BTRFS_I(inode)->lock); ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush); @@@@ -4246,22 -4249,35 -4246,22 +4250,35 @@@@ spin_lock(&BTRFS_I(inode)->lock); dropped = drop_outstanding_extent(inode); - - to_free = calc_csum_metadata_size(inode, num_bytes, 0); - - spin_unlock(&BTRFS_I(inode)->lock); - - to_free += btrfs_calc_trans_metadata_size(root, dropped); - - /* - - * Somebody could have come in and twiddled with the - - * reservation, so if we have to free more than we would have - - * reserved from this reservation go ahead and release those - - * bytes. + + * If the inodes csum_bytes is the same as the original + + * csum_bytes then we know we haven't raced with any free()ers + + * so we can just reduce our inodes csum bytes and carry on. + + * Otherwise we have to do the normal free thing to account for + + * the case that the free side didn't free up its reserve + + * because of this outstanding reservation. */ - - to_free -= to_reserve; + + if (BTRFS_I(inode)->csum_bytes == csum_bytes) + + calc_csum_metadata_size(inode, num_bytes, 0); + + else + + to_free = calc_csum_metadata_size(inode, num_bytes, 0); + + spin_unlock(&BTRFS_I(inode)->lock); + + if (dropped) + + to_free += btrfs_calc_trans_metadata_size(root, dropped); + + if (to_free) btrfs_block_rsv_release(root, block_rsv, to_free); return ret; } + + spin_lock(&BTRFS_I(inode)->lock); + + if (extra_reserve) { + + BTRFS_I(inode)->delalloc_meta_reserved = 1; + + nr_extents--; + + } + + BTRFS_I(inode)->reserved_extents += nr_extents; + + spin_unlock(&BTRFS_I(inode)->lock); + + block_rsv_add_bytes(block_rsv, to_reserve, 1); return 0; diff --combined fs/btrfs/file.c index dafdfa0,cc7492c,52305a8..97fbe93 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@@@ -1167,6 -1167,6 -1167,8 +1167,8 @@@@ static noinline ssize_t __btrfs_buffere nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / (sizeof(struct page *))); ++ nrptrs = min(nrptrs, current->nr_dirtied_pause - current->nr_dirtied); ++ nrptrs = max(nrptrs, 8); pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL); if (!pages) return -ENOMEM; @@@@ -1387,7 -1387,11 -1389,7 +1389,11 @@@@ static ssize_t btrfs_file_aio_write(str goto out; } - - file_update_time(file); + + err = btrfs_update_time(file); + + if (err) { + + mutex_unlock(&inode->i_mutex); + + goto out; + + } BTRFS_I(inode)->sequence++; start_pos = round_down(pos, root->sectorsize); @@@@ -1832,7 -1836,7 -1834,7 +1838,7 @@@@ static loff_t btrfs_file_llseek(struct switch (origin) { case SEEK_END: case SEEK_CUR: - offset = generic_file_llseek_unlocked(file, offset, origin); + offset = generic_file_llseek(file, offset, origin); goto out; case SEEK_DATA: case SEEK_HOLE: diff --combined fs/btrfs/inode.c index 2c984f7,740e67b,2c984f7..0a6b928 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@@@ -38,6 -38,7 -38,6 +38,7 @@@@ #include #include #include + +#include #include "compat.h" #include "ctree.h" #include "disk-io.h" @@@@ -2031,7 -2032,7 -2031,7 +2032,7 @@@@ int btrfs_orphan_add(struct btrfs_trans /* insert an orphan item to track this unlinked/truncated file */ if (insert >= 1) { ret = btrfs_insert_orphan_item(trans, root, btrfs_ino(inode)); - - BUG_ON(ret); + + BUG_ON(ret && ret != -EEXIST); } /* insert an orphan item to track subvolume contains orphan files */ @@@@ -2158,6 -2159,38 -2158,6 +2159,38 @@@@ int btrfs_orphan_cleanup(struct btrfs_r if (ret && ret != -ESTALE) goto out; + + if (ret == -ESTALE && root == root->fs_info->tree_root) { + + struct btrfs_root *dead_root; + + struct btrfs_fs_info *fs_info = root->fs_info; + + int is_dead_root = 0; + + + + /* + + * this is an orphan in the tree root. Currently these + + * could come from 2 sources: + + * a) a snapshot deletion in progress + + * b) a free space cache inode + + * We need to distinguish those two, as the snapshot + + * orphan must not get deleted. + + * find_dead_roots already ran before us, so if this + + * is a snapshot deletion, we should find the root + + * in the dead_roots list + + */ + + spin_lock(&fs_info->trans_lock); + + list_for_each_entry(dead_root, &fs_info->dead_roots, + + root_list) { + + if (dead_root->root_key.objectid == + + found_key.objectid) { + + is_dead_root = 1; + + break; + + } + + } + + spin_unlock(&fs_info->trans_lock); + + if (is_dead_root) { + + /* prevent this orphan from being found again */ + + key.offset = found_key.objectid - 1; + + continue; + + } + + } /* * Inode is already gone but the orphan item is still there, * kill the orphan item. @@@@ -2191,7 -2224,14 -2191,7 +2224,14 @@@@ continue; } nr_truncate++; + + /* + + * Need to hold the imutex for reservation purposes, not + + * a huge deal here but I have a WARN_ON in + + * btrfs_delalloc_reserve_space to catch offenders. + + */ + + mutex_lock(&inode->i_mutex); ret = btrfs_truncate(inode); + + mutex_unlock(&inode->i_mutex); } else { nr_unlink++; } @@@@ -2318,7 -2358,7 -2318,7 +2358,7 @@@@ static void btrfs_read_locked_inode(str inode_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_item); inode->i_mode = btrfs_inode_mode(leaf, inode_item); - inode->i_nlink = btrfs_inode_nlink(leaf, inode_item); + set_nlink(inode, btrfs_inode_nlink(leaf, inode_item)); inode->i_uid = btrfs_inode_uid(leaf, inode_item); inode->i_gid = btrfs_inode_gid(leaf, inode_item); btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item)); @@@@ -3327,7 -3367,7 -3327,7 +3367,7 @@@@ int btrfs_cont_expand(struct inode *ino u64 hint_byte = 0; hole_size = last_byte - cur_offset; - - trans = btrfs_start_transaction(root, 2); + + trans = btrfs_start_transaction(root, 3); if (IS_ERR(trans)) { err = PTR_ERR(trans); break; @@@@ -3337,6 -3377,7 -3337,6 +3377,7 @@@@ cur_offset + hole_size, &hint_byte, 1); if (err) { + + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@@@ -3346,6 -3387,7 -3346,6 +3387,7 @@@@ 0, hole_size, 0, hole_size, 0, 0, 0); if (err) { + + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); break; } @@@@ -3353,6 -3395,7 -3353,6 +3395,7 @@@@ btrfs_drop_extent_cache(inode, hole_start, last_byte - 1, 0); + + btrfs_update_inode(trans, root, inode); btrfs_end_transaction(trans, root); } free_extent_map(em); @@@@ -3370,6 -3413,8 -3370,6 +3413,8 @@@@ static int btrfs_setsize(struct inode *inode, loff_t newsize) { + + struct btrfs_root *root = BTRFS_I(inode)->root; + + struct btrfs_trans_handle *trans; loff_t oldsize = i_size_read(inode); int ret; @@@@ -3377,16 -3422,19 -3377,16 +3422,19 @@@@ return 0; if (newsize > oldsize) { - - i_size_write(inode, newsize); - - btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); truncate_pagecache(inode, oldsize, newsize); ret = btrfs_cont_expand(inode, oldsize, newsize); - - if (ret) { - - btrfs_setsize(inode, oldsize); + + if (ret) return ret; - - } - - mark_inode_dirty(inode); + + trans = btrfs_start_transaction(root, 1); + + if (IS_ERR(trans)) + + return PTR_ERR(trans); + + + + i_size_write(inode, newsize); + + btrfs_ordered_update_i_size(inode, i_size_read(inode), NULL); + + ret = btrfs_update_inode(trans, root, inode); + + btrfs_end_transaction_throttle(trans, root); } else { /* @@@@ -3426,9 -3474,9 -3426,9 +3474,9 @@@@ static int btrfs_setattr(struct dentry if (attr->ia_valid) { setattr_copy(inode, attr); - - mark_inode_dirty(inode); + + err = btrfs_dirty_inode(inode); - - if (attr->ia_valid & ATTR_MODE) + + if (!err && attr->ia_valid & ATTR_MODE) err = btrfs_acl_chmod(inode); } @@@@ -4204,42 -4252,80 -4204,42 +4252,80 @@@@ int btrfs_write_inode(struct inode *ino * FIXME, needs more benchmarking...there are no reasons other than performance * to keep or drop this code. */ - -void btrfs_dirty_inode(struct inode *inode, int flags) + +int btrfs_dirty_inode(struct inode *inode) { struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_trans_handle *trans; int ret; if (BTRFS_I(inode)->dummy_inode) - - return; + + return 0; trans = btrfs_join_transaction(root); - - BUG_ON(IS_ERR(trans)); + + if (IS_ERR(trans)) + + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); if (ret && ret == -ENOSPC) { /* whoops, lets try again with the full transaction */ btrfs_end_transaction(trans, root); trans = btrfs_start_transaction(root, 1); - - if (IS_ERR(trans)) { - - printk_ratelimited(KERN_ERR "btrfs: fail to " - - "dirty inode %llu error %ld\n", - - (unsigned long long)btrfs_ino(inode), - - PTR_ERR(trans)); - - return; - - } + + if (IS_ERR(trans)) + + return PTR_ERR(trans); ret = btrfs_update_inode(trans, root, inode); - - if (ret) { - - printk_ratelimited(KERN_ERR "btrfs: fail to " - - "dirty inode %llu error %d\n", - - (unsigned long long)btrfs_ino(inode), - - ret); - - } } btrfs_end_transaction(trans, root); if (BTRFS_I(inode)->delayed_node) btrfs_balance_delayed_items(root); + + + + return ret; + +} + + + +/* + + * This is a copy of file_update_time. We need this so we can return error on + + * ENOSPC for updating the inode in the case of file write and mmap writes. + + */ + +int btrfs_update_time(struct file *file) + +{ + + struct inode *inode = file->f_path.dentry->d_inode; + + struct timespec now; + + int ret; + + enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0; + + + + /* First try to exhaust all avenues to not sync */ + + if (IS_NOCMTIME(inode)) + + return 0; + + + + now = current_fs_time(inode->i_sb); + + if (!timespec_equal(&inode->i_mtime, &now)) + + sync_it = S_MTIME; + + + + if (!timespec_equal(&inode->i_ctime, &now)) + + sync_it |= S_CTIME; + + + + if (IS_I_VERSION(inode)) + + sync_it |= S_VERSION; + + + + if (!sync_it) + + return 0; + + + + /* Finally allowed to write? Takes lock. */ + + if (mnt_want_write_file(file)) + + return 0; + + + + /* Only change inode inside the lock region */ + + if (sync_it & S_VERSION) + + inode_inc_iversion(inode); + + if (sync_it & S_CTIME) + + inode->i_ctime = now; + + if (sync_it & S_MTIME) + + inode->i_mtime = now; + + ret = btrfs_dirty_inode(inode); + + if (!ret) + + mark_inode_dirty_sync(inode); + + mnt_drop_write(file->f_path.mnt); + + return ret; } /* @@@@ -4555,11 -4641,18 -4555,11 +4641,18 @@@@ static int btrfs_mknod(struct inode *di goto out_unlock; } + + /* + + * If the active LSM wants to access the inode during + + * d_instantiate it needs these. Smack checks to see + + * if the filesystem supports xattrs by looking at the + + * ops vector. + + */ + + + + inode->i_op = &btrfs_special_inode_operations; err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { - - inode->i_op = &btrfs_special_inode_operations; init_special_inode(inode, inode->i_mode, rdev); btrfs_update_inode(trans, root, inode); } @@@@ -4613,14 -4706,21 -4613,14 +4706,21 @@@@ static int btrfs_create(struct inode *d goto out_unlock; } + + /* + + * If the active LSM wants to access the inode during + + * d_instantiate it needs these. Smack checks to see + + * if the filesystem supports xattrs by looking at the + + * ops vector. + + */ + + inode->i_fop = &btrfs_file_operations; + + inode->i_op = &btrfs_file_inode_operations; + + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - - inode->i_fop = &btrfs_file_operations; - - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } out_unlock: @@@@ -6303,7 -6403,12 -6303,7 +6403,12 @@@@ int btrfs_page_mkwrite(struct vm_area_s u64 page_start; u64 page_end; + + /* Need this to keep space reservations serialized */ + + mutex_lock(&inode->i_mutex); ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); + + mutex_unlock(&inode->i_mutex); + + if (!ret) + + ret = btrfs_update_time(vma->vm_file); if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; @@@@ -6515,8 -6620,9 -6515,8 +6620,9 @@@@ static int btrfs_truncate(struct inode /* Just need the 1 for updating the inode */ trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { - - err = PTR_ERR(trans); - - goto out; + + ret = err = PTR_ERR(trans); + + trans = NULL; + + break; } } @@@@ -6593,7 -6699,7 -6593,7 +6699,7 @@@@ int btrfs_create_subvol_root(struct btr inode->i_op = &btrfs_dir_inode_operations; inode->i_fop = &btrfs_dir_file_operations; - inode->i_nlink = 1; + set_nlink(inode, 1); btrfs_i_size_write(inode, 0); err = btrfs_update_inode(trans, new_root, inode); @@@@ -7076,14 -7182,21 -7076,14 +7182,21 @@@@ static int btrfs_symlink(struct inode * goto out_unlock; } + + /* + + * If the active LSM wants to access the inode during + + * d_instantiate it needs these. Smack checks to see + + * if the filesystem supports xattrs by looking at the + + * ops vector. + + */ + + inode->i_fop = &btrfs_file_operations; + + inode->i_op = &btrfs_file_inode_operations; + + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); if (err) drop_inode = 1; else { inode->i_mapping->a_ops = &btrfs_aops; inode->i_mapping->backing_dev_info = &root->fs_info->bdi; - - inode->i_fop = &btrfs_file_operations; - - inode->i_op = &btrfs_file_inode_operations; BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; } if (drop_inode) @@@@ -7353,6 -7466,7 -7353,6 +7466,7 @@@@ static const struct inode_operations bt .follow_link = page_follow_link_light, .put_link = page_put_link, .getattr = btrfs_getattr, + + .setattr = btrfs_setattr, .permission = btrfs_permission, .setxattr = btrfs_setxattr, .getxattr = btrfs_getxattr, diff --combined fs/btrfs/super.c index e28ad4b,34a8b61,e28ad4b..200f63b --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@@@ -41,6 -41,7 -41,6 +41,7 @@@@ #include #include #include + +#include #include "compat.h" #include "delayed-inode.h" #include "ctree.h" @@@@ -825,9 -826,13 -825,9 +826,9 @@@@ static char *setup_root_args(char *args static struct dentry *mount_subvol(const char *subvol_name, int flags, const char *device_name, char *data) { - struct super_block *s; struct dentry *root; struct vfsmount *mnt; - struct mnt_namespace *ns_private; char *newargs; - struct path path; - int error; newargs = setup_root_args(data); if (!newargs) @@@@ -838,17 -843,39 -838,17 +839,17 @@@@ if (IS_ERR(mnt)) return ERR_CAST(mnt); - ns_private = create_mnt_ns(mnt); - if (IS_ERR(ns_private)) { - mntput(mnt); - return ERR_CAST(ns_private); - } + root = mount_subtree(mnt, subvol_name); - /* - * This will trigger the automount of the subvol so we can just - * drop the mnt we have here and return the dentry that we - * found. - */ - error = vfs_path_lookup(mnt->mnt_root, mnt, subvol_name, - LOOKUP_FOLLOW, &path); - put_mnt_ns(ns_private); - if (error) - return ERR_PTR(error); - - if (!is_subvolume_inode(path.dentry->d_inode)) { - path_put(&path); - mntput(mnt); - error = -EINVAL; + if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) { + struct super_block *s = root->d_sb; + dput(root); + root = ERR_PTR(-EINVAL); + deactivate_locked_super(s); printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n", subvol_name); - return ERR_PTR(-EINVAL); } - /* Get a ref to the sb and the dentry we found and return it */ - s = path.mnt->mnt_sb; - atomic_inc(&s->s_active); - root = dget(path.dentry); - path_put(&path); - down_write(&s->s_umount); - return root; } @@@@ -1053,7 -1080,7 -1053,7 +1054,7 @@@@ static int btrfs_calc_avail_data_space( u64 avail_space; u64 used_space; u64 min_stripe_size; - - int min_stripes = 1; + + int min_stripes = 1, num_stripes = 1; int i = 0, nr_devices; int ret; @@@@ -1067,12 -1094,16 -1067,12 +1068,16 @@@@ /* calc min stripe number for data space alloction */ type = btrfs_get_alloc_profile(root, 1); - - if (type & BTRFS_BLOCK_GROUP_RAID0) + + if (type & BTRFS_BLOCK_GROUP_RAID0) { min_stripes = 2; - - else if (type & BTRFS_BLOCK_GROUP_RAID1) + + num_stripes = nr_devices; + + } else if (type & BTRFS_BLOCK_GROUP_RAID1) { min_stripes = 2; - - else if (type & BTRFS_BLOCK_GROUP_RAID10) + + num_stripes = 2; + + } else if (type & BTRFS_BLOCK_GROUP_RAID10) { min_stripes = 4; + + num_stripes = 4; + + } if (type & BTRFS_BLOCK_GROUP_DUP) min_stripe_size = 2 * BTRFS_STRIPE_LEN; @@@@ -1141,13 -1172,16 -1141,13 +1146,16 @@@@ i = nr_devices - 1; avail_space = 0; while (nr_devices >= min_stripes) { + + if (num_stripes > nr_devices) + + num_stripes = nr_devices; + + if (devices_info[i].max_avail >= min_stripe_size) { int j; u64 alloc_size; - - avail_space += devices_info[i].max_avail * min_stripes; + + avail_space += devices_info[i].max_avail * num_stripes; alloc_size = devices_info[i].max_avail; - - for (j = i + 1 - min_stripes; j <= i; j++) + + for (j = i + 1 - num_stripes; j <= i; j++) devices_info[j].max_avail -= alloc_size; } i--; @@@@ -1264,6 -1298,16 -1264,6 +1272,16 @@@@ static int btrfs_unfreeze(struct super_ return 0; } + +static void btrfs_fs_dirty_inode(struct inode *inode, int flags) + +{ + + int ret; + + + + ret = btrfs_dirty_inode(inode); + + if (ret) + + printk_ratelimited(KERN_ERR "btrfs: fail to dirty inode %Lu " + + "error %d\n", btrfs_ino(inode), ret); + +} + + static const struct super_operations btrfs_super_ops = { .drop_inode = btrfs_drop_inode, .evict_inode = btrfs_evict_inode, @@@@ -1271,7 -1315,7 -1271,7 +1289,7 @@@@ .sync_fs = btrfs_sync_fs, .show_options = btrfs_show_options, .write_inode = btrfs_write_inode, - - .dirty_inode = btrfs_dirty_inode, + + .dirty_inode = btrfs_fs_dirty_inode, .alloc_inode = btrfs_alloc_inode, .destroy_inode = btrfs_destroy_inode, .statfs = btrfs_statfs,