コード例 #1
0
int
cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
	    struct inode *target_inode, struct dentry *target_direntry)
{
	char *fromName;
	char *toName;
	struct cifs_sb_info *cifs_sb_source;
	struct cifs_sb_info *cifs_sb_target;
	struct cifsTconInfo *pTcon;
	int xid;
	int rc = 0;

	xid = GetXid();

	cifs_sb_target = CIFS_SB(target_inode->i_sb);
	cifs_sb_source = CIFS_SB(source_inode->i_sb);
	pTcon = cifs_sb_source->tcon;

	if (pTcon != cifs_sb_target->tcon) {
		FreeXid(xid);    
		return -EXDEV;	/* BB actually could be allowed if same server, but
                     different share. Might eventually add support for this */
	}

	/* we already  have the rename sem so we do not need
	to grab it again here to protect the path integrity */
	fromName = build_path_from_dentry(source_direntry);
	toName = build_path_from_dentry(target_direntry);
	if((fromName == NULL) || (toName == NULL)) {
		rc = -ENOMEM;
		goto cifs_rename_exit;
	}

	rc = CIFSSMBRename(xid, pTcon, fromName, toName,
			   cifs_sb_source->local_nls);
	if(rc == -EEXIST) {
		/* check if they are the same file 
		because rename of hardlinked files is a noop */
		FILE_UNIX_BASIC_INFO * info_buf_source;
		FILE_UNIX_BASIC_INFO * info_buf_target;

		info_buf_source = 
			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),GFP_KERNEL);
		if(info_buf_source != NULL) {
			info_buf_target = info_buf_source+1;
			rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, 
				info_buf_source, cifs_sb_source->local_nls);
			if(rc == 0) {
				rc = CIFSSMBUnixQPathInfo(xid,pTcon,toName,
						info_buf_target,
						cifs_sb_target->local_nls);
			}
			if((rc == 0) && 
				(info_buf_source->UniqueId == 
				 info_buf_target->UniqueId)) {
			/* do not rename since the files are hardlinked 
			   which is a noop */
			} else {
			/* we either can not tell the files are hardlinked
			(as with Windows servers) or files are not hardlinked 
			so delete the target manually before renaming to
			follow POSIX rather than Windows semantics */
				cifs_unlink(target_inode, target_direntry);
				rc = CIFSSMBRename(xid, pTcon, fromName, toName,
					cifs_sb_source->local_nls);
			}
			kfree(info_buf_source);
		} /* if we can not get memory just leave rc as EEXIST */
	}

	if((rc == -EIO)||(rc == -EEXIST)) {
		int oplock = FALSE;
		__u16 netfid;

		rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
					CREATE_NOT_DIR,
					&netfid, &oplock, NULL, cifs_sb_source->local_nls);
		if(rc==0) {
			CIFSSMBRenameOpenFile(xid,pTcon,netfid,
					toName, cifs_sb_source->local_nls);
			CIFSSMBClose(xid, pTcon, netfid);
		}
	}

cifs_rename_exit:
	if (fromName)
		kfree(fromName);
	if (toName)
		kfree(toName);

	FreeXid(xid);
	return rc;
}
コード例 #2
0
int
cifs_get_inode_info_unix(struct inode **pinode,
			 const unsigned char *search_path,
			 struct super_block *sb,int xid)
{
	int rc = 0;
	FILE_UNIX_BASIC_INFO findData;
	struct cifsTconInfo *pTcon;
	struct inode *inode;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	char *tmp_path;

