Commit 36cd5c19 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 update from Ted Ts'o:
 "There are two major features for this merge window.  The first is
  inline data, which allows small files or directories to be stored in
  the in-inode extended attribute area.  (This requires that the file
  system use inodes which are at least 256 bytes or larger; 128 byte
  inodes do not have any room for in-inode xattrs.)

  The second new feature is SEEK_HOLE/SEEK_DATA support.  This is
  enabled by the extent status tree patches, and this infrastructure
  will be used to further optimize ext4 in the future.

  Beyond that, we have the usual collection of code cleanups and bug
  fixes."

* tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: (63 commits)
  ext4: zero out inline data using memset() instead of empty_zero_page
  ext4: ensure Inode flags consistency are checked at build time
  ext4: Remove CONFIG_EXT4_FS_XATTR
  ext4: remove unused variable from ext4_ext_in_cache()
  ext4: remove redundant initialization in ext4_fill_super()
  ext4: remove redundant code in ext4_alloc_inode()
  ext4: use sync_inode_metadata() when syncing inode metadata
  ext4: enable ext4 inline support
  ext4: let fallocate handle inline data correctly
  ext4: let ext4_truncate handle inline data correctly
  ext4: evict inline data out if we need to strore xattr in inode
  ext4: let fiemap work with inline data
  ext4: let ext4_rename handle inline dir
  ext4: let empty_dir handle inline dir
  ext4: let ext4_delete_entry() handle inline data
  ext4: make ext4_delete_entry generic
  ext4: let ext4_find_entry handle inline data
  ext4: create a new function search_dir
  ext4: let ext4_readdir handle inline data
  ext4: let add_dir_entry handle inline data properly
  ...
