diff options
Diffstat (limited to 'fs/cifs/inode.c')
| -rw-r--r-- | fs/cifs/inode.c | 31 | 
1 files changed, 25 insertions, 6 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a174605f6afa..7899a40465b3 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1627,8 +1627,9 @@ do_rename_exit:  }  int -cifs_rename(struct inode *source_dir, struct dentry *source_dentry, -	    struct inode *target_dir, struct dentry *target_dentry) +cifs_rename2(struct inode *source_dir, struct dentry *source_dentry, +	     struct inode *target_dir, struct dentry *target_dentry, +	     unsigned int flags)  {  	char *from_name = NULL;  	char *to_name = NULL; @@ -1640,6 +1641,9 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,  	unsigned int xid;  	int rc, tmprc; +	if (flags & ~RENAME_NOREPLACE) +		return -EINVAL; +  	cifs_sb = CIFS_SB(source_dir->i_sb);  	tlink = cifs_sb_tlink(cifs_sb);  	if (IS_ERR(tlink)) @@ -1667,6 +1671,12 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,  	rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,  			    to_name); +	/* +	 * No-replace is the natural behavior for CIFS, so skip unlink hacks. +	 */ +	if (flags & RENAME_NOREPLACE) +		goto cifs_rename_exit; +  	if (rc == -EEXIST && tcon->unix_ext) {  		/*  		 * Are src and dst hardlinks of same inode? We can only tell @@ -1710,13 +1720,22 @@ cifs_rename(struct inode *source_dir, struct dentry *source_dentry,  unlink_target:  	/* Try unlinking the target dentry if it's not negative */  	if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { -		tmprc = cifs_unlink(target_dir, target_dentry); +		if (d_is_dir(target_dentry)) +			tmprc = cifs_rmdir(target_dir, target_dentry); +		else +			tmprc = cifs_unlink(target_dir, target_dentry);  		if (tmprc)  			goto cifs_rename_exit;  		rc = cifs_do_rename(xid, source_dentry, from_name,  				    target_dentry, to_name);  	} +	/* force revalidate to go get info when needed */ +	CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; + +	source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime = +		target_dir->i_mtime = current_fs_time(source_dir->i_sb); +  cifs_rename_exit:  	kfree(info_buf_source);  	kfree(from_name); @@ -1780,7 +1799,7 @@ cifs_invalidate_mapping(struct inode *inode)   * @word: long word containing the bit lock   */  static int -cifs_wait_bit_killable(void *word) +cifs_wait_bit_killable(struct wait_bit_key *key)  {  	if (fatal_signal_pending(current))  		return -ERESTARTSYS; @@ -1794,8 +1813,8 @@ cifs_revalidate_mapping(struct inode *inode)  	int rc;  	unsigned long *flags = &CIFS_I(inode)->flags; -	rc = wait_on_bit_lock(flags, CIFS_INO_LOCK, cifs_wait_bit_killable, -				TASK_KILLABLE); +	rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable, +				     TASK_KILLABLE);  	if (rc)  		return rc;  |