Commit eee2a817 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (25 commits)
  Btrfs: forced readonly mounts on errors
  btrfs: Require CAP_SYS_ADMIN for filesystem rebalance
  Btrfs: don't warn if we get ENOSPC in btrfs_block_rsv_check
  btrfs: Fix memory leak in btrfs_read_fs_root_no_radix()
  btrfs: check NULL or not
  btrfs: Don't pass NULL ptr to func that may deref it.
  btrfs: mount failure return value fix
  btrfs: Mem leak in btrfs_get_acl()
  btrfs: fix wrong free space information of btrfs
  btrfs: make the chunk allocator utilize the devices better
  btrfs: restructure find_free_dev_extent()
  btrfs: fix wrong calculation of stripe size
  btrfs: try to reclaim some space when chunk allocation fails
  btrfs: fix wrong data space statistics
  fs/btrfs: Fix build of ctree
  Btrfs: fix off by one while setting block groups readonly
  Btrfs: Add BTRFS_IOC_SUBVOL_GETFLAGS/SETFLAGS ioctls
  Btrfs: Add readonly snapshots support
  Btrfs: Refactor btrfs_ioctl_snap_create()
  btrfs: Extract duplicate decompress code
  ...
parents 83896fb5 acce952b
...@@ -4,6 +4,8 @@ config BTRFS_FS ...@@ -4,6 +4,8 @@ config BTRFS_FS
select LIBCRC32C select LIBCRC32C
select ZLIB_INFLATE select ZLIB_INFLATE
select ZLIB_DEFLATE select ZLIB_DEFLATE
select LZO_COMPRESS
select LZO_DECOMPRESS
help help
Btrfs is a new filesystem with extents, writable snapshotting, Btrfs is a new filesystem with extents, writable snapshotting,
support for multiple devices and many more features. support for multiple devices and many more features.
......
...@@ -6,5 +6,5 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ ...@@ -6,5 +6,5 @@ btrfs-y += super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
transaction.o inode.o file.o tree-defrag.o \ transaction.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \ extent_io.o volumes.o async-thread.o ioctl.o locking.o orphan.o \
export.o tree-log.o acl.o free-space-cache.o zlib.o \ export.o tree-log.o acl.o free-space-cache.o zlib.o lzo.o \
compression.o delayed-ref.o relocation.o compression.o delayed-ref.o relocation.o
...@@ -60,8 +60,10 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type) ...@@ -60,8 +60,10 @@ static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
size = __btrfs_getxattr(inode, name, value, size); size = __btrfs_getxattr(inode, name, value, size);
if (size > 0) { if (size > 0) {
acl = posix_acl_from_xattr(value, size); acl = posix_acl_from_xattr(value, size);
if (IS_ERR(acl)) if (IS_ERR(acl)) {
kfree(value);
return acl; return acl;
}
set_cached_acl(inode, type, acl); set_cached_acl(inode, type, acl);
} }
kfree(value); kfree(value);
......
...@@ -157,7 +157,7 @@ struct btrfs_inode { ...@@ -157,7 +157,7 @@ struct btrfs_inode {
/* /*
* always compress this one file * always compress this one file
*/ */
unsigned force_compress:1; unsigned force_compress:4;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
This diff is collapsed.
...@@ -19,24 +19,27 @@ ...@@ -19,24 +19,27 @@
#ifndef __BTRFS_COMPRESSION_ #ifndef __BTRFS_COMPRESSION_
#define __BTRFS_COMPRESSION_ #define __BTRFS_COMPRESSION_
int btrfs_zlib_decompress(unsigned char *data_in, int btrfs_init_compress(void);
struct page *dest_page, void btrfs_exit_compress(void);
unsigned long start_byte,
size_t srclen, size_t destlen); int btrfs_compress_pages(int type, struct address_space *mapping,
int btrfs_zlib_compress_pages(struct address_space *mapping, u64 start, unsigned long len,
u64 start, unsigned long len, struct page **pages,
struct page **pages, unsigned long nr_dest_pages,
unsigned long nr_dest_pages, unsigned long *out_pages,
unsigned long *out_pages, unsigned long *total_in,
unsigned long *total_in, unsigned long *total_out,
unsigned long *total_out, unsigned long max_out);
unsigned long max_out); int btrfs_decompress_biovec(int type, struct page **pages_in, u64 disk_start,
int btrfs_zlib_decompress_biovec(struct page **pages_in, struct bio_vec *bvec, int vcnt, size_t srclen);
u64 disk_start, int btrfs_decompress(int type, unsigned char *data_in, struct page *dest_page,
struct bio_vec *bvec, unsigned long start_byte, size_t srclen, size_t destlen);
int vcnt, int btrfs_decompress_buf2page(char *buf, unsigned long buf_start,
size_t srclen); unsigned long total_out, u64 disk_start,
void btrfs_zlib_exit(void); struct bio_vec *bvec, int vcnt,
unsigned long *page_index,
unsigned long *pg_offset);
int btrfs_submit_compressed_write(struct inode *inode, u64 start, int btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long len, u64 disk_start, unsigned long len, u64 disk_start,
unsigned long compressed_len, unsigned long compressed_len,
...@@ -44,4 +47,37 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, ...@@ -44,4 +47,37 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
unsigned long nr_pages); unsigned long nr_pages);
int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
int mirror_num, unsigned long bio_flags); int mirror_num, unsigned long bio_flags);
struct btrfs_compress_op {
struct list_head *(*alloc_workspace)(void);
void (*free_workspace)(struct list_head *workspace);
int (*compress_pages)(struct list_head *workspace,
struct address_space *mapping,
u64 start, unsigned long len,
struct page **pages,
unsigned long nr_dest_pages,
unsigned long *out_pages,
unsigned long *total_in,
unsigned long *total_out,
unsigned long max_out);
int (*decompress_biovec)(struct list_head *workspace,
struct page **pages_in,
u64 disk_start,
struct bio_vec *bvec,
int vcnt,
size_t srclen);
int (*decompress)(struct list_head *workspace,
unsigned char *data_in,
struct page *dest_page,
unsigned long start_byte,
size_t srclen, size_t destlen);
};
extern struct btrfs_compress_op btrfs_zlib_compress;
extern struct btrfs_compress_op btrfs_lzo_compress;
#endif #endif
...@@ -105,6 +105,8 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p, ...@@ -105,6 +105,8 @@ noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
/* this also releases the path */ /* this also releases the path */
void btrfs_free_path(struct btrfs_path *p) void btrfs_free_path(struct btrfs_path *p)
{ {
if (!p)
return;
btrfs_release_path(NULL, p); btrfs_release_path(NULL, p);
kmem_cache_free(btrfs_path_cachep, p); kmem_cache_free(btrfs_path_cachep, p);
} }
...@@ -2514,6 +2516,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -2514,6 +2516,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_assert_tree_locked(path->nodes[1]); btrfs_assert_tree_locked(path->nodes[1]);
right = read_node_slot(root, upper, slot + 1); right = read_node_slot(root, upper, slot + 1);
if (right == NULL)
return 1;
btrfs_tree_lock(right); btrfs_tree_lock(right);
btrfs_set_lock_blocking(right); btrfs_set_lock_blocking(right);
...@@ -2764,6 +2769,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -2764,6 +2769,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_assert_tree_locked(path->nodes[1]); btrfs_assert_tree_locked(path->nodes[1]);
left = read_node_slot(root, path->nodes[1], slot - 1); left = read_node_slot(root, path->nodes[1], slot - 1);
if (left == NULL)
return 1;
btrfs_tree_lock(left); btrfs_tree_lock(left);
btrfs_set_lock_blocking(left); btrfs_set_lock_blocking(left);
......
...@@ -295,6 +295,14 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes) ...@@ -295,6 +295,14 @@ static inline unsigned long btrfs_chunk_item_size(int num_stripes)
#define BTRFS_FSID_SIZE 16 #define BTRFS_FSID_SIZE 16
#define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0) #define BTRFS_HEADER_FLAG_WRITTEN (1ULL << 0)
#define BTRFS_HEADER_FLAG_RELOC (1ULL << 1) #define BTRFS_HEADER_FLAG_RELOC (1ULL << 1)
/*
* File system states
*/
/* Errors detected */
#define BTRFS_SUPER_FLAG_ERROR (1ULL << 2)
#define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32) #define BTRFS_SUPER_FLAG_SEEDING (1ULL << 32)
#define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33) #define BTRFS_SUPER_FLAG_METADUMP (1ULL << 33)
...@@ -399,13 +407,15 @@ struct btrfs_super_block { ...@@ -399,13 +407,15 @@ struct btrfs_super_block {
#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0)
#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1)
#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2)
#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3)
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_SUPP 0ULL
#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL
#define BTRFS_FEATURE_INCOMPAT_SUPP \ #define BTRFS_FEATURE_INCOMPAT_SUPP \
(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO)
/* /*
* A leaf is full of items. offset and size tell us where to find * A leaf is full of items. offset and size tell us where to find
...@@ -552,9 +562,11 @@ struct btrfs_timespec { ...@@ -552,9 +562,11 @@ struct btrfs_timespec {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
enum btrfs_compression_type { enum btrfs_compression_type {
BTRFS_COMPRESS_NONE = 0, BTRFS_COMPRESS_NONE = 0,
BTRFS_COMPRESS_ZLIB = 1, BTRFS_COMPRESS_ZLIB = 1,
BTRFS_COMPRESS_LAST = 2, BTRFS_COMPRESS_LZO = 2,
BTRFS_COMPRESS_TYPES = 2,
BTRFS_COMPRESS_LAST = 3,
}; };
struct btrfs_inode_item { struct btrfs_inode_item {
...@@ -598,6 +610,8 @@ struct btrfs_dir_item { ...@@ -598,6 +610,8 @@ struct btrfs_dir_item {
u8 type; u8 type;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
#define BTRFS_ROOT_SUBVOL_RDONLY (1ULL << 0)
struct btrfs_root_item { struct btrfs_root_item {
struct btrfs_inode_item inode; struct btrfs_inode_item inode;
__le64 generation; __le64 generation;
...@@ -896,7 +910,8 @@ struct btrfs_fs_info { ...@@ -896,7 +910,8 @@ struct btrfs_fs_info {
*/ */
u64 last_trans_log_full_commit; u64 last_trans_log_full_commit;
u64 open_ioctl_trans; u64 open_ioctl_trans;
unsigned long mount_opt; unsigned long mount_opt:20;
unsigned long compress_type:4;
u64 max_inline; u64 max_inline;
u64 alloc_start; u64 alloc_start;
struct btrfs_transaction *running_transaction; struct btrfs_transaction *running_transaction;
...@@ -1051,6 +1066,9 @@ struct btrfs_fs_info { ...@@ -1051,6 +1066,9 @@ struct btrfs_fs_info {
unsigned metadata_ratio; unsigned metadata_ratio;
void *bdev_holder; void *bdev_holder;
/* filesystem state */
u64 fs_state;
}; };
/* /*
...@@ -1894,6 +1912,11 @@ BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64); ...@@ -1894,6 +1912,11 @@ BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item, BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
last_snapshot, 64); last_snapshot, 64);
static inline bool btrfs_root_readonly(struct btrfs_root *root)
{
return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
}
/* struct btrfs_super_block */ /* struct btrfs_super_block */
BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
...@@ -2146,6 +2169,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, ...@@ -2146,6 +2169,7 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
int btrfs_remove_block_group(struct btrfs_trans_handle *trans, int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 group_start); struct btrfs_root *root, u64 group_start);
u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags); u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags);
u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data);
void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde); void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
void btrfs_clear_space_info_full(struct btrfs_fs_info *info); void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
int btrfs_check_data_free_space(struct inode *inode, u64 bytes); int btrfs_check_data_free_space(struct inode *inode, u64 bytes);
...@@ -2189,6 +2213,12 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, ...@@ -2189,6 +2213,12 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
int btrfs_set_block_group_rw(struct btrfs_root *root, int btrfs_set_block_group_rw(struct btrfs_root *root,
struct btrfs_block_group_cache *cache); struct btrfs_block_group_cache *cache);
void btrfs_put_block_group_cache(struct btrfs_fs_info *info); void btrfs_put_block_group_cache(struct btrfs_fs_info *info);
u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
int btrfs_error_unpin_extent_range(struct btrfs_root *root,
u64 start, u64 end);
int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
u64 num_bytes);
/* ctree.c */ /* ctree.c */
int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key, int btrfs_bin_search(struct extent_buffer *eb, struct btrfs_key *key,
int level, int *slot); int level, int *slot);
...@@ -2542,6 +2572,14 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size); ...@@ -2542,6 +2572,14 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
/* super.c */ /* super.c */
int btrfs_parse_options(struct btrfs_root *root, char *options); int btrfs_parse_options(struct btrfs_root *root, char *options);
int btrfs_sync_fs(struct super_block *sb, int wait); int btrfs_sync_fs(struct super_block *sb, int wait);
void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
unsigned int line, int errno);
#define btrfs_std_error(fs_info, errno) \
do { \
if ((errno)) \
__btrfs_std_error((fs_info), __func__, __LINE__, (errno));\
} while (0)
/* acl.c */ /* acl.c */
#ifdef CONFIG_BTRFS_FS_POSIX_ACL #ifdef CONFIG_BTRFS_FS_POSIX_ACL
......
This diff is collapsed.
...@@ -52,6 +52,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans, ...@@ -52,6 +52,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
struct btrfs_root *root, int max_mirrors); struct btrfs_root *root, int max_mirrors);
struct buffer_head *btrfs_read_dev_super(struct block_device *bdev); struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
int btrfs_commit_super(struct btrfs_root *root); int btrfs_commit_super(struct btrfs_root *root);
int btrfs_error_commit_super(struct btrfs_root *root);
struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
u64 bytenr, u32 blocksize); u64 bytenr, u32 blocksize);
struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
......
...@@ -3089,7 +3089,7 @@ static u64 get_alloc_profile(struct btrfs_root *root, u64 flags) ...@@ -3089,7 +3089,7 @@ static u64 get_alloc_profile(struct btrfs_root *root, u64 flags)
return btrfs_reduce_alloc_profile(root, flags); return btrfs_reduce_alloc_profile(root, flags);
} }
static u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data) u64 btrfs_get_alloc_profile(struct btrfs_root *root, int data)
{ {
u64 flags; u64 flags;
...@@ -3161,8 +3161,12 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes) ...@@ -3161,8 +3161,12 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
bytes + 2 * 1024 * 1024, bytes + 2 * 1024 * 1024,
alloc_target, 0); alloc_target, 0);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
if (ret < 0) if (ret < 0) {
return ret; if (ret != -ENOSPC)
return ret;
else
goto commit_trans;
}
if (!data_sinfo) { if (!data_sinfo) {
btrfs_set_inode_space_info(root, inode); btrfs_set_inode_space_info(root, inode);
...@@ -3173,6 +3177,7 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes) ...@@ -3173,6 +3177,7 @@ int btrfs_check_data_free_space(struct inode *inode, u64 bytes)
spin_unlock(&data_sinfo->lock); spin_unlock(&data_sinfo->lock);
/* commit the current transaction and try again */ /* commit the current transaction and try again */
commit_trans:
if (!committed && !root->fs_info->open_ioctl_trans) { if (!committed && !root->fs_info->open_ioctl_trans) {
committed = 1; committed = 1;
trans = btrfs_join_transaction(root, 1); trans = btrfs_join_transaction(root, 1);
...@@ -3721,11 +3726,6 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans, ...@@ -3721,11 +3726,6 @@ int btrfs_block_rsv_check(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
WARN_ON(1);
printk(KERN_INFO"block_rsv size %llu reserved %llu freed %llu %llu\n",
block_rsv->size, block_rsv->reserved,
block_rsv->freed[0], block_rsv->freed[1]);
return -ENOSPC; return -ENOSPC;
} }
...@@ -7970,13 +7970,14 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache) ...@@ -7970,13 +7970,14 @@ static int set_block_group_ro(struct btrfs_block_group_cache *cache)
if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned + if (sinfo->bytes_used + sinfo->bytes_reserved + sinfo->bytes_pinned +
sinfo->bytes_may_use + sinfo->bytes_readonly + sinfo->bytes_may_use + sinfo->bytes_readonly +
cache->reserved_pinned + num_bytes < sinfo->total_bytes) { cache->reserved_pinned + num_bytes <= sinfo->total_bytes) {
sinfo->bytes_readonly += num_bytes; sinfo->bytes_readonly += num_bytes;
sinfo->bytes_reserved += cache->reserved_pinned; sinfo->bytes_reserved += cache->reserved_pinned;
cache->reserved_pinned = 0; cache->reserved_pinned = 0;
cache->ro = 1; cache->ro = 1;
ret = 0; ret = 0;
} }
spin_unlock(&cache->lock); spin_unlock(&cache->lock);
spin_unlock(&sinfo->lock); spin_unlock(&sinfo->lock);
return ret; return ret;
...@@ -8012,6 +8013,62 @@ int btrfs_set_block_group_ro(struct btrfs_root *root, ...@@ -8012,6 +8013,62 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
return ret; return ret;
} }
/*
* helper to account the unused space of all the readonly block group in the
* list. takes mirrors into account.
*/
static u64 __btrfs_get_ro_block_group_free_space(struct list_head *groups_list)
{
struct btrfs_block_group_cache *block_group;
u64 free_bytes = 0;
int factor;
list_for_each_entry(block_group, groups_list, list) {
spin_lock(&block_group->lock);
if (!block_group->ro) {
spin_unlock(&block_group->lock);
continue;
}
if (block_group->flags & (BTRFS_BLOCK_GROUP_RAID1 |
BTRFS_BLOCK_GROUP_RAID10 |
BTRFS_BLOCK_GROUP_DUP))
factor = 2;
else
factor = 1;
free_bytes += (block_group->key.offset -
btrfs_block_group_used(&block_group->item)) *
factor;
spin_unlock(&block_group->lock);
}
return free_bytes;
}
/*
* helper to account the unused space of all the readonly block group in the
* space_info. takes mirrors into account.
*/
u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo)
{
int i;
u64 free_bytes = 0;
spin_lock(&sinfo->lock);
for(i = 0; i < BTRFS_NR_RAID_TYPES; i++)
if (!list_empty(&sinfo->block_groups[i]))
free_bytes += __btrfs_get_ro_block_group_free_space(
&sinfo->block_groups[i]);
spin_unlock(&sinfo->lock);
return free_bytes;
}
int btrfs_set_block_group_rw(struct btrfs_root *root, int btrfs_set_block_group_rw(struct btrfs_root *root,
struct btrfs_block_group_cache *cache) struct btrfs_block_group_cache *cache)
{ {
...@@ -8092,7 +8149,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) ...@@ -8092,7 +8149,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
mutex_lock(&root->fs_info->chunk_mutex); mutex_lock(&root->fs_info->chunk_mutex);
list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) { list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
u64 min_free = btrfs_block_group_used(&block_group->item); u64 min_free = btrfs_block_group_used(&block_group->item);
u64 dev_offset, max_avail; u64 dev_offset;
/* /*
* check to make sure we can actually find a chunk with enough * check to make sure we can actually find a chunk with enough
...@@ -8100,7 +8157,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr) ...@@ -8100,7 +8157,7 @@ int btrfs_can_relocate(struct btrfs_root *root, u64 bytenr)
*/ */
if (device->total_bytes > device->bytes_used + min_free) { if (device->total_bytes > device->bytes_used + min_free) {
ret = find_free_dev_extent(NULL, device, min_free, ret = find_free_dev_extent(NULL, device, min_free,
&dev_offset, &max_avail); &dev_offset, NULL);
if (!ret) if (!ret)
break; break;
ret = -1; ret = -1;
...@@ -8584,3 +8641,14 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -8584,3 +8641,14 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
} }
int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
{
return unpin_extent_range(root, start, end);
}
int btrfs_error_discard_extent(struct btrfs_root *root, u64 bytenr,
u64 num_bytes)
{
return btrfs_discard_extent(root, bytenr, num_bytes);
}
...@@ -2028,8 +2028,11 @@ static int __extent_read_full_page(struct extent_io_tree *tree, ...@@ -2028,8 +2028,11 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
BUG_ON(extent_map_end(em) <= cur); BUG_ON(extent_map_end(em) <= cur);
BUG_ON(end < cur); BUG_ON(end < cur);
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
this_bio_flag = EXTENT_BIO_COMPRESSED; this_bio_flag = EXTENT_BIO_COMPRESSED;
extent_set_compress_type(&this_bio_flag,
em->compress_type);
}
iosize = min(extent_map_end(em) - cur, end - cur + 1); iosize = min(extent_map_end(em) - cur, end - cur + 1);
cur_end = min(extent_map_end(em) - 1, end); cur_end = min(extent_map_end(em) - 1, end);
...@@ -3072,6 +3075,8 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, ...@@ -3072,6 +3075,8 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree,
#endif #endif
eb = kmem_cache_zalloc(extent_buffer_cache, mask); eb = kmem_cache_zalloc(extent_buffer_cache, mask);
if (eb == NULL)
return NULL;
eb->start = start; eb->start = start;
eb->len = len; eb->len = len;
spin_lock_init(&eb->lock); spin_lock_init(&eb->lock);
......
...@@ -20,8 +20,12 @@ ...@@ -20,8 +20,12 @@
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK) #define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
#define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC) #define EXTENT_CTLBITS (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
/* flags for bio submission */ /*
* flags for bio submission. The high bits indicate the compression
* type for this bio
*/
#define EXTENT_BIO_COMPRESSED 1 #define EXTENT_BIO_COMPRESSED 1
#define EXTENT_BIO_FLAG_SHIFT 16
/* these are bit numbers for test/set bit */ /* these are bit numbers for test/set bit */
#define EXTENT_BUFFER_UPTODATE 0 #define EXTENT_BUFFER_UPTODATE 0
...@@ -135,6 +139,17 @@ struct extent_buffer { ...@@ -135,6 +139,17 @@ struct extent_buffer {
wait_queue_head_t lock_wq; wait_queue_head_t lock_wq;
}; };
static inline void extent_set_compress_type(unsigned long *bio_flags,
int compress_type)
{
*bio_flags |= compress_type << EXTENT_BIO_FLAG_SHIFT;
}
static inline int extent_compress_type(unsigned long bio_flags)
{
return bio_flags >> EXTENT_BIO_FLAG_SHIFT;
}
struct extent_map_tree; struct extent_map_tree;
static inline struct extent_state *extent_state_next(struct extent_state *state) static inline struct extent_state *extent_state_next(struct extent_state *state)
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include "ctree.h"
#include "extent_map.h" #include "extent_map.h"
...@@ -54,6 +55,7 @@ struct extent_map *alloc_extent_map(gfp_t mask) ...@@ -54,6 +55,7 @@ struct extent_map *alloc_extent_map(gfp_t mask)
return em; return em;
em->in_tree = 0; em->in_tree = 0;
em->flags = 0; em->flags = 0;
em->compress_type = BTRFS_COMPRESS_NONE;
atomic_set(&em->refs, 1); atomic_set(&em->refs, 1);
return em; return em;
} }
......
...@@ -26,7 +26,8 @@ struct extent_map { ...@@ -26,7 +26,8 @@ struct extent_map {
unsigned long flags; unsigned long flags;
struct block_device *bdev; struct block_device *bdev;
atomic_t refs; atomic_t refs;
int in_tree; unsigned int in_tree:1;
unsigned int compress_type:4;
}; };
struct extent_map_tree { struct extent_map_tree {
......
...@@ -225,6 +225,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -225,6 +225,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->bdev = em->bdev; split->bdev = em->bdev;
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type;
ret = add_extent_mapping(em_tree, split); ret = add_extent_mapping(em_tree, split);
BUG_ON(ret); BUG_ON(ret);
free_extent_map(split); free_extent_map(split);
...@@ -239,6 +240,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, ...@@ -239,6 +240,7 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
split->len = em->start + em->len - (start + len); split->len = em->start + em->len - (start + len);
split->bdev = em->bdev; split->bdev = em->bdev;
split->flags = flags; split->flags = flags;
split->compress_type = em->compress_type;
if (compressed) { if (compressed) {
split->block_len = em->block_len; split->block_len = em->block_len;
...@@ -891,6 +893,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, ...@@ -891,6 +893,17 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
if (err) if (err)
goto out; goto out;
/*
* If BTRFS flips readonly due to some impossible error
* (fs_info->fs_state now has BTRFS_SUPER_FLAG_ERROR),
* although we have opened a file as writable, we have
* to stop this write operation to ensure FS consistency.
*/
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
err = -EROFS;
goto out;
}
file_update_time(file); file_update_time(file);
BTRFS_I(inode)->sequence++; BTRFS_I(inode)->sequence++;
......
...@@ -122,10 +122,10 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -122,10 +122,10 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
size_t cur_size = size; size_t cur_size = size;
size_t datasize; size_t datasize;
unsigned long offset; unsigned long offset;
int use_compress = 0; int compress_type = BTRFS_COMPRESS_NONE;
if (compressed_size && compressed_pages) { if (compressed_size && compressed_pages) {
use_compress = 1; compress_type = root->fs_info->compress_type;
cur_size = compressed_size; cur_size = compressed_size;
} }
...@@ -159,7 +159,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -159,7 +159,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
btrfs_set_file_extent_ram_bytes(leaf, ei, size); btrfs_set_file_extent_ram_bytes(leaf, ei, size);
ptr = btrfs_file_extent_inline_start(ei); ptr = btrfs_file_extent_inline_start(ei);
if (use_compress) { if (compress_type != BTRFS_COMPRESS_NONE) {
struct page *cpage; struct page *cpage;
int i = 0; int i = 0;
while (compressed_size > 0) { while (compressed_size > 0) {
...@@ -176,7 +176,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, ...@@ -176,7 +176,7 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans,
compressed_size -= cur_size; compressed_size -= cur_size;
} }
btrfs_set_file_extent_compression(leaf, ei, btrfs_set_file_extent_compression(leaf, ei,
BTRFS_COMPRESS_ZLIB); compress_type);
} else { } else {
page = find_get_page(inode->i_mapping, page = find_get_page(inode->i_mapping,
start >> PAGE_CACHE_SHIFT); start >> PAGE_CACHE_SHIFT);
...@@ -263,6 +263,7 @@ struct async_extent { ...@@ -263,6 +263,7 @@ struct async_extent {
u64 compressed_size; u64 compressed_size;
struct page **pages; struct page **pages;
unsigned long nr_pages; unsigned long nr_pages;
int compress_type;
struct list_head list; struct list_head list;
}; };
...@@ -280,7 +281,8 @@ static noinline int add_async_extent(struct async_cow *cow, ...@@ -280,7 +281,8 @@ static noinline int add_async_extent(struct async_cow *cow,
u64 start, u64 ram_size, u64 start, u64 ram_size,
u64 compressed_size, u64 compressed_size,
struct page **pages, struct page **pages,
unsigned long nr_pages) unsigned long nr_pages,
int compress_type)
{ {
struct async_extent *async_extent; struct async_extent *async_extent;
...@@ -290,6 +292,7 @@ static noinline int add_async_extent(struct async_cow *cow, ...@@ -290,6 +292,7 @@ static noinline int add_async_extent(struct async_cow *cow,
async_extent->compressed_size = compressed_size; async_extent->compressed_size = compressed_size;
async_extent->pages = pages; async_extent->pages = pages;
async_extent->nr_pages = nr_pages; async_extent->nr_pages = nr_pages;
async_extent->compress_type = compress_type;
list_add_tail(&async_extent->list, &cow->extents); list_add_tail(&async_extent->list, &cow->extents);
return 0; return 0;
} }
...@@ -332,6 +335,7 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -332,6 +335,7 @@ static noinline int compress_file_range(struct inode *inode,
unsigned long max_uncompressed = 128 * 1024; unsigned long max_uncompressed = 128 * 1024;
int i; int i;
int will_compress; int will_compress;
int compress_type = root->fs_info->compress_type;
actual_end = min_t(u64, isize, end + 1); actual_end = min_t(u64, isize, end + 1);
again: again:
...@@ -381,12 +385,16 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -381,12 +385,16 @@ static noinline int compress_file_range(struct inode *inode,
WARN_ON(pages); WARN_ON(pages);
pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
ret = btrfs_zlib_compress_pages(inode->i_mapping, start, if (BTRFS_I(inode)->force_compress)
total_compressed, pages, compress_type = BTRFS_I(inode)->force_compress;
nr_pages, &nr_pages_ret,
&total_in, ret = btrfs_compress_pages(compress_type,
&total_compressed, inode->i_mapping, start,
max_compressed); total_compressed, pages,
nr_pages, &nr_pages_ret,
&total_in,
&total_compressed,
max_compressed);
if (!ret) { if (!ret) {
unsigned long offset = total_compressed & unsigned long offset = total_compressed &
...@@ -493,7 +501,8 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -493,7 +501,8 @@ static noinline int compress_file_range(struct inode *inode,
* and will submit them to the elevator. * and will submit them to the elevator.
*/ */
add_async_extent(async_cow, start, num_bytes, add_async_extent(async_cow, start, num_bytes,
total_compressed, pages, nr_pages_ret); total_compressed, pages, nr_pages_ret,
compress_type);
if (start + num_bytes < end) { if (start + num_bytes < end) {
start += num_bytes; start += num_bytes;
...@@ -515,7 +524,8 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -515,7 +524,8 @@ static noinline int compress_file_range(struct inode *inode,
__set_page_dirty_nobuffers(locked_page); __set_page_dirty_nobuffers(locked_page);
/* unlocked later on in the async handlers */ /* unlocked later on in the async handlers */
} }
add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0); add_async_extent(async_cow, start, end - start + 1,
0, NULL, 0, BTRFS_COMPRESS_NONE);
*num_added += 1; *num_added += 1;
} }
...@@ -640,6 +650,7 @@ static noinline int submit_compressed_extents(struct inode *inode, ...@@ -640,6 +650,7 @@ static noinline int submit_compressed_extents(struct inode *inode,
em->block_start = ins.objectid; em->block_start = ins.objectid;
em->block_len = ins.offset; em->block_len = ins.offset;
em->bdev = root->fs_info->fs_devices->latest_bdev; em->bdev = root->fs_info->fs_devices->latest_bdev;
em->compress_type = async_extent->compress_type;
set_bit(EXTENT_FLAG_PINNED, &em->flags); set_bit(EXTENT_FLAG_PINNED, &em->flags);
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
...@@ -656,11 +667,13 @@ static noinline int submit_compressed_extents(struct inode *inode, ...@@ -656,11 +667,13 @@ static noinline int submit_compressed_extents(struct inode *inode,
async_extent->ram_size - 1, 0); async_extent->ram_size - 1, 0);
} }
ret = btrfs_add_ordered_extent(inode, async_extent->start, ret = btrfs_add_ordered_extent_compress(inode,
ins.objectid, async_extent->start,
async_extent->ram_size, ins.objectid,
ins.offset, async_extent->ram_size,
BTRFS_ORDERED_COMPRESSED); ins.offset,
BTRFS_ORDERED_COMPRESSED,
async_extent->compress_type);
BUG_ON(ret); BUG_ON(ret);
/* /*
...@@ -1670,7 +1683,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1670,7 +1683,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
struct btrfs_ordered_extent *ordered_extent = NULL; struct btrfs_ordered_extent *ordered_extent = NULL;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
int compressed = 0; int compress_type = 0;
int ret; int ret;
bool nolock = false; bool nolock = false;
...@@ -1711,9 +1724,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1711,9 +1724,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
trans->block_rsv = &root->fs_info->delalloc_block_rsv; trans->block_rsv = &root->fs_info->delalloc_block_rsv;
if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags)) if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
compressed = 1; compress_type = ordered_extent->compress_type;
if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
BUG_ON(compressed); BUG_ON(compress_type);
ret = btrfs_mark_extent_written(trans, inode, ret = btrfs_mark_extent_written(trans, inode,
ordered_extent->file_offset, ordered_extent->file_offset,
ordered_extent->file_offset + ordered_extent->file_offset +
...@@ -1727,7 +1740,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) ...@@ -1727,7 +1740,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
ordered_extent->disk_len, ordered_extent->disk_len,
ordered_extent->len, ordered_extent->len,
ordered_extent->len, ordered_extent->len,
compressed, 0, 0, compress_type, 0, 0,
BTRFS_FILE_EXTENT_REG); BTRFS_FILE_EXTENT_REG);
unpin_extent_cache(&BTRFS_I(inode)->extent_tree, unpin_extent_cache(&BTRFS_I(inode)->extent_tree,
ordered_extent->file_offset, ordered_extent->file_offset,
...@@ -1829,6 +1842,8 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, ...@@ -1829,6 +1842,8 @@ static int btrfs_io_failed_hook(struct bio *failed_bio,
if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) { if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
logical = em->block_start; logical = em->block_start;
failrec->bio_flags = EXTENT_BIO_COMPRESSED; failrec->bio_flags = EXTENT_BIO_COMPRESSED;
extent_set_compress_type(&failrec->bio_flags,
em->compress_type);
} }
failrec->logical = logical; failrec->logical = logical;
free_extent_map(em); free_extent_map(em);
...@@ -3671,8 +3686,12 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr) ...@@ -3671,8 +3686,12 @@ static int btrfs_setattr_size(struct inode *inode, struct iattr *attr)
static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) static int btrfs_setattr(struct dentry *dentry, struct iattr *attr)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
int err; int err;
if (btrfs_root_readonly(root))
return -EROFS;
err = inode_change_ok(inode, attr); err = inode_change_ok(inode, attr);
if (err) if (err)
return err; return err;
...@@ -4928,8 +4947,10 @@ static noinline int uncompress_inline(struct btrfs_path *path, ...@@ -4928,8 +4947,10 @@ static noinline int uncompress_inline(struct btrfs_path *path,
size_t max_size; size_t max_size;
unsigned long inline_size; unsigned long inline_size;
unsigned long ptr; unsigned long ptr;
int compress_type;
WARN_ON(pg_offset != 0); WARN_ON(pg_offset != 0);
compress_type = btrfs_file_extent_compression(leaf, item);
max_size = btrfs_file_extent_ram_bytes(leaf, item); max_size = btrfs_file_extent_ram_bytes(leaf, item);
inline_size = btrfs_file_extent_inline_item_len(leaf, inline_size = btrfs_file_extent_inline_item_len(leaf,
btrfs_item_nr(leaf, path->slots[0])); btrfs_item_nr(leaf, path->slots[0]));
...@@ -4939,8 +4960,8 @@ static noinline int uncompress_inline(struct btrfs_path *path, ...@@ -4939,8 +4960,8 @@ static noinline int uncompress_inline(struct btrfs_path *path,
read_extent_buffer(leaf, tmp, ptr, inline_size); read_extent_buffer(leaf, tmp, ptr, inline_size);
max_size = min_t(unsigned long, PAGE_CACHE_SIZE, max_size); max_size = min_t(unsigned long, PAGE_CACHE_SIZE, max_size);
ret = btrfs_zlib_decompress(tmp, page, extent_offset, ret = btrfs_decompress(compress_type, tmp, page,
inline_size, max_size); extent_offset, inline_size, max_size);
if (ret) { if (ret) {
char *kaddr = kmap_atomic(page, KM_USER0); char *kaddr = kmap_atomic(page, KM_USER0);
unsigned long copy_size = min_t(u64, unsigned long copy_size = min_t(u64,
...@@ -4982,7 +5003,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -4982,7 +5003,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct btrfs_trans_handle *trans = NULL; struct btrfs_trans_handle *trans = NULL;
int compressed; int compress_type;
again: again:
read_lock(&em_tree->lock); read_lock(&em_tree->lock);
...@@ -5041,7 +5062,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5041,7 +5062,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
found_type = btrfs_file_extent_type(leaf, item); found_type = btrfs_file_extent_type(leaf, item);
extent_start = found_key.offset; extent_start = found_key.offset;
compressed = btrfs_file_extent_compression(leaf, item); compress_type = btrfs_file_extent_compression(leaf, item);
if (found_type == BTRFS_FILE_EXTENT_REG || if (found_type == BTRFS_FILE_EXTENT_REG ||
found_type == BTRFS_FILE_EXTENT_PREALLOC) { found_type == BTRFS_FILE_EXTENT_PREALLOC) {
extent_end = extent_start + extent_end = extent_start +
...@@ -5087,8 +5108,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5087,8 +5108,9 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
em->block_start = EXTENT_MAP_HOLE; em->block_start = EXTENT_MAP_HOLE;
goto insert; goto insert;
} }
if (compressed) { if (compress_type != BTRFS_COMPRESS_NONE) {
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->compress_type = compress_type;
em->block_start = bytenr; em->block_start = bytenr;
em->block_len = btrfs_file_extent_disk_num_bytes(leaf, em->block_len = btrfs_file_extent_disk_num_bytes(leaf,
item); item);
...@@ -5122,12 +5144,14 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5122,12 +5144,14 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
em->len = (copy_size + root->sectorsize - 1) & em->len = (copy_size + root->sectorsize - 1) &
~((u64)root->sectorsize - 1); ~((u64)root->sectorsize - 1);
em->orig_start = EXTENT_MAP_INLINE; em->orig_start = EXTENT_MAP_INLINE;
if (compressed) if (compress_type) {
set_bit(EXTENT_FLAG_COMPRESSED, &em->flags); set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
em->compress_type = compress_type;
}
ptr = btrfs_file_extent_inline_start(item) + extent_offset; ptr = btrfs_file_extent_inline_start(item) + extent_offset;
if (create == 0 && !PageUptodate(page)) { if (create == 0 && !PageUptodate(page)) {
if (btrfs_file_extent_compression(leaf, item) == if (btrfs_file_extent_compression(leaf, item) !=
BTRFS_COMPRESS_ZLIB) { BTRFS_COMPRESS_NONE) {
ret = uncompress_inline(path, inode, page, ret = uncompress_inline(path, inode, page,
pg_offset, pg_offset,
extent_offset, item); extent_offset, item);
...@@ -6477,7 +6501,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ...@@ -6477,7 +6501,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->ordered_data_close = 0; ei->ordered_data_close = 0;
ei->orphan_meta_reserved = 0; ei->orphan_meta_reserved = 0;
ei->dummy_inode = 0; ei->dummy_inode = 0;
ei->force_compress = 0; ei->force_compress = BTRFS_COMPRESS_NONE;
inode = &ei->vfs_inode; inode = &ei->vfs_inode;
extent_map_tree_init(&ei->extent_tree, GFP_NOFS); extent_map_tree_init(&ei->extent_tree, GFP_NOFS);
...@@ -7105,6 +7129,10 @@ static int btrfs_set_page_dirty(struct page *page) ...@@ -7105,6 +7129,10 @@ static int btrfs_set_page_dirty(struct page *page)
static int btrfs_permission(struct inode *inode, int mask, unsigned int flags) static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
{ {
struct btrfs_root *root = BTRFS_I(inode)->root;
if (btrfs_root_readonly(root) && (mask & MAY_WRITE))
return -EROFS;
if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
return -EACCES; return -EACCES;
return generic_permission(inode, mask, flags, btrfs_check_acl); return generic_permission(inode, mask, flags, btrfs_check_acl);
......
This diff is collapsed.
...@@ -31,6 +31,7 @@ struct btrfs_ioctl_vol_args { ...@@ -31,6 +31,7 @@ struct btrfs_ioctl_vol_args {
}; };
#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
#define BTRFS_SUBVOL_NAME_MAX 4039 #define BTRFS_SUBVOL_NAME_MAX 4039
struct btrfs_ioctl_vol_args_v2 { struct btrfs_ioctl_vol_args_v2 {
...@@ -133,8 +134,15 @@ struct btrfs_ioctl_defrag_range_args { ...@@ -133,8 +134,15 @@ struct btrfs_ioctl_defrag_range_args {
*/ */
__u32 extent_thresh; __u32 extent_thresh;
/*
* which compression method to use if turning on compression
* for this defrag operation. If unspecified, zlib will
* be used
*/
__u32 compress_type;
/* spare for later */ /* spare for later */
__u32 unused[5]; __u32 unused[4];
}; };
struct btrfs_ioctl_space_info { struct btrfs_ioctl_space_info {
...@@ -193,4 +201,6 @@ struct btrfs_ioctl_space_args { ...@@ -193,4 +201,6 @@ struct btrfs_ioctl_space_args {
#define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
struct btrfs_ioctl_vol_args_v2) struct btrfs_ioctl_vol_args_v2)
#define BTRFS_IOC_SUBVOL_GETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 25, __u64)
#define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64)
#endif #endif
This diff is collapsed.
...@@ -172,7 +172,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree, ...@@ -172,7 +172,7 @@ static inline struct rb_node *tree_search(struct btrfs_ordered_inode_tree *tree,
*/ */
static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, u64 start, u64 len, u64 disk_len,
int type, int dio) int type, int dio, int compress_type)
{ {
struct btrfs_ordered_inode_tree *tree; struct btrfs_ordered_inode_tree *tree;
struct rb_node *node; struct rb_node *node;
...@@ -189,6 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -189,6 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
entry->disk_len = disk_len; entry->disk_len = disk_len;
entry->bytes_left = len; entry->bytes_left = len;
entry->inode = inode; entry->inode = inode;
entry->compress_type = compress_type;
if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE) if (type != BTRFS_ORDERED_IO_DONE && type != BTRFS_ORDERED_COMPLETE)
set_bit(type, &entry->flags); set_bit(type, &entry->flags);
...@@ -220,14 +221,25 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -220,14 +221,25 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type) u64 start, u64 len, u64 disk_len, int type)
{ {
return __btrfs_add_ordered_extent(inode, file_offset, start, len, return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 0); disk_len, type, 0,
BTRFS_COMPRESS_NONE);
} }
int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type) u64 start, u64 len, u64 disk_len, int type)
{ {
return __btrfs_add_ordered_extent(inode, file_offset, start, len, return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 1); disk_len, type, 1,
BTRFS_COMPRESS_NONE);
}
int btrfs_add_ordered_extent_compress(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len,
int type, int compress_type)
{
return __btrfs_add_ordered_extent(inode, file_offset, start, len,
disk_len, type, 0,
compress_type);
} }
/* /*
......
...@@ -68,7 +68,7 @@ struct btrfs_ordered_sum { ...@@ -68,7 +68,7 @@ struct btrfs_ordered_sum {
#define BTRFS_ORDERED_NOCOW 2 /* set when we want to write in place */ #define BTRFS_ORDERED_NOCOW 2 /* set when we want to write in place */
#define BTRFS_ORDERED_COMPRESSED 3 /* writing a compressed extent */ #define BTRFS_ORDERED_COMPRESSED 3 /* writing a zlib compressed extent */
#define BTRFS_ORDERED_PREALLOC 4 /* set when writing to prealloced extent */ #define BTRFS_ORDERED_PREALLOC 4 /* set when writing to prealloced extent */
...@@ -93,6 +93,9 @@ struct btrfs_ordered_extent { ...@@ -93,6 +93,9 @@ struct btrfs_ordered_extent {
/* flags (described above) */ /* flags (described above) */
unsigned long flags; unsigned long flags;
/* compression algorithm */
int compress_type;
/* reference count */ /* reference count */
atomic_t refs; atomic_t refs;
...@@ -148,6 +151,9 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, ...@@ -148,6 +151,9 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type); u64 start, u64 len, u64 disk_len, int type);
int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len, int type); u64 start, u64 len, u64 disk_len, int type);
int btrfs_add_ordered_extent_compress(struct inode *inode, u64 file_offset,
u64 start, u64 len, u64 disk_len,
int type, int compress_type);
int btrfs_add_ordered_sum(struct inode *inode, int btrfs_add_ordered_sum(struct inode *inode,
struct btrfs_ordered_extent *entry, struct btrfs_ordered_extent *entry,
struct btrfs_ordered_sum *sum); struct btrfs_ordered_sum *sum);
......
This diff is collapsed.
...@@ -181,6 +181,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, ...@@ -181,6 +181,9 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
struct btrfs_trans_handle *h; struct btrfs_trans_handle *h;
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
int ret; int ret;
if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
return ERR_PTR(-EROFS);
again: again:
h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
if (!h) if (!h)
...@@ -910,6 +913,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -910,6 +913,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
u64 to_reserve = 0; u64 to_reserve = 0;
u64 index = 0; u64 index = 0;
u64 objectid; u64 objectid;
u64 root_flags;
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
if (!new_root_item) { if (!new_root_item) {
...@@ -967,6 +971,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, ...@@ -967,6 +971,13 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_set_root_last_snapshot(&root->root_item, trans->transid); btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
root_flags = btrfs_root_flags(new_root_item);
if (pending->readonly)
root_flags |= BTRFS_ROOT_SUBVOL_RDONLY;
else
root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY;
btrfs_set_root_flags(new_root_item, root_flags);
old = btrfs_lock_root_node(root); old = btrfs_lock_root_node(root);
btrfs_cow_block(trans, root, old, NULL, 0, &old); btrfs_cow_block(trans, root, old, NULL, 0, &old);
btrfs_set_lock_blocking(old); btrfs_set_lock_blocking(old);
......
...@@ -62,6 +62,7 @@ struct btrfs_pending_snapshot { ...@@ -62,6 +62,7 @@ struct btrfs_pending_snapshot {
struct btrfs_block_rsv block_rsv; struct btrfs_block_rsv block_rsv;
/* extra metadata reseration for relocation */ /* extra metadata reseration for relocation */
int error; int error;
bool readonly;
struct list_head list; struct list_head list;
}; };
......
This diff is collapsed.
...@@ -20,8 +20,11 @@ ...@@ -20,8 +20,11 @@
#define __BTRFS_VOLUMES_ #define __BTRFS_VOLUMES_
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/sort.h>
#include "async-thread.h" #include "async-thread.h"
#define BTRFS_STRIPE_LEN (64 * 1024)
struct buffer_head; struct buffer_head;
struct btrfs_pending_bios { struct btrfs_pending_bios {
struct bio *head; struct bio *head;
...@@ -136,6 +139,30 @@ struct btrfs_multi_bio { ...@@ -136,6 +139,30 @@ struct btrfs_multi_bio {
struct btrfs_bio_stripe stripes[]; struct btrfs_bio_stripe stripes[];
}; };
struct btrfs_device_info {
struct btrfs_device *dev;
u64 dev_offset;
u64 max_avail;
};
/* Used to sort the devices by max_avail(descending sort) */
int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2);
/*
* sort the devices by max_avail, in which max free extent size of each device
* is stored.(Descending Sort)
*/
static inline void btrfs_descending_sort_devices(
struct btrfs_device_info *devices,
size_t nr_devices)
{
sort(devices, nr_devices, sizeof(struct btrfs_device_info),
btrfs_cmp_device_free_bytes, NULL);
}
int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start,
u64 end, u64 *length);
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \ #define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n))) (sizeof(struct btrfs_bio_stripe) * (n)))
......
...@@ -316,6 +316,15 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name, ...@@ -316,6 +316,15 @@ ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags) size_t size, int flags)
{ {
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
/*
* The permission on security.* and system.* is not checked
* in permission().
*/
if (btrfs_root_readonly(root))
return -EROFS;
/* /*
* If this is a request for a synthetic attribute in the system.* * If this is a request for a synthetic attribute in the system.*
* namespace use the generic infrastructure to resolve a handler * namespace use the generic infrastructure to resolve a handler
...@@ -336,6 +345,15 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value, ...@@ -336,6 +345,15 @@ int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
int btrfs_removexattr(struct dentry *dentry, const char *name) int btrfs_removexattr(struct dentry *dentry, const char *name)
{ {
struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
/*
* The permission on security.* and system.* is not checked
* in permission().
*/
if (btrfs_root_readonly(root))
return -EROFS;
/* /*
* If this is a request for a synthetic attribute in the system.* * If this is a request for a synthetic attribute in the system.*
* namespace use the generic infrastructure to resolve a handler * namespace use the generic infrastructure to resolve a handler
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment