cifs: add comments explaining cifs_new_fileinfo behavior
[pandora-kernel.git] / fs / cifs / dir.c
1 /*
2  *   fs/cifs/dir.c
3  *
4  *   vfs operations that deal with dentries
5  *
6  *   Copyright (C) International Business Machines  Corp., 2002,2009
7  *   Author(s): Steve French (sfrench@us.ibm.com)
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 #include <linux/fs.h>
24 #include <linux/stat.h>
25 #include <linux/slab.h>
26 #include <linux/namei.h>
27 #include <linux/mount.h>
28 #include "cifsfs.h"
29 #include "cifspdu.h"
30 #include "cifsglob.h"
31 #include "cifsproto.h"
32 #include "cifs_debug.h"
33 #include "cifs_fs_sb.h"
34
35 static void
36 renew_parental_timestamps(struct dentry *direntry)
37 {
38         /* BB check if there is a way to get the kernel to do this or if we
39            really need this */
40         do {
41                 direntry->d_time = jiffies;
42                 direntry = direntry->d_parent;
43         } while (!IS_ROOT(direntry));
44 }
45
46 /* Note: caller must free return buffer */
47 char *
48 build_path_from_dentry(struct dentry *direntry)
49 {
50         struct dentry *temp;
51         int namelen;
52         int pplen;
53         int dfsplen;
54         char *full_path;
55         char dirsep;
56         struct cifs_sb_info *cifs_sb;
57
58         if (direntry == NULL)
59                 return NULL;  /* not much we can do if dentry is freed and
60                 we need to reopen the file after it was closed implicitly
61                 when the server crashed */
62
63         cifs_sb = CIFS_SB(direntry->d_sb);
64         dirsep = CIFS_DIR_SEP(cifs_sb);
65         pplen = cifs_sb->prepathlen;
66         if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
67                 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
68         else
69                 dfsplen = 0;
70 cifs_bp_rename_retry:
71         namelen = pplen + dfsplen;
72         for (temp = direntry; !IS_ROOT(temp);) {
73                 namelen += (1 + temp->d_name.len);
74                 temp = temp->d_parent;
75                 if (temp == NULL) {
76                         cERROR(1, "corrupt dentry");
77                         return NULL;
78                 }
79         }
80
81         full_path = kmalloc(namelen+1, GFP_KERNEL);
82         if (full_path == NULL)
83                 return full_path;
84         full_path[namelen] = 0; /* trailing null */
85         for (temp = direntry; !IS_ROOT(temp);) {
86                 namelen -= 1 + temp->d_name.len;
87                 if (namelen < 0) {
88                         break;
89                 } else {
90                         full_path[namelen] = dirsep;
91                         strncpy(full_path + namelen + 1, temp->d_name.name,
92                                 temp->d_name.len);
93                         cFYI(0, "name: %s", full_path + namelen);
94                 }
95                 temp = temp->d_parent;
96                 if (temp == NULL) {
97                         cERROR(1, "corrupt dentry");
98                         kfree(full_path);
99                         return NULL;
100                 }
101         }
102         if (namelen != pplen + dfsplen) {
103                 cERROR(1, "did not end path lookup where expected namelen is %d",
104                         namelen);
105                 /* presumably this is only possible if racing with a rename
106                 of one of the parent directories  (we can not lock the dentries
107                 above us to prevent this, but retrying should be harmless) */
108                 kfree(full_path);
109                 goto cifs_bp_rename_retry;
110         }
111         /* DIR_SEP already set for byte  0 / vs \ but not for
112            subsequent slashes in prepath which currently must
113            be entered the right way - not sure if there is an alternative
114            since the '\' is a valid posix character so we can not switch
115            those safely to '/' if any are found in the middle of the prepath */
116         /* BB test paths to Windows with '/' in the midst of prepath */
117
118         if (dfsplen) {
119                 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
120                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
121                         int i;
122                         for (i = 0; i < dfsplen; i++) {
123                                 if (full_path[i] == '\\')
124                                         full_path[i] = '/';
125                         }
126                 }
127         }
128         strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
129         return full_path;
130 }
131
132 /*
133  * When called with struct file pointer set to NULL, there is no way we could
134  * update file->private_data, but getting it stuck on openFileList provides a
135  * way to access it from cifs_fill_filedata and thereby set file->private_data
136  * from cifs_open.
137  */
138 struct cifsFileInfo *
139 cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
140                   struct file *file, struct vfsmount *mnt, unsigned int oflags)
141 {
142         int oplock = 0;
143         struct cifsFileInfo *pCifsFile;
144         struct cifsInodeInfo *pCifsInode;
145         struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb);
146
147         pCifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
148         if (pCifsFile == NULL)
149                 return pCifsFile;
150
151         if (oplockEnabled)
152                 oplock = REQ_OPLOCK;
153
154         pCifsFile->netfid = fileHandle;
155         pCifsFile->pid = current->tgid;
156         pCifsFile->pInode = igrab(newinode);
157         pCifsFile->mnt = mnt;
158         pCifsFile->pfile = file;
159         pCifsFile->invalidHandle = false;
160         pCifsFile->closePend = false;
161         mutex_init(&pCifsFile->fh_mutex);
162         mutex_init(&pCifsFile->lock_mutex);
163         INIT_LIST_HEAD(&pCifsFile->llist);
164         atomic_set(&pCifsFile->count, 1);
165         slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops);
166
167         write_lock(&GlobalSMBSeslock);
168         list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
169         pCifsInode = CIFS_I(newinode);
170         if (pCifsInode) {
171                 /* if readable file instance put first in list*/
172                 if (oflags & FMODE_READ)
173                         list_add(&pCifsFile->flist, &pCifsInode->openFileList);
174                 else
175                         list_add_tail(&pCifsFile->flist,
176                                       &pCifsInode->openFileList);
177
178                 if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
179                         pCifsInode->clientCanCacheAll = true;
180                         pCifsInode->clientCanCacheRead = true;
181                         cFYI(1, "Exclusive Oplock inode %p", newinode);
182                 } else if ((oplock & 0xF) == OPLOCK_READ)
183                                 pCifsInode->clientCanCacheRead = true;
184         }
185         write_unlock(&GlobalSMBSeslock);
186
187         return pCifsFile;
188 }
189
190 int cifs_posix_open(char *full_path, struct inode **pinode,
191                         struct vfsmount *mnt, struct super_block *sb,
192                         int mode, int oflags,
193                         __u32 *poplock, __u16 *pnetfid, int xid)
194 {
195         int rc;
196         FILE_UNIX_BASIC_INFO *presp_data;
197         __u32 posix_flags = 0;
198         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
199         struct cifs_fattr fattr;
200
201         cFYI(1, "posix open %s", full_path);
202
203         presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
204         if (presp_data == NULL)
205                 return -ENOMEM;
206
207 /* So far cifs posix extensions can only map the following flags.
208    There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
209    so far we do not seem to need them, and we can treat them as local only */
210         if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
211                 (FMODE_READ | FMODE_WRITE))
212                 posix_flags = SMB_O_RDWR;
213         else if (oflags & FMODE_READ)
214                 posix_flags = SMB_O_RDONLY;
215         else if (oflags & FMODE_WRITE)
216                 posix_flags = SMB_O_WRONLY;
217         if (oflags & O_CREAT)
218                 posix_flags |= SMB_O_CREAT;
219         if (oflags & O_EXCL)
220                 posix_flags |= SMB_O_EXCL;
221         if (oflags & O_TRUNC)
222                 posix_flags |= SMB_O_TRUNC;
223         /* be safe and imply O_SYNC for O_DSYNC */
224         if (oflags & O_DSYNC)
225                 posix_flags |= SMB_O_SYNC;
226         if (oflags & O_DIRECTORY)
227                 posix_flags |= SMB_O_DIRECTORY;
228         if (oflags & O_NOFOLLOW)
229                 posix_flags |= SMB_O_NOFOLLOW;
230         if (oflags & O_DIRECT)
231                 posix_flags |= SMB_O_DIRECT;
232
233         mode &= ~current_umask();
234         rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
235                         pnetfid, presp_data, poplock, full_path,
236                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
237                                         CIFS_MOUNT_MAP_SPECIAL_CHR);
238         if (rc)
239                 goto posix_open_ret;
240
241         if (presp_data->Type == cpu_to_le32(-1))
242                 goto posix_open_ret; /* open ok, caller does qpathinfo */
243
244         if (!pinode)
245                 goto posix_open_ret; /* caller does not need info */
246
247         cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
248
249         /* get new inode and set it up */
250         if (*pinode == NULL) {
251                 *pinode = cifs_iget(sb, &fattr);
252                 if (!*pinode) {
253                         rc = -ENOMEM;
254                         goto posix_open_ret;
255                 }
256         } else {
257                 cifs_fattr_to_inode(*pinode, &fattr);
258         }
259
260         /*
261          * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
262          * file->private_data.
263          */
264         if (mnt)
265                 cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags);
266
267 posix_open_ret:
268         kfree(presp_data);
269         return rc;
270 }
271
272 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
273                               struct dentry *direntry,
274                               struct inode *newinode)
275 {
276         if (tcon->nocase)
277                 direntry->d_op = &cifs_ci_dentry_ops;
278         else
279                 direntry->d_op = &cifs_dentry_ops;
280         d_instantiate(direntry, newinode);
281 }
282
283 /* Inode operations in similar order to how they appear in Linux file fs.h */
284
285 int
286 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
287                 struct nameidata *nd)
288 {
289         int rc = -ENOENT;
290         int xid;
291         int create_options = CREATE_NOT_DIR;
292         __u32 oplock = 0;
293         int oflags;
294         bool posix_create = false;
295         /*
296          * BB below access is probably too much for mknod to request
297          *    but we have to do query and setpathinfo so requesting
298          *    less could fail (unless we want to request getatr and setatr
299          *    permissions (only).  At least for POSIX we do not have to
300          *    request so much.
301          */
302         int desiredAccess = GENERIC_READ | GENERIC_WRITE;
303         __u16 fileHandle;
304         struct cifs_sb_info *cifs_sb;
305         struct cifsTconInfo *tcon;
306         char *full_path = NULL;
307         FILE_ALL_INFO *buf = NULL;
308         struct inode *newinode = NULL;
309         int disposition = FILE_OVERWRITE_IF;
310
311         xid = GetXid();
312
313         cifs_sb = CIFS_SB(inode->i_sb);
314         tcon = cifs_sb->tcon;
315
316         full_path = build_path_from_dentry(direntry);
317         if (full_path == NULL) {
318                 rc = -ENOMEM;
319                 FreeXid(xid);
320                 return rc;
321         }
322
323         if (oplockEnabled)
324                 oplock = REQ_OPLOCK;
325
326         if (nd && (nd->flags & LOOKUP_OPEN))
327                 oflags = nd->intent.open.flags;
328         else
329                 oflags = FMODE_READ | SMB_O_CREAT;
330
331         if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
332             (CIFS_UNIX_POSIX_PATH_OPS_CAP &
333                         le64_to_cpu(tcon->fsUnixInfo.Capability))) {
334                 rc = cifs_posix_open(full_path, &newinode,
335                         nd ? nd->path.mnt : NULL,
336                         inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
337                 /* EIO could indicate that (posix open) operation is not
338                    supported, despite what server claimed in capability
339                    negotation.  EREMOTE indicates DFS junction, which is not
340                    handled in posix open */
341
342                 if (rc == 0) {
343                         posix_create = true;
344                         if (newinode == NULL) /* query inode info */
345                                 goto cifs_create_get_file_info;
346                         else /* success, no need to query */
347                                 goto cifs_create_set_dentry;
348                 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
349                          (rc != -EOPNOTSUPP) && (rc != -EINVAL))
350                         goto cifs_create_out;
351                 /* else fallthrough to retry, using older open call, this is
352                    case where server does not support this SMB level, and
353                    falsely claims capability (also get here for DFS case
354                    which should be rare for path not covered on files) */
355         }
356
357         if (nd && (nd->flags & LOOKUP_OPEN)) {
358                 /* if the file is going to stay open, then we
359                    need to set the desired access properly */
360                 desiredAccess = 0;
361                 if (oflags & FMODE_READ)
362                         desiredAccess |= GENERIC_READ; /* is this too little? */
363                 if (oflags & FMODE_WRITE)
364                         desiredAccess |= GENERIC_WRITE;
365
366                 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
367                         disposition = FILE_CREATE;
368                 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
369                         disposition = FILE_OVERWRITE_IF;
370                 else if ((oflags & O_CREAT) == O_CREAT)
371                         disposition = FILE_OPEN_IF;
372                 else
373                         cFYI(1, "Create flag not set in create function");
374         }
375
376         /* BB add processing to set equivalent of mode - e.g. via CreateX with
377            ACLs */
378
379         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
380         if (buf == NULL) {
381                 kfree(full_path);
382                 FreeXid(xid);
383                 return -ENOMEM;
384         }
385
386         /*
387          * if we're not using unix extensions, see if we need to set
388          * ATTR_READONLY on the create call
389          */
390         if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
391                 create_options |= CREATE_OPTION_READONLY;
392
393         if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
394                 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
395                          desiredAccess, create_options,
396                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
397                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
398         else
399                 rc = -EIO; /* no NT SMB support fall into legacy open below */
400
401         if (rc == -EIO) {
402                 /* old server, retry the open legacy style */
403                 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
404                         desiredAccess, create_options,
405                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
406                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
407         }
408         if (rc) {
409                 cFYI(1, "cifs_create returned 0x%x", rc);
410                 goto cifs_create_out;
411         }
412
413         /* If Open reported that we actually created a file
414            then we now have to set the mode if possible */
415         if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
416                 struct cifs_unix_set_info_args args = {
417                                 .mode   = mode,
418                                 .ctime  = NO_CHANGE_64,
419                                 .atime  = NO_CHANGE_64,
420                                 .mtime  = NO_CHANGE_64,
421                                 .device = 0,
422                 };
423
424                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
425                         args.uid = (__u64) current_fsuid();
426                         if (inode->i_mode & S_ISGID)
427                                 args.gid = (__u64) inode->i_gid;
428                         else
429                                 args.gid = (__u64) current_fsgid();
430                 } else {
431                         args.uid = NO_CHANGE_64;
432                         args.gid = NO_CHANGE_64;
433                 }
434                 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
435                                         cifs_sb->local_nls,
436                                         cifs_sb->mnt_cifs_flags &
437                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
438         } else {
439                 /* BB implement mode setting via Windows security
440                    descriptors e.g. */
441                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
442
443                 /* Could set r/o dos attribute if mode & 0222 == 0 */
444         }
445
446 cifs_create_get_file_info:
447         /* server might mask mode so we have to query for it */
448         if (tcon->unix_ext)
449                 rc = cifs_get_inode_info_unix(&newinode, full_path,
450                                               inode->i_sb, xid);
451         else {
452                 rc = cifs_get_inode_info(&newinode, full_path, buf,
453                                          inode->i_sb, xid, &fileHandle);
454                 if (newinode) {
455                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
456                                 newinode->i_mode = mode;
457                         if ((oplock & CIFS_CREATE_ACTION) &&
458                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
459                                 newinode->i_uid = current_fsuid();
460                                 if (inode->i_mode & S_ISGID)
461                                         newinode->i_gid = inode->i_gid;
462                                 else
463                                         newinode->i_gid = current_fsgid();
464                         }
465                 }
466         }
467
468 cifs_create_set_dentry:
469         if (rc == 0)
470                 setup_cifs_dentry(tcon, direntry, newinode);
471         else
472                 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
473
474         /* nfsd case - nfs srv does not set nd */
475         if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
476                 /* mknod case - do not leave file open */
477                 CIFSSMBClose(xid, tcon, fileHandle);
478         } else if (!(posix_create) && (newinode)) {
479                 /*
480                  * cifs_fill_filedata() takes care of setting cifsFileInfo
481                  * pointer to file->private_data.
482                  */
483                 cifs_new_fileinfo(newinode, fileHandle, NULL, nd->path.mnt,
484                                   oflags);
485         }
486 cifs_create_out:
487         kfree(buf);
488         kfree(full_path);
489         FreeXid(xid);
490         return rc;
491 }
492
493 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
494                 dev_t device_number)
495 {
496         int rc = -EPERM;
497         int xid;
498         struct cifs_sb_info *cifs_sb;
499         struct cifsTconInfo *pTcon;
500         char *full_path = NULL;
501         struct inode *newinode = NULL;
502
503         if (!old_valid_dev(device_number))
504                 return -EINVAL;
505
506         xid = GetXid();
507
508         cifs_sb = CIFS_SB(inode->i_sb);
509         pTcon = cifs_sb->tcon;
510
511         full_path = build_path_from_dentry(direntry);
512         if (full_path == NULL)
513                 rc = -ENOMEM;
514         else if (pTcon->unix_ext) {
515                 struct cifs_unix_set_info_args args = {
516                         .mode   = mode & ~current_umask(),
517                         .ctime  = NO_CHANGE_64,
518                         .atime  = NO_CHANGE_64,
519                         .mtime  = NO_CHANGE_64,
520                         .device = device_number,
521                 };
522                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
523                         args.uid = (__u64) current_fsuid();
524                         args.gid = (__u64) current_fsgid();
525                 } else {
526                         args.uid = NO_CHANGE_64;
527                         args.gid = NO_CHANGE_64;
528                 }
529                 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
530                                             cifs_sb->local_nls,
531                                             cifs_sb->mnt_cifs_flags &
532                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
533
534                 if (!rc) {
535                         rc = cifs_get_inode_info_unix(&newinode, full_path,
536                                                 inode->i_sb, xid);
537                         if (pTcon->nocase)
538                                 direntry->d_op = &cifs_ci_dentry_ops;
539                         else
540                                 direntry->d_op = &cifs_dentry_ops;
541                         if (rc == 0)
542                                 d_instantiate(direntry, newinode);
543                 }
544         } else {
545                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
546                         int oplock = 0;
547                         u16 fileHandle;
548                         FILE_ALL_INFO *buf;
549
550                         cFYI(1, "sfu compat create special file");
551
552                         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
553                         if (buf == NULL) {
554                                 kfree(full_path);
555                                 rc = -ENOMEM;
556                                 FreeXid(xid);
557                                 return rc;
558                         }
559
560                         rc = CIFSSMBOpen(xid, pTcon, full_path,
561                                          FILE_CREATE, /* fail if exists */
562                                          GENERIC_WRITE /* BB would
563                                           WRITE_OWNER | WRITE_DAC be better? */,
564                                          /* Create a file and set the
565                                             file attribute to SYSTEM */
566                                          CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
567                                          &fileHandle, &oplock, buf,
568                                          cifs_sb->local_nls,
569                                          cifs_sb->mnt_cifs_flags &
570                                             CIFS_MOUNT_MAP_SPECIAL_CHR);
571
572                         /* BB FIXME - add handling for backlevel servers
573                            which need legacy open and check for all
574                            calls to SMBOpen for fallback to SMBLeagcyOpen */
575                         if (!rc) {
576                                 /* BB Do not bother to decode buf since no
577                                    local inode yet to put timestamps in,
578                                    but we can reuse it safely */
579                                 unsigned int bytes_written;
580                                 struct win_dev *pdev;
581                                 pdev = (struct win_dev *)buf;
582                                 if (S_ISCHR(mode)) {
583                                         memcpy(pdev->type, "IntxCHR", 8);
584                                         pdev->major =
585                                               cpu_to_le64(MAJOR(device_number));
586                                         pdev->minor =
587                                               cpu_to_le64(MINOR(device_number));
588                                         rc = CIFSSMBWrite(xid, pTcon,
589                                                 fileHandle,
590                                                 sizeof(struct win_dev),
591                                                 0, &bytes_written, (char *)pdev,
592                                                 NULL, 0);
593                                 } else if (S_ISBLK(mode)) {
594                                         memcpy(pdev->type, "IntxBLK", 8);
595                                         pdev->major =
596                                               cpu_to_le64(MAJOR(device_number));
597                                         pdev->minor =
598                                               cpu_to_le64(MINOR(device_number));
599                                         rc = CIFSSMBWrite(xid, pTcon,
600                                                 fileHandle,
601                                                 sizeof(struct win_dev),
602                                                 0, &bytes_written, (char *)pdev,
603                                                 NULL, 0);
604                                 } /* else if(S_ISFIFO */
605                                 CIFSSMBClose(xid, pTcon, fileHandle);
606                                 d_drop(direntry);
607                         }
608                         kfree(buf);
609                         /* add code here to set EAs */
610                 }
611         }
612
613         kfree(full_path);
614         FreeXid(xid);
615         return rc;
616 }
617
618 struct dentry *
619 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
620             struct nameidata *nd)
621 {
622         int xid;
623         int rc = 0; /* to get around spurious gcc warning, set to zero here */
624         __u32 oplock = 0;
625         __u16 fileHandle = 0;
626         bool posix_open = false;
627         struct cifs_sb_info *cifs_sb;
628         struct cifsTconInfo *pTcon;
629         struct inode *newInode = NULL;
630         char *full_path = NULL;
631         struct file *filp;
632
633         xid = GetXid();
634
635         cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
636               parent_dir_inode, direntry->d_name.name, direntry);
637
638         /* check whether path exists */
639
640         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
641         pTcon = cifs_sb->tcon;
642
643         /*
644          * Don't allow the separator character in a path component.
645          * The VFS will not allow "/", but "\" is allowed by posix.
646          */
647         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
648                 int i;
649                 for (i = 0; i < direntry->d_name.len; i++)
650                         if (direntry->d_name.name[i] == '\\') {
651                                 cFYI(1, "Invalid file name");
652                                 FreeXid(xid);
653                                 return ERR_PTR(-EINVAL);
654                         }
655         }
656
657         /*
658          * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
659          * the VFS handle the create.
660          */
661         if (nd && (nd->flags & LOOKUP_EXCL)) {
662                 d_instantiate(direntry, NULL);
663                 return NULL;
664         }
665
666         /* can not grab the rename sem here since it would
667         deadlock in the cases (beginning of sys_rename itself)
668         in which we already have the sb rename sem */
669         full_path = build_path_from_dentry(direntry);
670         if (full_path == NULL) {
671                 FreeXid(xid);
672                 return ERR_PTR(-ENOMEM);
673         }
674
675         if (direntry->d_inode != NULL) {
676                 cFYI(1, "non-NULL inode in lookup");
677         } else {
678                 cFYI(1, "NULL inode in lookup");
679         }
680         cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
681
682         /* Posix open is only called (at lookup time) for file create now.
683          * For opens (rather than creates), because we do not know if it
684          * is a file or directory yet, and current Samba no longer allows
685          * us to do posix open on dirs, we could end up wasting an open call
686          * on what turns out to be a dir. For file opens, we wait to call posix
687          * open till cifs_open.  It could be added here (lookup) in the future
688          * but the performance tradeoff of the extra network request when EISDIR
689          * or EACCES is returned would have to be weighed against the 50%
690          * reduction in network traffic in the other paths.
691          */
692         if (pTcon->unix_ext) {
693                 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
694                      (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
695                      (nd->intent.open.flags & O_CREAT)) {
696                         rc = cifs_posix_open(full_path, &newInode, nd->path.mnt,
697                                         parent_dir_inode->i_sb,
698                                         nd->intent.open.create_mode,
699                                         nd->intent.open.flags, &oplock,
700                                         &fileHandle, xid);
701                         /*
702                          * The check below works around a bug in POSIX
703                          * open in samba versions 3.3.1 and earlier where
704                          * open could incorrectly fail with invalid parameter.
705                          * If either that or op not supported returned, follow
706                          * the normal lookup.
707                          */
708                         if ((rc == 0) || (rc == -ENOENT))
709                                 posix_open = true;
710                         else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
711                                 pTcon->broken_posix_open = true;
712                 }
713                 if (!posix_open)
714                         rc = cifs_get_inode_info_unix(&newInode, full_path,
715                                                 parent_dir_inode->i_sb, xid);
716         } else
717                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
718                                 parent_dir_inode->i_sb, xid, NULL);
719
720         if ((rc == 0) && (newInode != NULL)) {
721                 if (pTcon->nocase)
722                         direntry->d_op = &cifs_ci_dentry_ops;
723                 else
724                         direntry->d_op = &cifs_dentry_ops;
725                 d_add(direntry, newInode);
726                 if (posix_open)
727                         filp = lookup_instantiate_filp(nd, direntry, NULL);
728                 /* since paths are not looked up by component - the parent
729                    directories are presumed to be good here */
730                 renew_parental_timestamps(direntry);
731
732         } else if (rc == -ENOENT) {
733                 rc = 0;
734                 direntry->d_time = jiffies;
735                 if (pTcon->nocase)
736                         direntry->d_op = &cifs_ci_dentry_ops;
737                 else
738                         direntry->d_op = &cifs_dentry_ops;
739                 d_add(direntry, NULL);
740         /*      if it was once a directory (but how can we tell?) we could do
741                 shrink_dcache_parent(direntry); */
742         } else if (rc != -EACCES) {
743                 cERROR(1, "Unexpected lookup error %d", rc);
744                 /* We special case check for Access Denied - since that
745                 is a common return code */
746         }
747
748         kfree(full_path);
749         FreeXid(xid);
750         return ERR_PTR(rc);
751 }
752
753 static int
754 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
755 {
756         int isValid = 1;
757
758         if (direntry->d_inode) {
759                 if (cifs_revalidate_dentry(direntry))
760                         return 0;
761         } else {
762                 cFYI(1, "neg dentry 0x%p name = %s",
763                          direntry, direntry->d_name.name);
764                 if (time_after(jiffies, direntry->d_time + HZ) ||
765                         !lookupCacheEnabled) {
766                         d_drop(direntry);
767                         isValid = 0;
768                 }
769         }
770
771         return isValid;
772 }
773
774 /* static int cifs_d_delete(struct dentry *direntry)
775 {
776         int rc = 0;
777
778         cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
779
780         return rc;
781 }     */
782
783 const struct dentry_operations cifs_dentry_ops = {
784         .d_revalidate = cifs_d_revalidate,
785 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
786 };
787
788 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
789 {
790         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
791         unsigned long hash;
792         int i;
793
794         hash = init_name_hash();
795         for (i = 0; i < q->len; i++)
796                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
797                                          hash);
798         q->hash = end_name_hash(hash);
799
800         return 0;
801 }
802
803 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
804                            struct qstr *b)
805 {
806         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
807
808         if ((a->len == b->len) &&
809             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
810                 /*
811                  * To preserve case, don't let an existing negative dentry's
812                  * case take precedence.  If a is not a negative dentry, this
813                  * should have no side effects
814                  */
815                 memcpy((void *)a->name, b->name, a->len);
816                 return 0;
817         }
818         return 1;
819 }
820
821 const struct dentry_operations cifs_ci_dentry_ops = {
822         .d_revalidate = cifs_d_revalidate,
823         .d_hash = cifs_ci_hash,
824         .d_compare = cifs_ci_compare,
825 };