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 tag 'vfs-6.19-rc1.directory.delegations' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull directory delegations update from Christian Brauner:
"This contains the work for recall-only directory delegations for
knfsd.

Add support for simple, recallable-only directory delegations. This
was decided at the fall NFS Bakeathon where the NFS client and server
maintainers discussed how to merge directory delegation support.

The approach starts with recallable-only delegations for several reasons:

1. RFC8881 has gaps that are being addressed in RFC8881bis. In
particular, it requires directory position information for
CB_NOTIFY callbacks, which is difficult to implement properly
under Linux. The spec is being extended to allow that information
to be omitted.

2. Client-side support for CB_NOTIFY still lags. The client side
involves heuristics about when to request a delegation.

3. Early indication shows simple, recallable-only delegations can
help performance. Anna Schumaker mentioned seeing a multi-minute
speedup in xfstests runs with them enabled.

With these changes, userspace can also request a read lease on a
directory that will be recalled on conflicting accesses. This may be
useful for applications like Samba. Users can disable leases
altogether via the fs.leases-enable sysctl if needed.

VFS changes:

- Dedicated Type for Delegations

Introduce struct delegated_inode to track inodes that may have
delegations that need to be broken. This replaces the previous
approach of passing raw inode pointers through the delegation
breaking code paths, providing better type safety and clearer
semantics for the delegation machinery.

- Break parent directory delegations in open(..., O_CREAT) codepath

- Allow mkdir to wait for delegation break on parent

- Allow rmdir to wait for delegation break on parent

- Add try_break_deleg calls for parents to vfs_link(), vfs_rename(),
and vfs_unlink()

- Make vfs_create(), vfs_mknod(), and vfs_symlink() break delegations
on parent directory

- Clean up argument list for vfs_create()

- Expose delegation support to userland

Filelock changes:

- Make lease_alloc() take a flags argument

- Rework the __break_lease API to use flags

- Add struct delegated_inode

- Push the S_ISREG check down to ->setlease handlers

- Lift the ban on directory leases in generic_setlease

NFSD changes:

- Allow filecache to hold S_IFDIR files

- Allow DELEGRETURN on directories

- Wire up GET_DIR_DELEGATION handling

Fixes:

- Fix kernel-doc warnings in __fcntl_getlease

- Add needed headers for new struct delegation definition"

* tag 'vfs-6.19-rc1.directory.delegations' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
vfs: add needed headers for new struct delegation definition
filelock: __fcntl_getlease: fix kernel-doc warnings
vfs: expose delegation support to userland
nfsd: wire up GET_DIR_DELEGATION handling
nfsd: allow DELEGRETURN on directories
nfsd: allow filecache to hold S_IFDIR files
filelock: lift the ban on directory leases in generic_setlease
vfs: make vfs_symlink break delegations on parent dir
vfs: make vfs_mknod break delegations on parent directory
vfs: make vfs_create break delegations on parent directory
vfs: clean up argument list for vfs_create()
vfs: break parent dir delegations in open(..., O_CREAT) codepath
vfs: allow rmdir to wait for delegation break on parent
vfs: allow mkdir to wait for delegation break on parent
vfs: add try_break_deleg calls for parents to vfs_{link,rename,unlink}
filelock: push the S_ISREG check down to ->setlease handlers
filelock: add struct delegated_inode
filelock: rework the __break_lease API to use flags
filelock: make lease_alloc() take a flags argument