	pTcon = cifs_sb->tcon;
	cFYI(1, (" Getting info on %s ", search_path));
	/* we could have done a find first instead but this returns more info */
	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
				  cifs_sb->local_nls);
	/* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */
	if (rc) {
		if (rc == -EREMOTE) {
			tmp_path =
			    kmalloc(strnlen
				    (pTcon->treeName,
				     MAX_TREE_SIZE + 1) +
				    strnlen(search_path, MAX_PATHCONF) + 1,
				    GFP_KERNEL);
			if (tmp_path == NULL) {
				return -ENOMEM;
			}
        /* have to skip first of the double backslash of UNC name */
			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);	
			strncat(tmp_path, search_path, MAX_PATHCONF);
			rc = connect_to_dfs_path(xid, pTcon->ses,
						 /* treename + */ tmp_path,
						 cifs_sb->local_nls);
			kfree(tmp_path);

			/* BB fix up inode etc. */
		} else if (rc) {
			return rc;
		}

	} else {
		struct cifsInodeInfo *cifsInfo;

		/* get new inode */
		if (*pinode == NULL) {
			*pinode = new_inode(sb);
			if(*pinode == NULL) 
				return -ENOMEM;
			insert_inode_hash(*pinode);
		}
			
		inode = *pinode;
		cifsInfo = CIFS_I(inode);

		cFYI(1, (" Old time %ld ", cifsInfo->time));
		cifsInfo->time = jiffies;
		cFYI(1, (" New time %ld ", cifsInfo->time));
		atomic_set(&cifsInfo->inUse,1);	/* ok to set on every refresh of inode */

		inode->i_atime =
		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
		inode->i_mtime =
		    cifs_NTtimeToUnix(le64_to_cpu
				(findData.LastModificationTime));
		inode->i_ctime =
		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
		inode->i_mode = le64_to_cpu(findData.Permissions);
		findData.Type = le32_to_cpu(findData.Type);
		if (findData.Type == UNIX_FILE) {
			inode->i_mode |= S_IFREG;
		} else if (findData.Type == UNIX_SYMLINK) {
			inode->i_mode |= S_IFLNK;
		} else if (findData.Type == UNIX_DIR) {
			inode->i_mode |= S_IFDIR;
		} else if (findData.Type == UNIX_CHARDEV) {
			inode->i_mode |= S_IFCHR;
			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
				le64_to_cpu(findData.DevMinor) & MINORMASK);
		} else if (findData.Type == UNIX_BLOCKDEV) {
			inode->i_mode |= S_IFBLK;
			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
				le64_to_cpu(findData.DevMinor) & MINORMASK);
		} else if (findData.Type == UNIX_FIFO) {
			inode->i_mode |= S_IFIFO;
		} else if (findData.Type == UNIX_SOCKET) {
			inode->i_mode |= S_IFSOCK;
		}
		inode->i_uid = le64_to_cpu(findData.Uid);
		inode->i_gid = le64_to_cpu(findData.Gid);
		inode->i_nlink = le64_to_cpu(findData.Nlinks);
		findData.NumOfBytes = le64_to_cpu(findData.NumOfBytes);
		findData.EndOfFile = le64_to_cpu(findData.EndOfFile);

		if(is_size_safe_to_change(cifsInfo)) {
		/* can not safely change the file size here if the 
		   client is writing to it due to potential races */

			i_size_write(inode,findData.EndOfFile);
/* blksize needs to be multiple of two. So safer to default to blksize
	and blkbits set in superblock so 2**blkbits and blksize will match */
/*		inode->i_blksize =
		    (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/

		/* This seems incredibly stupid but it turns out that
		i_blocks is not related to (i_size / i_blksize), instead a
		size of 512 is required to be used for calculating num blocks */
		 

/*		inode->i_blocks = 
	                (inode->i_blksize - 1 + findData.NumOfBytes) >> inode->i_blkbits;*/

		/* 512 bytes (2**9) is the fake blocksize that must be used */
		/* for this calculation */
			inode->i_blocks = (512 - 1 + findData.NumOfBytes) >> 9;
		}

		if (findData.NumOfBytes < findData.EndOfFile)
			cFYI(1, ("Server inconsistency Error: it says allocation size less than end of file "));
		cFYI(1,
		     ("Size %ld and blocks %ld ",
		      (unsigned long) inode->i_size, inode->i_blocks));
		if (S_ISREG(inode->i_mode)) {
			cFYI(1, (" File inode "));
			inode->i_op = &cifs_file_inode_ops;
			inode->i_fop = &cifs_file_ops;
			inode->i_data.a_ops = &cifs_addr_ops;
		} else if (S_ISDIR(inode->i_mode)) {
			cFYI(1, (" Directory inode"));
			inode->i_op = &cifs_dir_inode_ops;
			inode->i_fop = &cifs_dir_ops;
		} else if (S_ISLNK(inode->i_mode)) {
			cFYI(1, (" Symbolic Link inode "));
			inode->i_op = &cifs_symlink_inode_ops;
/* tmp_inode->i_fop = *//* do not need to set to anything */
		} else {
			cFYI(1, (" Init special inode "));
			init_special_inode(inode, inode->i_mode,
					   inode->i_rdev);
		}
	}
	return rc;
}
コード例 #3
0
ファイル: inode.c プロジェクト: piastry/etercifs
int cifs_get_inode_info_unix(struct inode **pinode,
	const unsigned char *search_path, struct super_block *sb, int xid)
{
	int rc = 0;
	FILE_UNIX_BASIC_INFO findData;
	struct cifsTconInfo *pTcon;
	struct inode *inode;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	const unsigned char *full_path;
	bool is_dfs_referral = false;

	pTcon = cifs_sb->tcon;
	cFYI(1, ("Getting info on %s", search_path));

	full_path = cifs_get_search_path(cifs_sb, search_path);

try_again_CIFSSMBUnixQPathInfo:
	/* could have done a find first instead but this returns more info */
	rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
/*	dump_mem("\nUnixQPathInfo return data", &findData,
		 sizeof(findData)); */
	if (rc) {
		if (rc == -EREMOTE && !is_dfs_referral) {
			is_dfs_referral = true;
			if (full_path != search_path) {
				kfree(full_path);
				full_path = search_path;
			}
			goto try_again_CIFSSMBUnixQPathInfo;
		}
		goto cgiiu_exit;
	} else {
		struct cifsInodeInfo *cifsInfo;
		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
		__u64 end_of_file = le64_to_cpu(findData.EndOfFile);

		/* get new inode */
		if (*pinode == NULL) {
			*pinode = new_inode(sb);
			if (*pinode == NULL) {
				rc = -ENOMEM;
				goto cgiiu_exit;
			}
			/* Is an i_ino of zero legal? */
			/* Are there sanity checks we can use to ensure that
			   the server is really filling in that field? */
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
				(*pinode)->i_ino =
					(unsigned long)findData.UniqueId;
			} /* note ino incremented to unique num in new_inode */
			if (sb->s_flags & MS_NOATIME)
				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;

			insert_inode_hash(*pinode);
		}

		inode = *pinode;
		cifsInfo = CIFS_I(inode);

		cFYI(1, ("Old time %ld", cifsInfo->time));
		cifsInfo->time = jiffies;
		cFYI(1, ("New time %ld", cifsInfo->time));
		/* this is ok to set on every inode revalidate */
		atomic_set(&cifsInfo->inUse, 1);

		cifs_unix_info_to_inode(inode, &findData, 0);


		if (num_of_bytes < end_of_file)
			cFYI(1, ("allocation size less than end of file"));
		cFYI(1, ("Size %ld and blocks %llu",
			(unsigned long) inode->i_size,
			(unsigned long long)inode->i_blocks));

		cifs_set_ops(inode, is_dfs_referral);
	}
