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

Merge tag 'vfs-6.18-rc1.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull afs updates from Christian Brauner:
"This contains the change to enable afs to support RENAME_NOREPLACE and
RENAME_EXCHANGE if the server supports it"

* tag 'vfs-6.18-rc1.afs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
afs: Add support for RENAME_NOREPLACE and RENAME_EXCHANGE

+480 -64
+176 -47
fs/afs/dir.c
··· 1823 1823 1824 1824 static void afs_rename_success(struct afs_operation *op) 1825 1825 { 1826 - struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry)); 1826 + struct afs_vnode *vnode = op->more_files[0].vnode; 1827 + struct afs_vnode *new_vnode = op->more_files[1].vnode; 1827 1828 1828 1829 _enter("op=%08x", op->debug_id); 1829 1830 ··· 1835 1834 op->ctime = op->file[1].scb.status.mtime_client; 1836 1835 afs_vnode_commit_status(op, &op->file[1]); 1837 1836 } 1837 + if (op->more_files[0].scb.have_status) 1838 + afs_vnode_commit_status(op, &op->more_files[0]); 1839 + if (op->more_files[1].scb.have_status) 1840 + afs_vnode_commit_status(op, &op->more_files[1]); 1838 1841 1839 1842 /* If we're moving a subdir between dirs, we need to update 1840 1843 * its DV counter too as the ".." will be altered. 1841 1844 */ 1842 - if (S_ISDIR(vnode->netfs.inode.i_mode) && 1843 - op->file[0].vnode != op->file[1].vnode) { 1844 - u64 new_dv; 1845 + if (op->file[0].vnode != op->file[1].vnode) { 1846 + if (S_ISDIR(vnode->netfs.inode.i_mode)) { 1847 + u64 new_dv; 1845 1848 1846 - write_seqlock(&vnode->cb_lock); 1849 + write_seqlock(&vnode->cb_lock); 1847 1850 1848 - new_dv = vnode->status.data_version + 1; 1849 - trace_afs_set_dv(vnode, new_dv); 1850 - vnode->status.data_version = new_dv; 1851 - inode_set_iversion_raw(&vnode->netfs.inode, new_dv); 1851 + new_dv = vnode->status.data_version + 1; 1852 + trace_afs_set_dv(vnode, new_dv); 1853 + vnode->status.data_version = new_dv; 1854 + inode_set_iversion_raw(&vnode->netfs.inode, new_dv); 1852 1855 1853 - write_sequnlock(&vnode->cb_lock); 1856 + write_sequnlock(&vnode->cb_lock); 1857 + } 1858 + 1859 + if ((op->rename.rename_flags & RENAME_EXCHANGE) && 1860 + S_ISDIR(new_vnode->netfs.inode.i_mode)) { 1861 + u64 new_dv; 1862 + 1863 + write_seqlock(&new_vnode->cb_lock); 1864 + 1865 + new_dv = new_vnode->status.data_version + 1; 1866 + new_vnode->status.data_version = new_dv; 1867 + inode_set_iversion_raw(&new_vnode->netfs.inode, new_dv); 1868 + 1869 + write_sequnlock(&new_vnode->cb_lock); 1870 + } 1854 1871 } 1855 1872 } 1856 1873 ··· 1919 1900 if (S_ISDIR(vnode->netfs.inode.i_mode) && 1920 1901 new_dvnode != orig_dvnode && 1921 1902 test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) 1922 - afs_edit_dir_update_dotdot(vnode, new_dvnode, 1923 - afs_edit_dir_for_rename_sub); 1903 + afs_edit_dir_update(vnode, &dotdot_name, new_dvnode, 1904 + afs_edit_dir_for_rename_sub); 1924 1905 1925 1906 new_inode = d_inode(new_dentry); 1926 1907 if (new_inode) { ··· 1934 1915 1935 1916 /* Now we can update d_fsdata on the dentries to reflect their 1936 1917 * new parent's data_version. 1937 - * 1938 - * Note that if we ever implement RENAME_EXCHANGE, we'll have 1939 - * to update both dentries with opposing dir versions. 1940 1918 */ 1941 1919 afs_update_dentry_version(op, new_dvp, op->dentry); 1942 1920 afs_update_dentry_version(op, new_dvp, op->dentry_2); ··· 1944 1928 fscache_end_operation(&orig_cres); 1945 1929 if (new_dvnode != orig_dvnode) 1946 1930 fscache_end_operation(&new_cres); 1931 + } 1932 + 1933 + static void afs_rename_exchange_edit_dir(struct afs_operation *op) 1934 + { 1935 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1936 + struct afs_vnode_param *new_dvp = &op->file[1]; 1937 + struct afs_vnode *orig_dvnode = orig_dvp->vnode; 1938 + struct afs_vnode *new_dvnode = new_dvp->vnode; 1939 + struct afs_vnode *old_vnode = op->more_files[0].vnode; 1940 + struct afs_vnode *new_vnode = op->more_files[1].vnode; 1941 + struct dentry *old_dentry = op->dentry; 1942 + struct dentry *new_dentry = op->dentry_2; 1943 + 1944 + _enter("op=%08x", op->debug_id); 1945 + 1946 + if (new_dvnode == orig_dvnode) { 1947 + down_write(&orig_dvnode->validate_lock); 1948 + if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) && 1949 + orig_dvnode->status.data_version == orig_dvp->dv_before + orig_dvp->dv_delta) { 1950 + afs_edit_dir_update(orig_dvnode, &old_dentry->d_name, 1951 + new_vnode, afs_edit_dir_for_rename_0); 1952 + afs_edit_dir_update(orig_dvnode, &new_dentry->d_name, 1953 + old_vnode, afs_edit_dir_for_rename_1); 1954 + } 1955 + 1956 + d_exchange(old_dentry, new_dentry); 1957 + up_write(&orig_dvnode->validate_lock); 1958 + } else { 1959 + down_write(&orig_dvnode->validate_lock); 1960 + if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) && 1961 + orig_dvnode->status.data_version == orig_dvp->dv_before + orig_dvp->dv_delta) 1962 + afs_edit_dir_update(orig_dvnode, &old_dentry->d_name, 1963 + new_vnode, afs_edit_dir_for_rename_0); 1964 + 1965 + up_write(&orig_dvnode->validate_lock); 1966 + down_write(&new_dvnode->validate_lock); 1967 + 1968 + if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) && 1969 + new_dvnode->status.data_version == new_dvp->dv_before + new_dvp->dv_delta) 1970 + afs_edit_dir_update(new_dvnode, &new_dentry->d_name, 1971 + old_vnode, afs_edit_dir_for_rename_1); 1972 + 1973 + if (S_ISDIR(old_vnode->netfs.inode.i_mode) && 1974 + test_bit(AFS_VNODE_DIR_VALID, &old_vnode->flags)) 1975 + afs_edit_dir_update(old_vnode, &dotdot_name, new_dvnode, 1976 + afs_edit_dir_for_rename_sub); 1977 + 1978 + if (S_ISDIR(new_vnode->netfs.inode.i_mode) && 1979 + test_bit(AFS_VNODE_DIR_VALID, &new_vnode->flags)) 1980 + afs_edit_dir_update(new_vnode, &dotdot_name, orig_dvnode, 1981 + afs_edit_dir_for_rename_sub); 1982 + 1983 + /* Now we can update d_fsdata on the dentries to reflect their 1984 + * new parents' data_version. 1985 + */ 1986 + afs_update_dentry_version(op, new_dvp, old_dentry); 1987 + afs_update_dentry_version(op, orig_dvp, new_dentry); 1988 + 1989 + d_exchange(old_dentry, new_dentry); 1990 + up_write(&new_dvnode->validate_lock); 1991 + } 1947 1992 } 1948 1993 1949 1994 static void afs_rename_put(struct afs_operation *op) ··· 2025 1948 .put = afs_rename_put, 2026 1949 }; 2027 1950 1951 + #if 0 /* Autoswitched in yfs_fs_rename_replace(). */ 1952 + static const struct afs_operation_ops afs_rename_replace_operation = { 1953 + .issue_afs_rpc = NULL, 1954 + .issue_yfs_rpc = yfs_fs_rename_replace, 1955 + .success = afs_rename_success, 1956 + .edit_dir = afs_rename_edit_dir, 1957 + .put = afs_rename_put, 1958 + }; 1959 + #endif 1960 + 1961 + static const struct afs_operation_ops afs_rename_noreplace_operation = { 1962 + .issue_afs_rpc = NULL, 1963 + .issue_yfs_rpc = yfs_fs_rename_noreplace, 1964 + .success = afs_rename_success, 1965 + .edit_dir = afs_rename_edit_dir, 1966 + .put = afs_rename_put, 1967 + }; 1968 + 1969 + static const struct afs_operation_ops afs_rename_exchange_operation = { 1970 + .issue_afs_rpc = NULL, 1971 + .issue_yfs_rpc = yfs_fs_rename_exchange, 1972 + .success = afs_rename_success, 1973 + .edit_dir = afs_rename_exchange_edit_dir, 1974 + .put = afs_rename_put, 1975 + }; 1976 + 2028 1977 /* 2029 1978 * rename a file in an AFS filesystem and/or move it between directories 2030 1979 */ ··· 2059 1956 struct dentry *new_dentry, unsigned int flags) 2060 1957 { 2061 1958 struct afs_operation *op; 2062 - struct afs_vnode *orig_dvnode, *new_dvnode, *vnode; 1959 + struct afs_vnode *orig_dvnode, *new_dvnode, *vnode, *new_vnode = NULL; 2063 1960 int ret; 2064 1961 2065 - if (flags) 1962 + if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) 2066 1963 return -EINVAL; 2067 1964 2068 1965 /* Don't allow silly-rename files be moved around. */ ··· 2072 1969 vnode = AFS_FS_I(d_inode(old_dentry)); 2073 1970 orig_dvnode = AFS_FS_I(old_dir); 2074 1971 new_dvnode = AFS_FS_I(new_dir); 1972 + if (d_is_positive(new_dentry)) 1973 + new_vnode = AFS_FS_I(d_inode(new_dentry)); 2075 1974 2076 1975 _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}", 2077 1976 orig_dvnode->fid.vid, orig_dvnode->fid.vnode, ··· 2094 1989 if (ret < 0) 2095 1990 goto error; 2096 1991 1992 + ret = -ENOMEM; 1993 + op->more_files = kvcalloc(2, sizeof(struct afs_vnode_param), GFP_KERNEL); 1994 + if (!op->more_files) 1995 + goto error; 1996 + 2097 1997 afs_op_set_vnode(op, 0, orig_dvnode); 2098 1998 afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */ 2099 1999 op->file[0].dv_delta = 1; ··· 2107 1997 op->file[1].modification = true; 2108 1998 op->file[0].update_ctime = true; 2109 1999 op->file[1].update_ctime = true; 2000 + op->more_files[0].vnode = vnode; 2001 + op->more_files[0].speculative = true; 2002 + op->more_files[1].vnode = new_vnode; 2003 + op->more_files[1].speculative = true; 2004 + op->nr_files = 4; 2110 2005 2111 2006 op->dentry = old_dentry; 2112 2007 op->dentry_2 = new_dentry; 2008 + op->rename.rename_flags = flags; 2113 2009 op->rename.new_negative = d_is_negative(new_dentry); 2114 - op->ops = &afs_rename_operation; 2115 2010 2116 - /* For non-directories, check whether the target is busy and if so, 2117 - * make a copy of the dentry and then do a silly-rename. If the 2118 - * silly-rename succeeds, the copied dentry is hashed and becomes the 2119 - * new target. 2120 - */ 2121 - if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) { 2122 - /* To prevent any new references to the target during the 2123 - * rename, we unhash the dentry in advance. 2011 + if (flags & RENAME_NOREPLACE) { 2012 + op->ops = &afs_rename_noreplace_operation; 2013 + } else if (flags & RENAME_EXCHANGE) { 2014 + op->ops = &afs_rename_exchange_operation; 2015 + d_drop(new_dentry); 2016 + } else { 2017 + /* If we might displace the target, we might need to do silly 2018 + * rename. 2124 2019 */ 2125 - if (!d_unhashed(new_dentry)) { 2126 - d_drop(new_dentry); 2127 - op->rename.rehash = new_dentry; 2128 - } 2020 + op->ops = &afs_rename_operation; 2129 2021 2130 - if (d_count(new_dentry) > 2) { 2131 - /* copy the target dentry's name */ 2132 - op->rename.tmp = d_alloc(new_dentry->d_parent, 2133 - &new_dentry->d_name); 2134 - if (!op->rename.tmp) { 2135 - afs_op_nomem(op); 2136 - goto error; 2022 + /* For non-directories, check whether the target is busy and if 2023 + * so, make a copy of the dentry and then do a silly-rename. 2024 + * If the silly-rename succeeds, the copied dentry is hashed 2025 + * and becomes the new target. 2026 + */ 2027 + if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) { 2028 + /* To prevent any new references to the target during 2029 + * the rename, we unhash the dentry in advance. 2030 + */ 2031 + if (!d_unhashed(new_dentry)) { 2032 + d_drop(new_dentry); 2033 + op->rename.rehash = new_dentry; 2137 2034 } 2138 2035 2139 - ret = afs_sillyrename(new_dvnode, 2140 - AFS_FS_I(d_inode(new_dentry)), 2141 - new_dentry, op->key); 2142 - if (ret) { 2143 - afs_op_set_error(op, ret); 2144 - goto error; 2145 - } 2036 + if (d_count(new_dentry) > 2) { 2037 + /* copy the target dentry's name */ 2038 + op->rename.tmp = d_alloc(new_dentry->d_parent, 2039 + &new_dentry->d_name); 2040 + if (!op->rename.tmp) { 2041 + afs_op_nomem(op); 2042 + goto error; 2043 + } 2146 2044 2147 - op->dentry_2 = op->rename.tmp; 2148 - op->rename.rehash = NULL; 2149 - op->rename.new_negative = true; 2045 + ret = afs_sillyrename(new_dvnode, 2046 + AFS_FS_I(d_inode(new_dentry)), 2047 + new_dentry, op->key); 2048 + if (ret) { 2049 + afs_op_set_error(op, ret); 2050 + goto error; 2051 + } 2052 + 2053 + op->dentry_2 = op->rename.tmp; 2054 + op->rename.rehash = NULL; 2055 + op->rename.new_negative = true; 2056 + } 2150 2057 } 2151 2058 } 2152 2059 ··· 2179 2052 d_drop(old_dentry); 2180 2053 2181 2054 ret = afs_do_sync_operation(op); 2055 + if (ret == -ENOTSUPP) 2056 + ret = -EINVAL; 2182 2057 out: 2183 2058 afs_dir_unuse_cookie(orig_dvnode, ret); 2184 2059 if (new_dvnode != orig_dvnode)
+9 -9
fs/afs/dir_edit.c
··· 522 522 } 523 523 524 524 /* 525 - * Edit a subdirectory that has been moved between directories to update the 526 - * ".." entry. 525 + * Edit an entry in a directory to update the vnode it refers to. This is also 526 + * used to update the ".." entry in a directory. 527 527 */ 528 - void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode, 529 - enum afs_edit_dir_reason why) 528 + void afs_edit_dir_update(struct afs_vnode *vnode, const struct qstr *name, 529 + struct afs_vnode *new_dvnode, enum afs_edit_dir_reason why) 530 530 { 531 531 union afs_xdr_dir_block *block; 532 532 union afs_xdr_dirent *de; ··· 557 557 if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) 558 558 goto already_invalidated; 559 559 560 - slot = afs_dir_scan_block(block, &dotdot_name, b); 560 + slot = afs_dir_scan_block(block, name, b); 561 561 if (slot >= 0) 562 562 goto found_dirent; 563 563 ··· 566 566 567 567 /* Didn't find the dirent to clobber. Download the directory again. */ 568 568 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_nodd, 569 - 0, 0, 0, 0, ".."); 569 + 0, 0, 0, 0, name->name); 570 570 afs_invalidate_dir(vnode, afs_dir_invalid_edit_upd_no_dd); 571 571 goto out; 572 572 ··· 576 576 de->u.unique = htonl(new_dvnode->fid.unique); 577 577 578 578 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_dd, b, slot, 579 - ntohl(de->u.vnode), ntohl(de->u.unique), ".."); 579 + ntohl(de->u.vnode), ntohl(de->u.unique), name->name); 580 580 581 581 kunmap_local(block); 582 582 netfs_single_mark_inode_dirty(&vnode->netfs.inode); ··· 589 589 already_invalidated: 590 590 kunmap_local(block); 591 591 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_inval, 592 - 0, 0, 0, 0, ".."); 592 + 0, 0, 0, 0, name->name); 593 593 goto out; 594 594 595 595 error: 596 596 trace_afs_edit_dir(vnode, why, afs_edit_dir_update_error, 597 - 0, 0, 0, 0, ".."); 597 + 0, 0, 0, 0, name->name); 598 598 goto out; 599 599 } 600 600
+11
fs/afs/dir_silly.c
··· 69 69 if (IS_ERR(op)) 70 70 return PTR_ERR(op); 71 71 72 + op->more_files = kvcalloc(2, sizeof(struct afs_vnode_param), GFP_KERNEL); 73 + if (!op->more_files) { 74 + afs_put_operation(op); 75 + return -ENOMEM; 76 + } 77 + 72 78 afs_op_set_vnode(op, 0, dvnode); 73 79 afs_op_set_vnode(op, 1, dvnode); 74 80 op->file[0].dv_delta = 1; ··· 83 77 op->file[1].modification = true; 84 78 op->file[0].update_ctime = true; 85 79 op->file[1].update_ctime = true; 80 + op->more_files[0].vnode = AFS_FS_I(d_inode(old)); 81 + op->more_files[0].speculative = true; 82 + op->more_files[1].vnode = AFS_FS_I(d_inode(new)); 83 + op->more_files[1].speculative = true; 84 + op->nr_files = 4; 86 85 87 86 op->dentry = old; 88 87 op->dentry_2 = new;
+10 -5
fs/afs/internal.h
··· 562 562 #define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */ 563 563 #define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */ 564 564 #define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */ 565 + #define AFS_SERVER_FL_NO_RENAME2 20 /* YFS Fileserver doesn't support enhanced rename */ 565 566 refcount_t ref; /* Object refcount */ 566 567 atomic_t active; /* Active user count */ 567 568 u32 addr_version; /* Address list version */ ··· 892 891 bool need_rehash; 893 892 } unlink; 894 893 struct { 895 - struct dentry *rehash; 896 - struct dentry *tmp; 897 - bool new_negative; 894 + struct dentry *rehash; 895 + struct dentry *tmp; 896 + unsigned int rename_flags; 897 + bool new_negative; 898 898 } rename; 899 899 struct { 900 900 struct netfs_io_subrequest *subreq; ··· 1102 1100 extern void afs_edit_dir_add(struct afs_vnode *, struct qstr *, struct afs_fid *, 1103 1101 enum afs_edit_dir_reason); 1104 1102 extern void afs_edit_dir_remove(struct afs_vnode *, struct qstr *, enum afs_edit_dir_reason); 1105 - void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode, 1106 - enum afs_edit_dir_reason why); 1103 + void afs_edit_dir_update(struct afs_vnode *vnode, const struct qstr *name, 1104 + struct afs_vnode *new_dvnode, enum afs_edit_dir_reason why); 1107 1105 void afs_mkdir_init_dir(struct afs_vnode *dvnode, struct afs_vnode *parent_vnode); 1108 1106 1109 1107 /* ··· 1695 1693 extern void yfs_fs_link(struct afs_operation *); 1696 1694 extern void yfs_fs_symlink(struct afs_operation *); 1697 1695 extern void yfs_fs_rename(struct afs_operation *); 1696 + void yfs_fs_rename_replace(struct afs_operation *op); 1697 + void yfs_fs_rename_noreplace(struct afs_operation *op); 1698 + void yfs_fs_rename_exchange(struct afs_operation *op); 1698 1699 extern void yfs_fs_store_data(struct afs_operation *); 1699 1700 extern void yfs_fs_setattr(struct afs_operation *); 1700 1701 extern void yfs_fs_get_volume_status(struct afs_operation *);
+1
fs/afs/misc.c
··· 131 131 case KRB5_PROG_KEYTYPE_NOSUPP: return -ENOPKG; 132 132 133 133 case RXGEN_OPCODE: return -ENOTSUPP; 134 + case RX_INVALID_OPERATION: return -ENOTSUPP; 134 135 135 136 default: return -EREMOTEIO; 136 137 }
+3
fs/afs/protocol_yfs.h
··· 50 50 YFSREMOVEACL = 64171, 51 51 YFSREMOVEFILE2 = 64173, 52 52 YFSSTOREOPAQUEACL2 = 64174, 53 + YFSRENAME_REPLACE = 64176, 54 + YFSRENAME_NOREPLACE = 64177, 55 + YFSRENAME_EXCHANGE = 64187, 53 56 YFSINLINEBULKSTATUS = 64536, /* YFS Fetch multiple file statuses with errors */ 54 57 YFSFETCHDATA64 = 64537, /* YFS Fetch file data */ 55 58 YFSSTOREDATA64 = 64538, /* YFS Store file data */
+14 -3
fs/afs/rotate.c
··· 432 432 afs_op_set_error(op, -EDQUOT); 433 433 goto failed_but_online; 434 434 435 + case RX_INVALID_OPERATION: 436 + case RXGEN_OPCODE: 437 + /* Handle downgrading to an older operation. */ 438 + afs_op_set_error(op, -ENOTSUPP); 439 + if (op->flags & AFS_OPERATION_DOWNGRADE) { 440 + op->flags &= ~AFS_OPERATION_DOWNGRADE; 441 + goto go_again; 442 + } 443 + goto failed_but_online; 444 + 435 445 default: 436 446 afs_op_accumulate_error(op, error, abort_code); 437 447 failed_but_online: ··· 630 620 op->addr_index = addr_index; 631 621 set_bit(addr_index, &op->addr_tried); 632 622 633 - op->volsync.creation = TIME64_MIN; 634 - op->volsync.update = TIME64_MIN; 635 - op->call_responded = false; 636 623 _debug("address [%u] %u/%u %pISp", 637 624 op->server_index, addr_index, alist->nr_addrs, 638 625 rxrpc_kernel_remote_addr(alist->addrs[op->addr_index].peer)); 626 + go_again: 627 + op->volsync.creation = TIME64_MIN; 628 + op->volsync.update = TIME64_MIN; 629 + op->call_responded = false; 639 630 _leave(" = t"); 640 631 return true; 641 632
+249
fs/afs/yfsclient.c
··· 1042 1042 1043 1043 _enter(""); 1044 1044 1045 + if (!test_bit(AFS_SERVER_FL_NO_RENAME2, &op->server->flags)) 1046 + return yfs_fs_rename_replace(op); 1047 + 1045 1048 call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename, 1046 1049 sizeof(__be32) + 1047 1050 sizeof(struct yfs_xdr_RPCFlags) + ··· 1061 1058 /* marshall the parameters */ 1062 1059 bp = call->request; 1063 1060 bp = xdr_encode_u32(bp, YFSRENAME); 1061 + bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1062 + bp = xdr_encode_YFSFid(bp, &orig_dvp->fid); 1063 + bp = xdr_encode_name(bp, orig_name); 1064 + bp = xdr_encode_YFSFid(bp, &new_dvp->fid); 1065 + bp = xdr_encode_name(bp, new_name); 1066 + yfs_check_req(call, bp); 1067 + 1068 + call->fid = orig_dvp->fid; 1069 + trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name); 1070 + afs_make_op_call(op, call, GFP_NOFS); 1071 + } 1072 + 1073 + /* 1074 + * Deliver reply data to a YFS.Rename_NoReplace operation. This does not 1075 + * return the status of a displaced target inode as there cannot be one. 1076 + */ 1077 + static int yfs_deliver_fs_rename_1(struct afs_call *call) 1078 + { 1079 + struct afs_operation *op = call->op; 1080 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1081 + struct afs_vnode_param *new_dvp = &op->file[1]; 1082 + struct afs_vnode_param *old_vp = &op->more_files[0]; 1083 + const __be32 *bp; 1084 + int ret; 1085 + 1086 + _enter("{%u}", call->unmarshall); 1087 + 1088 + ret = afs_transfer_reply(call); 1089 + if (ret < 0) 1090 + return ret; 1091 + 1092 + bp = call->buffer; 1093 + /* If the two dirs are the same, we have two copies of the same status 1094 + * report, so we just decode it twice. 1095 + */ 1096 + xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb); 1097 + xdr_decode_YFSFid(&bp, &old_vp->fid); 1098 + xdr_decode_YFSFetchStatus(&bp, call, &old_vp->scb); 1099 + xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb); 1100 + xdr_decode_YFSVolSync(&bp, &op->volsync); 1101 + _leave(" = 0 [done]"); 1102 + return 0; 1103 + } 1104 + 1105 + /* 1106 + * Deliver reply data to a YFS.Rename_Replace or a YFS.Rename_Exchange 1107 + * operation. These return the status of the displaced target inode if there 1108 + * was one. 1109 + */ 1110 + static int yfs_deliver_fs_rename_2(struct afs_call *call) 1111 + { 1112 + struct afs_operation *op = call->op; 1113 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1114 + struct afs_vnode_param *new_dvp = &op->file[1]; 1115 + struct afs_vnode_param *old_vp = &op->more_files[0]; 1116 + struct afs_vnode_param *new_vp = &op->more_files[1]; 1117 + const __be32 *bp; 1118 + int ret; 1119 + 1120 + _enter("{%u}", call->unmarshall); 1121 + 1122 + ret = afs_transfer_reply(call); 1123 + if (ret < 0) 1124 + return ret; 1125 + 1126 + bp = call->buffer; 1127 + /* If the two dirs are the same, we have two copies of the same status 1128 + * report, so we just decode it twice. 1129 + */ 1130 + xdr_decode_YFSFetchStatus(&bp, call, &orig_dvp->scb); 1131 + xdr_decode_YFSFid(&bp, &old_vp->fid); 1132 + xdr_decode_YFSFetchStatus(&bp, call, &old_vp->scb); 1133 + xdr_decode_YFSFetchStatus(&bp, call, &new_dvp->scb); 1134 + xdr_decode_YFSFid(&bp, &new_vp->fid); 1135 + xdr_decode_YFSFetchStatus(&bp, call, &new_vp->scb); 1136 + xdr_decode_YFSVolSync(&bp, &op->volsync); 1137 + _leave(" = 0 [done]"); 1138 + return 0; 1139 + } 1140 + 1141 + static void yfs_done_fs_rename_replace(struct afs_call *call) 1142 + { 1143 + if (call->error == -ECONNABORTED && 1144 + (call->abort_code == RX_INVALID_OPERATION || 1145 + call->abort_code == RXGEN_OPCODE)) { 1146 + set_bit(AFS_SERVER_FL_NO_RENAME2, &call->op->server->flags); 1147 + call->op->flags |= AFS_OPERATION_DOWNGRADE; 1148 + } 1149 + } 1150 + 1151 + /* 1152 + * YFS.Rename_Replace operation type 1153 + */ 1154 + static const struct afs_call_type yfs_RXYFSRename_Replace = { 1155 + .name = "FS.Rename_Replace", 1156 + .op = yfs_FS_Rename_Replace, 1157 + .deliver = yfs_deliver_fs_rename_2, 1158 + .done = yfs_done_fs_rename_replace, 1159 + .destructor = afs_flat_call_destructor, 1160 + }; 1161 + 1162 + /* 1163 + * YFS.Rename_NoReplace operation type 1164 + */ 1165 + static const struct afs_call_type yfs_RXYFSRename_NoReplace = { 1166 + .name = "FS.Rename_NoReplace", 1167 + .op = yfs_FS_Rename_NoReplace, 1168 + .deliver = yfs_deliver_fs_rename_1, 1169 + .destructor = afs_flat_call_destructor, 1170 + }; 1171 + 1172 + /* 1173 + * YFS.Rename_Exchange operation type 1174 + */ 1175 + static const struct afs_call_type yfs_RXYFSRename_Exchange = { 1176 + .name = "FS.Rename_Exchange", 1177 + .op = yfs_FS_Rename_Exchange, 1178 + .deliver = yfs_deliver_fs_rename_2, 1179 + .destructor = afs_flat_call_destructor, 1180 + }; 1181 + 1182 + /* 1183 + * Rename a file or directory, replacing the target if it exists. The status 1184 + * of a displaced target is returned. 1185 + */ 1186 + void yfs_fs_rename_replace(struct afs_operation *op) 1187 + { 1188 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1189 + struct afs_vnode_param *new_dvp = &op->file[1]; 1190 + const struct qstr *orig_name = &op->dentry->d_name; 1191 + const struct qstr *new_name = &op->dentry_2->d_name; 1192 + struct afs_call *call; 1193 + __be32 *bp; 1194 + 1195 + _enter(""); 1196 + 1197 + call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename_Replace, 1198 + sizeof(__be32) + 1199 + sizeof(struct yfs_xdr_RPCFlags) + 1200 + sizeof(struct yfs_xdr_YFSFid) + 1201 + xdr_strlen(orig_name->len) + 1202 + sizeof(struct yfs_xdr_YFSFid) + 1203 + xdr_strlen(new_name->len), 1204 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1205 + sizeof(struct yfs_xdr_YFSFid) + 1206 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1207 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1208 + sizeof(struct yfs_xdr_YFSFid) + 1209 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1210 + sizeof(struct yfs_xdr_YFSVolSync)); 1211 + if (!call) 1212 + return afs_op_nomem(op); 1213 + 1214 + /* Marshall the parameters. */ 1215 + bp = call->request; 1216 + bp = xdr_encode_u32(bp, YFSRENAME_REPLACE); 1217 + bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1218 + bp = xdr_encode_YFSFid(bp, &orig_dvp->fid); 1219 + bp = xdr_encode_name(bp, orig_name); 1220 + bp = xdr_encode_YFSFid(bp, &new_dvp->fid); 1221 + bp = xdr_encode_name(bp, new_name); 1222 + yfs_check_req(call, bp); 1223 + 1224 + call->fid = orig_dvp->fid; 1225 + trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name); 1226 + afs_make_op_call(op, call, GFP_NOFS); 1227 + } 1228 + 1229 + /* 1230 + * Rename a file or directory, failing if the target dirent exists. 1231 + */ 1232 + void yfs_fs_rename_noreplace(struct afs_operation *op) 1233 + { 1234 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1235 + struct afs_vnode_param *new_dvp = &op->file[1]; 1236 + const struct qstr *orig_name = &op->dentry->d_name; 1237 + const struct qstr *new_name = &op->dentry_2->d_name; 1238 + struct afs_call *call; 1239 + __be32 *bp; 1240 + 1241 + _enter(""); 1242 + 1243 + call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename_NoReplace, 1244 + sizeof(__be32) + 1245 + sizeof(struct yfs_xdr_RPCFlags) + 1246 + sizeof(struct yfs_xdr_YFSFid) + 1247 + xdr_strlen(orig_name->len) + 1248 + sizeof(struct yfs_xdr_YFSFid) + 1249 + xdr_strlen(new_name->len), 1250 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1251 + sizeof(struct yfs_xdr_YFSFid) + 1252 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1253 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1254 + sizeof(struct yfs_xdr_YFSVolSync)); 1255 + if (!call) 1256 + return afs_op_nomem(op); 1257 + 1258 + /* Marshall the parameters. */ 1259 + bp = call->request; 1260 + bp = xdr_encode_u32(bp, YFSRENAME_NOREPLACE); 1261 + bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1262 + bp = xdr_encode_YFSFid(bp, &orig_dvp->fid); 1263 + bp = xdr_encode_name(bp, orig_name); 1264 + bp = xdr_encode_YFSFid(bp, &new_dvp->fid); 1265 + bp = xdr_encode_name(bp, new_name); 1266 + yfs_check_req(call, bp); 1267 + 1268 + call->fid = orig_dvp->fid; 1269 + trace_afs_make_fs_call2(call, &orig_dvp->fid, orig_name, new_name); 1270 + afs_make_op_call(op, call, GFP_NOFS); 1271 + } 1272 + 1273 + /* 1274 + * Exchange a pair of files directories. 1275 + */ 1276 + void yfs_fs_rename_exchange(struct afs_operation *op) 1277 + { 1278 + struct afs_vnode_param *orig_dvp = &op->file[0]; 1279 + struct afs_vnode_param *new_dvp = &op->file[1]; 1280 + const struct qstr *orig_name = &op->dentry->d_name; 1281 + const struct qstr *new_name = &op->dentry_2->d_name; 1282 + struct afs_call *call; 1283 + __be32 *bp; 1284 + 1285 + _enter(""); 1286 + 1287 + call = afs_alloc_flat_call(op->net, &yfs_RXYFSRename_Exchange, 1288 + sizeof(__be32) + 1289 + sizeof(struct yfs_xdr_RPCFlags) + 1290 + sizeof(struct yfs_xdr_YFSFid) + 1291 + xdr_strlen(orig_name->len) + 1292 + sizeof(struct yfs_xdr_YFSFid) + 1293 + xdr_strlen(new_name->len), 1294 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1295 + sizeof(struct yfs_xdr_YFSFid) + 1296 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1297 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1298 + sizeof(struct yfs_xdr_YFSFid) + 1299 + sizeof(struct yfs_xdr_YFSFetchStatus) + 1300 + sizeof(struct yfs_xdr_YFSVolSync)); 1301 + if (!call) 1302 + return afs_op_nomem(op); 1303 + 1304 + /* Marshall the parameters. */ 1305 + bp = call->request; 1306 + bp = xdr_encode_u32(bp, YFSRENAME_EXCHANGE); 1064 1307 bp = xdr_encode_u32(bp, 0); /* RPC flags */ 1065 1308 bp = xdr_encode_YFSFid(bp, &orig_dvp->fid); 1066 1309 bp = xdr_encode_name(bp, orig_name);
+1
fs/dcache.c
··· 2922 2922 2923 2923 write_sequnlock(&rename_lock); 2924 2924 } 2925 + EXPORT_SYMBOL(d_exchange); 2925 2926 2926 2927 /** 2927 2928 * d_ancestor - search for an ancestor
+6
include/trace/events/afs.h
··· 69 69 yfs_FS_RemoveACL = 64171, 70 70 yfs_FS_RemoveFile2 = 64173, 71 71 yfs_FS_StoreOpaqueACL2 = 64174, 72 + yfs_FS_Rename_Replace = 64176, 73 + yfs_FS_Rename_NoReplace = 64177, 74 + yfs_FS_Rename_Exchange = 64187, 72 75 yfs_FS_InlineBulkStatus = 64536, /* YFS Fetch multiple file statuses with errors */ 73 76 yfs_FS_FetchData64 = 64537, /* YFS Fetch file data */ 74 77 yfs_FS_StoreData64 = 64538, /* YFS Store file data */ ··· 303 300 EM(yfs_FS_RemoveACL, "YFS.RemoveACL") \ 304 301 EM(yfs_FS_RemoveFile2, "YFS.RemoveFile2") \ 305 302 EM(yfs_FS_StoreOpaqueACL2, "YFS.StoreOpaqueACL2") \ 303 + EM(yfs_FS_Rename_Replace, "YFS.Rename_Replace") \ 304 + EM(yfs_FS_Rename_NoReplace, "YFS.Rename_NoReplace") \ 305 + EM(yfs_FS_Rename_Exchange, "YFS.Rename_Exchange") \ 306 306 EM(yfs_FS_InlineBulkStatus, "YFS.InlineBulkStatus") \ 307 307 EM(yfs_FS_FetchData64, "YFS.FetchData64") \ 308 308 EM(yfs_FS_StoreData64, "YFS.StoreData64") \