aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-02-27 20:10:32 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-02-27 20:10:32 -0500
commit12b9fa6a97b3150477ab182e321be512b59fa899 (patch)
tree3ff6cf7f3b2d74f6c3e0ec81b75cb36c06332bfa
parent340b3a5b35c0919e1535b355a9eafe1f81c4cae3 (diff)
parent5129fa482b16615fd4464d2f5d23acb1b7056c66 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: do_last(): ELOOP failure exit should be done after leaving RCU mode should_follow_link(): validate ->d_seq after having decided to follow namei: ->d_inode of a pinned dentry is stable only for positives do_last(): don't let a bogus return value from ->open() et.al. to confuse us fs: return -EOPNOTSUPP if clone is not supported hpfs: don't truncate the file when delete fails
-rw-r--r--fs/hpfs/namei.c31
-rw-r--r--fs/namei.c22
-rw-r--r--fs/read_write.c6
3 files changed, 22 insertions, 37 deletions
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 506765afa1a3..bb8d67e2740a 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -376,12 +376,11 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
376 struct inode *inode = d_inode(dentry); 376 struct inode *inode = d_inode(dentry);
377 dnode_secno dno; 377 dnode_secno dno;
378 int r; 378 int r;
379 int rep = 0;
380 int err; 379 int err;
381 380
382 hpfs_lock(dir->i_sb); 381 hpfs_lock(dir->i_sb);
383 hpfs_adjust_length(name, &len); 382 hpfs_adjust_length(name, &len);
384again: 383
385 err = -ENOENT; 384 err = -ENOENT;
386 de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); 385 de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
387 if (!de) 386 if (!de)
@@ -401,33 +400,9 @@ again:
401 hpfs_error(dir->i_sb, "there was error when removing dirent"); 400 hpfs_error(dir->i_sb, "there was error when removing dirent");
402 err = -EFSERROR; 401 err = -EFSERROR;
403 break; 402 break;
404 case 2: /* no space for deleting, try to truncate file */ 403 case 2: /* no space for deleting */
405
406 err = -ENOSPC; 404 err = -ENOSPC;
407 if (rep++) 405 break;
408 break;
409
410 dentry_unhash(dentry);
411 if (!d_unhashed(dentry)) {
412 hpfs_unlock(dir->i_sb);
413 return -ENOSPC;
414 }
415 if (generic_permission(inode, MAY_WRITE) ||
416 !S_ISREG(inode->i_mode) ||
417 get_write_access(inode)) {
418 d_rehash(dentry);
419 } else {
420 struct iattr newattrs;
421 /*pr_info("truncating file before delete.\n");*/
422 newattrs.ia_size = 0;
423 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
424 err = notify_change(dentry, &newattrs, NULL);
425 put_write_access(inode);
426 if (!err)
427 goto again;
428 }
429 hpfs_unlock(dir->i_sb);
430 return -ENOSPC;
431 default: 406 default:
432 drop_nlink(inode); 407 drop_nlink(inode);
433 err = 0; 408 err = 0;
diff --git a/fs/namei.c b/fs/namei.c
index f624d132e01e..9c590e0f66e9 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1712,6 +1712,11 @@ static inline int should_follow_link(struct nameidata *nd, struct path *link,
1712 return 0; 1712 return 0;
1713 if (!follow) 1713 if (!follow)
1714 return 0; 1714 return 0;
1715 /* make sure that d_is_symlink above matches inode */
1716 if (nd->flags & LOOKUP_RCU) {
1717 if (read_seqcount_retry(&link->dentry->d_seq, seq))
1718 return -ECHILD;
1719 }
1715 return pick_link(nd, link, inode, seq); 1720 return pick_link(nd, link, inode, seq);
1716} 1721}
1717 1722
@@ -1743,11 +1748,11 @@ static int walk_component(struct nameidata *nd, int flags)
1743 if (err < 0) 1748 if (err < 0)
1744 return err; 1749 return err;
1745 1750
1746 inode = d_backing_inode(path.dentry);
1747 seq = 0; /* we are already out of RCU mode */ 1751 seq = 0; /* we are already out of RCU mode */
1748 err = -ENOENT; 1752 err = -ENOENT;
1749 if (d_is_negative(path.dentry)) 1753 if (d_is_negative(path.dentry))
1750 goto out_path_put; 1754 goto out_path_put;
1755 inode = d_backing_inode(path.dentry);
1751 } 1756 }
1752 1757
1753 if (flags & WALK_PUT) 1758 if (flags & WALK_PUT)
@@ -3192,12 +3197,12 @@ retry_lookup:
3192 return error; 3197 return error;
3193 3198
3194 BUG_ON(nd->flags & LOOKUP_RCU); 3199 BUG_ON(nd->flags & LOOKUP_RCU);
3195 inode = d_backing_inode(path.dentry);
3196 seq = 0; /* out of RCU mode, so the value doesn't matter */ 3200 seq = 0; /* out of RCU mode, so the value doesn't matter */
3197 if (unlikely(d_is_negative(path.dentry))) { 3201 if (unlikely(d_is_negative(path.dentry))) {
3198 path_to_nameidata(&path, nd); 3202 path_to_nameidata(&path, nd);
3199 return -ENOENT; 3203 return -ENOENT;
3200 } 3204 }
3205 inode = d_backing_inode(path.dentry);
3201finish_lookup: 3206finish_lookup:
3202 if (nd->depth) 3207 if (nd->depth)
3203 put_link(nd); 3208 put_link(nd);
@@ -3206,11 +3211,6 @@ finish_lookup:
3206 if (unlikely(error)) 3211 if (unlikely(error))
3207 return error; 3212 return error;
3208 3213
3209 if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
3210 path_to_nameidata(&path, nd);
3211 return -ELOOP;
3212 }
3213
3214 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) { 3214 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
3215 path_to_nameidata(&path, nd); 3215 path_to_nameidata(&path, nd);
3216 } else { 3216 } else {
@@ -3229,6 +3229,10 @@ finish_open:
3229 return error; 3229 return error;
3230 } 3230 }
3231 audit_inode(nd->name, nd->path.dentry, 0); 3231 audit_inode(nd->name, nd->path.dentry, 0);
3232 if (unlikely(d_is_symlink(nd->path.dentry)) && !(open_flag & O_PATH)) {
3233 error = -ELOOP;
3234 goto out;
3235 }
3232 error = -EISDIR; 3236 error = -EISDIR;
3233 if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) 3237 if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
3234 goto out; 3238 goto out;
@@ -3273,6 +3277,10 @@ opened:
3273 goto exit_fput; 3277 goto exit_fput;
3274 } 3278 }
3275out: 3279out:
3280 if (unlikely(error > 0)) {
3281 WARN_ON(1);
3282 error = -EINVAL;
3283 }
3276 if (got_write) 3284 if (got_write)
3277 mnt_drop_write(nd->path.mnt); 3285 mnt_drop_write(nd->path.mnt);
3278 path_put(&save_parent); 3286 path_put(&save_parent);
diff --git a/fs/read_write.c b/fs/read_write.c
index 0c8782aa3d71..dadf24e5c95b 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1533,10 +1533,12 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
1533 1533
1534 if (!(file_in->f_mode & FMODE_READ) || 1534 if (!(file_in->f_mode & FMODE_READ) ||
1535 !(file_out->f_mode & FMODE_WRITE) || 1535 !(file_out->f_mode & FMODE_WRITE) ||
1536 (file_out->f_flags & O_APPEND) || 1536 (file_out->f_flags & O_APPEND))
1537 !file_in->f_op->clone_file_range)
1538 return -EBADF; 1537 return -EBADF;
1539 1538
1539 if (!file_in->f_op->clone_file_range)
1540 return -EOPNOTSUPP;
1541
1540 ret = clone_verify_area(file_in, pos_in, len, false); 1542 ret = clone_verify_area(file_in, pos_in, len, false);
1541 if (ret) 1543 if (ret)
1542 return ret; 1544 return ret;