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