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