@@ -1823,7 +1823,8 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,
18231823
18241824static void afs_rename_success (struct afs_operation * op )
18251825{
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 ;
18271828
18281829 _enter ("op=%08x" , op -> debug_id );
18291830
@@ -1834,22 +1835,40 @@ static void afs_rename_success(struct afs_operation *op)
18341835 op -> ctime = op -> file [1 ].scb .status .mtime_client ;
18351836 afs_vnode_commit_status (op , & op -> file [1 ]);
18361837 }
1838+ if (op -> more_files [0 ].scb .have_status )
1839+ afs_vnode_commit_status (op , & op -> more_files [0 ]);
1840+ if (op -> more_files [1 ].scb .have_status )
1841+ afs_vnode_commit_status (op , & op -> more_files [1 ]);
18371842
18381843 /* If we're moving a subdir between dirs, we need to update
18391844 * its DV counter too as the ".." will be altered.
18401845 */
1841- if (S_ISDIR ( vnode -> netfs . inode . i_mode ) &&
1842- op -> file [ 0 ]. vnode != op -> file [ 1 ]. vnode ) {
1843- u64 new_dv ;
1846+ if (op -> file [ 0 ]. vnode != op -> file [ 1 ]. vnode ) {
1847+ if ( S_ISDIR ( vnode -> netfs . inode . i_mode ) ) {
1848+ u64 new_dv ;
18441849
1845- write_seqlock (& vnode -> cb_lock );
1850+ write_seqlock (& vnode -> cb_lock );
18461851
1847- new_dv = vnode -> status .data_version + 1 ;
1848- trace_afs_set_dv (vnode , new_dv );
1849- vnode -> status .data_version = new_dv ;
1850- inode_set_iversion_raw (& vnode -> netfs .inode , new_dv );
1852+ new_dv = vnode -> status .data_version + 1 ;
1853+ trace_afs_set_dv (vnode , new_dv );
1854+ vnode -> status .data_version = new_dv ;
1855+ inode_set_iversion_raw (& vnode -> netfs .inode , new_dv );
18511856
1852- write_sequnlock (& vnode -> cb_lock );
1857+ write_sequnlock (& vnode -> cb_lock );
1858+ }
1859+
1860+ if ((op -> rename .rename_flags & RENAME_EXCHANGE ) &&
1861+ S_ISDIR (new_vnode -> netfs .inode .i_mode )) {
1862+ u64 new_dv ;
1863+
1864+ write_seqlock (& new_vnode -> cb_lock );
1865+
1866+ new_dv = new_vnode -> status .data_version + 1 ;
1867+ new_vnode -> status .data_version = new_dv ;
1868+ inode_set_iversion_raw (& new_vnode -> netfs .inode , new_dv );
1869+
1870+ write_sequnlock (& new_vnode -> cb_lock );
1871+ }
18531872 }
18541873}
18551874
@@ -1900,8 +1919,8 @@ static void afs_rename_edit_dir(struct afs_operation *op)
19001919 if (S_ISDIR (vnode -> netfs .inode .i_mode ) &&
19011920 new_dvnode != orig_dvnode &&
19021921 test_bit (AFS_VNODE_DIR_VALID , & vnode -> flags ))
1903- afs_edit_dir_update_dotdot (vnode , new_dvnode ,
1904- afs_edit_dir_for_rename_sub );
1922+ afs_edit_dir_update (vnode , & dotdot_name , new_dvnode ,
1923+ afs_edit_dir_for_rename_sub );
19051924
19061925 new_inode = d_inode (new_dentry );
19071926 if (new_inode ) {
@@ -1915,9 +1934,6 @@ static void afs_rename_edit_dir(struct afs_operation *op)
19151934
19161935 /* Now we can update d_fsdata on the dentries to reflect their
19171936 * new parent's data_version.
1918- *
1919- * Note that if we ever implement RENAME_EXCHANGE, we'll have
1920- * to update both dentries with opposing dir versions.
19211937 */
19221938 afs_update_dentry_version (op , new_dvp , op -> dentry );
19231939 afs_update_dentry_version (op , new_dvp , op -> dentry_2 );
@@ -1930,6 +1946,67 @@ static void afs_rename_edit_dir(struct afs_operation *op)
19301946 fscache_end_operation (& new_cres );
19311947}
19321948
1949+ static void afs_rename_exchange_edit_dir (struct afs_operation * op )
1950+ {
1951+ struct afs_vnode_param * orig_dvp = & op -> file [0 ];
1952+ struct afs_vnode_param * new_dvp = & op -> file [1 ];
1953+ struct afs_vnode * orig_dvnode = orig_dvp -> vnode ;
1954+ struct afs_vnode * new_dvnode = new_dvp -> vnode ;
1955+ struct afs_vnode * old_vnode = op -> more_files [0 ].vnode ;
1956+ struct afs_vnode * new_vnode = op -> more_files [1 ].vnode ;
1957+ struct dentry * old_dentry = op -> dentry ;
1958+ struct dentry * new_dentry = op -> dentry_2 ;
1959+
1960+ _enter ("op=%08x" , op -> debug_id );
1961+
1962+ if (new_dvnode == orig_dvnode ) {
1963+ down_write (& orig_dvnode -> validate_lock );
1964+ if (test_bit (AFS_VNODE_DIR_VALID , & orig_dvnode -> flags ) &&
1965+ orig_dvnode -> status .data_version == orig_dvp -> dv_before + orig_dvp -> dv_delta ) {
1966+ afs_edit_dir_update (orig_dvnode , & old_dentry -> d_name ,
1967+ new_vnode , afs_edit_dir_for_rename_0 );
1968+ afs_edit_dir_update (orig_dvnode , & new_dentry -> d_name ,
1969+ old_vnode , afs_edit_dir_for_rename_1 );
1970+ }
1971+
1972+ d_exchange (old_dentry , new_dentry );
1973+ up_write (& orig_dvnode -> validate_lock );
1974+ } else {
1975+ down_write (& orig_dvnode -> validate_lock );
1976+ if (test_bit (AFS_VNODE_DIR_VALID , & orig_dvnode -> flags ) &&
1977+ orig_dvnode -> status .data_version == orig_dvp -> dv_before + orig_dvp -> dv_delta )
1978+ afs_edit_dir_update (orig_dvnode , & old_dentry -> d_name ,
1979+ new_vnode , afs_edit_dir_for_rename_0 );
1980+
1981+ up_write (& orig_dvnode -> validate_lock );
1982+ down_write (& new_dvnode -> validate_lock );
1983+
1984+ if (test_bit (AFS_VNODE_DIR_VALID , & new_dvnode -> flags ) &&
1985+ new_dvnode -> status .data_version == new_dvp -> dv_before + new_dvp -> dv_delta )
1986+ afs_edit_dir_update (new_dvnode , & new_dentry -> d_name ,
1987+ old_vnode , afs_edit_dir_for_rename_1 );
1988+
1989+ if (S_ISDIR (old_vnode -> netfs .inode .i_mode ) &&
1990+ test_bit (AFS_VNODE_DIR_VALID , & old_vnode -> flags ))
1991+ afs_edit_dir_update (old_vnode , & dotdot_name , new_dvnode ,
1992+ afs_edit_dir_for_rename_sub );
1993+
1994+ if (S_ISDIR (new_vnode -> netfs .inode .i_mode ) &&
1995+ test_bit (AFS_VNODE_DIR_VALID , & new_vnode -> flags ))
1996+ afs_edit_dir_update (new_vnode , & dotdot_name , orig_dvnode ,
1997+ afs_edit_dir_for_rename_sub );
1998+
1999+ /* Now we can update d_fsdata on the dentries to reflect their
2000+ * new parents' data_version.
2001+ */
2002+ afs_update_dentry_version (op , new_dvp , old_dentry );
2003+ afs_update_dentry_version (op , orig_dvp , new_dentry );
2004+
2005+ d_exchange (old_dentry , new_dentry );
2006+ up_write (& new_dvnode -> validate_lock );
2007+ }
2008+ }
2009+
19332010static void afs_rename_put (struct afs_operation * op )
19342011{
19352012 _enter ("op=%08x" , op -> debug_id );
@@ -1948,6 +2025,32 @@ static const struct afs_operation_ops afs_rename_operation = {
19482025 .put = afs_rename_put ,
19492026};
19502027
2028+ #if 0 /* Autoswitched in yfs_fs_rename_replace(). */
2029+ static const struct afs_operation_ops afs_rename_replace_operation = {
2030+ .issue_afs_rpc = NULL ,
2031+ .issue_yfs_rpc = yfs_fs_rename_replace ,
2032+ .success = afs_rename_success ,
2033+ .edit_dir = afs_rename_edit_dir ,
2034+ .put = afs_rename_put ,
2035+ };
2036+ #endif
2037+
2038+ static const struct afs_operation_ops afs_rename_noreplace_operation = {
2039+ .issue_afs_rpc = NULL ,
2040+ .issue_yfs_rpc = yfs_fs_rename_noreplace ,
2041+ .success = afs_rename_success ,
2042+ .edit_dir = afs_rename_edit_dir ,
2043+ .put = afs_rename_put ,
2044+ };
2045+
2046+ static const struct afs_operation_ops afs_rename_exchange_operation = {
2047+ .issue_afs_rpc = NULL ,
2048+ .issue_yfs_rpc = yfs_fs_rename_exchange ,
2049+ .success = afs_rename_success ,
2050+ .edit_dir = afs_rename_exchange_edit_dir ,
2051+ .put = afs_rename_put ,
2052+ };
2053+
19512054/*
19522055 * rename a file in an AFS filesystem and/or move it between directories
19532056 */
@@ -1956,10 +2059,10 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
19562059 struct dentry * new_dentry , unsigned int flags )
19572060{
19582061 struct afs_operation * op ;
1959- struct afs_vnode * orig_dvnode , * new_dvnode , * vnode ;
2062+ struct afs_vnode * orig_dvnode , * new_dvnode , * vnode , * new_vnode = NULL ;
19602063 int ret ;
19612064
1962- if (flags )
2065+ if (flags & ~( RENAME_NOREPLACE | RENAME_EXCHANGE ) )
19632066 return - EINVAL ;
19642067
19652068 /* Don't allow silly-rename files be moved around. */
@@ -1969,6 +2072,8 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
19692072 vnode = AFS_FS_I (d_inode (old_dentry ));
19702073 orig_dvnode = AFS_FS_I (old_dir );
19712074 new_dvnode = AFS_FS_I (new_dir );
2075+ if (d_is_positive (new_dentry ))
2076+ new_vnode = AFS_FS_I (d_inode (new_dentry ));
19722077
19732078 _enter ("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}" ,
19742079 orig_dvnode -> fid .vid , orig_dvnode -> fid .vnode ,
@@ -1989,6 +2094,11 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
19892094 if (ret < 0 )
19902095 goto error ;
19912096
2097+ ret = - ENOMEM ;
2098+ op -> more_files = kvcalloc (2 , sizeof (struct afs_vnode_param ), GFP_KERNEL );
2099+ if (!op -> more_files )
2100+ goto error ;
2101+
19922102 afs_op_set_vnode (op , 0 , orig_dvnode );
19932103 afs_op_set_vnode (op , 1 , new_dvnode ); /* May be same as orig_dvnode */
19942104 op -> file [0 ].dv_delta = 1 ;
@@ -1997,46 +2107,63 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
19972107 op -> file [1 ].modification = true;
19982108 op -> file [0 ].update_ctime = true;
19992109 op -> file [1 ].update_ctime = true;
2110+ op -> more_files [0 ].vnode = vnode ;
2111+ op -> more_files [0 ].speculative = true;
2112+ op -> more_files [1 ].vnode = new_vnode ;
2113+ op -> more_files [1 ].speculative = true;
2114+ op -> nr_files = 4 ;
20002115
20012116 op -> dentry = old_dentry ;
20022117 op -> dentry_2 = new_dentry ;
2118+ op -> rename .rename_flags = flags ;
20032119 op -> rename .new_negative = d_is_negative (new_dentry );
2004- op -> ops = & afs_rename_operation ;
20052120
2006- /* For non-directories, check whether the target is busy and if so,
2007- * make a copy of the dentry and then do a silly-rename. If the
2008- * silly-rename succeeds, the copied dentry is hashed and becomes the
2009- * new target.
2010- */
2011- if ( d_is_positive ( new_dentry ) && ! d_is_dir ( new_dentry )) {
2012- /* To prevent any new references to the target during the
2013- * rename, we unhash the dentry in advance .
2121+ if ( flags & RENAME_NOREPLACE ) {
2122+ op -> ops = & afs_rename_noreplace_operation ;
2123+ } else if ( flags & RENAME_EXCHANGE ) {
2124+ op -> ops = & afs_rename_exchange_operation ;
2125+ d_drop ( new_dentry );
2126+ } else {
2127+ /* If we might displace the target, we might need to do silly
2128+ * rename.
20142129 */
2015- if (!d_unhashed (new_dentry )) {
2016- d_drop (new_dentry );
2017- op -> rename .rehash = new_dentry ;
2018- }
2130+ op -> ops = & afs_rename_operation ;
20192131
2020- if (d_count (new_dentry ) > 2 ) {
2021- /* copy the target dentry's name */
2022- op -> rename .tmp = d_alloc (new_dentry -> d_parent ,
2023- & new_dentry -> d_name );
2024- if (!op -> rename .tmp ) {
2025- afs_op_nomem (op );
2026- goto error ;
2132+ /* For non-directories, check whether the target is busy and if
2133+ * so, make a copy of the dentry and then do a silly-rename.
2134+ * If the silly-rename succeeds, the copied dentry is hashed
2135+ * and becomes the new target.
2136+ */
2137+ if (d_is_positive (new_dentry ) && !d_is_dir (new_dentry )) {
2138+ /* To prevent any new references to the target during
2139+ * the rename, we unhash the dentry in advance.
2140+ */
2141+ if (!d_unhashed (new_dentry )) {
2142+ d_drop (new_dentry );
2143+ op -> rename .rehash = new_dentry ;
20272144 }
20282145
2029- ret = afs_sillyrename (new_dvnode ,
2030- AFS_FS_I (d_inode (new_dentry )),
2031- new_dentry , op -> key );
2032- if (ret ) {
2033- afs_op_set_error (op , ret );
2034- goto error ;
2146+ if (d_count (new_dentry ) > 2 ) {
2147+ /* copy the target dentry's name */
2148+ op -> rename .tmp = d_alloc (new_dentry -> d_parent ,
2149+ & new_dentry -> d_name );
2150+ if (!op -> rename .tmp ) {
2151+ afs_op_nomem (op );
2152+ goto error ;
2153+ }
2154+
2155+ ret = afs_sillyrename (new_dvnode ,
2156+ AFS_FS_I (d_inode (new_dentry )),
2157+ new_dentry , op -> key );
2158+ if (ret ) {
2159+ afs_op_set_error (op , ret );
2160+ goto error ;
2161+ }
2162+
2163+ op -> dentry_2 = op -> rename .tmp ;
2164+ op -> rename .rehash = NULL ;
2165+ op -> rename .new_negative = true;
20352166 }
2036-
2037- op -> dentry_2 = op -> rename .tmp ;
2038- op -> rename .rehash = NULL ;
2039- op -> rename .new_negative = true;
20402167 }
20412168 }
20422169
@@ -2052,6 +2179,8 @@ static int afs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
20522179 d_drop (old_dentry );
20532180
20542181 ret = afs_do_sync_operation (op );
2182+ if (ret == - ENOTSUPP )
2183+ ret = - EINVAL ;
20552184out :
20562185 afs_dir_unuse_cookie (orig_dvnode , ret );
20572186 if (new_dvnode != orig_dvnode )
0 commit comments