cgiiu_exit:
	if (full_path != search_path)
		kfree(full_path);
	return rc;
}
コード例 #4
0
int cifs_get_inode_info_unix(struct inode **pinode,
	const unsigned char *search_path, struct super_block *sb, int xid)
{
	int rc = 0;
	FILE_UNIX_BASIC_INFO findData;
	struct cifsTconInfo *pTcon;
	struct inode *inode;
	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
	char *tmp_path;

	pTcon = cifs_sb->tcon;
	cFYI(1, ("Getting info on %s", search_path));
	/* could have done a find first instead but this returns more info */
	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
/*	dump_mem("\nUnixQPathInfo return data", &findData,
		 sizeof(findData)); */
	if (rc) {
		if (rc == -EREMOTE) {
			tmp_path =
			    kmalloc(strnlen(pTcon->treeName,
					    MAX_TREE_SIZE + 1) +
				    strnlen(search_path, MAX_PATHCONF) + 1,
				    GFP_KERNEL);
			if (tmp_path == NULL) {
				return -ENOMEM;
			}
        		/* have to skip first of the double backslash of
			   UNC name */
			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
			strncat(tmp_path, search_path, MAX_PATHCONF);
			rc = connect_to_dfs_path(xid, pTcon->ses,
						 /* treename + */ tmp_path,
						 cifs_sb->local_nls, 
						 cifs_sb->mnt_cifs_flags & 
						    CIFS_MOUNT_MAP_SPECIAL_CHR);
			kfree(tmp_path);

			/* BB fix up inode etc. */
		} else if (rc) {
			return rc;
		}
	} else {
		struct cifsInodeInfo *cifsInfo;
		__u32 type = le32_to_cpu(findData.Type);
		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
		__u64 end_of_file = le64_to_cpu(findData.EndOfFile);

		/* get new inode */
		if (*pinode == NULL) {
			*pinode = new_inode(sb);
			if (*pinode == NULL) 
				return -ENOMEM;
			/* Is an i_ino of zero legal? */
			/* Are there sanity checks we can use to ensure that
			   the server is really filling in that field? */
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
				(*pinode)->i_ino =
					(unsigned long)findData.UniqueId;
			} /* note ino incremented to unique num in new_inode */
			if(sb->s_flags & MS_NOATIME)
				(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
				
			insert_inode_hash(*pinode);
		}

		inode = *pinode;
		cifsInfo = CIFS_I(inode);

		cFYI(1, ("Old time %ld", cifsInfo->time));
		cifsInfo->time = jiffies;
		cFYI(1, ("New time %ld", cifsInfo->time));
		/* this is ok to set on every inode revalidate */
		atomic_set(&cifsInfo->inUse,1);

		inode->i_atime =
		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
		inode->i_mtime =
		    cifs_NTtimeToUnix(le64_to_cpu
				(findData.LastModificationTime));
		inode->i_ctime =
		    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
		inode->i_mode = le64_to_cpu(findData.Permissions);
		/* since we set the inode type below we need to mask off
                   to avoid strange results if bits set above */
                        inode->i_mode &= ~S_IFMT;
		if (type == UNIX_FILE) {
			inode->i_mode |= S_IFREG;
		} else if (type == UNIX_SYMLINK) {
			inode->i_mode |= S_IFLNK;
		} else if (type == UNIX_DIR) {
			inode->i_mode |= S_IFDIR;
		} else if (type == UNIX_CHARDEV) {
			inode->i_mode |= S_IFCHR;
			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
				le64_to_cpu(findData.DevMinor) & MINORMASK);
		} else if (type == UNIX_BLOCKDEV) {
			inode->i_mode |= S_IFBLK;
			inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
				le64_to_cpu(findData.DevMinor) & MINORMASK);
		} else if (type == UNIX_FIFO) {
			inode->i_mode |= S_IFIFO;
		} else if (type == UNIX_SOCKET) {
			inode->i_mode |= S_IFSOCK;
		} else {
			/* safest to call it a file if we do not know */
			inode->i_mode |= S_IFREG;
			cFYI(1,("unknown type %d",type));
		}
		inode->i_uid = le64_to_cpu(findData.Uid);
		inode->i_gid = le64_to_cpu(findData.Gid);
		inode->i_nlink = le64_to_cpu(findData.Nlinks);

		spin_lock(&inode->i_lock);
		if (is_size_safe_to_change(cifsInfo, end_of_file)) {
		/* can not safely change the file size here if the
		   client is writing to it due to potential races */
			i_size_write(inode, end_of_file);

		/* blksize needs to be multiple of two. So safer to default to
		blksize and blkbits set in superblock so 2**blkbits and blksize
		will match rather than setting to:
		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/

		/* This seems incredibly stupid but it turns out that i_blocks
		   is not related to (i_size / i_blksize), instead 512 byte size
		   is required for calculating num blocks */

		/* 512 bytes (2**9) is the fake blocksize that must be used */
		/* for this calculation */
			inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
		}
		spin_unlock(&inode->i_lock);

		if (num_of_bytes < end_of_file)
			cFYI(1, ("allocation size less than end of file"));
		cFYI(1, ("Size %ld and blocks %llu",
			(unsigned long) inode->i_size,
			(unsigned long long)inode->i_blocks));
		if (S_ISREG(inode->i_mode)) {
			cFYI(1, ("File inode"));
			inode->i_op = &cifs_file_inode_ops;
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
				if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
					inode->i_fop = 
						&cifs_file_direct_nobrl_ops;
				else
					inode->i_fop = &cifs_file_direct_ops;
			} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
				inode->i_fop = &cifs_file_nobrl_ops;
			else /* not direct, send byte range locks */ 
				inode->i_fop = &cifs_file_ops;

			/* check if server can support readpages */
			if(pTcon->ses->server->maxBuf < 
			    PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
				inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
			else
				inode->i_data.a_ops = &cifs_addr_ops;
		} else if (S_ISDIR(inode->i_mode)) {
			cFYI(1, ("Directory inode"));
			inode->i_op = &cifs_dir_inode_ops;
			inode->i_fop = &cifs_dir_ops;
		} else if (S_ISLNK(inode->i_mode)) {
			cFYI(1, ("Symbolic Link inode"));
			inode->i_op = &cifs_symlink_inode_ops;
		/* tmp_inode->i_fop = */ /* do not need to set to anything */
		} else {
			cFYI(1, ("Init special inode"));
			init_special_inode(inode, inode->i_mode,
					   inode->i_rdev);
		}
	}
	return rc;
}
コード例 #5
0
ファイル: inode.c プロジェクト: piastry/etercifs
int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
	struct inode *target_inode, struct dentry *target_direntry)
{
	char *fromName;
	char *toName;
	struct cifs_sb_info *cifs_sb_source;
	struct cifs_sb_info *cifs_sb_target;
	struct cifsTconInfo *pTcon;
	int xid;
	int rc = 0;

