xref: /linux/fs/smb/client/link.c (revision 6f7e6393d1ce636bb7ec77a7fe7b77458fddf701)
1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  */
8 #include <crypto/md5.h>
9 #include <linux/fs.h>
10 #include <linux/stat.h>
11 #include <linux/slab.h>
12 #include <linux/namei.h>
13 #include "cifsfs.h"
14 #include "cifsglob.h"
15 #include "cifsproto.h"
16 #include "cifs_debug.h"
17 #include "cifs_fs_sb.h"
18 #include "cifs_unicode.h"
19 #include "smb2proto.h"
20 #include "cifs_ioctl.h"
21 #include "fs_context.h"
22 #include "reparse.h"
23 
24 /*
25  * M-F Symlink Functions - Begin
26  */
27 
28 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
29 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
30 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
31 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
32 #define CIFS_MF_SYMLINK_FILE_SIZE \
33 	(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
34 
35 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
36 #define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
37 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
38 
39 static int
40 parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
41 		 char **_link_str)
42 {
43 	int rc;
44 	unsigned int link_len;
45 	const char *md5_str1;
46 	const char *link_str;
47 	u8 md5_hash[16];
48 	char md5_str2[34];
49 
50 	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
51 		return -EINVAL;
52 
53 	md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
54 	link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
55 
56 	rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
57 	if (rc != 1)
58 		return -EINVAL;
59 
60 	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
61 		return -EINVAL;
62 
63 	md5(link_str, link_len, md5_hash);
64 
65 	scnprintf(md5_str2, sizeof(md5_str2),
66 		  CIFS_MF_SYMLINK_MD5_FORMAT,
67 		  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
68 
69 	if (strncmp(md5_str1, md5_str2, 17) != 0)
70 		return -EINVAL;
71 
72 	if (_link_str) {
73 		*_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
74 		if (!*_link_str)
75 			return -ENOMEM;
76 	}
77 
78 	*_link_len = link_len;
79 	return 0;
80 }
81 
82 static int
83 format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
84 {
85 	unsigned int link_len;
86 	unsigned int ofs;
87 	u8 md5_hash[16];
88 
89 	if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
90 		return -EINVAL;
91 
92 	link_len = strlen(link_str);
93 
94 	if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
95 		return -ENAMETOOLONG;
96 
97 	md5(link_str, link_len, md5_hash);
98 
99 	scnprintf(buf, buf_len,
100 		  CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
101 		  link_len,
102 		  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
103 
104 	ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
105 	memcpy(buf + ofs, link_str, link_len);
106 
107 	ofs += link_len;
108 	if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
109 		buf[ofs] = '\n';
110 		ofs++;
111 	}
112 
113 	while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
114 		buf[ofs] = ' ';
115 		ofs++;
116 	}
117 
118 	return 0;
119 }
120 
121 bool
122 couldbe_mf_symlink(const struct cifs_fattr *fattr)
123 {
124 	if (!S_ISREG(fattr->cf_mode))
125 		/* it's not a symlink */
126 		return false;
127 
128 	if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
129 		/* it's not a symlink */
130 		return false;
131 
132 	return true;
133 }
134 
135 static int
136 create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
137 		  struct cifs_sb_info *cifs_sb, const char *fromName,
138 		  const char *toName)
139 {
140 	int rc;
141 	u8 *buf;
142 	unsigned int bytes_written = 0;
143 
144 	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
145 	if (!buf)
146 		return -ENOMEM;
147 
148 	rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
149 	if (rc)
150 		goto out;
151 
152 	if (tcon->ses->server->ops->create_mf_symlink)
153 		rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
154 					cifs_sb, fromName, buf, &bytes_written);
155 	else
156 		rc = -EOPNOTSUPP;
157 
158 	if (rc)
159 		goto out;
160 
161 	if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
162 		rc = smb_EIO2(smb_eio_trace_symlink_file_size,
163 			      bytes_written, CIFS_MF_SYMLINK_FILE_SIZE);
164 out:
165 	kfree(buf);
166 	return rc;
167 }
168 
169 int
170 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
171 		 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
172 		 const unsigned char *path)
173 {
174 	int rc;
175 	u8 *buf = NULL;
176 	unsigned int link_len = 0;
177 	unsigned int bytes_read = 0;
178 	char *symlink = NULL;
179 
180 	if (!couldbe_mf_symlink(fattr))
181 		/* it's not a symlink */
182 		return 0;
183 
184 	buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
185 	if (!buf)
186 		return -ENOMEM;
187 
188 	if (tcon->ses->server->ops->query_mf_symlink)
189 		rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
190 					      cifs_sb, path, buf, &bytes_read);
191 	else
192 		rc = -ENOSYS;
193 
194 	if (rc)
195 		goto out;
196 
197 	if (bytes_read == 0) /* not a symlink */
198 		goto out;
199 
200 	rc = parse_mf_symlink(buf, bytes_read, &link_len, &symlink);
201 	if (rc == -EINVAL) {
202 		/* it's not a symlink */
203 		rc = 0;
204 		goto out;
205 	}
206 
207 	if (rc != 0)
208 		goto out;
209 
210 	/* it is a symlink */
211 	fattr->cf_eof = link_len;
212 	fattr->cf_mode &= ~S_IFMT;
213 	fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
214 	fattr->cf_dtype = DT_LNK;
215 	fattr->cf_symlink_target = symlink;
216 out:
217 	kfree(buf);
218 	return rc;
219 }
220 
221 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
222 /*
223  * SMB 1.0 Protocol specific functions
224  */
225 
226 int
227 cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
228 		      struct cifs_sb_info *cifs_sb, const unsigned char *path,
229 		      char *pbuf, unsigned int *pbytes_read)
230 {
231 	int rc;
232 	int oplock = 0;
233 	struct cifs_fid fid;
234 	struct cifs_open_parms oparms;
235 	struct cifs_io_parms io_parms = {0};
236 	int buf_type = CIFS_NO_BUFFER;
237 	struct cifs_open_info_data query_data;
238 
239 	oparms = (struct cifs_open_parms) {
240 		.tcon = tcon,
241 		.cifs_sb = cifs_sb,
242 		.desired_access = GENERIC_READ,
243 		.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
244 		.disposition = FILE_OPEN,
245 		.path = path,
246 		.fid = &fid,
247 	};
248 
249 	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &query_data);
250 	if (rc)
251 		return rc;
252 
253 	if (query_data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
254 		rc = -ENOENT;
255 		/* it's not a symlink */
256 		goto out;
257 	}
258 
259 	io_parms.netfid = fid.netfid;
260 	io_parms.pid = current->tgid;
261 	io_parms.tcon = tcon;
262 	io_parms.offset = 0;
263 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
264 
265 	rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
266 out:
267 	CIFSSMBClose(xid, tcon, fid.netfid);
268 	return rc;
269 }
270 
271 int
272 cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
273 		       struct cifs_sb_info *cifs_sb, const unsigned char *path,
274 		       char *pbuf, unsigned int *pbytes_written)
275 {
276 	int rc;
277 	int oplock = 0;
278 	struct cifs_fid fid;
279 	struct cifs_open_parms oparms;
280 	struct cifs_io_parms io_parms = {0};
281 
282 	oparms = (struct cifs_open_parms) {
283 		.tcon = tcon,
284 		.cifs_sb = cifs_sb,
285 		.desired_access = GENERIC_WRITE,
286 		.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
287 		.disposition = FILE_CREATE,
288 		.path = path,
289 		.fid = &fid,
290 	};
291 
292 	rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
293 	if (rc)
294 		return rc;
295 
296 	io_parms.netfid = fid.netfid;
297 	io_parms.pid = current->tgid;
298 	io_parms.tcon = tcon;
299 	io_parms.offset = 0;
300 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
301 
302 	rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
303 	CIFSSMBClose(xid, tcon, fid.netfid);
304 	return rc;
305 }
306 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
307 
308 /*
309  * SMB 2.1/SMB3 Protocol specific functions
310  */
311 int
312 smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
313 		      struct cifs_sb_info *cifs_sb, const unsigned char *path,
314 		      char *pbuf, unsigned int *pbytes_read)
315 {
316 	int rc;
317 	struct cifs_fid fid;
318 	struct cifs_open_parms oparms;
319 	struct cifs_io_parms io_parms = {0};
320 	int buf_type = CIFS_NO_BUFFER;
321 	__le16 *utf16_path;
322 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
323 	struct smb2_file_all_info *pfile_info = NULL;
324 
325 	oparms = (struct cifs_open_parms) {
326 		.tcon = tcon,
327 		.cifs_sb = cifs_sb,
328 		.path = path,
329 		.desired_access = GENERIC_READ,
330 		.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
331 		.disposition = FILE_OPEN,
332 		.fid = &fid,
333 	};
334 
335 	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
336 	if (utf16_path == NULL)
337 		return -ENOMEM;
338 
339 	pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
340 			     GFP_KERNEL);
341 
342 	if (pfile_info == NULL) {
343 		kfree(utf16_path);
344 		return  -ENOMEM;
345 	}
346 
347 	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
348 		       NULL, NULL);
349 	if (rc)
350 		goto qmf_out_open_fail;
351 
352 	if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
353 		/* it's not a symlink */
354 		rc = -ENOENT; /* Is there a better rc to return? */
355 		goto qmf_out;
356 	}
357 
358 	io_parms.netfid = fid.netfid;
359 	io_parms.pid = current->tgid;
360 	io_parms.tcon = tcon;
361 	io_parms.offset = 0;
362 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
363 	io_parms.persistent_fid = fid.persistent_fid;
364 	io_parms.volatile_fid = fid.volatile_fid;
365 	rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
366 qmf_out:
367 	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
368 qmf_out_open_fail:
369 	kfree(utf16_path);
370 	kfree(pfile_info);
371 	return rc;
372 }
373 
374 int
375 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
376 		       struct cifs_sb_info *cifs_sb, const unsigned char *path,
377 		       char *pbuf, unsigned int *pbytes_written)
378 {
379 	int rc;
380 	struct cifs_fid fid;
381 	struct cifs_open_parms oparms;
382 	struct cifs_io_parms io_parms = {0};
383 	__le16 *utf16_path;
384 	__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
385 	struct kvec iov[2];
386 
387 	cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
388 
389 	utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
390 	if (!utf16_path)
391 		return -ENOMEM;
392 
393 	oparms = (struct cifs_open_parms) {
394 		.tcon = tcon,
395 		.cifs_sb = cifs_sb,
396 		.path = path,
397 		.desired_access = GENERIC_WRITE,
398 		.create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
399 		.disposition = FILE_CREATE,
400 		.fid = &fid,
401 		.mode = 0644,
402 	};
403 
404 	rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
405 		       NULL, NULL);
406 	if (rc) {
407 		kfree(utf16_path);
408 		return rc;
409 	}
410 
411 	io_parms.netfid = fid.netfid;
412 	io_parms.pid = current->tgid;
413 	io_parms.tcon = tcon;
414 	io_parms.offset = 0;
415 	io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
416 	io_parms.persistent_fid = fid.persistent_fid;
417 	io_parms.volatile_fid = fid.volatile_fid;
418 
419 	/* iov[0] is reserved for smb header */
420 	iov[1].iov_base = pbuf;
421 	iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
422 
423 	rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
424 
425 	/* Make sure we wrote all of the symlink data */
426 	if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
427 		rc = smb_EIO2(smb_eio_trace_short_symlink_write,
428 			      *pbytes_written, CIFS_MF_SYMLINK_FILE_SIZE);
429 
430 	SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
431 
432 	kfree(utf16_path);
433 	return rc;
434 }
435 
436 /*
437  * M-F Symlink Functions - End
438  */
439 
440 int
441 cifs_hardlink(struct dentry *old_file, struct inode *inode,
442 	      struct dentry *direntry)
443 {
444 	int rc = -EACCES;
445 	unsigned int xid;
446 	const char *from_name, *to_name;
447 	void *page1, *page2;
448 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
449 	struct tcon_link *tlink;
450 	struct cifs_tcon *tcon;
451 	struct TCP_Server_Info *server;
452 	struct cifsInodeInfo *cifsInode;
453 
454 	if (unlikely(cifs_forced_shutdown(cifs_sb)))
455 		return smb_EIO(smb_eio_trace_forced_shutdown);
456 
457 	tlink = cifs_sb_tlink(cifs_sb);
458 	if (IS_ERR(tlink))
459 		return PTR_ERR(tlink);
460 	tcon = tlink_tcon(tlink);
461 
462 	xid = get_xid();
463 	page1 = alloc_dentry_path();
464 	page2 = alloc_dentry_path();
465 
466 	from_name = build_path_from_dentry(old_file, page1);
467 	if (IS_ERR(from_name)) {
468 		rc = PTR_ERR(from_name);
469 		goto cifs_hl_exit;
470 	}
471 	to_name = build_path_from_dentry(direntry, page2);
472 	if (IS_ERR(to_name)) {
473 		rc = PTR_ERR(to_name);
474 		goto cifs_hl_exit;
475 	}
476 
477 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
478 	if (tcon->unix_ext)
479 		rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
480 					    cifs_sb->local_nls,
481 					    cifs_remap(cifs_sb));
482 	else {
483 #else
484 	{
485 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
486 		server = tcon->ses->server;
487 		if (!server->ops->create_hardlink) {
488 			rc = -ENOSYS;
489 			goto cifs_hl_exit;
490 		}
491 		rc = server->ops->create_hardlink(xid, tcon, old_file,
492 						  from_name, to_name, cifs_sb);
493 		if ((rc == -EIO) || (rc == -EINVAL))
494 			rc = -EOPNOTSUPP;
495 	}
496 
497 	d_drop(direntry);	/* force new lookup from server of target */
498 
499 	/*
500 	 * if source file is cached (oplocked) revalidate will not go to server
501 	 * until the file is closed or oplock broken so update nlinks locally
502 	 */
503 	if (d_really_is_positive(old_file)) {
504 		cifsInode = CIFS_I(d_inode(old_file));
505 		if (rc == 0) {
506 			spin_lock(&d_inode(old_file)->i_lock);
507 			inc_nlink(d_inode(old_file));
508 			spin_unlock(&d_inode(old_file)->i_lock);
509 
510 			/*
511 			 * parent dir timestamps will update from srv within a
512 			 * second, would it really be worth it to set the parent
513 			 * dir cifs inode time to zero to force revalidate
514 			 * (faster) for it too?
515 			 */
516 		}
517 		/*
518 		 * if not oplocked will force revalidate to get info on source
519 		 * file from srv.  Note Samba server prior to 4.2 has bug -
520 		 * not updating src file ctime on hardlinks but Windows servers
521 		 * handle it properly
522 		 */
523 		cifsInode->time = 0;
524 
525 		/*
526 		 * Will update parent dir timestamps from srv within a second.
527 		 * Would it really be worth it to set the parent dir (cifs
528 		 * inode) time field to zero to force revalidate on parent
529 		 * directory faster ie
530 		 *
531 		 * CIFS_I(inode)->time = 0;
532 		 */
533 	}
534 
535 cifs_hl_exit:
536 	free_dentry_path(page1);
537 	free_dentry_path(page2);
538 	free_xid(xid);
539 	cifs_put_tlink(tlink);
540 	return rc;
541 }
542 
543 int
544 cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
545 	     struct dentry *direntry, const char *symname)
546 {
547 	int rc = -EOPNOTSUPP;
548 	unsigned int xid;
549 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
550 	struct tcon_link *tlink;
551 	struct cifs_tcon *pTcon;
552 	const char *full_path;
553 	void *page;
554 	struct inode *newinode = NULL;
555 
556 	if (unlikely(cifs_forced_shutdown(cifs_sb)))
557 		return smb_EIO(smb_eio_trace_forced_shutdown);
558 
559 	page = alloc_dentry_path();
560 	if (!page)
561 		return -ENOMEM;
562 
563 	xid = get_xid();
564 
565 	tlink = cifs_sb_tlink(cifs_sb);
566 	if (IS_ERR(tlink)) {
567 		rc = PTR_ERR(tlink);
568 		/* BB could be clearer if skipped put_tlink on error here, but harmless */
569 		goto symlink_exit;
570 	}
571 	pTcon = tlink_tcon(tlink);
572 
573 	full_path = build_path_from_dentry(direntry, page);
574 	if (IS_ERR(full_path)) {
575 		rc = PTR_ERR(full_path);
576 		goto symlink_exit;
577 	}
578 
579 	cifs_dbg(FYI, "Full path: %s\n", full_path);
580 	cifs_dbg(FYI, "symname is %s\n", symname);
581 
582 	/* BB what if DFS and this volume is on different share? BB */
583 	rc = -EOPNOTSUPP;
584 	switch (cifs_symlink_type(cifs_sb)) {
585 	case CIFS_SYMLINK_TYPE_UNIX:
586 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
587 		if (pTcon->unix_ext) {
588 			rc = CIFSUnixCreateSymLink(xid, pTcon, full_path,
589 						   symname,
590 						   cifs_sb->local_nls,
591 						   cifs_remap(cifs_sb));
592 		}
593 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
594 		break;
595 
596 	case CIFS_SYMLINK_TYPE_MFSYMLINKS:
597 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
598 			rc = create_mf_symlink(xid, pTcon, cifs_sb,
599 					       full_path, symname);
600 		}
601 		break;
602 
603 	case CIFS_SYMLINK_TYPE_SFU:
604 		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
605 			rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon,
606 						  full_path, S_IFLNK,
607 						  0, symname);
608 		}
609 		break;
610 
611 	case CIFS_SYMLINK_TYPE_NATIVE:
612 	case CIFS_SYMLINK_TYPE_NFS:
613 	case CIFS_SYMLINK_TYPE_WSL:
614 		if (CIFS_REPARSE_SUPPORT(pTcon)) {
615 			rc = create_reparse_symlink(xid, inode, direntry, pTcon,
616 						    full_path, symname);
617 			goto symlink_exit;
618 		}
619 		break;
620 	default:
621 		break;
622 	}
623 
624 	if (rc == 0) {
625 		if (pTcon->posix_extensions) {
626 			rc = smb311_posix_get_inode_info(&newinode, full_path,
627 							 NULL, inode->i_sb, xid);
628 		} else if (pTcon->unix_ext) {
629 			rc = cifs_get_inode_info_unix(&newinode, full_path,
630 						      inode->i_sb, xid);
631 		} else {
632 			rc = cifs_get_inode_info(&newinode, full_path, NULL,
633 						 inode->i_sb, xid, NULL);
634 		}
635 
636 		if (rc != 0) {
637 			cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
638 				 rc);
639 		} else {
640 			d_instantiate(direntry, newinode);
641 		}
642 	}
643 symlink_exit:
644 	free_dentry_path(page);
645 	cifs_put_tlink(tlink);
646 	free_xid(xid);
647 	return rc;
648 }
649