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
parse_mf_symlink(const u8 * buf,unsigned int buf_len,unsigned int * _link_len,char ** _link_str)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
format_mf_symlink(u8 * buf,unsigned int buf_len,const char * link_str)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
couldbe_mf_symlink(const struct cifs_fattr * fattr)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
create_mf_symlink(const unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,const char * fromName,const char * toName)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
check_mf_symlink(unsigned int xid,struct cifs_tcon * tcon,struct cifs_sb_info * cifs_sb,struct cifs_fattr * fattr,const unsigned char * path)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
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)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
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)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
smb3_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)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 cifs_open_info_data data = {};
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 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, &data, NULL,
340 NULL, NULL);
341 if (rc)
342 goto qmf_out_open_fail;
343
344 if (data.fi.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
345 /* it's not a symlink */
346 rc = -ENOENT; /* Is there a better rc to return? */
347 goto qmf_out;
348 }
349
350 io_parms.netfid = fid.netfid;
351 io_parms.pid = current->tgid;
352 io_parms.tcon = tcon;
353 io_parms.offset = 0;
354 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
355 io_parms.persistent_fid = fid.persistent_fid;
356 io_parms.volatile_fid = fid.volatile_fid;
357 rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
358 qmf_out:
359 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
360 qmf_out_open_fail:
361 kfree(utf16_path);
362 return rc;
363 }
364
365 int
smb3_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)366 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
367 struct cifs_sb_info *cifs_sb, const unsigned char *path,
368 char *pbuf, unsigned int *pbytes_written)
369 {
370 int rc;
371 struct cifs_fid fid;
372 struct cifs_open_parms oparms;
373 struct cifs_io_parms io_parms = {0};
374 __le16 *utf16_path;
375 __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
376 struct kvec iov[2];
377
378 cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
379
380 utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
381 if (!utf16_path)
382 return -ENOMEM;
383
384 oparms = (struct cifs_open_parms) {
385 .tcon = tcon,
386 .cifs_sb = cifs_sb,
387 .path = path,
388 .desired_access = GENERIC_WRITE,
389 .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR),
390 .disposition = FILE_CREATE,
391 .fid = &fid,
392 .mode = 0644,
393 };
394
395 rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
396 NULL, NULL);
397 if (rc) {
398 kfree(utf16_path);
399 return rc;
400 }
401
402 io_parms.netfid = fid.netfid;
403 io_parms.pid = current->tgid;
404 io_parms.tcon = tcon;
405 io_parms.offset = 0;
406 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
407 io_parms.persistent_fid = fid.persistent_fid;
408 io_parms.volatile_fid = fid.volatile_fid;
409
410 /* iov[0] is reserved for smb header */
411 iov[1].iov_base = pbuf;
412 iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
413
414 rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
415
416 /* Make sure we wrote all of the symlink data */
417 if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
418 rc = smb_EIO2(smb_eio_trace_short_symlink_write,
419 *pbytes_written, CIFS_MF_SYMLINK_FILE_SIZE);
420
421 SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
422
423 kfree(utf16_path);
424 return rc;
425 }
426
427 /*
428 * M-F Symlink Functions - End
429 */
430
431 int
cifs_hardlink(struct dentry * old_file,struct inode * inode,struct dentry * direntry)432 cifs_hardlink(struct dentry *old_file, struct inode *inode,
433 struct dentry *direntry)
434 {
435 int rc = -EACCES;
436 unsigned int xid;
437 const char *from_name, *to_name;
438 void *page1, *page2;
439 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
440 struct tcon_link *tlink;
441 struct cifs_tcon *tcon;
442 struct TCP_Server_Info *server;
443 struct cifsInodeInfo *cifsInode;
444
445 if (unlikely(cifs_forced_shutdown(cifs_sb)))
446 return smb_EIO(smb_eio_trace_forced_shutdown);
447
448 tlink = cifs_sb_tlink(cifs_sb);
449 if (IS_ERR(tlink))
450 return PTR_ERR(tlink);
451 tcon = tlink_tcon(tlink);
452
453 xid = get_xid();
454 page1 = alloc_dentry_path();
455 page2 = alloc_dentry_path();
456
457 from_name = build_path_from_dentry(old_file, page1);
458 if (IS_ERR(from_name)) {
459 rc = PTR_ERR(from_name);
460 goto cifs_hl_exit;
461 }
462 to_name = build_path_from_dentry(direntry, page2);
463 if (IS_ERR(to_name)) {
464 rc = PTR_ERR(to_name);
465 goto cifs_hl_exit;
466 }
467
468 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
469 if (tcon->unix_ext)
470 rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
471 cifs_sb->local_nls,
472 cifs_remap(cifs_sb));
473 else {
474 #else
475 {
476 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
477 server = tcon->ses->server;
478 if (!server->ops->create_hardlink) {
479 rc = -ENOSYS;
480 goto cifs_hl_exit;
481 }
482 rc = server->ops->create_hardlink(xid, tcon, old_file,
483 from_name, to_name, cifs_sb);
484 if ((rc == -EIO) || (rc == -EINVAL))
485 rc = -EOPNOTSUPP;
486 }
487
488 d_drop(direntry); /* force new lookup from server of target */
489
490 /*
491 * if source file is cached (oplocked) revalidate will not go to server
492 * until the file is closed or oplock broken so update nlinks locally
493 */
494 if (d_really_is_positive(old_file)) {
495 cifsInode = CIFS_I(d_inode(old_file));
496 if (rc == 0) {
497 clear_bit(CIFS_INO_TMPFILE, &cifsInode->flags);
498 spin_lock(&d_inode(old_file)->i_lock);
499 inc_nlink(d_inode(old_file));
500 spin_unlock(&d_inode(old_file)->i_lock);
501
502 /*
503 * parent dir timestamps will update from srv within a
504 * second, would it really be worth it to set the parent
505 * dir cifs inode time to zero to force revalidate
506 * (faster) for it too?
507 */
508 }
509 /*
510 * if not oplocked will force revalidate to get info on source
511 * file from srv. Note Samba server prior to 4.2 has bug -
512 * not updating src file ctime on hardlinks but Windows servers
513 * handle it properly
514 */
515 cifsInode->time = 0;
516
517 /*
518 * Will update parent dir timestamps from srv within a second.
519 * Would it really be worth it to set the parent dir (cifs
520 * inode) time field to zero to force revalidate on parent
521 * directory faster ie
522 *
523 * CIFS_I(inode)->time = 0;
524 */
525 }
526
527 cifs_hl_exit:
528 free_dentry_path(page1);
529 free_dentry_path(page2);
530 free_xid(xid);
531 cifs_put_tlink(tlink);
532 return rc;
533 }
534
535 int
536 cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
537 struct dentry *direntry, const char *symname)
538 {
539 struct cifs_sb_info *cifs_sb = CIFS_SB(inode);
540 struct inode *newinode = NULL;
541 struct tcon_link *tlink;
542 struct cifs_tcon *pTcon;
543 const char *full_path;
544 int rc = -EOPNOTSUPP;
545 unsigned int sbflags;
546 unsigned int xid;
547 void *page;
548
549 if (unlikely(cifs_forced_shutdown(cifs_sb)))
550 return smb_EIO(smb_eio_trace_forced_shutdown);
551
552 page = alloc_dentry_path();
553 if (!page)
554 return -ENOMEM;
555
556 xid = get_xid();
557
558 tlink = cifs_sb_tlink(cifs_sb);
559 if (IS_ERR(tlink)) {
560 rc = PTR_ERR(tlink);
561 /* BB could be clearer if skipped put_tlink on error here, but harmless */
562 goto symlink_exit;
563 }
564 pTcon = tlink_tcon(tlink);
565
566 full_path = build_path_from_dentry(direntry, page);
567 if (IS_ERR(full_path)) {
568 rc = PTR_ERR(full_path);
569 goto symlink_exit;
570 }
571
572 cifs_dbg(FYI, "Full path: %s\n", full_path);
573 cifs_dbg(FYI, "symname is %s\n", symname);
574
575 /* BB what if DFS and this volume is on different share? BB */
576 sbflags = cifs_sb_flags(cifs_sb);
577 rc = -EOPNOTSUPP;
578 switch (cifs_symlink_type(cifs_sb)) {
579 case CIFS_SYMLINK_TYPE_UNIX:
580 #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
581 if (pTcon->unix_ext) {
582 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path,
583 symname,
584 cifs_sb->local_nls,
585 cifs_remap(cifs_sb));
586 }
587 #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
588 break;
589
590 case CIFS_SYMLINK_TYPE_MFSYMLINKS:
591 if (sbflags & CIFS_MOUNT_MF_SYMLINKS) {
592 rc = create_mf_symlink(xid, pTcon, cifs_sb,
593 full_path, symname);
594 }
595 break;
596
597 case CIFS_SYMLINK_TYPE_SFU:
598 if (sbflags & CIFS_MOUNT_UNX_EMUL) {
599 rc = __cifs_sfu_make_node(xid, inode, direntry, pTcon,
600 full_path, S_IFLNK,
601 0, symname);
602 }
603 break;
604
605 case CIFS_SYMLINK_TYPE_NATIVE:
606 case CIFS_SYMLINK_TYPE_NFS:
607 case CIFS_SYMLINK_TYPE_WSL:
608 if (CIFS_REPARSE_SUPPORT(pTcon)) {
609 rc = create_reparse_symlink(xid, inode, direntry, pTcon,
610 full_path, symname);
611 goto symlink_exit;
612 }
613 break;
614 default:
615 break;
616 }
617
618 if (rc == 0) {
619 if (pTcon->posix_extensions) {
620 rc = smb311_posix_get_inode_info(&newinode, full_path,
621 NULL, inode->i_sb, xid);
622 } else if (pTcon->unix_ext) {
623 rc = cifs_get_inode_info_unix(&newinode, full_path,
624 inode->i_sb, xid);
625 } else {
626 rc = cifs_get_inode_info(&newinode, full_path, NULL,
627 inode->i_sb, xid, NULL);
628 }
629
630 if (rc != 0) {
631 cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
632 rc);
633 } else {
634 d_instantiate(direntry, newinode);
635 }
636 }
637 symlink_exit:
638 free_dentry_path(page);
639 cifs_put_tlink(tlink);
640 free_xid(xid);
641 return rc;
642 }
643