Commit 50f2d407 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://github.com/chrismason/linux

* 'for-linus' of git://github.com/chrismason/linux:
  Btrfs: only clear the need lookup flag after the dentry is setup
  BTRFS: Fix lseek return value for error
  Btrfs: don't change inode flag of the dest clone file
  Btrfs: don't make a file partly checksummed through file clone
  Btrfs: fix pages truncation in btrfs_ioctl_clone()
  btrfs: fix d_off in the first dirent
parents c2d7b49f a66e7cc6
...@@ -1817,6 +1817,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) ...@@ -1817,6 +1817,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
goto out; goto out;
case SEEK_DATA: case SEEK_DATA:
case SEEK_HOLE: case SEEK_HOLE:
if (offset >= i_size_read(inode)) {
mutex_unlock(&inode->i_mutex);
return -ENXIO;
}
ret = find_desired_extent(inode, &offset, origin); ret = find_desired_extent(inode, &offset, origin);
if (ret) { if (ret) {
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
...@@ -1825,11 +1830,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) ...@@ -1825,11 +1830,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
} }
if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) {
ret = -EINVAL; offset = -EINVAL;
goto out; goto out;
} }
if (offset > inode->i_sb->s_maxbytes) { if (offset > inode->i_sb->s_maxbytes) {
ret = -EINVAL; offset = -EINVAL;
goto out; goto out;
} }
......
...@@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) ...@@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key)); memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
kfree(dentry->d_fsdata); kfree(dentry->d_fsdata);
dentry->d_fsdata = NULL; dentry->d_fsdata = NULL;
d_clear_need_lookup(dentry); /* This thing is hashed, drop it for now */
d_drop(dentry);
} else { } else {
ret = btrfs_inode_by_name(dir, dentry, &location); ret = btrfs_inode_by_name(dir, dentry, &location);
} }
...@@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry) ...@@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry)
static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd) struct nameidata *nd)
{ {
return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry); struct dentry *ret;
ret = d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
if (unlikely(d_need_lookup(dentry))) {
spin_lock(&dentry->d_lock);
dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
spin_unlock(&dentry->d_lock);
}
return ret;
} }
unsigned char btrfs_filetype_table[] = { unsigned char btrfs_filetype_table[] = {
...@@ -4125,7 +4134,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, ...@@ -4125,7 +4134,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
/* special case for "." */ /* special case for "." */
if (filp->f_pos == 0) { if (filp->f_pos == 0) {
over = filldir(dirent, ".", 1, 1, btrfs_ino(inode), DT_DIR); over = filldir(dirent, ".", 1,
filp->f_pos, btrfs_ino(inode), DT_DIR);
if (over) if (over)
return 0; return 0;
filp->f_pos = 1; filp->f_pos = 1;
...@@ -4134,7 +4144,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, ...@@ -4134,7 +4144,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
if (filp->f_pos == 1) { if (filp->f_pos == 1) {
u64 pino = parent_ino(filp->f_path.dentry); u64 pino = parent_ino(filp->f_path.dentry);
over = filldir(dirent, "..", 2, over = filldir(dirent, "..", 2,
2, pino, DT_DIR); filp->f_pos, pino, DT_DIR);
if (over) if (over)
return 0; return 0;
filp->f_pos = 2; filp->f_pos = 2;
......
...@@ -2177,6 +2177,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2177,6 +2177,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
if (!(src_file->f_mode & FMODE_READ)) if (!(src_file->f_mode & FMODE_READ))
goto out_fput; goto out_fput;
/* don't make the dst file partly checksummed */
if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
goto out_fput;
ret = -EISDIR; ret = -EISDIR;
if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
goto out_fput; goto out_fput;
...@@ -2226,6 +2231,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2226,6 +2231,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
goto out_unlock; goto out_unlock;
} }
/* truncate page cache pages from target inode range */
truncate_inode_pages_range(&inode->i_data, destoff,
PAGE_CACHE_ALIGN(destoff + len) - 1);
/* do any pending delalloc/csum calc on src, one way or /* do any pending delalloc/csum calc on src, one way or
another, and lock file content */ another, and lock file content */
while (1) { while (1) {
...@@ -2242,10 +2251,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2242,10 +2251,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
btrfs_wait_ordered_range(src, off, len); btrfs_wait_ordered_range(src, off, len);
} }
/* truncate page cache pages from target inode range */
truncate_inode_pages_range(&inode->i_data, off,
ALIGN(off + len, PAGE_CACHE_SIZE) - 1);
/* clone data */ /* clone data */
key.objectid = btrfs_ino(src); key.objectid = btrfs_ino(src);
key.type = BTRFS_EXTENT_DATA_KEY; key.type = BTRFS_EXTENT_DATA_KEY;
...@@ -2442,7 +2447,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ...@@ -2442,7 +2447,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
if (endoff > inode->i_size) if (endoff > inode->i_size)
btrfs_i_size_write(inode, endoff); btrfs_i_size_write(inode, endoff);
BTRFS_I(inode)->flags = BTRFS_I(src)->flags;
ret = btrfs_update_inode(trans, root, inode); ret = btrfs_update_inode(trans, root, inode);
BUG_ON(ret); BUG_ON(ret);
btrfs_end_transaction(trans, root); btrfs_end_transaction(trans, root);
......
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