diff options
Diffstat (limited to 'fs/cifs/link.c')
| -rw-r--r-- | fs/cifs/link.c | 518 | 
1 files changed, 291 insertions, 227 deletions
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 85cdbf831e7..68559fd557f 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -28,7 +28,10 @@  #include "cifsproto.h"  #include "cifs_debug.h"  #include "cifs_fs_sb.h" -#include "md5.h" + +/* + * M-F Symlink Functions - Begin + */  #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)  #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) @@ -47,16 +50,58 @@  	md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]  static int -CIFSParseMFSymlink(const u8 *buf, -		   unsigned int buf_len, -		   unsigned int *_link_len, -		   char **_link_str) +symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) +{ +	int rc; +	unsigned int size; +	struct crypto_shash *md5; +	struct sdesc *sdescmd5; + +	md5 = crypto_alloc_shash("md5", 0, 0); +	if (IS_ERR(md5)) { +		rc = PTR_ERR(md5); +		cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n", +			 __func__, rc); +		return rc; +	} +	size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); +	sdescmd5 = kmalloc(size, GFP_KERNEL); +	if (!sdescmd5) { +		rc = -ENOMEM; +		goto symlink_hash_err; +	} +	sdescmd5->shash.tfm = md5; +	sdescmd5->shash.flags = 0x0; + +	rc = crypto_shash_init(&sdescmd5->shash); +	if (rc) { +		cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__); +		goto symlink_hash_err; +	} +	rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len); +	if (rc) { +		cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__); +		goto symlink_hash_err; +	} +	rc = crypto_shash_final(&sdescmd5->shash, md5_hash); +	if (rc) +		cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__); + +symlink_hash_err: +	crypto_free_shash(md5); +	kfree(sdescmd5); + +	return rc; +} + +static int +parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, +		 char **_link_str)  {  	int rc;  	unsigned int link_len;  	const char *md5_str1;  	const char *link_str; -	struct MD5Context md5_ctx;  	u8 md5_hash[16];  	char md5_str2[34]; @@ -70,9 +115,11 @@ CIFSParseMFSymlink(const u8 *buf,  	if (rc != 1)  		return -EINVAL; -	cifs_MD5_init(&md5_ctx); -	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); -	cifs_MD5_final(md5_hash, &md5_ctx); +	rc = symlink_hash(link_len, link_str, md5_hash); +	if (rc) { +		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc); +		return rc; +	}  	snprintf(md5_str2, sizeof(md5_str2),  		 CIFS_MF_SYMLINK_MD5_FORMAT, @@ -92,11 +139,11 @@ CIFSParseMFSymlink(const u8 *buf,  }  static int -CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) +format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)  { +	int rc;  	unsigned int link_len;  	unsigned int ofs; -	struct MD5Context md5_ctx;  	u8 md5_hash[16];  	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) @@ -107,9 +154,11 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)  	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)  		return -ENAMETOOLONG; -	cifs_MD5_init(&md5_ctx); -	cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); -	cifs_MD5_final(md5_hash, &md5_ctx); +	rc = symlink_hash(link_len, link_str, md5_hash); +	if (rc) { +		cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc); +		return rc; +	}  	snprintf(buf, buf_len,  		 CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, @@ -133,14 +182,26 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)  	return 0;  } +bool +couldbe_mf_symlink(const struct cifs_fattr *fattr) +{ +	if (!S_ISREG(fattr->cf_mode)) +		/* it's not a symlink */ +		return false; + +	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) +		/* it's not a symlink */ +		return false; + +	return true; +} +  static int -CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon, -		    const char *fromName, const char *toName, -		    const struct nls_table *nls_codepage, int remap) +create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, +		  struct cifs_sb_info *cifs_sb, const char *fromName, +		  const char *toName)  {  	int rc; -	int oplock = 0; -	__u16 netfid = 0;  	u8 *buf;  	unsigned int bytes_written = 0; @@ -148,158 +209,87 @@ CIFSCreateMFSymLink(const int xid, struct cifsTconInfo *tcon,  	if (!buf)  		return -ENOMEM; -	rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); -	if (rc != 0) { -		kfree(buf); -		return rc; -	} - -	rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, -			 CREATE_NOT_DIR, &netfid, &oplock, NULL, -			 nls_codepage, remap); -	if (rc != 0) { -		kfree(buf); -		return rc; -	} +	rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); +	if (rc) +		goto out; -	rc = CIFSSMBWrite(xid, tcon, netfid, -			  CIFS_MF_SYMLINK_FILE_SIZE /* length */, -			  0 /* offset */, -			  &bytes_written, buf, NULL, 0); -	CIFSSMBClose(xid, tcon, netfid); -	kfree(buf); -	if (rc != 0) -		return rc; +	rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb, +					fromName, buf, &bytes_written); +	if (rc) +		goto out;  	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) -		return -EIO; - -	return 0; +		rc = -EIO; +out: +	kfree(buf); +	return rc;  }  static int -CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon, -		   const unsigned char *searchName, char **symlinkinfo, -		   const struct nls_table *nls_codepage, int remap) +query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon, +		 struct cifs_sb_info *cifs_sb, const unsigned char *path, +		 char **symlinkinfo)  {  	int rc; -	int oplock = 0; -	__u16 netfid = 0; -	u8 *buf; -	char *pbuf; -	unsigned int bytes_read = 0; -	int buf_type = CIFS_NO_BUFFER; +	u8 *buf = NULL;  	unsigned int link_len = 0; -	FILE_ALL_INFO file_info; - -	rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ, -			 CREATE_NOT_DIR, &netfid, &oplock, &file_info, -			 nls_codepage, remap); -	if (rc != 0) -		return rc; - -	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) { -		CIFSSMBClose(xid, tcon, netfid); -		/* it's not a symlink */ -		return -EINVAL; -	} +	unsigned int bytes_read = 0;  	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);  	if (!buf)  		return -ENOMEM; -	pbuf = buf; -	rc = CIFSSMBRead(xid, tcon, netfid, -			 CIFS_MF_SYMLINK_FILE_SIZE /* length */, -			 0 /* offset */, -			 &bytes_read, &pbuf, &buf_type); -	CIFSSMBClose(xid, tcon, netfid); -	if (rc != 0) { -		kfree(buf); -		return rc; -	} +	if (tcon->ses->server->ops->query_mf_symlink) +		rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, +					      cifs_sb, path, buf, &bytes_read); +	else +		rc = -ENOSYS; -	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo); -	kfree(buf); -	if (rc != 0) -		return rc; - -	return 0; -} - -bool -CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr) -{ -	if (!(fattr->cf_mode & S_IFREG)) -		/* it's not a symlink */ -		return false; +	if (rc) +		goto out; -	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) -		/* it's not a symlink */ -		return false; +	if (bytes_read == 0) { /* not a symlink */ +		rc = -EINVAL; +		goto out; +	} -	return true; +	rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo); +out: +	kfree(buf); +	return rc;  }  int -CIFSCheckMFSymlink(struct cifs_fattr *fattr, -		   const unsigned char *path, -		   struct cifs_sb_info *cifs_sb, int xid) +check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, +		 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, +		 const unsigned char *path)  {  	int rc; -	int oplock = 0; -	__u16 netfid = 0; -	struct tcon_link *tlink; -	struct cifsTconInfo *pTcon; -	u8 *buf; -	char *pbuf; -	unsigned int bytes_read = 0; -	int buf_type = CIFS_NO_BUFFER; +	u8 *buf = NULL;  	unsigned int link_len = 0; -	FILE_ALL_INFO file_info; +	unsigned int bytes_read = 0; -	if (!CIFSCouldBeMFSymlink(fattr)) +	if (!couldbe_mf_symlink(fattr))  		/* it's not a symlink */  		return 0; -	tlink = cifs_sb_tlink(cifs_sb); -	if (IS_ERR(tlink)) -		return PTR_ERR(tlink); -	pTcon = tlink_tcon(tlink); - -	rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ, -			 CREATE_NOT_DIR, &netfid, &oplock, &file_info, -			 cifs_sb->local_nls, -			 cifs_sb->mnt_cifs_flags & -				CIFS_MOUNT_MAP_SPECIAL_CHR); -	if (rc != 0) -		goto out; +	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; -	if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) { -		CIFSSMBClose(xid, pTcon, netfid); -		/* it's not a symlink */ -		goto out; -	} +	if (tcon->ses->server->ops->query_mf_symlink) +		rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon, +					      cifs_sb, path, buf, &bytes_read); +	else +		rc = -ENOSYS; -	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); -	if (!buf) { -		rc = -ENOMEM; +	if (rc)  		goto out; -	} -	pbuf = buf; -	rc = CIFSSMBRead(xid, pTcon, netfid, -			 CIFS_MF_SYMLINK_FILE_SIZE /* length */, -			 0 /* offset */, -			 &bytes_read, &pbuf, &buf_type); -	CIFSSMBClose(xid, pTcon, netfid); -	if (rc != 0) { -		kfree(buf); +	if (bytes_read == 0) /* not a symlink */  		goto out; -	} -	rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); -	kfree(buf); +	rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);  	if (rc == -EINVAL) {  		/* it's not a symlink */  		rc = 0; @@ -315,81 +305,188 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,  	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;  	fattr->cf_dtype = DT_LNK;  out: -	cifs_put_tlink(tlink); +	kfree(buf);  	return rc;  } +/* + * SMB 1.0 Protocol specific functions + */ + +int +cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, +		      struct cifs_sb_info *cifs_sb, const unsigned char *path, +		      char *pbuf, unsigned int *pbytes_read) +{ +	int rc; +	int oplock = 0; +	struct cifs_fid fid; +	struct cifs_open_parms oparms; +	struct cifs_io_parms io_parms; +	int buf_type = CIFS_NO_BUFFER; +	FILE_ALL_INFO file_info; + +	oparms.tcon = tcon; +	oparms.cifs_sb = cifs_sb; +	oparms.desired_access = GENERIC_READ; +	oparms.create_options = CREATE_NOT_DIR; +	oparms.disposition = FILE_OPEN; +	oparms.path = path; +	oparms.fid = &fid; +	oparms.reconnect = false; + +	rc = CIFS_open(xid, &oparms, &oplock, &file_info); +	if (rc) +		return rc; + +	if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) +		/* it's not a symlink */ +		goto out; + +	io_parms.netfid = fid.netfid; +	io_parms.pid = current->tgid; +	io_parms.tcon = tcon; +	io_parms.offset = 0; +	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; + +	rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type); +out: +	CIFSSMBClose(xid, tcon, fid.netfid); +	return rc; +} + +int +cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon, +		       struct cifs_sb_info *cifs_sb, const unsigned char *path, +		       char *pbuf, unsigned int *pbytes_written) +{ +	int rc; +	int oplock = 0; +	struct cifs_fid fid; +	struct cifs_open_parms oparms; +	struct cifs_io_parms io_parms; +	int create_options = CREATE_NOT_DIR; + +	if (backup_cred(cifs_sb)) +		create_options |= CREATE_OPEN_BACKUP_INTENT; + +	oparms.tcon = tcon; +	oparms.cifs_sb = cifs_sb; +	oparms.desired_access = GENERIC_WRITE; +	oparms.create_options = create_options; +	oparms.disposition = FILE_CREATE; +	oparms.path = path; +	oparms.fid = &fid; +	oparms.reconnect = false; + +	rc = CIFS_open(xid, &oparms, &oplock, NULL); +	if (rc) +		return rc; + +	io_parms.netfid = fid.netfid; +	io_parms.pid = current->tgid; +	io_parms.tcon = tcon; +	io_parms.offset = 0; +	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE; + +	rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0); +	CIFSSMBClose(xid, tcon, fid.netfid); +	return rc; +} + +/* + * M-F Symlink Functions - End + */ +  int  cifs_hardlink(struct dentry *old_file, struct inode *inode,  	      struct dentry *direntry)  {  	int rc = -EACCES; -	int xid; -	char *fromName = NULL; -	char *toName = NULL; +	unsigned int xid; +	char *from_name = NULL; +	char *to_name = NULL;  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);  	struct tcon_link *tlink; -	struct cifsTconInfo *pTcon; +	struct cifs_tcon *tcon; +	struct TCP_Server_Info *server;  	struct cifsInodeInfo *cifsInode;  	tlink = cifs_sb_tlink(cifs_sb);  	if (IS_ERR(tlink))  		return PTR_ERR(tlink); -	pTcon = tlink_tcon(tlink); +	tcon = tlink_tcon(tlink); -	xid = GetXid(); +	xid = get_xid(); -	fromName = build_path_from_dentry(old_file); -	toName = build_path_from_dentry(direntry); -	if ((fromName == NULL) || (toName == NULL)) { +	from_name = build_path_from_dentry(old_file); +	to_name = build_path_from_dentry(direntry); +	if ((from_name == NULL) || (to_name == NULL)) {  		rc = -ENOMEM;  		goto cifs_hl_exit;  	} -	if (pTcon->unix_ext) -		rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, +	if (tcon->unix_ext) +		rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,  					    cifs_sb->local_nls,  					    cifs_sb->mnt_cifs_flags &  						CIFS_MOUNT_MAP_SPECIAL_CHR);  	else { -		rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, -					cifs_sb->local_nls, -					cifs_sb->mnt_cifs_flags & -						CIFS_MOUNT_MAP_SPECIAL_CHR); +		server = tcon->ses->server; +		if (!server->ops->create_hardlink) { +			rc = -ENOSYS; +			goto cifs_hl_exit; +		} +		rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, +						  cifs_sb);  		if ((rc == -EIO) || (rc == -EINVAL))  			rc = -EOPNOTSUPP;  	}  	d_drop(direntry);	/* force new lookup from server of target */ -	/* if source file is cached (oplocked) revalidate will not go to server -	   until the file is closed or oplock broken so update nlinks locally */ +	/* +	 * if source file is cached (oplocked) revalidate will not go to server +	 * until the file is closed or oplock broken so update nlinks locally +	 */  	if (old_file->d_inode) {  		cifsInode = CIFS_I(old_file->d_inode);  		if (rc == 0) { -			old_file->d_inode->i_nlink++; -/* BB should we make this contingent on superblock flag NOATIME? */ -/*			old_file->d_inode->i_ctime = CURRENT_TIME;*/ -			/* parent dir timestamps will update from srv -			within a second, would it really be worth it -			to set the parent dir cifs inode time to zero -			to force revalidate (faster) for it too? */ +			spin_lock(&old_file->d_inode->i_lock); +			inc_nlink(old_file->d_inode); +			spin_unlock(&old_file->d_inode->i_lock); +			/* +			 * BB should we make this contingent on superblock flag +			 * NOATIME? +			 */ +			/* old_file->d_inode->i_ctime = CURRENT_TIME; */ +			/* +			 * parent dir timestamps will update from srv within a +			 * second, would it really be worth it to set the parent +			 * dir cifs inode time to zero to force revalidate +			 * (faster) for it too? +			 */  		} -		/* if not oplocked will force revalidate to get info -		   on source file from srv */ +		/* +		 * if not oplocked will force revalidate to get info on source +		 * file from srv +		 */  		cifsInode->time = 0; -		/* Will update parent dir timestamps from srv within a second. -		   Would it really be worth it to set the parent dir (cifs -		   inode) time field to zero to force revalidate on parent -		   directory faster ie -			CIFS_I(inode)->time = 0;  */ +		/* +		 * Will update parent dir timestamps from srv within a second. +		 * Would it really be worth it to set the parent dir (cifs +		 * inode) time field to zero to force revalidate on parent +		 * directory faster ie +		 * +		 * CIFS_I(inode)->time = 0; +		 */  	}  cifs_hl_exit: -	kfree(fromName); -	kfree(toName); -	FreeXid(xid); +	kfree(from_name); +	kfree(to_name); +	free_xid(xid);  	cifs_put_tlink(tlink);  	return rc;  } @@ -399,14 +496,15 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)  {  	struct inode *inode = direntry->d_inode;  	int rc = -ENOMEM; -	int xid; +	unsigned int xid;  	char *full_path = NULL;  	char *target_path = NULL;  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);  	struct tcon_link *tlink = NULL; -	struct cifsTconInfo *tcon; +	struct cifs_tcon *tcon; +	struct TCP_Server_Info *server; -	xid = GetXid(); +	xid = get_xid();  	tlink = cifs_sb_tlink(cifs_sb);  	if (IS_ERR(tlink)) { @@ -415,31 +513,13 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)  		goto out;  	}  	tcon = tlink_tcon(tlink); - -	/* -	 * For now, we just handle symlinks with unix extensions enabled. -	 * Eventually we should handle NTFS reparse points, and MacOS -	 * symlink support. For instance... -	 * -	 * rc = CIFSSMBQueryReparseLinkInfo(...) -	 * -	 * For now, just return -EACCES when the server doesn't support posix -	 * extensions. Note that we still allow querying symlinks when posix -	 * extensions are manually disabled. We could disable these as well -	 * but there doesn't seem to be any harm in allowing the client to -	 * read them. -	 */ -	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) -	    && !(tcon->ses->capabilities & CAP_UNIX)) { -		rc = -EACCES; -		goto out; -	} +	server = tcon->ses->server;  	full_path = build_path_from_dentry(direntry);  	if (!full_path)  		goto out; -	cFYI(1, "Full path: %s inode = 0x%p", full_path, inode); +	cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);  	rc = -EACCES;  	/* @@ -447,14 +527,12 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)  	 * and fallback to UNIX Extensions Symlinks.  	 */  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) -		rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, -					cifs_sb->local_nls, -					cifs_sb->mnt_cifs_flags & -						CIFS_MOUNT_MAP_SPECIAL_CHR); +		rc = query_mf_symlink(xid, tcon, cifs_sb, full_path, +				      &target_path); -	if ((rc != 0) && (tcon->ses->capabilities & CAP_UNIX)) -		rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, -					     cifs_sb->local_nls); +	if (rc != 0 && server->ops->query_symlink) +		rc = server->ops->query_symlink(xid, tcon, full_path, +						&target_path, cifs_sb);  	kfree(full_path);  out: @@ -463,7 +541,7 @@ out:  		target_path = ERR_PTR(rc);  	} -	FreeXid(xid); +	free_xid(xid);  	if (tlink)  		cifs_put_tlink(tlink);  	nd_set_link(nd, target_path); @@ -474,14 +552,14 @@ int  cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)  {  	int rc = -EOPNOTSUPP; -	int xid; +	unsigned int xid;  	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);  	struct tcon_link *tlink; -	struct cifsTconInfo *pTcon; +	struct cifs_tcon *pTcon;  	char *full_path = NULL;  	struct inode *newinode = NULL; -	xid = GetXid(); +	xid = get_xid();  	tlink = cifs_sb_tlink(cifs_sb);  	if (IS_ERR(tlink)) { @@ -496,15 +574,12 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)  		goto symlink_exit;  	} -	cFYI(1, "Full path: %s", full_path); -	cFYI(1, "symname is %s", symname); +	cifs_dbg(FYI, "Full path: %s\n", full_path); +	cifs_dbg(FYI, "symname is %s\n", symname);  	/* BB what if DFS and this volume is on different share? BB */  	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) -		rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, -					 cifs_sb->local_nls, -					 cifs_sb->mnt_cifs_flags & -						CIFS_MOUNT_MAP_SPECIAL_CHR); +		rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);  	else if (pTcon->unix_ext)  		rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,  					   cifs_sb->local_nls); @@ -521,26 +596,15 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)  						 inode->i_sb, xid, NULL);  		if (rc != 0) { -			cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", -			      rc); +			cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n", +				 rc);  		} else { -			if (pTcon->nocase) -				direntry->d_op = &cifs_ci_dentry_ops; -			else -				direntry->d_op = &cifs_dentry_ops;  			d_instantiate(direntry, newinode);  		}  	}  symlink_exit:  	kfree(full_path);  	cifs_put_tlink(tlink); -	FreeXid(xid); +	free_xid(xid);  	return rc;  } - -void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) -{ -	char *p = nd_get_link(nd); -	if (!IS_ERR(p)) -		kfree(p); -}  | 