	xid = GetXid();

	cifs_sb_target = CIFS_SB(target_inode->i_sb);
	cifs_sb_source = CIFS_SB(source_inode->i_sb);
	pTcon = cifs_sb_source->tcon;

	if (pTcon != cifs_sb_target->tcon) {
		FreeXid(xid);
		return -EXDEV;	/* BB actually could be allowed if same server,
				   but different share.
				   Might eventually add support for this */
	}

	/* we already  have the rename sem so we do not need to grab it again
	   here to protect the path integrity */
	fromName = build_path_from_dentry(source_direntry);
	toName = build_path_from_dentry(target_direntry);
	if ((fromName == NULL) || (toName == NULL)) {
		rc = -ENOMEM;
		goto cifs_rename_exit;
	}

	rc = CIFSSMBRename(xid, pTcon, fromName, toName,
			   cifs_sb_source->local_nls,
			   cifs_sb_source->mnt_cifs_flags &
				CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc == -EEXIST) {
		/* check if they are the same file because rename of hardlinked
		   files is a noop */
		FILE_UNIX_BASIC_INFO *info_buf_source;
		FILE_UNIX_BASIC_INFO *info_buf_target;

		info_buf_source =
			kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
		if (info_buf_source != NULL) {
			info_buf_target = info_buf_source + 1;
			if (pTcon->unix_ext)
				rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
					info_buf_source,
					cifs_sb_source->local_nls,
					cifs_sb_source->mnt_cifs_flags &
						CIFS_MOUNT_MAP_SPECIAL_CHR);
			/* else rc is still EEXIST so will fall through to
			   unlink the target and retry rename */
			if (rc == 0) {
				rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
						info_buf_target,
						cifs_sb_target->local_nls,
						/* remap based on source sb */
						cifs_sb_source->mnt_cifs_flags &
						    CIFS_MOUNT_MAP_SPECIAL_CHR);
			}
			if ((rc == 0) &&
			    (info_buf_source->UniqueId ==
			     info_buf_target->UniqueId)) {
			/* do not rename since the files are hardlinked which
			   is a noop */
			} else {
			/* we either can not tell the files are hardlinked
			   (as with Windows servers) or files are not
			   hardlinked so delete the target manually before
			   renaming to follow POSIX rather than Windows
			   semantics */
				cifs_unlink(target_inode, target_direntry);
				rc = CIFSSMBRename(xid, pTcon, fromName,
						   toName,
						   cifs_sb_source->local_nls,
						   cifs_sb_source->mnt_cifs_flags
						   & CIFS_MOUNT_MAP_SPECIAL_CHR);
			}
			kfree(info_buf_source);
		} /* if we can not get memory just leave rc as EEXIST */
	}

	if (rc)
		cFYI(1, ("rename rc %d", rc));

	if ((rc == -EIO) || (rc == -EEXIST)) {
		int oplock = FALSE;
		__u16 netfid;

		/* BB FIXME Is Generic Read correct for rename? */
		/* if renaming directory - we should not say CREATE_NOT_DIR,
		   need to test renaming open directory, also GENERIC_READ
		   might not right be right access to request */
		rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, FILE_SHARE_ALL,
				 CREATE_NOT_DIR, &netfid, &oplock, NULL,
				 cifs_sb_source->local_nls,
				 cifs_sb_source->mnt_cifs_flags &
					CIFS_MOUNT_MAP_SPECIAL_CHR);
		if (rc == 0) {
			rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
					      cifs_sb_source->local_nls,
					      cifs_sb_source->mnt_cifs_flags &
						CIFS_MOUNT_MAP_SPECIAL_CHR);
			CIFSSMBClose(xid, pTcon, netfid);
		}
	}

cifs_rename_exit:
	kfree(fromName);
	kfree(toName);
	FreeXid(xid);
	return rc;
}