forked from Minki/linux
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
This commit is contained in:
commit
50f2d407c0
@ -1817,6 +1817,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
|
||||
goto out;
|
||||
case SEEK_DATA:
|
||||
case SEEK_HOLE:
|
||||
if (offset >= i_size_read(inode)) {
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = find_desired_extent(inode, &offset, origin);
|
||||
if (ret) {
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
@ -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)) {
|
||||
ret = -EINVAL;
|
||||
offset = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (offset > inode->i_sb->s_maxbytes) {
|
||||
ret = -EINVAL;
|
||||
offset = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -4018,7 +4018,8 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
|
||||
memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
|
||||
kfree(dentry->d_fsdata);
|
||||
dentry->d_fsdata = NULL;
|
||||
d_clear_need_lookup(dentry);
|
||||
/* This thing is hashed, drop it for now */
|
||||
d_drop(dentry);
|
||||
} else {
|
||||
ret = btrfs_inode_by_name(dir, dentry, &location);
|
||||
}
|
||||
@ -4085,7 +4086,15 @@ static void btrfs_dentry_release(struct dentry *dentry)
|
||||
static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
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[] = {
|
||||
@ -4125,7 +4134,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
|
||||
|
||||
/* special case for "." */
|
||||
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)
|
||||
return 0;
|
||||
filp->f_pos = 1;
|
||||
@ -4134,7 +4144,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
|
||||
if (filp->f_pos == 1) {
|
||||
u64 pino = parent_ino(filp->f_path.dentry);
|
||||
over = filldir(dirent, "..", 2,
|
||||
2, pino, DT_DIR);
|
||||
filp->f_pos, pino, DT_DIR);
|
||||
if (over)
|
||||
return 0;
|
||||
filp->f_pos = 2;
|
||||
|
@ -2177,6 +2177,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
if (!(src_file->f_mode & FMODE_READ))
|
||||
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;
|
||||
if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
|
||||
goto out_fput;
|
||||
@ -2226,6 +2231,10 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
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
|
||||
another, and lock file content */
|
||||
while (1) {
|
||||
@ -2242,10 +2251,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
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 */
|
||||
key.objectid = btrfs_ino(src);
|
||||
key.type = BTRFS_EXTENT_DATA_KEY;
|
||||
@ -2442,7 +2447,6 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
|
||||
if (endoff > inode->i_size)
|
||||
btrfs_i_size_write(inode, endoff);
|
||||
|
||||
BTRFS_I(inode)->flags = BTRFS_I(src)->flags;
|
||||
ret = btrfs_update_inode(trans, root, inode);
|
||||
BUG_ON(ret);
|
||||
btrfs_end_transaction(trans, root);
|
||||
|
Loading…
Reference in New Issue
Block a user