parents 2a74dbb9 bd9926e8
......@@ -200,12 +200,9 @@ inode_readahead_blks=n This tuning parameter controls the maximum
table readahead algorithm will pre-read into
the buffer cache. The default value is 32 blocks.
nouser_xattr Disables Extended User Attributes. If you have extended
attribute support enabled in the kernel configuration
(CONFIG_EXT4_FS_XATTR), extended attribute support
is enabled by default on mount. See the attr(5) manual
page and http://acl.bestbits.at/ for more information
about extended attributes.
nouser_xattr Disables Extended User Attributes. See the
attr(5) manual page and http://acl.bestbits.at/
for more information about extended attributes.
noacl This option disables POSIX Access Control List
support. If ACL support is enabled in the kernel
......
......@@ -28,8 +28,8 @@ config FS_MBCACHE
tristate
default y if EXT2_FS=y && EXT2_FS_XATTR
default y if EXT3_FS=y && EXT3_FS_XATTR
default y if EXT4_FS=y && EXT4_FS_XATTR
default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS_XATTR
default y if EXT4_FS=y
default m if EXT2_FS_XATTR || EXT3_FS_XATTR || EXT4_FS
source "fs/reiserfs/Kconfig"
source "fs/jfs/Kconfig"
......
......@@ -39,22 +39,8 @@ config EXT4_USE_FOR_EXT23
compiled kernel size by using one file system driver for
ext2, ext3, and ext4 file systems.
config EXT4_FS_XATTR
bool "Ext4 extended attributes"
depends on EXT4_FS
default y
help
Extended attributes are name:value pairs associated with inodes by
the kernel or by users (see the attr(5) manual page, or visit
<http://acl.bestbits.at/> for details).
If unsure, say N.
You need this for POSIX ACL support on ext4.
config EXT4_FS_POSIX_ACL
bool "Ext4 POSIX Access Control Lists"
depends on EXT4_FS_XATTR
select FS_POSIX_ACL
help
POSIX Access Control Lists (ACLs) support permissions for users and
......@@ -67,7 +53,6 @@ config EXT4_FS_POSIX_ACL
config EXT4_FS_SECURITY
bool "Ext4 Security Labels"
depends on EXT4_FS_XATTR
help
Security labels support alternative access control models
implemented by security modules like SELinux. This option
......
......@@ -7,8 +7,8 @@ obj-$(CONFIG_EXT4_FS) += ext4.o
ext4-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o page-io.o \
ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \
ext4_jbd2.o migrate.o mballoc.o block_validity.o move_extent.o \
mmp.o indirect.o
mmp.o indirect.o extents_status.o xattr.o xattr_user.o \
xattr_trusted.o inline.o
ext4-$(CONFIG_EXT4_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
......@@ -423,8 +423,10 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value,
retry:
handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
goto release_and_out;
}
error = ext4_set_acl(handle, inode, type, acl);
ext4_journal_stop(handle);
if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
......
......@@ -27,23 +27,11 @@
#include <linux/slab.h>
#include <linux/rbtree.h>
#include "ext4.h"
static unsigned char ext4_filetype_table[] = {
DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
};
#include "xattr.h"
static int ext4_dx_readdir(struct file *filp,
void *dirent, filldir_t filldir);
static unsigned char get_dtype(struct super_block *sb, int filetype)
{
if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FILETYPE) ||
(filetype >= EXT4_FT_MAX))
return DT_UNKNOWN;
return (ext4_filetype_table[filetype]);
}
/**
* Check if the given dir-inode refers to an htree-indexed directory
* (or a directory which chould potentially get coverted to use htree
......@@ -68,11 +56,14 @@ static int is_dx_dir(struct inode *inode)
* Return 0 if the directory entry is OK, and 1 if there is a problem
*
* Note: this is the opposite of what ext2 and ext3 historically returned...
*
* bh passed here can be an inode block or a dir data block, depending
* on the inode inline data flag.
*/
int __ext4_check_dir_entry(const char *function, unsigned int line,
struct inode *dir, struct file *filp,
struct ext4_dir_entry_2 *de,
struct buffer_head *bh,
struct buffer_head *bh, char *buf, int size,
unsigned int offset)
{
const char *error_msg = NULL;
......@@ -85,9 +76,8 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
error_msg = "rec_len % 4 != 0";
else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
error_msg = "rec_len is too small for name_len";
else if (unlikely(((char *) de - bh->b_data) + rlen >
dir->i_sb->s_blocksize))
error_msg = "directory entry across blocks";
else if (unlikely(((char *) de - buf) + rlen > size))
error_msg = "directory entry across range";
else if (unlikely(le32_to_cpu(de->inode) >
le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
error_msg = "inode out of bounds";
......@@ -98,14 +88,14 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
ext4_error_file(filp, function, line, bh->b_blocknr,
"bad entry in directory: %s - offset=%u(%u), "
"inode=%u, rec_len=%d, name_len=%d",
error_msg, (unsigned) (offset % bh->b_size),
error_msg, (unsigned) (offset % size),
offset, le32_to_cpu(de->inode),
rlen, de->name_len);
else
ext4_error_inode(dir, function, line, bh->b_blocknr,
"bad entry in directory: %s - offset=%u(%u), "
"inode=%u, rec_len=%d, name_len=%d",
error_msg, (unsigned) (offset % bh->b_size),
error_msg, (unsigned) (offset % size),
offset, le32_to_cpu(de->inode),
rlen, de->name_len);
......@@ -125,6 +115,14 @@ static int ext4_readdir(struct file *filp,
int ret = 0;
int dir_has_error = 0;
if (ext4_has_inline_data(inode)) {
int has_inline_data = 1;
ret = ext4_read_inline_dir(filp, dirent, filldir,
&has_inline_data);
if (has_inline_data)
return ret;
}
if (is_dx_dir(inode)) {
err = ext4_dx_readdir(filp, dirent, filldir);
if (err != ERR_BAD_DX_DIR) {
......@@ -221,8 +219,9 @@ static int ext4_readdir(struct file *filp,
while (!error && filp->f_pos < inode->i_size
&& offset < sb->s_blocksize) {
de = (struct ext4_dir_entry_2 *) (bh->b_data + offset);
if (ext4_check_dir_entry(inode, filp, de,
bh, offset)) {
if (ext4_check_dir_entry(inode, filp, de, bh,
bh->b_data, bh->b_size,
offset)) {
/*
* On error, skip the f_pos to the next block
*/
......
This diff is collapsed.
......@@ -42,16 +42,6 @@
*/
#define CHECK_BINSEARCH__
/*
* Turn on EXT_DEBUG to get lots of info about extents operations.
*/
#define EXT_DEBUG__
#ifdef EXT_DEBUG
#define ext_debug(fmt, ...) printk(fmt, ##__VA_ARGS__)
#else
#define ext_debug(fmt, ...) no_printk(fmt, ##__VA_ARGS__)
#endif
/*
* If EXT_STATS is defined then stats numbers are collected.
* These number will be displayed at umount time.
......@@ -143,20 +133,6 @@ struct ext4_ext_path {
* structure for external API
*/
/*
* to be called by ext4_ext_walk_space()
* negative retcode - error
* positive retcode - signal for ext4_ext_walk_space(), see below
* callback must return valid extent (passed or newly created)
*/
typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t,
struct ext4_ext_cache *,
struct ext4_extent *, void *);
#define EXT_CONTINUE 0
#define EXT_BREAK 1
#define EXT_REPEAT 2
/*
* Maximum number of logical blocks in a file; ext4_extent's ee_block is
* __le32.
......@@ -300,21 +276,5 @@ static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix,
0xffff);
}
extern int ext4_ext_calc_metadata_amount(struct inode *inode,
ext4_lblk_t lblocks);
extern int ext4_extent_tree_init(handle_t *, struct inode *);
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
int num,
struct ext4_ext_path *path);
extern int ext4_can_extents_be_merged(struct inode *inode,
struct ext4_extent *ex1,
struct ext4_extent *ex2);
extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *, int);
extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t,
struct ext4_ext_path *);
extern void ext4_ext_drop_refs(struct ext4_ext_path *);
extern int ext4_ext_check_inode(struct inode *inode);
extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk,
int search_hint_reverse);
#endif /* _EXT4_EXTENTS */
......@@ -254,13 +254,6 @@ static inline void ext4_handle_sync(handle_t *handle)
handle->h_sync = 1;
}
static inline void ext4_handle_release_buffer(handle_t *handle,
struct buffer_head *bh)
{
if (ext4_handle_valid(handle))
jbd2_journal_release_buffer(handle, bh);
}
static inline int ext4_handle_is_aborted(handle_t *handle)
{
if (ext4_handle_valid(handle))
......
This diff is collapsed.
This diff is collapsed.
/*
* fs/ext4/extents_status.h
*
* Written by Yongqiang Yang <xiaoqiangnk@gmail.com>
* Modified by
* Allison Henderson <achender@linux.vnet.ibm.com>
* Zheng Liu <wenqing.lz@taobao.com>
*
*/
#ifndef _EXT4_EXTENTS_STATUS_H
#define _EXT4_EXTENTS_STATUS_H
/*
* Turn on ES_DEBUG__ to get lots of info about extent status operations.
*/
#ifdef ES_DEBUG__
#define es_debug(fmt, ...) printk(fmt, ##__VA_ARGS__)
#else
#define es_debug(fmt, ...) no_printk(fmt, ##__VA_ARGS__)
#endif
struct extent_status {
struct rb_node rb_node;
ext4_lblk_t start; /* first block extent covers */
ext4_lblk_t len; /* length of extent in block */
};
struct ext4_es_tree {
struct rb_root root;
struct extent_status *cache_es; /* recently accessed extent */
};
extern int __init ext4_init_es(void);
extern void ext4_exit_es(void);
extern void ext4_es_init_tree(struct ext4_es_tree *tree);
extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t start,
ext4_lblk_t len);
extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t start,
ext4_lblk_t len);
extern ext4_lblk_t ext4_es_find_extent(struct inode *inode,
struct extent_status *es);
#endif /* _EXT4_EXTENTS_STATUS_H */
......@@ -24,6 +24,7 @@
#include <linux/mount.h>
#include <linux/path.h>
#include <linux/quotaops.h>
#include <linux/pagevec.h>
#include "ext4.h"
#include "ext4_jbd2.h"
#include "xattr.h"
......@@ -285,6 +286,324 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
return dquot_file_open(inode, filp);
}
/*
* Here we use ext4_map_blocks() to get a block mapping for a extent-based
* file rather than ext4_ext_walk_space() because we can introduce
* SEEK_DATA/SEEK_HOLE for block-mapped and extent-mapped file at the same
* function. When extent status tree has been fully implemented, it will
* track all extent status for a file and we can directly use it to
* retrieve the offset for SEEK_DATA/SEEK_HOLE.
*/
/*
* When we retrieve the offset for SEEK_DATA/SEEK_HOLE, we would need to
* lookup page cache to check whether or not there has some data between
* [startoff, endoff] because, if this range contains an unwritten extent,
* we determine this extent as a data or a hole according to whether the
* page cache has data or not.
*/
static int ext4_find_unwritten_pgoff(struct inode *inode,
int origin,
struct ext4_map_blocks *map,
loff_t *offset)
{
struct pagevec pvec;
unsigned int blkbits;
pgoff_t index;
pgoff_t end;
loff_t endoff;
loff_t startoff;
loff_t lastoff;
int found = 0;
blkbits = inode->i_sb->s_blocksize_bits;
startoff = *offset;
lastoff = startoff;
endoff = (map->m_lblk + map->m_len) << blkbits;
index = startoff >> PAGE_CACHE_SHIFT;
end = endoff >> PAGE_CACHE_SHIFT;
pagevec_init(&pvec, 0);
do {
int i, num;
unsigned long nr_pages;
num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
(pgoff_t)num);
if (nr_pages == 0) {
if (origin == SEEK_DATA)
break;
BUG_ON(origin != SEEK_HOLE);
/*
* If this is the first time to go into the loop and
* offset is not beyond the end offset, it will be a
* hole at this offset
*/
if (lastoff == startoff || lastoff < endoff)
found = 1;
break;
}
/*
* If this is the first time to go into the loop and
* offset is smaller than the first page offset, it will be a
* hole at this offset.
*/
if (lastoff == startoff && origin == SEEK_HOLE &&
lastoff < page_offset(pvec.pages[0])) {
found = 1;
break;
}
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
struct buffer_head *bh, *head;
/*
* If the current offset is not beyond the end of given
* range, it will be a hole.
*/
if (lastoff < endoff && origin == SEEK_HOLE &&
page->index > end) {
found = 1;
*offset = lastoff;
goto out;
}
lock_page(page);
if (unlikely(page->mapping != inode->i_mapping)) {
unlock_page(page);
continue;
}
if (!page_has_buffers(page)) {
unlock_page(page);
continue;
}
if (page_has_buffers(page)) {
lastoff = page_offset(page);
bh = head = page_buffers(page);
do {
if (buffer_uptodate(bh) ||
buffer_unwritten(bh)) {
if (origin == SEEK_DATA)
found = 1;
} else {
if (origin == SEEK_HOLE)
found = 1;
}
if (found) {
*offset = max_t(loff_t,
startoff, lastoff);
unlock_page(page);
goto out;
}
lastoff += bh->b_size;
bh = bh->b_this_page;
} while (bh != head);
}
lastoff = page_offset(page) + PAGE_SIZE;
unlock_page(page);
}
/*
* The no. of pages is less than our desired, that would be a
* hole in there.
*/
if (nr_pages < num && origin == SEEK_HOLE) {
found = 1;
*offset = lastoff;
break;
}
index = pvec.pages[i - 1]->index + 1;
pagevec_release(&pvec);
} while (index <= end);
out:
pagevec_release(&pvec);
return found;
}
/*
* ext4_seek_data() retrieves the offset for SEEK_DATA.
*/
static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize)
{
struct inode *inode = file->f_mapping->host;
struct ext4_map_blocks map;
struct extent_status es;
ext4_lblk_t start, last, end;
loff_t dataoff, isize;
int blkbits;
int ret = 0;
mutex_lock(&inode->i_mutex);
isize = i_size_read(inode);
if (offset >= isize) {
mutex_unlock(&inode->i_mutex);
return -ENXIO;
}
blkbits = inode->i_sb->s_blocksize_bits;
start = offset >> blkbits;
last = start;
end = isize >> blkbits;
dataoff = offset;
do {
map.m_lblk = last;
map.m_len = end - last + 1;
ret = ext4_map_blocks(NULL, inode, &map, 0);
if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
if (last != start)
dataoff = last << blkbits;
break;
}
/*
* If there is a delay extent at this offset,
* it will be as a data.
*/
es.start = last;
(void)ext4_es_find_extent(inode, &es);
if (last >= es.start &&
last < es.start + es.len) {
if (last != start)
dataoff = last << blkbits;
break;
}
/*
* If there is a unwritten extent at this offset,
* it will be as a data or a hole according to page
* cache that has data or not.
*/
if (map.m_flags & EXT4_MAP_UNWRITTEN) {
int unwritten;
unwritten = ext4_find_unwritten_pgoff(inode, SEEK_DATA,
&map, &dataoff);
if (unwritten)
break;
}
last++;
dataoff = last << blkbits;
} while (last <= end);
mutex_unlock(&inode->i_mutex);
if (dataoff > isize)
return -ENXIO;
if (dataoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
return -EINVAL;
if (dataoff > maxsize)
return -EINVAL;
if (dataoff != file->f_pos) {
file->f_pos = dataoff;
file->f_version = 0;
}
return dataoff;
}
/*
* ext4_seek_hole() retrieves the offset for SEEK_HOLE.
*/
static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize)
{
struct inode *inode = file->f_mapping->host;
struct ext4_map_blocks map;
struct extent_status es;
ext4_lblk_t start, last, end;
loff_t holeoff, isize;
int blkbits;
int ret = 0;
mutex_lock(&inode->i_mutex);
isize = i_size_read(inode);
if (offset >= isize) {
mutex_unlock(&inode->i_mutex);
return -ENXIO;
}
blkbits = inode->i_sb->s_blocksize_bits;
start = offset >> blkbits;
last = start;
end = isize >> blkbits;
holeoff = offset;
do {
map.m_lblk = last;
map.m_len = end - last + 1;
ret = ext4_map_blocks(NULL, inode, &map, 0);
if (ret > 0 && !(map.m_flags & EXT4_MAP_UNWRITTEN)) {
last += ret;
holeoff = last << blkbits;
continue;
}
/*
* If there is a delay extent at this offset,
* we will skip this extent.
*/
es.start = last;
(void)ext4_es_find_extent(inode, &es);
if (last >= es.start &&
last < es.start + es.len) {
last = es.start + es.len;
holeoff = last << blkbits;
continue;
}
/*
* If there is a unwritten extent at this offset,
* it will be as a data or a hole according to page
* cache that has data or not.
*/
if (map.m_flags & EXT4_MAP_UNWRITTEN) {
int unwritten;
unwritten = ext4_find_unwritten_pgoff(inode, SEEK_HOLE,
&map, &holeoff);
if (!unwritten) {
last += ret;
holeoff = last << blkbits;
continue;
}
}
/* find a hole */
break;
} while (last <= end);
mutex_unlock(&inode->i_mutex);
if (holeoff > isize)
holeoff = isize;
if (holeoff < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
return -EINVAL;
if (holeoff > maxsize)
return -EINVAL;
if (holeoff != file->f_pos) {
file->f_pos = holeoff;
file->f_version = 0;
}
return holeoff;
}
/*
* ext4_llseek() handles both block-mapped and extent-mapped maxbytes values
* by calling generic_file_llseek_size() with the appropriate maxbytes
......@@ -300,8 +619,19 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
else
maxbytes = inode->i_sb->s_maxbytes;
switch (origin) {
case SEEK_SET:
case SEEK_CUR:
case SEEK_END:
return generic_file_llseek_size(file, offset, origin,
maxbytes, i_size_read(inode));
case SEEK_DATA:
return ext4_seek_data(file, offset, maxbytes);
case SEEK_HOLE:
return ext4_seek_hole(file, offset, maxbytes);
}
return -EINVAL;
}
const struct file_operations ext4_file_operations = {
......@@ -326,12 +656,10 @@ const struct file_operations ext4_file_operations = {
const struct inode_operations ext4_file_inode_operations = {
.setattr = ext4_setattr,
.getattr = ext4_getattr,
#ifdef CONFIG_EXT4_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
#endif
.get_acl = ext4_get_acl,
.fiemap = ext4_fiemap,
};
......
......@@ -44,7 +44,6 @@
*/
static int ext4_sync_parent(struct inode *inode)
{
struct writeback_control wbc;
struct dentry *dentry = NULL;
struct inode *next;
int ret = 0;
......@@ -66,10 +65,7 @@ static int ext4_sync_parent(struct inode *inode)
ret = sync_mapping_buffers(inode->i_mapping);
if (ret)
break;
memset(&wbc, 0, sizeof(wbc));
wbc.sync_mode = WB_SYNC_ALL;
wbc.nr_to_write = 0; /* only write out the inode */
ret = sync_inode(inode, &wbc);
ret = sync_inode_metadata(inode, 1);
if (ret)
break;
}
......
......@@ -762,7 +762,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap");
err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh);
brelse(block_bitmap_bh);
/* recheck and clear flag under lock if we still need to */
ext4_lock_group(sb, group);
......@@ -775,6 +774,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
ext4_group_desc_csum_set(sb, group, gdp);
}
ext4_unlock_group(sb, group);
brelse(block_bitmap_bh);
if (err)
goto fail;
......@@ -902,6 +902,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode,
ei->i_extra_isize = EXT4_SB(sb)->s_want_extra_isize;
ei->i_inline_off = 0;
if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_INLINE_DATA))
ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
ret = inode;
dquot_initialize(inode);
err = dquot_alloc_inode(inode);
......
......@@ -22,6 +22,7 @@
#include "ext4_jbd2.h"
#include "truncate.h"
#include "ext4_extents.h" /* Needed for EXT_MAX_BLOCKS */
#include <trace/events/ext4.h>
......@@ -755,8 +756,7 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
partial--;
}
out:
trace_ext4_ind_map_blocks_exit(inode, map->m_lblk,
map->m_pblk, map->m_len, err);
trace_ext4_ind_map_blocks_exit(inode, map, err);
return err;
}
......@@ -1412,6 +1412,7 @@ void ext4_ind_truncate(struct inode *inode)
down_write(&ei->i_data_sem);
ext4_discard_preallocations(inode);
ext4_es_remove_extent(inode, last_block, EXT_MAX_BLOCKS - last_block);
/*
* The orphan list entry will now protect us from any crash which
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include "ext4_jbd2.h"
#include "ext4_extents.h"
/*
* The contiguous blocks details which can be
......
......@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include "ext4_jbd2.h"
#include "ext4.h"
#include "ext4_extents.h"
/**
* get_ext_path - Find an extent path for designated logical block number.
......
This diff is collapsed.
......@@ -27,7 +27,6 @@
#include "ext4_jbd2.h"
#include "xattr.h"
#include "acl.h"
#include "ext4_extents.h"
static struct kmem_cache *io_page_cachep, *io_end_cachep;
......@@ -111,7 +110,7 @@ static int ext4_end_io(ext4_io_end_t *io)
inode_dio_done(inode);
/* Wake up anyone waiting on unwritten extent conversion */
if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten))
wake_up_all(ext4_ioend_wq(io->inode));
wake_up_all(ext4_ioend_wq(inode));
return ret;
}
......
......@@ -783,7 +783,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
err = ext4_journal_get_write_access(handle, gdb_bh);
if (unlikely(err))
goto exit_sbh;
goto exit_dind;
err = ext4_journal_get_write_access(handle, dind);
if (unlikely(err))
......@@ -792,7 +792,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
/* ext4_reserve_inode_write() gets a reference on the iloc */
err = ext4_reserve_inode_write(handle, inode, &iloc);
if (unlikely(err))
goto exit_dindj;
goto exit_dind;
n_group_desc = ext4_kvmalloc((gdb_num + 1) *
sizeof(struct buffer_head *),
......@@ -846,12 +846,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
exit_inode:
ext4_kvfree(n_group_desc);
/* ext4_handle_release_buffer(handle, iloc.bh); */
brelse(iloc.bh);
exit_dindj:
/* ext4_handle_release_buffer(handle, dind); */
exit_sbh:
/* ext4_handle_release_buffer(handle, EXT4_SB(sb)->s_sbh); */
exit_dind:
brelse(dind);
exit_bh:
......@@ -969,15 +964,9 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
}
for (i = 0; i < reserved_gdb; i++) {
if ((err = ext4_journal_get_write_access(handle, primary[i]))) {
/*
int j;
for (j = 0; j < i; j++)
ext4_handle_release_buffer(handle, primary[j]);
*/
if ((err = ext4_journal_get_write_access(handle, primary[i])))
goto exit_bh;
}
}
if ((err = ext4_reserve_inode_write(handle, inode, &iloc)))
goto exit_bh;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -60,7 +60,6 @@ EXPORT_SYMBOL(jbd2_journal_get_create_access);
EXPORT_SYMBOL(jbd2_journal_get_undo_access);
EXPORT_SYMBOL(jbd2_journal_set_triggers);
EXPORT_SYMBOL(jbd2_journal_dirty_metadata);
EXPORT_SYMBOL(jbd2_journal_release_buffer);
EXPORT_SYMBOL(jbd2_journal_forget);
#if 0
EXPORT_SYMBOL(journal_sync_buffer);
......
This diff is collapsed.
This diff is collapsed.
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