+550 -177
+3 -3
drivers/base/devtmpfs.c
··· 180 180 if (IS_ERR(dentry)) 181 181 return PTR_ERR(dentry); 182 182 183 - dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode); 183 + dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, NULL); 184 184 if (!IS_ERR(dentry)) 185 185 /* mark as kernel-created inode */ 186 186 d_inode(dentry)->i_private = &thread; ··· 231 231 return PTR_ERR(dentry); 232 232 233 233 err = vfs_mknod(&nop_mnt_idmap, d_inode(path.dentry), dentry, mode, 234 - dev->devt); 234 + dev->devt, NULL); 235 235 if (!err) { 236 236 struct iattr newattrs; 237 237 ··· 261 261 return PTR_ERR(dentry); 262 262 if (d_inode(dentry)->i_private == &thread) 263 263 err = vfs_rmdir(&nop_mnt_idmap, d_inode(parent.dentry), 264 - dentry); 264 + dentry, NULL); 265 265 else 266 266 err = -EPERM; 267 267
+1 -1
fs/attr.c
··· 415 415 * performed on the raw inode simply pass @nop_mnt_idmap. 416 416 */ 417 417 int notify_change(struct mnt_idmap *idmap, struct dentry *dentry, 418 - struct iattr *attr, struct inode **delegated_inode) 418 + struct iattr *attr, struct delegated_inode *delegated_inode) 419 419 { 420 420 struct inode *inode = dentry->d_inode; 421 421 umode_t mode = inode->i_mode;
+1 -1
fs/cachefiles/namei.c
··· 130 130 goto mkdir_error; 131 131 ret = cachefiles_inject_write_error(); 132 132 if (ret == 0) 133 - subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700); 133 + subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL); 134 134 else 135 135 subdir = ERR_PTR(ret); 136 136 if (IS_ERR(subdir)) {
+5 -6
fs/ecryptfs/inode.c
··· 188 188 189 189 rc = lock_parent(ecryptfs_dentry, &lower_dentry, &lower_dir); 190 190 if (!rc) 191 - rc = vfs_create(&nop_mnt_idmap, lower_dir, 192 - lower_dentry, mode, true); 191 + rc = vfs_create(&nop_mnt_idmap, lower_dentry, mode, NULL); 193 192 if (rc) { 194 193 printk(KERN_ERR "%s: Failure to create dentry in lower fs; " 195 194 "rc = [%d]\n", __func__, rc); ··· 479 480 if (rc) 480 481 goto out_lock; 481 482 rc = vfs_symlink(&nop_mnt_idmap, lower_dir, lower_dentry, 482 - encoded_symname); 483 + encoded_symname, NULL); 483 484 kfree(encoded_symname); 484 485 if (rc || d_really_is_negative(lower_dentry)) 485 486 goto out_lock; ··· 507 508 goto out; 508 509 509 510 lower_dentry = vfs_mkdir(&nop_mnt_idmap, lower_dir, 510 - lower_dentry, mode); 511 + lower_dentry, mode, NULL); 511 512 rc = PTR_ERR(lower_dentry); 512 513 if (IS_ERR(lower_dentry)) 513 514 goto out; ··· 539 540 if (d_unhashed(lower_dentry)) 540 541 rc = -EINVAL; 541 542 else 542 - rc = vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry); 543 + rc = vfs_rmdir(&nop_mnt_idmap, lower_dir, lower_dentry, NULL); 543 544 } 544 545 if (!rc) { 545 546 clear_nlink(d_inode(dentry)); ··· 564 565 rc = lock_parent(dentry, &lower_dentry, &lower_dir); 565 566 if (!rc) 566 567 rc = vfs_mknod(&nop_mnt_idmap, lower_dir, 567 - lower_dentry, mode, dev); 568 + lower_dentry, mode, dev, NULL); 568 569 if (rc || d_really_is_negative(lower_dentry)) 569 570 goto out; 570 571 rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb);
+13
fs/fcntl.c
··· 445 445 struct file *filp) 446 446 { 447 447 void __user *argp = (void __user *)arg; 448 + struct delegation deleg; 448 449 int argi = (int)arg; 449 450 struct flock flock; 450 451 long err = -EINVAL; ··· 550 549 break; 551 550 case F_SET_RW_HINT: 552 551 err = fcntl_set_rw_hint(filp, arg); 552 + break; 553 + case F_GETDELEG: 554 + if (copy_from_user(&deleg, argp, sizeof(deleg))) 555 + return -EFAULT; 556 + err = fcntl_getdeleg(filp, &deleg); 557 + if (!err && copy_to_user(argp, &deleg, sizeof(deleg))) 558 + return -EFAULT; 559 + break; 560 + case F_SETDELEG: 561 + if (copy_from_user(&deleg, argp, sizeof(deleg))) 562 + return -EFAULT; 563 + err = fcntl_setdeleg(fd, filp, &deleg); 553 564 break; 554 565 default: 555 566 break;
+1
fs/fuse/dir.c
··· 2230 2230 .fsync = fuse_dir_fsync, 2231 2231 .unlocked_ioctl = fuse_dir_ioctl, 2232 2232 .compat_ioctl = fuse_dir_compat_ioctl, 2233 + .setlease = simple_nosetlease, 2233 2234 }; 2234 2235 2235 2236 static const struct inode_operations fuse_common_inode_operations = {
+3 -3
fs/init.c
··· 157 157 error = security_path_mknod(&path, dentry, mode, dev); 158 158 if (!error) 159 159 error = vfs_mknod(mnt_idmap(path.mnt), path.dentry->d_inode, 160 - dentry, mode, new_decode_dev(dev)); 160 + dentry, mode, new_decode_dev(dev), NULL); 161 161 end_creating_path(&path, dentry); 162 162 return error; 163 163 } ··· 209 209 error = security_path_symlink(&path, dentry, oldname); 210 210 if (!error) 211 211 error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, 212 - dentry, oldname); 212 + dentry, oldname, NULL); 213 213 end_creating_path(&path, dentry); 214 214 return error; 215 215 } ··· 233 233 error = security_path_mkdir(&path, dentry, mode); 234 234 if (!error) { 235 235 dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, 236 - dentry, mode); 236 + dentry, mode, NULL); 237 237 if (IS_ERR(dentry)) 238 238 error = PTR_ERR(dentry); 239 239 }
+77 -26
fs/locks.c
··· 585 585 /* 586 586 * Initialize a lease, use the default lock manager operations 587 587 */ 588 - static int lease_init(struct file *filp, int type, struct file_lease *fl) 588 + static int lease_init(struct file *filp, unsigned int flags, int type, struct file_lease *fl) 589 589 { 590 590 if (assign_type(&fl->c, type) != 0) 591 591 return -EINVAL; ··· 594 594 fl->c.flc_pid = current->tgid; 595 595 596 596 fl->c.flc_file = filp; 597 - fl->c.flc_flags = FL_LEASE; 597 + fl->c.flc_flags = flags; 598 598 fl->fl_lmops = &lease_manager_ops; 599 599 return 0; 600 600 } 601 601 602 602 /* Allocate a file_lock initialised to this type of lease */ 603 - static struct file_lease *lease_alloc(struct file *filp, int type) 603 + static struct file_lease *lease_alloc(struct file *filp, unsigned int flags, int type) 604 604 { 605 605 struct file_lease *fl = locks_alloc_lease(); 606 606 int error = -ENOMEM; ··· 608 608 if (fl == NULL) 609 609 return ERR_PTR(error); 610 610 611 - error = lease_init(filp, type, fl); 611 + error = lease_init(filp, flags, type, fl); 612 612 if (error) { 613 613 locks_free_lease(fl); 614 614 return ERR_PTR(error); ··· 1529 1529 /** 1530 1530 * __break_lease - revoke all outstanding leases on file 1531 1531 * @inode: the inode of the file to return 1532 - * @mode: O_RDONLY: break only write leases; O_WRONLY or O_RDWR: 1533 - * break all leases 1534 - * @type: FL_LEASE: break leases and delegations; FL_DELEG: break 1535 - * only delegations 1532 + * @flags: LEASE_BREAK_* flags 1536 1533 * 1537 1534 * break_lease (inlined for speed) has checked there already is at least 1538 1535 * some kind of lock (maybe a lease) on this file. Leases are broken on 1539 - * a call to open() or truncate(). This function can sleep unless you 1540 - * specified %O_NONBLOCK to your open(). 1536 + * a call to open() or truncate(). This function can block waiting for the 1537 + * lease break unless you specify LEASE_BREAK_NONBLOCK. 1541 1538 */ 1542 - int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) 1539 + int __break_lease(struct inode *inode, unsigned int flags) 1543 1540 { 1544 - int error = 0; 1545 - struct file_lock_context *ctx; 1546 1541 struct file_lease *new_fl, *fl, *tmp; 1542 + struct file_lock_context *ctx; 1547 1543 unsigned long break_time; 1548 - int want_write = (mode & O_ACCMODE) != O_RDONLY; 1544 + unsigned int type; 1549 1545 LIST_HEAD(dispose); 1546 + bool want_write = !(flags & LEASE_BREAK_OPEN_RDONLY); 1547 + int error = 0; 1550 1548 1551 - new_fl = lease_alloc(NULL, want_write ? F_WRLCK : F_RDLCK); 1549 + if (flags & LEASE_BREAK_LEASE) 1550 + type = FL_LEASE; 1551 + else if (flags & LEASE_BREAK_DELEG) 1552 + type = FL_DELEG; 1553 + else if (flags & LEASE_BREAK_LAYOUT) 1554 + type = FL_LAYOUT; 1555 + else 1556 + return -EINVAL; 1557 + 1558 + new_fl = lease_alloc(NULL, type, want_write ? F_WRLCK : F_RDLCK); 1552 1559 if (IS_ERR(new_fl)) 1553 1560 return PTR_ERR(new_fl); 1554 - new_fl->c.flc_flags = type; 1555 1561 1556 1562 /* typically we will check that ctx is non-NULL before calling */ 1557 1563 ctx = locks_inode_context(inode); ··· 1602 1596 if (list_empty(&ctx->flc_lease)) 1603 1597 goto out; 1604 1598 1605 - if (mode & O_NONBLOCK) { 1599 + if (flags & LEASE_BREAK_NONBLOCK) { 1606 1600 trace_break_lease_noblock(inode, new_fl); 1607 1601 error = -EWOULDBLOCK; 1608 1602 goto out; ··· 1681 1675 EXPORT_SYMBOL(lease_get_mtime); 1682 1676 1683 1677 /** 1684 - * fcntl_getlease - Enquire what lease is currently active 1678 + * __fcntl_getlease - Enquire what lease is currently active 1685 1679 * @filp: the file 1680 + * @flavor: type of lease flags to check 1686 1681 * 1687 1682 * The value returned by this function will be one of 1688 1683 * (if no lease break is pending): ··· 1704 1697 * XXX: sfr & willy disagree over whether F_INPROGRESS 1705 1698 * should be returned to userspace. 1706 1699 */ 1707 - int fcntl_getlease(struct file *filp) 1700 + static int __fcntl_getlease(struct file *filp, unsigned int flavor) 1708 1701 { 1709 1702 struct file_lease *fl; 1710 1703 struct inode *inode = file_inode(filp); ··· 1720 1713 list_for_each_entry(fl, &ctx->flc_lease, c.flc_list) { 1721 1714 if (fl->c.flc_file != filp) 1722 1715 continue; 1723 - type = target_leasetype(fl); 1716 + if (fl->c.flc_flags & flavor) 1717 + type = target_leasetype(fl); 1724 1718 break; 1725 1719 } 1726 1720 spin_unlock(&ctx->flc_lock); ··· 1730 1722 locks_dispose_list(&dispose); 1731 1723 } 1732 1724 return type; 1725 + } 1726 + 1727 + int fcntl_getlease(struct file *filp) 1728 + { 1729 + return __fcntl_getlease(filp, FL_LEASE); 1730 + } 1731 + 1732 + int fcntl_getdeleg(struct file *filp, struct delegation *deleg) 1733 + { 1734 + if (deleg->d_flags != 0 || deleg->__pad != 0) 1735 + return -EINVAL; 1736 + deleg->d_type = __fcntl_getlease(filp, FL_DELEG); 1737 + return 0; 1733 1738 } 1734 1739 1735 1740 /** ··· 1950 1929 int generic_setlease(struct file *filp, int arg, struct file_lease **flp, 1951 1930 void **priv) 1952 1931 { 1932 + struct inode *inode = file_inode(filp); 1933 + 1934 + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) 1935 + return -EINVAL; 1936 + 1953 1937 switch (arg) { 1954 1938 case F_UNLCK: 1955 1939 return generic_delete_lease(filp, *priv); 1956 - case F_RDLCK: 1957 1940 case F_WRLCK: 1941 + if (S_ISDIR(inode->i_mode)) 1942 + return -EINVAL; 1943 + fallthrough; 1944 + case F_RDLCK: 1958 1945 if (!(*flp)->fl_lmops->lm_break) { 1959 1946 WARN_ON_ONCE(1); 1960 1947 return -ENOLCK; ··· 2047 2018 2048 2019 if ((!vfsuid_eq_kuid(vfsuid, current_fsuid())) && !capable(CAP_LEASE)) 2049 2020 return -EACCES; 2050 - if (!S_ISREG(inode->i_mode)) 2051 - return -EINVAL; 2052 2021 error = security_file_lock(filp, arg); 2053 2022 if (error) 2054 2023 return error; ··· 2054 2027 } 2055 2028 EXPORT_SYMBOL_GPL(vfs_setlease); 2056 2029 2057 - static int do_fcntl_add_lease(unsigned int fd, struct file *filp, int arg) 2030 + static int do_fcntl_add_lease(unsigned int fd, struct file *filp, unsigned int flavor, int arg) 2058 2031 { 2059 2032 struct file_lease *fl; 2060 2033 struct fasync_struct *new; 2061 2034 int error; 2062 2035 2063 - fl = lease_alloc(filp, arg); 2036 + fl = lease_alloc(filp, flavor, arg); 2064 2037 if (IS_ERR(fl)) 2065 2038 return PTR_ERR(fl); 2066 2039 ··· 2091 2064 */ 2092 2065 int fcntl_setlease(unsigned int fd, struct file *filp, int arg) 2093 2066 { 2067 + if (S_ISDIR(file_inode(filp)->i_mode)) 2068 + return -EINVAL; 2069 + 2094 2070 if (arg == F_UNLCK) 2095 2071 return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); 2096 - return do_fcntl_add_lease(fd, filp, arg); 2072 + return do_fcntl_add_lease(fd, filp, FL_LEASE, arg); 2073 + } 2074 + 2075 + /** 2076 + * fcntl_setdeleg - sets a delegation on an open file 2077 + * @fd: open file descriptor 2078 + * @filp: file pointer 2079 + * @deleg: delegation request from userland 2080 + * 2081 + * Call this fcntl to establish a delegation on the file. 2082 + * Note that you also need to call %F_SETSIG to 2083 + * receive a signal when the lease is broken. 2084 + */ 2085 + int fcntl_setdeleg(unsigned int fd, struct file *filp, struct delegation *deleg) 2086 + { 2087 + /* For now, no flags are supported */ 2088 + if (deleg->d_flags != 0 || deleg->__pad != 0) 2089 + return -EINVAL; 2090 + 2091 + if (deleg->d_type == F_UNLCK) 2092 + return vfs_setlease(filp, F_UNLCK, NULL, (void **)&filp); 2093 + return do_fcntl_add_lease(fd, filp, FL_DELEG, deleg->d_type); 2097 2094 } 2098 2095 2099 2096 /**
+120 -42
fs/namei.c
··· 3531 3531 /** 3532 3532 * vfs_create - create new file 3533 3533 * @idmap: idmap of the mount the inode was found from 3534 - * @dir: inode of the parent directory 3535 3534 * @dentry: dentry of the child file 3536 3535 * @mode: mode of the child file 3537 - * @want_excl: whether the file must not yet exist 3536 + * @di: returns parent inode, if the inode is delegated. 3538 3537 * 3539 3538 * Create a new file. 3540 3539 * ··· 3543 3544 * On non-idmapped mounts or if permission checking is to be performed on the 3544 3545 * raw inode simply pass @nop_mnt_idmap. 3545 3546 */ 3546 - int vfs_create(struct mnt_idmap *idmap, struct inode *dir, 3547 - struct dentry *dentry, umode_t mode, bool want_excl) 3547 + int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode, 3548 + struct delegated_inode *di) 3548 3549 { 3550 + struct inode *dir = d_inode(dentry->d_parent); 3549 3551 int error; 3550 3552 3551 3553 error = may_create(idmap, dir, dentry); ··· 3560 3560 error = security_inode_create(dir, dentry, mode); 3561 3561 if (error) 3562 3562 return error; 3563 - error = dir->i_op->create(idmap, dir, dentry, mode, want_excl); 3563 + error = try_break_deleg(dir, di); 3564 + if (error) 3565 + return error; 3566 + error = dir->i_op->create(idmap, dir, dentry, mode, true); 3564 3567 if (!error) 3565 3568 fsnotify_create(dir, dentry); 3566 3569 return error; ··· 3770 3767 */ 3771 3768 static struct dentry *lookup_open(struct nameidata *nd, struct file *file, 3772 3769 const struct open_flags *op, 3773 - bool got_write) 3770 + bool got_write, struct delegated_inode *delegated_inode) 3774 3771 { 3775 3772 struct mnt_idmap *idmap; 3776 3773 struct dentry *dir = nd->path.dentry; ··· 3859 3856 3860 3857 /* Negative dentry, just create the file */ 3861 3858 if (!dentry->d_inode && (open_flag & O_CREAT)) { 3859 + /* but break the directory lease first! */ 3860 + error = try_break_deleg(dir_inode, delegated_inode); 3861 + if (error) 3862 + goto out_dput; 3863 + 3862 3864 file->f_mode |= FMODE_CREATED; 3863 3865 audit_inode_child(dir_inode, dentry, AUDIT_TYPE_CHILD_CREATE); 3864 3866 if (!dir_inode->i_op->create) { ··· 3926 3918 static const char *open_last_lookups(struct nameidata *nd, 3927 3919 struct file *file, const struct open_flags *op) 3928 3920 { 3921 + struct delegated_inode delegated_inode = { }; 3929 3922 struct dentry *dir = nd->path.dentry; 3930 3923 int open_flag = op->open_flag; 3931 3924 bool got_write = false; ··· 3958 3949 return ERR_PTR(-ECHILD); 3959 3950 } 3960 3951 } 3961 - 3952 + retry: 3962 3953 if (open_flag & (O_CREAT | O_TRUNC | O_WRONLY | O_RDWR)) { 3963 3954 got_write = !mnt_want_write(nd->path.mnt); 3964 3955 /* ··· 3971 3962 inode_lock(dir->d_inode); 3972 3963 else 3973 3964 inode_lock_shared(dir->d_inode); 3974 - dentry = lookup_open(nd, file, op, got_write); 3965 + dentry = lookup_open(nd, file, op, got_write, &delegated_inode); 3975 3966 if (!IS_ERR(dentry)) { 3976 3967 if (file->f_mode & FMODE_CREATED) 3977 3968 fsnotify_create(dir->d_inode, dentry); ··· 3986 3977 if (got_write) 3987 3978 mnt_drop_write(nd->path.mnt); 3988 3979 3989 - if (IS_ERR(dentry)) 3980 + if (IS_ERR(dentry)) { 3981 + if (is_delegated(&delegated_inode)) { 3982 + int error = break_deleg_wait(&delegated_inode); 3983 + 3984 + if (!error) 3985 + goto retry; 3986 + return ERR_PTR(error); 3987 + } 3990 3988 return ERR_CAST(dentry); 3989 + } 3991 3990 3992 3991 if (file->f_mode & (FMODE_OPENED | FMODE_CREATED)) { 3993 3992 dput(nd->path.dentry); ··· 4365 4348 } 4366 4349 EXPORT_SYMBOL(start_creating_user_path); 4367 4350 4351 + 4368 4352 /** 4369 4353 * vfs_mknod - create device node or file 4370 - * @idmap: idmap of the mount the inode was found from 4371 - * @dir: inode of the parent directory 4372 - * @dentry: dentry of the child device node 4373 - * @mode: mode of the child device node 4374 - * @dev: device number of device to create 4354 + * @idmap: idmap of the mount the inode was found from 4355 + * @dir: inode of the parent directory 4356 + * @dentry: dentry of the child device node 4357 + * @mode: mode of the child device node 4358 + * @dev: device number of device to create 4359 + * @delegated_inode: returns parent inode, if the inode is delegated. 4375 4360 * 4376 4361 * Create a device node or file. 4377 4362 * ··· 4384 4365 * raw inode simply pass @nop_mnt_idmap. 4385 4366 */ 4386 4367 int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir, 4387 - struct dentry *dentry, umode_t mode, dev_t dev) 4368 + struct dentry *dentry, umode_t mode, dev_t dev, 4369 + struct delegated_inode *delegated_inode) 4388 4370 { 4389 4371 bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV; 4390 4372 int error = may_create(idmap, dir, dentry); ··· 4406 4386 return error; 4407 4387 4408 4388 error = security_inode_mknod(dir, dentry, mode, dev); 4389 + if (error) 4390 + return error; 4391 + 4392 + error = try_break_deleg(dir, delegated_inode); 4409 4393 if (error) 4410 4394 return error; 4411 4395 ··· 4440 4416 static int do_mknodat(int dfd, struct filename *name, umode_t mode, 4441 4417 unsigned int dev) 4442 4418 { 4419 + struct delegated_inode di = { }; 4443 4420 struct mnt_idmap *idmap; 4444 4421 struct dentry *dentry; 4445 4422 struct path path; ··· 4464 4439 idmap = mnt_idmap(path.mnt); 4465 4440 switch (mode & S_IFMT) { 4466 4441 case 0: case S_IFREG: 4467 - error = vfs_create(idmap, path.dentry->d_inode, 4468 - dentry, mode, true); 4442 + error = vfs_create(idmap, dentry, mode, &di); 4469 4443 if (!error) 4470 4444 security_path_post_mknod(idmap, dentry); 4471 4445 break; 4472 4446 case S_IFCHR: case S_IFBLK: 4473 4447 error = vfs_mknod(idmap, path.dentry->d_inode, 4474 - dentry, mode, new_decode_dev(dev)); 4448 + dentry, mode, new_decode_dev(dev), &di); 4475 4449 break; 4476 4450 case S_IFIFO: case S_IFSOCK: 4477 4451 error = vfs_mknod(idmap, path.dentry->d_inode, 4478 - dentry, mode, 0); 4452 + dentry, mode, 0, &di); 4479 4453 break; 4480 4454 } 4481 4455 out2: 4482 4456 end_creating_path(&path, dentry); 4457 + if (is_delegated(&di)) { 4458 + error = break_deleg_wait(&di); 4459 + if (!error) 4460 + goto retry; 4461 + } 4483 4462 if (retry_estale(error, lookup_flags)) { 4484 4463 lookup_flags |= LOOKUP_REVAL; 4485 4464 goto retry; ··· 4506 4477 4507 4478 /** 4508 4479 * vfs_mkdir - create directory returning correct dentry if possible 4509 - * @idmap: idmap of the mount the inode was found from 4510 - * @dir: inode of the parent directory 4511 - * @dentry: dentry of the child directory 4512 - * @mode: mode of the child directory 4480 + * @idmap: idmap of the mount the inode was found from 4481 + * @dir: inode of the parent directory 4482 + * @dentry: dentry of the child directory 4483 + * @mode: mode of the child directory 4484 + * @delegated_inode: returns parent inode, if the inode is delegated. 4513 4485 * 4514 4486 * Create a directory. 4515 4487 * ··· 4527 4497 * In case of an error the dentry is dput() and an ERR_PTR() is returned. 4528 4498 */ 4529 4499 struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir, 4530 - struct dentry *dentry, umode_t mode) 4500 + struct dentry *dentry, umode_t mode, 4501 + struct delegated_inode *delegated_inode) 4531 4502 { 4532 4503 int error; 4533 4504 unsigned max_links = dir->i_sb->s_max_links; ··· 4549 4518 4550 4519 error = -EMLINK; 4551 4520 if (max_links && dir->i_nlink >= max_links) 4521 + goto err; 4522 + 4523 + error = try_break_deleg(dir, delegated_inode); 4524 + if (error) 4552 4525 goto err; 4553 4526 4554 4527 de = dir->i_op->mkdir(idmap, dir, dentry, mode); ··· 4578 4543 struct path path; 4579 4544 int error; 4580 4545 unsigned int lookup_flags = LOOKUP_DIRECTORY; 4546 + struct delegated_inode delegated_inode = { }; 4581 4547 4582 4548 retry: 4583 4549 dentry = filename_create(dfd, name, &path, lookup_flags); ··· 4590 4554 mode_strip_umask(path.dentry->d_inode, mode)); 4591 4555 if (!error) { 4592 4556 dentry = vfs_mkdir(mnt_idmap(path.mnt), path.dentry->d_inode, 4593 - dentry, mode); 4557 + dentry, mode, &delegated_inode); 4594 4558 if (IS_ERR(dentry)) 4595 4559 error = PTR_ERR(dentry); 4596 4560 } 4597 4561 end_creating_path(&path, dentry); 4562 + if (is_delegated(&delegated_inode)) { 4563 + error = break_deleg_wait(&delegated_inode); 4564 + if (!error) 4565 + goto retry; 4566 + } 4598 4567 if (retry_estale(error, lookup_flags)) { 4599 4568 lookup_flags |= LOOKUP_REVAL; 4600 4569 goto retry; ··· 4621 4580 4622 4581 /** 4623 4582 * vfs_rmdir - remove directory 4624 - * @idmap: idmap of the mount the inode was found from 4625 - * @dir: inode of the parent directory 4626 - * @dentry: dentry of the child directory 4583 + * @idmap: idmap of the mount the inode was found from 4584 + * @dir: inode of the parent directory 4585 + * @dentry: dentry of the child directory 4586 + * @delegated_inode: returns parent inode, if it's delegated. 4627 4587 * 4628 4588 * Remove a directory. 4629 4589 * ··· 4635 4593 * raw inode simply pass @nop_mnt_idmap. 4636 4594 */ 4637 4595 int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir, 4638 - struct dentry *dentry) 4596 + struct dentry *dentry, struct delegated_inode *delegated_inode) 4639 4597 { 4640 4598 int error = may_delete(idmap, dir, dentry, 1); 4641 4599 ··· 4654 4612 goto out; 4655 4613 4656 4614 error = security_inode_rmdir(dir, dentry); 4615 + if (error) 4616 + goto out; 4617 + 4618 + error = try_break_deleg(dir, delegated_inode); 4657 4619 if (error) 4658 4620 goto out; 4659 4621 ··· 4687 4641 struct qstr last; 4688 4642 int type; 4689 4643 unsigned int lookup_flags = 0; 4644 + struct delegated_inode delegated_inode = { }; 4690 4645 retry: 4691 4646 error = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); 4692 4647 if (error) ··· 4717 4670 error = security_path_rmdir(&path, dentry); 4718 4671 if (error) 4719 4672 goto exit4; 4720 - error = vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, dentry); 4673 + error = vfs_rmdir(mnt_idmap(path.mnt), path.dentry->d_inode, 4674 + dentry, &delegated_inode); 4721 4675 exit4: 4722 4676 dput(dentry); 4723 4677 exit3: ··· 4726 4678 mnt_drop_write(path.mnt); 4727 4679 exit2: 4728 4680 path_put(&path); 4681 + if (is_delegated(&delegated_inode)) { 4682 + error = break_deleg_wait(&delegated_inode); 4683 + if (!error) 4684 + goto retry; 4685 + } 4729 4686 if (retry_estale(error, lookup_flags)) { 4730 4687 lookup_flags |= LOOKUP_REVAL; 4731 4688 goto retry; ··· 4771 4718 * raw inode simply pass @nop_mnt_idmap. 4772 4719 */ 4773 4720 int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir, 4774 - struct dentry *dentry, struct inode **delegated_inode) 4721 + struct dentry *dentry, struct delegated_inode *delegated_inode) 4775 4722 { 4776 4723 struct inode *target = dentry->d_inode; 4777 4724 int error = may_delete(idmap, dir, dentry, 0); ··· 4790 4737 else { 4791 4738 error = security_inode_unlink(dir, dentry); 4792 4739 if (!error) { 4740 + error = try_break_deleg(dir, delegated_inode); 4741 + if (error) 4742 + goto out; 4793 4743 error = try_break_deleg(target, delegated_inode); 4794 4744 if (error) 4795 4745 goto out; ··· 4832 4776 struct qstr last; 4833 4777 int type; 4834 4778 struct inode *inode = NULL; 4835 - struct inode *delegated_inode = NULL; 4779 + struct delegated_inode delegated_inode = { }; 4836 4780 unsigned int lookup_flags = 0; 4837 4781 retry: 4838 4782 error = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); ··· 4869 4813 if (inode) 4870 4814 iput(inode); /* truncate the inode here */ 4871 4815 inode = NULL; 4872 - if (delegated_inode) { 4816 + if (is_delegated(&delegated_inode)) { 4873 4817 error = break_deleg_wait(&delegated_inode); 4874 4818 if (!error) 4875 4819 goto retry_deleg; ··· 4915 4859 * @dir: inode of the parent directory 4916 4860 * @dentry: dentry of the child symlink file 4917 4861 * @oldname: name of the file to link to 4862 + * @delegated_inode: returns victim inode, if the inode is delegated. 4918 4863 * 4919 4864 * Create a symlink. 4920 4865 * ··· 4926 4869 * raw inode simply pass @nop_mnt_idmap. 4927 4870 */ 4928 4871 int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir, 4929 - struct dentry *dentry, const char *oldname) 4872 + struct dentry *dentry, const char *oldname, 4873 + struct delegated_inode *delegated_inode) 4930 4874 { 4931 4875 int error; 4932 4876 ··· 4939 4881 return -EPERM; 4940 4882 4941 4883 error = security_inode_symlink(dir, dentry, oldname); 4884 + if (error) 4885 + return error; 4886 + 4887 + error = try_break_deleg(dir, delegated_inode); 4942 4888 if (error) 4943 4889 return error; 4944 4890 ··· 4959 4897 struct dentry *dentry; 4960 4898 struct path path; 4961 4899 unsigned int lookup_flags = 0; 4900 + struct delegated_inode delegated_inode = { }; 4962 4901 4963 4902 if (IS_ERR(from)) { 4964 4903 error = PTR_ERR(from); ··· 4974 4911 error = security_path_symlink(&path, dentry, from->name); 4975 4912 if (!error) 4976 4913 error = vfs_symlink(mnt_idmap(path.mnt), path.dentry->d_inode, 4977 - dentry, from->name); 4914 + dentry, from->name, &delegated_inode); 4978 4915 end_creating_path(&path, dentry); 4916 + if (is_delegated(&delegated_inode)) { 4917 + error = break_deleg_wait(&delegated_inode); 4918 + if (!error) 4919 + goto retry; 4920 + } 4979 4921 if (retry_estale(error, lookup_flags)) { 4980 4922 lookup_flags |= LOOKUP_REVAL; 4981 4923 goto retry; ··· 5030 4962 */ 5031 4963 int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap, 5032 4964 struct inode *dir, struct dentry *new_dentry, 5033 - struct inode **delegated_inode) 4965 + struct delegated_inode *delegated_inode) 5034 4966 { 5035 4967 struct inode *inode = old_dentry->d_inode; 5036 4968 unsigned max_links = dir->i_sb->s_max_links; ··· 5074 5006 else if (max_links && inode->i_nlink >= max_links) 5075 5007 error = -EMLINK; 5076 5008 else { 5077 - error = try_break_deleg(inode, delegated_inode); 5009 + error = try_break_deleg(dir, delegated_inode); 5010 + if (!error) 5011 + error = try_break_deleg(inode, delegated_inode); 5078 5012 if (!error) 5079 5013 error = dir->i_op->link(old_dentry, dir, new_dentry); 5080 5014 } ··· 5108 5038 struct mnt_idmap *idmap; 5109 5039 struct dentry *new_dentry; 5110 5040 struct path old_path, new_path; 5111 - struct inode *delegated_inode = NULL; 5041 + struct delegated_inode delegated_inode = { }; 5112 5042 int how = 0; 5113 5043 int error; 5114 5044 ··· 5152 5082 new_dentry, &delegated_inode); 5153 5083 out_dput: 5154 5084 end_creating_path(&new_path, new_dentry); 5155 - if (delegated_inode) { 5085 + if (is_delegated(&delegated_inode)) { 5156 5086 error = break_deleg_wait(&delegated_inode); 5157 5087 if (!error) { 5158 5088 path_put(&old_path); ··· 5238 5168 struct inode *new_dir = d_inode(rd->new_parent); 5239 5169 struct dentry *old_dentry = rd->old_dentry; 5240 5170 struct dentry *new_dentry = rd->new_dentry; 5241 - struct inode **delegated_inode = rd->delegated_inode; 5171 + struct delegated_inode *delegated_inode = rd->delegated_inode; 5242 5172 unsigned int flags = rd->flags; 5243 5173 bool is_dir = d_is_dir(old_dentry); 5244 5174 struct inode *source = old_dentry->d_inode; ··· 5343 5273 old_dir->i_nlink >= max_links) 5344 5274 goto out; 5345 5275 } 5276 + error = try_break_deleg(old_dir, delegated_inode); 5277 + if (error) 5278 + goto out; 5279 + if (new_dir != old_dir) { 5280 + error = try_break_deleg(new_dir, delegated_inode); 5281 + if (error) 5282 + goto out; 5283 + } 5346 5284 if (!is_dir) { 5347 5285 error = try_break_deleg(source, delegated_inode); 5348 5286 if (error) ··· 5409 5331 struct path old_path, new_path; 5410 5332 struct qstr old_last, new_last; 5411 5333 int old_type, new_type; 5412 - struct inode *delegated_inode = NULL; 5334 + struct delegated_inode delegated_inode = { }; 5413 5335 unsigned int lookup_flags = 0, target_flags = 5414 5336 LOOKUP_RENAME_TARGET | LOOKUP_CREATE; 5415 5337 bool should_retry = false; ··· 5517 5439 exit3: 5518 5440 unlock_rename(new_path.dentry, old_path.dentry); 5519 5441 exit_lock_rename: 5520 - if (delegated_inode) { 5442 + if (is_delegated(&delegated_inode)) { 5521 5443 error = break_deleg_wait(&delegated_inode); 5522 5444 if (!error) 5523 5445 goto retry_deleg;
+2
fs/nfs/nfs4file.c
··· 431 431 static int nfs4_setlease(struct file *file, int arg, struct file_lease **lease, 432 432 void **priv) 433 433 { 434 + if (!S_ISREG(file_inode(file)->i_mode)) 435 + return -EINVAL; 434 436 return nfs4_proc_setlease(file, arg, lease, priv); 435 437 } 436 438
+43 -14
fs/nfsd/filecache.c
··· 1086 1086 struct auth_domain *client, 1087 1087 struct svc_fh *fhp, 1088 1088 unsigned int may_flags, struct file *file, 1089 - struct nfsd_file **pnf, bool want_gc) 1089 + umode_t type, bool want_gc, struct nfsd_file **pnf) 1090 1090 { 1091 1091 unsigned char need = may_flags & NFSD_FILE_MAY_MASK; 1092 1092 struct nfsd_file *new, *nf; ··· 1097 1097 int ret; 1098 1098 1099 1099 retry: 1100 - if (rqstp) { 1101 - status = fh_verify(rqstp, fhp, S_IFREG, 1100 + if (rqstp) 1101 + status = fh_verify(rqstp, fhp, type, 1102 1102 may_flags|NFSD_MAY_OWNER_OVERRIDE); 1103 - } else { 1104 - status = fh_verify_local(net, cred, client, fhp, S_IFREG, 1103 + else 1104 + status = fh_verify_local(net, cred, client, fhp, type, 1105 1105 may_flags|NFSD_MAY_OWNER_OVERRIDE); 1106 - } 1106 + 1107 1107 if (status != nfs_ok) 1108 1108 return status; 1109 1109 inode = d_inode(fhp->fh_dentry); ··· 1176 1176 1177 1177 open_file: 1178 1178 trace_nfsd_file_alloc(nf); 1179 - nf->nf_mark = nfsd_file_mark_find_or_create(inode); 1180 - if (nf->nf_mark) { 1179 + 1180 + if (type == S_IFREG) 1181 + nf->nf_mark = nfsd_file_mark_find_or_create(inode); 1182 + 1183 + if (type != S_IFREG || nf->nf_mark) { 1181 1184 if (file) { 1182 1185 get_file(file); 1183 1186 nf->nf_file = file; 1184 1187 status = nfs_ok; 1185 1188 trace_nfsd_file_opened(nf, status); 1186 1189 } else { 1187 - ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file); 1190 + ret = nfsd_open_verified(fhp, type, may_flags, &nf->nf_file); 1188 1191 if (ret == -EOPENSTALE && stale_retry) { 1189 1192 stale_retry = false; 1190 1193 nfsd_file_unhash(nf); ··· 1249 1246 unsigned int may_flags, struct nfsd_file **pnf) 1250 1247 { 1251 1248 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1252 - fhp, may_flags, NULL, pnf, true); 1249 + fhp, may_flags, NULL, S_IFREG, true, pnf); 1253 1250 } 1254 1251 1255 1252 /** ··· 1274 1271 unsigned int may_flags, struct nfsd_file **pnf) 1275 1272 { 1276 1273 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1277 - fhp, may_flags, NULL, pnf, false); 1274 + fhp, may_flags, NULL, S_IFREG, false, pnf); 1278 1275 } 1279 1276 1280 1277 /** ··· 1317 1314 const struct cred *save_cred = get_current_cred(); 1318 1315 __be32 beres; 1319 1316 1320 - beres = nfsd_file_do_acquire(NULL, net, cred, client, 1321 - fhp, may_flags, NULL, pnf, false); 1317 + beres = nfsd_file_do_acquire(NULL, net, cred, client, fhp, may_flags, 1318 + NULL, S_IFREG, false, pnf); 1322 1319 put_cred(revert_creds(save_cred)); 1323 1320 return beres; 1324 1321 } ··· 1347 1344 struct nfsd_file **pnf) 1348 1345 { 1349 1346 return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, 1350 - fhp, may_flags, file, pnf, false); 1347 + fhp, may_flags, file, S_IFREG, false, pnf); 1348 + } 1349 + 1350 + /** 1351 + * nfsd_file_acquire_dir - Get a struct nfsd_file with an open directory 1352 + * @rqstp: the RPC transaction being executed 1353 + * @fhp: the NFS filehandle of the file to be opened 1354 + * @pnf: OUT: new or found "struct nfsd_file" object 1355 + * 1356 + * The nfsd_file_object returned by this API is reference-counted 1357 + * but not garbage-collected. The object is unhashed after the 1358 + * final nfsd_file_put(). This opens directories only, and only 1359 + * in O_RDONLY mode. 1360 + * 1361 + * Return values: 1362 + * %nfs_ok - @pnf points to an nfsd_file with its reference 1363 + * count boosted. 1364 + * 1365 + * On error, an nfsstat value in network byte order is returned. 1366 + */ 1367 + __be32 1368 + nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, 1369 + struct nfsd_file **pnf) 1370 + { 1371 + return nfsd_file_do_acquire(rqstp, SVC_NET(rqstp), NULL, NULL, fhp, 1372 + NFSD_MAY_READ|NFSD_MAY_64BIT_COOKIE, 1373 + NULL, S_IFDIR, false, pnf); 1351 1374 } 1352 1375 1353 1376 /*
+2
fs/nfsd/filecache.h
··· 82 82 __be32 nfsd_file_acquire_local(struct net *net, struct svc_cred *cred, 83 83 struct auth_domain *client, struct svc_fh *fhp, 84 84 unsigned int may_flags, struct nfsd_file **pnf); 85 + __be32 nfsd_file_acquire_dir(struct svc_rqst *rqstp, struct svc_fh *fhp, 86 + struct nfsd_file **pnf); 85 87 int nfsd_file_cache_stats_show(struct seq_file *m, void *v); 86 88 #endif /* _FS_NFSD_FILECACHE_H */
+1 -1
fs/nfsd/nfs3proc.c
··· 344 344 status = fh_fill_pre_attrs(fhp); 345 345 if (status != nfs_ok) 346 346 goto out; 347 - host_err = vfs_create(&nop_mnt_idmap, inode, child, iap->ia_mode, true); 347 + host_err = vfs_create(&nop_mnt_idmap, child, iap->ia_mode, NULL); 348 348 if (host_err < 0) { 349 349 status = nfserrno(host_err); 350 350 goto out;
+21 -1
fs/nfsd/nfs4proc.c
··· 2342 2342 union nfsd4_op_u *u) 2343 2343 { 2344 2344 struct nfsd4_get_dir_delegation *gdd = &u->get_dir_delegation; 2345 + struct nfs4_delegation *dd; 2346 + struct nfsd_file *nf; 2347 + __be32 status; 2348 + 2349 + status = nfsd_file_acquire_dir(rqstp, &cstate->current_fh, &nf); 2350 + if (status != nfs_ok) 2351 + return status; 2345 2352 2346 2353 /* 2347 2354 * RFC 8881, section 18.39.3 says: ··· 2362 2355 * return NFS4_OK with a non-fatal status of GDD4_UNAVAIL in this 2363 2356 * situation. 2364 2357 */ 2365 - gdd->gddrnf_status = GDD4_UNAVAIL; 2358 + dd = nfsd_get_dir_deleg(cstate, gdd, nf); 2359 + nfsd_file_put(nf); 2360 + if (IS_ERR(dd)) { 2361 + int err = PTR_ERR(dd); 2362 + 2363 + if (err != -EAGAIN) 2364 + return nfserrno(err); 2365 + gdd->gddrnf_status = GDD4_UNAVAIL; 2366 + return nfs_ok; 2367 + } 2368 + 2369 + gdd->gddrnf_status = GDD4_OK; 2370 + memcpy(&gdd->gddr_stateid, &dd->dl_stid.sc_stateid, sizeof(gdd->gddr_stateid)); 2371 + nfs4_put_stid(&dd->dl_stid); 2366 2372 return nfs_ok; 2367 2373 } 2368 2374
+3 -3
fs/nfsd/nfs4recover.c
··· 213 213 * as well be forgiving and just succeed silently. 214 214 */ 215 215 goto out_put; 216 - dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, S_IRWXU); 216 + dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, 0700, NULL); 217 217 if (IS_ERR(dentry)) 218 218 status = PTR_ERR(dentry); 219 219 out_put: ··· 337 337 status = -ENOENT; 338 338 if (d_really_is_negative(dentry)) 339 339 goto out; 340 - status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry); 340 + status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry, NULL); 341 341 out: 342 342 dput(dentry); 343 343 out_unlock: ··· 427 427 if (nfs4_has_reclaimed_state(name, nn)) 428 428 goto out_free; 429 429 430 - status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child); 430 + status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child, NULL); 431 431 if (status) 432 432 printk("failed to remove client recovery directory %pd\n", 433 433 child);
+102 -1
fs/nfsd/nfs4state.c
··· 7859 7859 __be32 status; 7860 7860 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 7861 7861 7862 - if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) 7862 + status = fh_verify(rqstp, &cstate->current_fh, 0, 0); 7863 + if (status) 7863 7864 return status; 7864 7865 7865 7866 status = nfsd4_lookup_stateid(cstate, stateid, SC_TYPE_DELEG, SC_STATUS_REVOKED, &s, nn); ··· 9377 9376 out_status: 9378 9377 nfs4_put_stid(&dp->dl_stid); 9379 9378 return status; 9379 + } 9380 + 9381 + /** 9382 + * nfsd_get_dir_deleg - attempt to get a directory delegation 9383 + * @cstate: compound state 9384 + * @gdd: GET_DIR_DELEGATION arg/resp structure 9385 + * @nf: nfsd_file opened on the directory 9386 + * 9387 + * Given a GET_DIR_DELEGATION request @gdd, attempt to acquire a delegation 9388 + * on the directory to which @nf refers. Note that this does not set up any 9389 + * sort of async notifications for the delegation. 9390 + */ 9391 + struct nfs4_delegation * 9392 + nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate, 9393 + struct nfsd4_get_dir_delegation *gdd, 9394 + struct nfsd_file *nf) 9395 + { 9396 + struct nfs4_client *clp = cstate->clp; 9397 + struct nfs4_delegation *dp; 9398 + struct file_lease *fl; 9399 + struct nfs4_file *fp, *rfp; 9400 + int status = 0; 9401 + 9402 + fp = nfsd4_alloc_file(); 9403 + if (!fp) 9404 + return ERR_PTR(-ENOMEM); 9405 + 9406 + nfsd4_file_init(&cstate->current_fh, fp); 9407 + 9408 + rfp = nfsd4_file_hash_insert(fp, &cstate->current_fh); 9409 + if (unlikely(!rfp)) { 9410 + put_nfs4_file(fp); 9411 + return ERR_PTR(-ENOMEM); 9412 + } 9413 + 9414 + if (rfp != fp) { 9415 + put_nfs4_file(fp); 9416 + fp = rfp; 9417 + } 9418 + 9419 + /* if this client already has one, return that it's unavailable */ 9420 + spin_lock(&state_lock); 9421 + spin_lock(&fp->fi_lock); 9422 + /* existing delegation? */ 9423 + if (nfs4_delegation_exists(clp, fp)) { 9424 + status = -EAGAIN; 9425 + } else if (!fp->fi_deleg_file) { 9426 + fp->fi_deleg_file = nfsd_file_get(nf); 9427 + fp->fi_delegees = 1; 9428 + } else { 9429 + ++fp->fi_delegees; 9430 + } 9431 + spin_unlock(&fp->fi_lock); 9432 + spin_unlock(&state_lock); 9433 + 9434 + if (status) { 9435 + put_nfs4_file(fp); 9436 + return ERR_PTR(status); 9437 + } 9438 + 9439 + /* Try to set up the lease */ 9440 + status = -ENOMEM; 9441 + dp = alloc_init_deleg(clp, fp, NULL, NFS4_OPEN_DELEGATE_READ); 9442 + if (!dp) 9443 + goto out_delegees; 9444 + 9445 + fl = nfs4_alloc_init_lease(dp); 9446 + if (!fl) 9447 + goto out_put_stid; 9448 + 9449 + status = kernel_setlease(nf->nf_file, 9450 + fl->c.flc_type, &fl, NULL); 9451 + if (fl) 9452 + locks_free_lease(fl); 9453 + if (status) 9454 + goto out_put_stid; 9455 + 9456 + /* 9457 + * Now, try to hash it. This can fail if we race another nfsd task 9458 + * trying to set a delegation on the same file. If that happens, 9459 + * then just say UNAVAIL. 9460 + */ 9461 + spin_lock(&state_lock); 9462 + spin_lock(&clp->cl_lock); 9463 + spin_lock(&fp->fi_lock); 9464 + status = hash_delegation_locked(dp, fp); 9465 + spin_unlock(&fp->fi_lock); 9466 + spin_unlock(&clp->cl_lock); 9467 + spin_unlock(&state_lock); 9468 + 9469 + if (!status) 9470 + return dp; 9471 + 9472 + /* Something failed. Drop the lease and clean up the stid */ 9473 + kernel_setlease(fp->fi_deleg_file->nf_file, F_UNLCK, NULL, (void **)&dp); 9474 + out_put_stid: 9475 + nfs4_put_stid(&dp->dl_stid); 9476 + out_delegees: 9477 + put_deleg_file(fp); 9478 + return ERR_PTR(status); 9380 9479 }
+5
fs/nfsd/state.h
··· 867 867 868 868 extern __be32 nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, 869 869 struct dentry *dentry, struct nfs4_delegation **pdp); 870 + 871 + struct nfsd4_get_dir_delegation; 872 + struct nfs4_delegation *nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate, 873 + struct nfsd4_get_dir_delegation *gdd, 874 + struct nfsd_file *nf); 870 875 #endif /* NFSD4_STATE_H */
+8 -8
fs/nfsd/vfs.c
··· 959 959 /** 960 960 * nfsd_open_verified - Open a regular file for the filecache 961 961 * @fhp: NFS filehandle of the file to open 962 + * @type: S_IFMT inode type allowed (0 means any type is allowed) 962 963 * @may_flags: internal permission flags 963 964 * @filp: OUT: open "struct file *" 964 965 * 965 966 * Returns zero on success, or a negative errno value. 966 967 */ 967 968 int 968 - nfsd_open_verified(struct svc_fh *fhp, int may_flags, struct file **filp) 969 + nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, struct file **filp) 969 970 { 970 - return __nfsd_open(fhp, S_IFREG, may_flags, filp); 971 + return __nfsd_open(fhp, type, may_flags, filp); 971 972 } 972 973 973 974 /* ··· 1553 1552 err = 0; 1554 1553 switch (type) { 1555 1554 case S_IFREG: 1556 - host_err = vfs_create(&nop_mnt_idmap, dirp, dchild, 1557 - iap->ia_mode, true); 1555 + host_err = vfs_create(&nop_mnt_idmap, dchild, iap->ia_mode, NULL); 1558 1556 if (!host_err) 1559 1557 nfsd_check_ignore_resizing(iap); 1560 1558 break; 1561 1559 case S_IFDIR: 1562 - dchild = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode); 1560 + dchild = vfs_mkdir(&nop_mnt_idmap, dirp, dchild, iap->ia_mode, NULL); 1563 1561 if (IS_ERR(dchild)) { 1564 1562 host_err = PTR_ERR(dchild); 1565 1563 } else if (d_is_negative(dchild)) { ··· 1574 1574 case S_IFIFO: 1575 1575 case S_IFSOCK: 1576 1576 host_err = vfs_mknod(&nop_mnt_idmap, dirp, dchild, 1577 - iap->ia_mode, rdev); 1577 + iap->ia_mode, rdev, NULL); 1578 1578 break; 1579 1579 default: 1580 1580 printk(KERN_WARNING "nfsd: bad file type %o in nfsd_create\n", ··· 1743 1743 err = fh_fill_pre_attrs(fhp); 1744 1744 if (err != nfs_ok) 1745 1745 goto out_unlock; 1746 - host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path); 1746 + host_err = vfs_symlink(&nop_mnt_idmap, d_inode(dentry), dnew, path, NULL); 1747 1747 err = nfserrno(host_err); 1748 1748 cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp); 1749 1749 if (!err) ··· 2108 2108 break; 2109 2109 } 2110 2110 } else { 2111 - host_err = vfs_rmdir(&nop_mnt_idmap, dirp, rdentry); 2111 + host_err = vfs_rmdir(&nop_mnt_idmap, dirp, rdentry, NULL); 2112 2112 } 2113 2113 fh_fill_post_attrs(fhp); 2114 2114
+1 -1
fs/nfsd/vfs.h
··· 114 114 int nfsd_open_break_lease(struct inode *, int); 115 115 __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, 116 116 int, struct file **); 117 - int nfsd_open_verified(struct svc_fh *fhp, int may_flags, 117 + int nfsd_open_verified(struct svc_fh *fhp, umode_t type, int may_flags, 118 118 struct file **filp); 119 119 __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 120 120 struct file *file, loff_t offset,
+5 -7
fs/open.c
··· 628 628 int chmod_common(const struct path *path, umode_t mode) 629 629 { 630 630 struct inode *inode = path->dentry->d_inode; 631 - struct inode *delegated_inode = NULL; 631 + struct delegated_inode delegated_inode = { }; 632 632 struct iattr newattrs; 633 633 int error; 634 634 ··· 648 648 &newattrs, &delegated_inode); 649 649 out_unlock: 650 650 inode_unlock(inode); 651 - if (delegated_inode) { 651 + if (is_delegated(&delegated_inode)) { 652 652 error = break_deleg_wait(&delegated_inode); 653 653 if (!error) 654 654 goto retry_deleg; ··· 753 753 struct mnt_idmap *idmap; 754 754 struct user_namespace *fs_userns; 755 755 struct inode *inode = path->dentry->d_inode; 756 - struct inode *delegated_inode = NULL; 756 + struct delegated_inode delegated_inode = { }; 757 757 int error; 758 758 struct iattr newattrs; 759 759 kuid_t uid; ··· 788 788 error = notify_change(idmap, path->dentry, &newattrs, 789 789 &delegated_inode); 790 790 inode_unlock(inode); 791 - if (delegated_inode) { 791 + if (is_delegated(&delegated_inode)) { 792 792 error = break_deleg_wait(&delegated_inode); 793 793 if (!error) 794 794 goto retry_deleg; ··· 1168 1168 if (IS_ERR(f)) 1169 1169 return f; 1170 1170 1171 - error = vfs_create(mnt_idmap(path->mnt), 1172 - d_inode(path->dentry->d_parent), 1173 - path->dentry, mode, true); 1171 + error = vfs_create(mnt_idmap(path->mnt), path->dentry, mode, NULL); 1174 1172 if (!error) 1175 1173 error = vfs_open(path, f); 1176 1174
+5 -5
fs/overlayfs/overlayfs.h
··· 206 206 static inline int ovl_do_rmdir(struct ovl_fs *ofs, 207 207 struct inode *dir, struct dentry *dentry) 208 208 { 209 - int err = vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry); 209 + int err = vfs_rmdir(ovl_upper_mnt_idmap(ofs), dir, dentry, NULL); 210 210 211 211 pr_debug("rmdir(%pd2) = %i\n", dentry, err); 212 212 return err; ··· 235 235 struct inode *dir, struct dentry *dentry, 236 236 umode_t mode) 237 237 { 238 - int err = vfs_create(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, true); 238 + int err = vfs_create(ovl_upper_mnt_idmap(ofs), dentry, mode, NULL); 239 239 240 240 pr_debug("create(%pd2, 0%o) = %i\n", dentry, mode, err); 241 241 return err; ··· 248 248 { 249 249 struct dentry *ret; 250 250 251 - ret = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode); 251 + ret = vfs_mkdir(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, NULL); 252 252 pr_debug("mkdir(%pd2, 0%o) = %i\n", dentry, mode, PTR_ERR_OR_ZERO(ret)); 253 253 return ret; 254 254 } ··· 257 257 struct inode *dir, struct dentry *dentry, 258 258 umode_t mode, dev_t dev) 259 259 { 260 - int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev); 260 + int err = vfs_mknod(ovl_upper_mnt_idmap(ofs), dir, dentry, mode, dev, NULL); 261 261 262 262 pr_debug("mknod(%pd2, 0%o, 0%o) = %i\n", dentry, mode, dev, err); 263 263 return err; ··· 267 267 struct inode *dir, struct dentry *dentry, 268 268 const char *oldname) 269 269 { 270 - int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname); 270 + int err = vfs_symlink(ovl_upper_mnt_idmap(ofs), dir, dentry, oldname, NULL); 271 271 272 272 pr_debug("symlink(\"%s\", %pd2) = %i\n", oldname, dentry, err); 273 273 return err;
+4 -4
fs/posix_acl.c
··· 1091 1091 int acl_type; 1092 1092 int error; 1093 1093 struct inode *inode = d_inode(dentry); 1094 - struct inode *delegated_inode = NULL; 1094 + struct delegated_inode delegated_inode = { }; 1095 1095 1096 1096 acl_type = posix_acl_type(acl_name); 1097 1097 if (acl_type < 0) ··· 1141 1141 out_inode_unlock: 1142 1142 inode_unlock(inode); 1143 1143 1144 - if (delegated_inode) { 1144 + if (is_delegated(&delegated_inode)) { 1145 1145 error = break_deleg_wait(&delegated_inode); 1146 1146 if (!error) 1147 1147 goto retry_deleg; ··· 1212 1212 int acl_type; 1213 1213 int error; 1214 1214 struct inode *inode = d_inode(dentry); 1215 - struct inode *delegated_inode = NULL; 1215 + struct delegated_inode delegated_inode = { }; 1216 1216 1217 1217 acl_type = posix_acl_type(acl_name); 1218 1218 if (acl_type < 0) ··· 1249 1249 out_inode_unlock: 1250 1250 inode_unlock(inode); 1251 1251 1252 - if (delegated_inode) { 1252 + if (is_delegated(&delegated_inode)) { 1253 1253 error = break_deleg_wait(&delegated_inode); 1254 1254 if (!error) 1255 1255 goto retry_deleg;
+3
fs/smb/client/cifsfs.c
··· 1149 1149 struct inode *inode = file_inode(file); 1150 1150 struct cifsFileInfo *cfile = file->private_data; 1151 1151 1152 + if (!S_ISREG(inode->i_mode)) 1153 + return -EINVAL; 1154 + 1152 1155 /* Check if file is oplocked if this is request for new lease */ 1153 1156 if (arg == F_UNLCK || 1154 1157 ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) ||
+4 -5
fs/smb/server/vfs.c
··· 188 188 } 189 189 190 190 mode |= S_IFREG; 191 - err = vfs_create(mnt_idmap(path.mnt), d_inode(path.dentry), 192 - dentry, mode, true); 191 + err = vfs_create(mnt_idmap(path.mnt), dentry, mode, NULL); 193 192 if (!err) { 194 193 ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), 195 194 d_inode(dentry)); ··· 229 230 idmap = mnt_idmap(path.mnt); 230 231 mode |= S_IFDIR; 231 232 d = dentry; 232 - dentry = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode); 233 + dentry = vfs_mkdir(idmap, d_inode(path.dentry), dentry, mode, NULL); 233 234 if (IS_ERR(dentry)) 234 235 err = PTR_ERR(dentry); 235 236 else if (d_is_negative(dentry)) ··· 608 609 609 610 idmap = mnt_idmap(path->mnt); 610 611 if (S_ISDIR(d_inode(path->dentry)->i_mode)) { 611 - err = vfs_rmdir(idmap, d_inode(parent), path->dentry); 612 + err = vfs_rmdir(idmap, d_inode(parent), path->dentry, NULL); 612 613 if (err && err != -ENOTEMPTY) 613 614 ksmbd_debug(VFS, "rmdir failed, err %d\n", err); 614 615 } else { ··· 1089 1090 dget(dentry); 1090 1091 1091 1092 if (S_ISDIR(d_inode(dentry)->i_mode)) 1092 - err = vfs_rmdir(idmap, d_inode(dir), dentry); 1093 + err = vfs_rmdir(idmap, d_inode(dir), dentry, NULL); 1093 1094 else 1094 1095 err = vfs_unlink(idmap, d_inode(dir), dentry, NULL); 1095 1096
+2 -2
fs/utimes.c
··· 22 22 int error; 23 23 struct iattr newattrs; 24 24 struct inode *inode = path->dentry->d_inode; 25 - struct inode *delegated_inode = NULL; 25 + struct delegated_inode delegated_inode = { }; 26 26 27 27 if (times) { 28 28 if (!nsec_valid(times[0].tv_nsec) || ··· 66 66 error = notify_change(mnt_idmap(path->mnt), path->dentry, &newattrs, 67 67 &delegated_inode); 68 68 inode_unlock(inode); 69 - if (delegated_inode) { 69 + if (is_delegated(&delegated_inode)) { 70 70 error = break_deleg_wait(&delegated_inode); 71 71 if (!error) 72 72 goto retry_deleg;
+6 -6
fs/xattr.c
··· 274 274 int 275 275 __vfs_setxattr_locked(struct mnt_idmap *idmap, struct dentry *dentry, 276 276 const char *name, const void *value, size_t size, 277 - int flags, struct inode **delegated_inode) 277 + int flags, struct delegated_inode *delegated_inode) 278 278 { 279 279 struct inode *inode = dentry->d_inode; 280 280 int error; ··· 305 305 const char *name, const void *value, size_t size, int flags) 306 306 { 307 307 struct inode *inode = dentry->d_inode; 308 - struct inode *delegated_inode = NULL; 308 + struct delegated_inode delegated_inode = { }; 309 309 const void *orig_value = value; 310 310 int error; 311 311 ··· 322 322 flags, &delegated_inode); 323 323 inode_unlock(inode); 324 324 325 - if (delegated_inode) { 325 + if (is_delegated(&delegated_inode)) { 326 326 error = break_deleg_wait(&delegated_inode); 327 327 if (!error) 328 328 goto retry_deleg; ··· 533 533 int 534 534 __vfs_removexattr_locked(struct mnt_idmap *idmap, 535 535 struct dentry *dentry, const char *name, 536 - struct inode **delegated_inode) 536 + struct delegated_inode *delegated_inode) 537 537 { 538 538 struct inode *inode = dentry->d_inode; 539 539 int error; ··· 567 567 const char *name) 568 568 { 569 569 struct inode *inode = dentry->d_inode; 570 - struct inode *delegated_inode = NULL; 570 + struct delegated_inode delegated_inode = { }; 571 571 int error; 572 572 573 573 retry_deleg: ··· 576 576 name, &delegated_inode); 577 577 inode_unlock(inode); 578 578 579 - if (delegated_inode) { 579 + if (is_delegated(&delegated_inode)) { 580 580 error = break_deleg_wait(&delegated_inode); 581 581 if (!error) 582 582 goto retry_deleg;
+1 -1
fs/xfs/scrub/orphanage.c
··· 167 167 */ 168 168 if (d_really_is_negative(orphanage_dentry)) { 169 169 orphanage_dentry = vfs_mkdir(&nop_mnt_idmap, root_inode, 170 - orphanage_dentry, 0750); 170 + orphanage_dentry, 0750, NULL); 171 171 error = PTR_ERR(orphanage_dentry); 172 172 if (IS_ERR(orphanage_dentry)) 173 173 goto out_unlock_root;
+76 -22
include/linux/filelock.h
··· 159 159 160 160 int fcntl_setlease(unsigned int fd, struct file *filp, int arg); 161 161 int fcntl_getlease(struct file *filp); 162 + int fcntl_setdeleg(unsigned int fd, struct file *filp, struct delegation *deleg); 163 + int fcntl_getdeleg(struct file *filp, struct delegation *deleg); 162 164 163 165 static inline bool lock_is_unlock(struct file_lock *fl) 164 166 { ··· 214 212 void locks_init_lease(struct file_lease *); 215 213 void locks_free_lease(struct file_lease *fl); 216 214 struct file_lease *locks_alloc_lease(void); 217 - int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); 215 + 216 + #define LEASE_BREAK_LEASE BIT(0) // break leases and delegations 217 + #define LEASE_BREAK_DELEG BIT(1) // break delegations only 218 + #define LEASE_BREAK_LAYOUT BIT(2) // break layouts only 219 + #define LEASE_BREAK_NONBLOCK BIT(3) // non-blocking break 220 + #define LEASE_BREAK_OPEN_RDONLY BIT(4) // readonly open event 221 + 222 + int __break_lease(struct inode *inode, unsigned int flags); 218 223 void lease_get_mtime(struct inode *, struct timespec64 *time); 219 224 int generic_setlease(struct file *, int, struct file_lease **, void **priv); 220 225 int kernel_setlease(struct file *, int, struct file_lease **, void **); ··· 278 269 static inline int fcntl_getlease(struct file *filp) 279 270 { 280 271 return F_UNLCK; 272 + } 273 + 274 + static inline int fcntl_setdeleg(unsigned int fd, struct file *filp, struct delegation *deleg) 275 + { 276 + return -EINVAL; 277 + } 278 + 279 + static inline int fcntl_getdeleg(struct file *filp, struct delegation *deleg) 280 + { 281 + return -EINVAL; 281 282 } 282 283 283 284 static inline bool lock_is_unlock(struct file_lock *fl) ··· 386 367 return -ENOLCK; 387 368 } 388 369 389 - static inline int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) 370 + static inline int __break_lease(struct inode *inode, unsigned int flags) 390 371 { 391 372 return 0; 392 373 } ··· 447 428 } 448 429 449 430 #ifdef CONFIG_FILE_LOCKING 431 + static inline unsigned int openmode_to_lease_flags(unsigned int mode) 432 + { 433 + unsigned int flags = 0; 434 + 435 + if ((mode & O_ACCMODE) == O_RDONLY) 436 + flags |= LEASE_BREAK_OPEN_RDONLY; 437 + if (mode & O_NONBLOCK) 438 + flags |= LEASE_BREAK_NONBLOCK; 439 + return flags; 440 + } 441 + 450 442 static inline int break_lease(struct inode *inode, unsigned int mode) 451 443 { 452 444 struct file_lock_context *flctx; ··· 473 443 return 0; 474 444 smp_mb(); 475 445 if (!list_empty_careful(&flctx->flc_lease)) 476 - return __break_lease(inode, mode, FL_LEASE); 446 + return __break_lease(inode, LEASE_BREAK_LEASE | openmode_to_lease_flags(mode)); 477 447 return 0; 478 448 } 479 449 480 - static inline int break_deleg(struct inode *inode, unsigned int mode) 450 + static inline int break_deleg(struct inode *inode, unsigned int flags) 481 451 { 482 452 struct file_lock_context *flctx; 483 453 ··· 491 461 if (!flctx) 492 462 return 0; 493 463 smp_mb(); 494 - if (!list_empty_careful(&flctx->flc_lease)) 495 - return __break_lease(inode, mode, FL_DELEG); 464 + if (!list_empty_careful(&flctx->flc_lease)) { 465 + flags |= LEASE_BREAK_DELEG; 466 + return __break_lease(inode, flags); 467 + } 496 468 return 0; 497 469 } 498 470 499 - static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) 471 + struct delegated_inode { 472 + struct inode *di_inode; 473 + }; 474 + 475 + static inline bool is_delegated(struct delegated_inode *di) 476 + { 477 + return di->di_inode; 478 + } 479 + 480 + static inline int try_break_deleg(struct inode *inode, 481 + struct delegated_inode *di) 500 482 { 501 483 int ret; 502 484 503 - ret = break_deleg(inode, O_WRONLY|O_NONBLOCK); 504 - if (ret == -EWOULDBLOCK && delegated_inode) { 505 - *delegated_inode = inode; 485 + ret = break_deleg(inode, LEASE_BREAK_NONBLOCK); 486 + if (ret == -EWOULDBLOCK && di) { 487 + di->di_inode = inode; 506 488 ihold(inode); 507 489 } 508 490 return ret; 509 491 } 510 492 511 - static inline int break_deleg_wait(struct inode **delegated_inode) 493 + static inline int break_deleg_wait(struct delegated_inode *di) 512 494 { 513 495 int ret; 514 496 515 - ret = break_deleg(*delegated_inode, O_WRONLY); 516 - iput(*delegated_inode); 517 - *delegated_inode = NULL; 497 + ret = break_deleg(di->di_inode, 0); 498 + iput(di->di_inode); 499 + di->di_inode = NULL; 518 500 return ret; 519 501 } 520 502 521 503 static inline int break_layout(struct inode *inode, bool wait) 522 504 { 523 505 smp_mb(); 524 - if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) 525 - return __break_lease(inode, 526 - wait ? O_WRONLY : O_WRONLY | O_NONBLOCK, 527 - FL_LAYOUT); 506 + if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease)) { 507 + unsigned int flags = LEASE_BREAK_LAYOUT; 508 + 509 + if (!wait) 510 + flags |= LEASE_BREAK_NONBLOCK; 511 + 512 + return __break_lease(inode, flags); 513 + } 528 514 return 0; 529 515 } 530 516 531 517 #else /* !CONFIG_FILE_LOCKING */ 532 - static inline int break_lease(struct inode *inode, unsigned int mode) 518 + struct delegated_inode { }; 519 + 520 + static inline bool is_delegated(struct delegated_inode *di) 521 + { 522 + return false; 523 + } 524 + 525 + static inline int break_lease(struct inode *inode, bool wait) 533 526 { 534 527 return 0; 535 528 } 536 529 537 - static inline int break_deleg(struct inode *inode, unsigned int mode) 530 + static inline int break_deleg(struct inode *inode, unsigned int flags) 538 531 { 539 532 return 0; 540 533 } 541 534 542 - static inline int try_break_deleg(struct inode *inode, struct inode **delegated_inode) 535 + static inline int try_break_deleg(struct inode *inode, 536 + struct delegated_inode *delegated_inode) 543 537 { 544 538 return 0; 545 539 } 546 540 547 - static inline int break_deleg_wait(struct inode **delegated_inode) 541 + static inline int break_deleg_wait(struct delegated_inode *delegated_inode) 548 542 { 549 543 BUG(); 550 544 return 0;
+13 -11
include/linux/fs.h
··· 73 73 struct fs_parameter_spec; 74 74 struct file_kattr; 75 75 struct iomap_ops; 76 + struct delegated_inode; 76 77 77 78 extern void __init inode_init(void); 78 79 extern void __init inode_init_early(void); ··· 1757 1756 /* 1758 1757 * VFS helper functions.. 1759 1758 */ 1760 - int vfs_create(struct mnt_idmap *, struct inode *, 1761 - struct dentry *, umode_t, bool); 1759 + int vfs_create(struct mnt_idmap *, struct dentry *, umode_t, 1760 + struct delegated_inode *); 1762 1761 struct dentry *vfs_mkdir(struct mnt_idmap *, struct inode *, 1763 - struct dentry *, umode_t); 1762 + struct dentry *, umode_t, struct delegated_inode *); 1764 1763 int vfs_mknod(struct mnt_idmap *, struct inode *, struct dentry *, 1765 - umode_t, dev_t); 1764 + umode_t, dev_t, struct delegated_inode *); 1766 1765 int vfs_symlink(struct mnt_idmap *, struct inode *, 1767 - struct dentry *, const char *); 1766 + struct dentry *, const char *, struct delegated_inode *); 1768 1767 int vfs_link(struct dentry *, struct mnt_idmap *, struct inode *, 1769 - struct dentry *, struct inode **); 1770 - int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *); 1768 + struct dentry *, struct delegated_inode *); 1769 + int vfs_rmdir(struct mnt_idmap *, struct inode *, struct dentry *, 1770 + struct delegated_inode *); 1771 1771 int vfs_unlink(struct mnt_idmap *, struct inode *, struct dentry *, 1772 - struct inode **); 1772 + struct delegated_inode *); 1773 1773 1774 1774 /** 1775 1775 * struct renamedata - contains all information required for renaming ··· 1788 1786 struct dentry *old_dentry; 1789 1787 struct dentry *new_parent; 1790 1788 struct dentry *new_dentry; 1791 - struct inode **delegated_inode; 1789 + struct delegated_inode *delegated_inode; 1792 1790 unsigned int flags; 1793 1791 } __randomize_layout; 1794 1792 ··· 1798 1796 struct inode *dir, struct dentry *dentry) 1799 1797 { 1800 1798 return vfs_mknod(idmap, dir, dentry, S_IFCHR | WHITEOUT_MODE, 1801 - WHITEOUT_DEV); 1799 + WHITEOUT_DEV, NULL); 1802 1800 } 1803 1801 1804 1802 struct file *kernel_tmpfile_open(struct mnt_idmap *idmap, ··· 2642 2640 #endif 2643 2641 2644 2642 int notify_change(struct mnt_idmap *, struct dentry *, 2645 - struct iattr *, struct inode **); 2643 + struct iattr *, struct delegated_inode *); 2646 2644 int inode_permission(struct mnt_idmap *, struct inode *, int); 2647 2645 int generic_permission(struct mnt_idmap *, struct inode *, int); 2648 2646 static inline int file_permission(struct file *file, int mask)
+2 -2
include/linux/xattr.h
··· 85 85 const char *, const void *, size_t, int); 86 86 int __vfs_setxattr_locked(struct mnt_idmap *, struct dentry *, 87 87 const char *, const void *, size_t, int, 88 - struct inode **); 88 + struct delegated_inode *); 89 89 int vfs_setxattr(struct mnt_idmap *, struct dentry *, const char *, 90 90 const void *, size_t, int); 91 91 int __vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); 92 92 int __vfs_removexattr_locked(struct mnt_idmap *, struct dentry *, 93 - const char *, struct inode **); 93 + const char *, struct delegated_inode *); 94 94 int vfs_removexattr(struct mnt_idmap *, struct dentry *, const char *); 95 95 96 96 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
+16
include/uapi/linux/fcntl.h
··· 4 4 5 5 #include <asm/fcntl.h> 6 6 #include <linux/openat2.h> 7 + #ifdef __KERNEL__ 8 + #include <linux/types.h> 9 + #else 10 + #include <stdint.h> 11 + #endif 7 12 8 13 #define F_SETLEASE (F_LINUX_SPECIFIC_BASE + 0) 9 14 #define F_GETLEASE (F_LINUX_SPECIFIC_BASE + 1) ··· 83 78 * v4.13-rc1~212^2~51. 84 79 */ 85 80 #define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET 81 + 82 + /* Set/Get delegations */ 83 + #define F_GETDELEG (F_LINUX_SPECIFIC_BASE + 15) 84 + #define F_SETDELEG (F_LINUX_SPECIFIC_BASE + 16) 85 + 86 + /* Argument structure for F_GETDELEG and F_SETDELEG */ 87 + struct delegation { 88 + uint32_t d_flags; /* Must be 0 */ 89 + uint16_t d_type; /* F_RDLCK, F_WRLCK, F_UNLCK */ 90 + uint16_t __pad; /* Must be 0 */ 91 + }; 86 92 87 93 /* 88 94 * Types of directory notifications that may be requested.
+1 -1
net/unix/af_unix.c
··· 1390 1390 idmap = mnt_idmap(parent.mnt); 1391 1391 err = security_path_mknod(&parent, dentry, mode, 0); 1392 1392 if (!err) 1393 - err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0); 1393 + err = vfs_mknod(idmap, d_inode(parent.dentry), dentry, mode, 0, NULL); 1394 1394 if (err) 1395 1395 goto out_path; 1396 1396 err = mutex_lock_interruptible(&u->bindlock);