Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+22 -37
+3 -28
fs/hpfs/namei.c
··· 376 376 struct inode *inode = d_inode(dentry); 377 377 dnode_secno dno; 378 378 int r; 379 - int rep = 0; 380 379 int err; 381 380 382 381 hpfs_lock(dir->i_sb); 383 382 hpfs_adjust_length(name, &len); 384 - again: 383 + 385 384 err = -ENOENT; 386 385 de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh); 387 386 if (!de) ··· 400 401 hpfs_error(dir->i_sb, "there was error when removing dirent"); 401 402 err = -EFSERROR; 402 403 break; 403 - case 2: /* no space for deleting, try to truncate file */ 404 - 404 + case 2: /* no space for deleting */ 405 405 err = -ENOSPC; 406 - if (rep++) 407 - break; 408 - 409 - dentry_unhash(dentry); 410 - if (!d_unhashed(dentry)) { 411 - hpfs_unlock(dir->i_sb); 412 - return -ENOSPC; 413 - } 414 - if (generic_permission(inode, MAY_WRITE) || 415 - !S_ISREG(inode->i_mode) || 416 - get_write_access(inode)) { 417 - d_rehash(dentry); 418 - } else { 419 - struct iattr newattrs; 420 - /*pr_info("truncating file before delete.\n");*/ 421 - newattrs.ia_size = 0; 422 - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; 423 - err = notify_change(dentry, &newattrs, NULL); 424 - put_write_access(inode); 425 - if (!err) 426 - goto again; 427 - } 428 - hpfs_unlock(dir->i_sb); 429 - return -ENOSPC; 406 + break; 430 407 default: 431 408 drop_nlink(inode); 432 409 err = 0;
+15 -7
fs/namei.c
··· 1712 1712 return 0; 1713 1713 if (!follow) 1714 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 1720 return pick_link(nd, link, inode, seq); 1716 1721 } 1717 1722 ··· 1748 1743 if (err < 0) 1749 1744 return err; 1750 1745 1751 - inode = d_backing_inode(path.dentry); 1752 1746 seq = 0; /* we are already out of RCU mode */ 1753 1747 err = -ENOENT; 1754 1748 if (d_is_negative(path.dentry)) 1755 1749 goto out_path_put; 1750 + inode = d_backing_inode(path.dentry); 1756 1751 } 1757 1752 1758 1753 if (flags & WALK_PUT) ··· 3197 3192 return error; 3198 3193 3199 3194 BUG_ON(nd->flags & LOOKUP_RCU); 3200 - inode = d_backing_inode(path.dentry); 3201 3195 seq = 0; /* out of RCU mode, so the value doesn't matter */ 3202 3196 if (unlikely(d_is_negative(path.dentry))) { 3203 3197 path_to_nameidata(&path, nd); 3204 3198 return -ENOENT; 3205 3199 } 3200 + inode = d_backing_inode(path.dentry); 3206 3201 finish_lookup: 3207 3202 if (nd->depth) 3208 3203 put_link(nd); ··· 3210 3205 inode, seq); 3211 3206 if (unlikely(error)) 3212 3207 return error; 3213 - 3214 - if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) { 3215 - path_to_nameidata(&path, nd); 3216 - return -ELOOP; 3217 - } 3218 3208 3219 3209 if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) { 3220 3210 path_to_nameidata(&path, nd); ··· 3229 3229 return error; 3230 3230 } 3231 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 3236 error = -EISDIR; 3233 3237 if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) 3234 3238 goto out; ··· 3277 3273 goto exit_fput; 3278 3274 } 3279 3275 out: 3276 + if (unlikely(error > 0)) { 3277 + WARN_ON(1); 3278 + error = -EINVAL; 3279 + } 3280 3280 if (got_write) 3281 3281 mnt_drop_write(nd->path.mnt); 3282 3282 path_put(&save_parent);
+4 -2
fs/read_write.c
··· 1533 1533 1534 1534 if (!(file_in->f_mode & FMODE_READ) || 1535 1535 !(file_out->f_mode & FMODE_WRITE) || 1536 - (file_out->f_flags & O_APPEND) || 1537 - !file_in->f_op->clone_file_range) 1536 + (file_out->f_flags & O_APPEND)) 1538 1537 return -EBADF; 1538 + 1539 + if (!file_in->f_op->clone_file_range) 1540 + return -EOPNOTSUPP; 1539 1541 1540 1542 ret = clone_verify_area(file_in, pos_in, len, false); 1541 1543 if (ret)