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