]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/cifs/link.c
Merge remote-tracking branches 'asoc/topic/rockchip', 'asoc/topic/rt5514', 'asoc...
[karo-tx-linux.git] / fs / cifs / link.c
1 /*
2  *   fs/cifs/link.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   This library is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU Lesser General Public License as published
9  *   by the Free Software Foundation; either version 2.1 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15  *   the GNU Lesser General Public License for more details.
16  *
17  *   You should have received a copy of the GNU Lesser General Public License
18  *   along with this library; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21 #include <linux/fs.h>
22 #include <linux/stat.h>
23 #include <linux/slab.h>
24 #include <linux/namei.h>
25 #include "cifsfs.h"
26 #include "cifspdu.h"
27 #include "cifsglob.h"
28 #include "cifsproto.h"
29 #include "cifs_debug.h"
30 #include "cifs_fs_sb.h"
31 #include "cifs_unicode.h"
32 #ifdef CONFIG_CIFS_SMB2
33 #include "smb2proto.h"
34 #endif
35
36 /*
37  * M-F Symlink Functions - Begin
38  */
39
40 #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
41 #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
42 #define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
43 #define CIFS_MF_SYMLINK_LINK_MAXLEN (1024)
44 #define CIFS_MF_SYMLINK_FILE_SIZE \
45         (CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
46
47 #define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
48 #define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
49 #define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
50
51 static int
52 symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)
53 {
54         int rc;
55         unsigned int size;
56         struct crypto_shash *md5;
57         struct sdesc *sdescmd5;
58
59         md5 = crypto_alloc_shash("md5", 0, 0);
60         if (IS_ERR(md5)) {
61                 rc = PTR_ERR(md5);
62                 cifs_dbg(VFS, "%s: Crypto md5 allocation error %d\n",
63                          __func__, rc);
64                 return rc;
65         }
66         size = sizeof(struct shash_desc) + crypto_shash_descsize(md5);
67         sdescmd5 = kmalloc(size, GFP_KERNEL);
68         if (!sdescmd5) {
69                 rc = -ENOMEM;
70                 goto symlink_hash_err;
71         }
72         sdescmd5->shash.tfm = md5;
73         sdescmd5->shash.flags = 0x0;
74
75         rc = crypto_shash_init(&sdescmd5->shash);
76         if (rc) {
77                 cifs_dbg(VFS, "%s: Could not init md5 shash\n", __func__);
78                 goto symlink_hash_err;
79         }
80         rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len);
81         if (rc) {
82                 cifs_dbg(VFS, "%s: Could not update with link_str\n", __func__);
83                 goto symlink_hash_err;
84         }
85         rc = crypto_shash_final(&sdescmd5->shash, md5_hash);
86         if (rc)
87                 cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
88
89 symlink_hash_err:
90         crypto_free_shash(md5);
91         kfree(sdescmd5);
92
93         return rc;
94 }
95
96 static int
97 parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
98                  char **_link_str)
99 {
100         int rc;
101         unsigned int link_len;
102         const char *md5_str1;
103         const char *link_str;
104         u8 md5_hash[16];
105         char md5_str2[34];
106
107         if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
108                 return -EINVAL;
109
110         md5_str1 = (const char *)&buf[CIFS_MF_SYMLINK_MD5_OFFSET];
111         link_str = (const char *)&buf[CIFS_MF_SYMLINK_LINK_OFFSET];
112
113         rc = sscanf(buf, CIFS_MF_SYMLINK_LEN_FORMAT, &link_len);
114         if (rc != 1)
115                 return -EINVAL;
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         snprintf(md5_str2, sizeof(md5_str2),
124                  CIFS_MF_SYMLINK_MD5_FORMAT,
125                  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
126
127         if (strncmp(md5_str1, md5_str2, 17) != 0)
128                 return -EINVAL;
129
130         if (_link_str) {
131                 *_link_str = kstrndup(link_str, link_len, GFP_KERNEL);
132                 if (!*_link_str)
133                         return -ENOMEM;
134         }
135
136         *_link_len = link_len;
137         return 0;
138 }
139
140 static int
141 format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
142 {
143         int rc;
144         unsigned int link_len;
145         unsigned int ofs;
146         u8 md5_hash[16];
147
148         if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE)
149                 return -EINVAL;
150
151         link_len = strlen(link_str);
152
153         if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN)
154                 return -ENAMETOOLONG;
155
156         rc = symlink_hash(link_len, link_str, md5_hash);
157         if (rc) {
158                 cifs_dbg(FYI, "%s: MD5 hash failure: %d\n", __func__, rc);
159                 return rc;
160         }
161
162         snprintf(buf, buf_len,
163                  CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT,
164                  link_len,
165                  CIFS_MF_SYMLINK_MD5_ARGS(md5_hash));
166
167         ofs = CIFS_MF_SYMLINK_LINK_OFFSET;
168         memcpy(buf + ofs, link_str, link_len);
169
170         ofs += link_len;
171         if (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
172                 buf[ofs] = '\n';
173                 ofs++;
174         }
175
176         while (ofs < CIFS_MF_SYMLINK_FILE_SIZE) {
177                 buf[ofs] = ' ';
178                 ofs++;
179         }
180
181         return 0;
182 }
183
184 bool
185 couldbe_mf_symlink(const struct cifs_fattr *fattr)
186 {
187         if (!S_ISREG(fattr->cf_mode))
188                 /* it's not a symlink */
189                 return false;
190
191         if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
192                 /* it's not a symlink */
193                 return false;
194
195         return true;
196 }
197
198 static int
199 create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
200                   struct cifs_sb_info *cifs_sb, const char *fromName,
201                   const char *toName)
202 {
203         int rc;
204         u8 *buf;
205         unsigned int bytes_written = 0;
206
207         buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
208         if (!buf)
209                 return -ENOMEM;
210
211         rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
212         if (rc)
213                 goto out;
214
215         if (tcon->ses->server->ops->create_mf_symlink)
216                 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon,
217                                         cifs_sb, fromName, buf, &bytes_written);
218         else
219                 rc = -EOPNOTSUPP;
220
221         if (rc)
222                 goto out;
223
224         if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
225                 rc = -EIO;
226 out:
227         kfree(buf);
228         return rc;
229 }
230
231 static int
232 query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
233                  struct cifs_sb_info *cifs_sb, const unsigned char *path,
234                  char **symlinkinfo)
235 {
236         int rc;
237         u8 *buf = NULL;
238         unsigned int link_len = 0;
239         unsigned int bytes_read = 0;
240
241         buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
242         if (!buf)
243                 return -ENOMEM;
244
245         if (tcon->ses->server->ops->query_mf_symlink)
246                 rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
247                                               cifs_sb, path, buf, &bytes_read);
248         else
249                 rc = -ENOSYS;
250
251         if (rc)
252                 goto out;
253
254         if (bytes_read == 0) { /* not a symlink */
255                 rc = -EINVAL;
256                 goto out;
257         }
258
259         rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
260 out:
261         kfree(buf);
262         return rc;
263 }
264
265 int
266 check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
267                  struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
268                  const unsigned char *path)
269 {
270         int rc;
271         u8 *buf = NULL;
272         unsigned int link_len = 0;
273         unsigned int bytes_read = 0;
274
275         if (!couldbe_mf_symlink(fattr))
276                 /* it's not a symlink */
277                 return 0;
278
279         buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
280         if (!buf)
281                 return -ENOMEM;
282
283         if (tcon->ses->server->ops->query_mf_symlink)
284                 rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
285                                               cifs_sb, path, buf, &bytes_read);
286         else
287                 rc = -ENOSYS;
288
289         if (rc)
290                 goto out;
291
292         if (bytes_read == 0) /* not a symlink */
293                 goto out;
294
295         rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
296         if (rc == -EINVAL) {
297                 /* it's not a symlink */
298                 rc = 0;
299                 goto out;
300         }
301
302         if (rc != 0)
303                 goto out;
304
305         /* it is a symlink */
306         fattr->cf_eof = link_len;
307         fattr->cf_mode &= ~S_IFMT;
308         fattr->cf_mode |= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
309         fattr->cf_dtype = DT_LNK;
310 out:
311         kfree(buf);
312         return rc;
313 }
314
315 /*
316  * SMB 1.0 Protocol specific functions
317  */
318
319 int
320 cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
321                       struct cifs_sb_info *cifs_sb, const unsigned char *path,
322                       char *pbuf, unsigned int *pbytes_read)
323 {
324         int rc;
325         int oplock = 0;
326         struct cifs_fid fid;
327         struct cifs_open_parms oparms;
328         struct cifs_io_parms io_parms;
329         int buf_type = CIFS_NO_BUFFER;
330         FILE_ALL_INFO file_info;
331
332         oparms.tcon = tcon;
333         oparms.cifs_sb = cifs_sb;
334         oparms.desired_access = GENERIC_READ;
335         oparms.create_options = CREATE_NOT_DIR;
336         oparms.disposition = FILE_OPEN;
337         oparms.path = path;
338         oparms.fid = &fid;
339         oparms.reconnect = false;
340
341         rc = CIFS_open(xid, &oparms, &oplock, &file_info);
342         if (rc)
343                 return rc;
344
345         if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
346                 rc = -ENOENT;
347                 /* it's not a symlink */
348                 goto out;
349         }
350
351         io_parms.netfid = fid.netfid;
352         io_parms.pid = current->tgid;
353         io_parms.tcon = tcon;
354         io_parms.offset = 0;
355         io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
356
357         rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
358 out:
359         CIFSSMBClose(xid, tcon, fid.netfid);
360         return rc;
361 }
362
363 int
364 cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
365                        struct cifs_sb_info *cifs_sb, const unsigned char *path,
366                        char *pbuf, unsigned int *pbytes_written)
367 {
368         int rc;
369         int oplock = 0;
370         struct cifs_fid fid;
371         struct cifs_open_parms oparms;
372         struct cifs_io_parms io_parms;
373         int create_options = CREATE_NOT_DIR;
374
375         if (backup_cred(cifs_sb))
376                 create_options |= CREATE_OPEN_BACKUP_INTENT;
377
378         oparms.tcon = tcon;
379         oparms.cifs_sb = cifs_sb;
380         oparms.desired_access = GENERIC_WRITE;
381         oparms.create_options = create_options;
382         oparms.disposition = FILE_CREATE;
383         oparms.path = path;
384         oparms.fid = &fid;
385         oparms.reconnect = false;
386
387         rc = CIFS_open(xid, &oparms, &oplock, NULL);
388         if (rc)
389                 return rc;
390
391         io_parms.netfid = fid.netfid;
392         io_parms.pid = current->tgid;
393         io_parms.tcon = tcon;
394         io_parms.offset = 0;
395         io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
396
397         rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf);
398         CIFSSMBClose(xid, tcon, fid.netfid);
399         return rc;
400 }
401
402 /*
403  * SMB 2.1/SMB3 Protocol specific functions
404  */
405 #ifdef CONFIG_CIFS_SMB2
406 int
407 smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
408                       struct cifs_sb_info *cifs_sb, const unsigned char *path,
409                       char *pbuf, unsigned int *pbytes_read)
410 {
411         int rc;
412         struct cifs_fid fid;
413         struct cifs_open_parms oparms;
414         struct cifs_io_parms io_parms;
415         int buf_type = CIFS_NO_BUFFER;
416         __le16 *utf16_path;
417         __u8 oplock = SMB2_OPLOCK_LEVEL_II;
418         struct smb2_file_all_info *pfile_info = NULL;
419
420         oparms.tcon = tcon;
421         oparms.cifs_sb = cifs_sb;
422         oparms.desired_access = GENERIC_READ;
423         oparms.create_options = CREATE_NOT_DIR;
424         if (backup_cred(cifs_sb))
425                 oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
426         oparms.disposition = FILE_OPEN;
427         oparms.fid = &fid;
428         oparms.reconnect = false;
429
430         utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
431         if (utf16_path == NULL)
432                 return -ENOMEM;
433
434         pfile_info = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
435                              GFP_KERNEL);
436
437         if (pfile_info == NULL) {
438                 kfree(utf16_path);
439                 return  -ENOMEM;
440         }
441
442         rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
443         if (rc)
444                 goto qmf_out_open_fail;
445
446         if (pfile_info->EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
447                 /* it's not a symlink */
448                 rc = -ENOENT; /* Is there a better rc to return? */
449                 goto qmf_out;
450         }
451
452         io_parms.netfid = fid.netfid;
453         io_parms.pid = current->tgid;
454         io_parms.tcon = tcon;
455         io_parms.offset = 0;
456         io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
457         io_parms.persistent_fid = fid.persistent_fid;
458         io_parms.volatile_fid = fid.volatile_fid;
459         rc = SMB2_read(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
460 qmf_out:
461         SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
462 qmf_out_open_fail:
463         kfree(utf16_path);
464         kfree(pfile_info);
465         return rc;
466 }
467
468 int
469 smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
470                        struct cifs_sb_info *cifs_sb, const unsigned char *path,
471                        char *pbuf, unsigned int *pbytes_written)
472 {
473         int rc;
474         struct cifs_fid fid;
475         struct cifs_open_parms oparms;
476         struct cifs_io_parms io_parms;
477         int create_options = CREATE_NOT_DIR;
478         __le16 *utf16_path;
479         __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
480         struct kvec iov[2];
481
482         if (backup_cred(cifs_sb))
483                 create_options |= CREATE_OPEN_BACKUP_INTENT;
484
485         cifs_dbg(FYI, "%s: path: %s\n", __func__, path);
486
487         utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
488         if (!utf16_path)
489                 return -ENOMEM;
490
491         oparms.tcon = tcon;
492         oparms.cifs_sb = cifs_sb;
493         oparms.desired_access = GENERIC_WRITE;
494         oparms.create_options = create_options;
495         oparms.disposition = FILE_CREATE;
496         oparms.fid = &fid;
497         oparms.reconnect = false;
498
499         rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
500         if (rc) {
501                 kfree(utf16_path);
502                 return rc;
503         }
504
505         io_parms.netfid = fid.netfid;
506         io_parms.pid = current->tgid;
507         io_parms.tcon = tcon;
508         io_parms.offset = 0;
509         io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
510         io_parms.persistent_fid = fid.persistent_fid;
511         io_parms.volatile_fid = fid.volatile_fid;
512
513         /* iov[0] is reserved for smb header */
514         iov[1].iov_base = pbuf;
515         iov[1].iov_len = CIFS_MF_SYMLINK_FILE_SIZE;
516
517         rc = SMB2_write(xid, &io_parms, pbytes_written, iov, 1);
518
519         /* Make sure we wrote all of the symlink data */
520         if ((rc == 0) && (*pbytes_written != CIFS_MF_SYMLINK_FILE_SIZE))
521                 rc = -EIO;
522
523         SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
524
525         kfree(utf16_path);
526         return rc;
527 }
528 #endif /* CONFIG_CIFS_SMB2 */
529
530 /*
531  * M-F Symlink Functions - End
532  */
533
534 int
535 cifs_hardlink(struct dentry *old_file, struct inode *inode,
536               struct dentry *direntry)
537 {
538         int rc = -EACCES;
539         unsigned int xid;
540         char *from_name = NULL;
541         char *to_name = NULL;
542         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
543         struct tcon_link *tlink;
544         struct cifs_tcon *tcon;
545         struct TCP_Server_Info *server;
546         struct cifsInodeInfo *cifsInode;
547
548         tlink = cifs_sb_tlink(cifs_sb);
549         if (IS_ERR(tlink))
550                 return PTR_ERR(tlink);
551         tcon = tlink_tcon(tlink);
552
553         xid = get_xid();
554
555         from_name = build_path_from_dentry(old_file);
556         to_name = build_path_from_dentry(direntry);
557         if ((from_name == NULL) || (to_name == NULL)) {
558                 rc = -ENOMEM;
559                 goto cifs_hl_exit;
560         }
561
562         if (tcon->unix_ext)
563                 rc = CIFSUnixCreateHardLink(xid, tcon, from_name, to_name,
564                                             cifs_sb->local_nls,
565                                             cifs_remap(cifs_sb));
566         else {
567                 server = tcon->ses->server;
568                 if (!server->ops->create_hardlink) {
569                         rc = -ENOSYS;
570                         goto cifs_hl_exit;
571                 }
572                 rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
573                                                   cifs_sb);
574                 if ((rc == -EIO) || (rc == -EINVAL))
575                         rc = -EOPNOTSUPP;
576         }
577
578         d_drop(direntry);       /* force new lookup from server of target */
579
580         /*
581          * if source file is cached (oplocked) revalidate will not go to server
582          * until the file is closed or oplock broken so update nlinks locally
583          */
584         if (d_really_is_positive(old_file)) {
585                 cifsInode = CIFS_I(d_inode(old_file));
586                 if (rc == 0) {
587                         spin_lock(&d_inode(old_file)->i_lock);
588                         inc_nlink(d_inode(old_file));
589                         spin_unlock(&d_inode(old_file)->i_lock);
590
591                         /*
592                          * parent dir timestamps will update from srv within a
593                          * second, would it really be worth it to set the parent
594                          * dir cifs inode time to zero to force revalidate
595                          * (faster) for it too?
596                          */
597                 }
598                 /*
599                  * if not oplocked will force revalidate to get info on source
600                  * file from srv.  Note Samba server prior to 4.2 has bug -
601                  * not updating src file ctime on hardlinks but Windows servers
602                  * handle it properly
603                  */
604                 cifsInode->time = 0;
605
606                 /*
607                  * Will update parent dir timestamps from srv within a second.
608                  * Would it really be worth it to set the parent dir (cifs
609                  * inode) time field to zero to force revalidate on parent
610                  * directory faster ie
611                  *
612                  * CIFS_I(inode)->time = 0;
613                  */
614         }
615
616 cifs_hl_exit:
617         kfree(from_name);
618         kfree(to_name);
619         free_xid(xid);
620         cifs_put_tlink(tlink);
621         return rc;
622 }
623
624 const char *
625 cifs_get_link(struct dentry *direntry, struct inode *inode,
626               struct delayed_call *done)
627 {
628         int rc = -ENOMEM;
629         unsigned int xid;
630         char *full_path = NULL;
631         char *target_path = NULL;
632         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
633         struct tcon_link *tlink = NULL;
634         struct cifs_tcon *tcon;
635         struct TCP_Server_Info *server;
636
637         if (!direntry)
638                 return ERR_PTR(-ECHILD);
639
640         xid = get_xid();
641
642         tlink = cifs_sb_tlink(cifs_sb);
643         if (IS_ERR(tlink)) {
644                 free_xid(xid);
645                 return ERR_CAST(tlink);
646         }
647         tcon = tlink_tcon(tlink);
648         server = tcon->ses->server;
649
650         full_path = build_path_from_dentry(direntry);
651         if (!full_path) {
652                 free_xid(xid);
653                 cifs_put_tlink(tlink);
654                 return ERR_PTR(-ENOMEM);
655         }
656
657         cifs_dbg(FYI, "Full path: %s inode = 0x%p\n", full_path, inode);
658
659         rc = -EACCES;
660         /*
661          * First try Minshall+French Symlinks, if configured
662          * and fallback to UNIX Extensions Symlinks.
663          */
664         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
665                 rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
666                                       &target_path);
667
668         if (rc != 0 && server->ops->query_symlink)
669                 rc = server->ops->query_symlink(xid, tcon, full_path,
670                                                 &target_path, cifs_sb);
671
672         kfree(full_path);
673         free_xid(xid);
674         cifs_put_tlink(tlink);
675         if (rc != 0) {
676                 kfree(target_path);
677                 return ERR_PTR(rc);
678         }
679         set_delayed_call(done, kfree_link, target_path);
680         return target_path;
681 }
682
683 int
684 cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
685 {
686         int rc = -EOPNOTSUPP;
687         unsigned int xid;
688         struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
689         struct tcon_link *tlink;
690         struct cifs_tcon *pTcon;
691         char *full_path = NULL;
692         struct inode *newinode = NULL;
693
694         xid = get_xid();
695
696         tlink = cifs_sb_tlink(cifs_sb);
697         if (IS_ERR(tlink)) {
698                 rc = PTR_ERR(tlink);
699                 goto symlink_exit;
700         }
701         pTcon = tlink_tcon(tlink);
702
703         full_path = build_path_from_dentry(direntry);
704         if (full_path == NULL) {
705                 rc = -ENOMEM;
706                 goto symlink_exit;
707         }
708
709         cifs_dbg(FYI, "Full path: %s\n", full_path);
710         cifs_dbg(FYI, "symname is %s\n", symname);
711
712         /* BB what if DFS and this volume is on different share? BB */
713         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
714                 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
715         else if (pTcon->unix_ext)
716                 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
717                                            cifs_sb->local_nls,
718                                            cifs_remap(cifs_sb));
719         /* else
720            rc = CIFSCreateReparseSymLink(xid, pTcon, fromName, toName,
721                                         cifs_sb_target->local_nls); */
722
723         if (rc == 0) {
724                 if (pTcon->unix_ext)
725                         rc = cifs_get_inode_info_unix(&newinode, full_path,
726                                                       inode->i_sb, xid);
727                 else
728                         rc = cifs_get_inode_info(&newinode, full_path, NULL,
729                                                  inode->i_sb, xid, NULL);
730
731                 if (rc != 0) {
732                         cifs_dbg(FYI, "Create symlink ok, getinodeinfo fail rc = %d\n",
733                                  rc);
734                 } else {
735                         d_instantiate(direntry, newinode);
736                 }
737         }
738 symlink_exit:
739         kfree(full_path);
740         cifs_put_tlink(tlink);
741         free_xid(xid);
742         return rc;
743 }