]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/cifs/dir.c
cifs: move cifs_new_fileinfo call out of cifs_posix_open
[karo-tx-linux.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 super_block *sb, int mode, int oflags,
192                         __u32 *poplock, __u16 *pnetfid, int xid)
193 {
194         int rc;
195         FILE_UNIX_BASIC_INFO *presp_data;
196         __u32 posix_flags = 0;
197         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
198         struct cifs_fattr fattr;
199
200         cFYI(1, "posix open %s", full_path);
201
202         presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
203         if (presp_data == NULL)
204                 return -ENOMEM;
205
206 /* So far cifs posix extensions can only map the following flags.
207    There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
208    so far we do not seem to need them, and we can treat them as local only */
209         if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
210                 (FMODE_READ | FMODE_WRITE))
211                 posix_flags = SMB_O_RDWR;
212         else if (oflags & FMODE_READ)
213                 posix_flags = SMB_O_RDONLY;
214         else if (oflags & FMODE_WRITE)
215                 posix_flags = SMB_O_WRONLY;
216         if (oflags & O_CREAT)
217                 posix_flags |= SMB_O_CREAT;
218         if (oflags & O_EXCL)
219                 posix_flags |= SMB_O_EXCL;
220         if (oflags & O_TRUNC)
221                 posix_flags |= SMB_O_TRUNC;
222         /* be safe and imply O_SYNC for O_DSYNC */
223         if (oflags & O_DSYNC)
224                 posix_flags |= SMB_O_SYNC;
225         if (oflags & O_DIRECTORY)
226                 posix_flags |= SMB_O_DIRECTORY;
227         if (oflags & O_NOFOLLOW)
228                 posix_flags |= SMB_O_NOFOLLOW;
229         if (oflags & O_DIRECT)
230                 posix_flags |= SMB_O_DIRECT;
231
232         mode &= ~current_umask();
233         rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
234                         pnetfid, presp_data, poplock, full_path,
235                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
236                                         CIFS_MOUNT_MAP_SPECIAL_CHR);
237         if (rc)
238                 goto posix_open_ret;
239
240         if (presp_data->Type == cpu_to_le32(-1))
241                 goto posix_open_ret; /* open ok, caller does qpathinfo */
242
243         if (!pinode)
244                 goto posix_open_ret; /* caller does not need info */
245
246         cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
247
248         /* get new inode and set it up */
249         if (*pinode == NULL) {
250                 cifs_fill_uniqueid(sb, &fattr);
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 posix_open_ret:
261         kfree(presp_data);
262         return rc;
263 }
264
265 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
266                               struct dentry *direntry,
267                               struct inode *newinode)
268 {
269         if (tcon->nocase)
270                 direntry->d_op = &cifs_ci_dentry_ops;
271         else
272                 direntry->d_op = &cifs_dentry_ops;
273         d_instantiate(direntry, newinode);
274 }
275
276 /* Inode operations in similar order to how they appear in Linux file fs.h */
277
278 int
279 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
280                 struct nameidata *nd)
281 {
282         int rc = -ENOENT;
283         int xid;
284         int create_options = CREATE_NOT_DIR;
285         __u32 oplock = 0;
286         int oflags;
287         /*
288          * BB below access is probably too much for mknod to request
289          *    but we have to do query and setpathinfo so requesting
290          *    less could fail (unless we want to request getatr and setatr
291          *    permissions (only).  At least for POSIX we do not have to
292          *    request so much.
293          */
294         int desiredAccess = GENERIC_READ | GENERIC_WRITE;
295         __u16 fileHandle;
296         struct cifs_sb_info *cifs_sb;
297         struct cifsTconInfo *tcon;
298         char *full_path = NULL;
299         FILE_ALL_INFO *buf = NULL;
300         struct inode *newinode = NULL;
301         int disposition = FILE_OVERWRITE_IF;
302
303         xid = GetXid();
304
305         cifs_sb = CIFS_SB(inode->i_sb);
306         tcon = cifs_sb->tcon;
307
308         full_path = build_path_from_dentry(direntry);
309         if (full_path == NULL) {
310                 rc = -ENOMEM;
311                 FreeXid(xid);
312                 return rc;
313         }
314
315         if (oplockEnabled)
316                 oplock = REQ_OPLOCK;
317
318         if (nd && (nd->flags & LOOKUP_OPEN))
319                 oflags = nd->intent.open.flags;
320         else
321                 oflags = FMODE_READ | SMB_O_CREAT;
322
323         if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
324             (CIFS_UNIX_POSIX_PATH_OPS_CAP &
325                         le64_to_cpu(tcon->fsUnixInfo.Capability))) {
326                 rc = cifs_posix_open(full_path, &newinode,
327                         inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
328                 /* EIO could indicate that (posix open) operation is not
329                    supported, despite what server claimed in capability
330                    negotation.  EREMOTE indicates DFS junction, which is not
331                    handled in posix open */
332
333                 if (rc == 0) {
334                         if (newinode == NULL) /* query inode info */
335                                 goto cifs_create_get_file_info;
336                         else /* success, no need to query */
337                                 goto cifs_create_set_dentry;
338                 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
339                          (rc != -EOPNOTSUPP) && (rc != -EINVAL))
340                         goto cifs_create_out;
341                 /* else fallthrough to retry, using older open call, this is
342                    case where server does not support this SMB level, and
343                    falsely claims capability (also get here for DFS case
344                    which should be rare for path not covered on files) */
345         }
346
347         if (nd && (nd->flags & LOOKUP_OPEN)) {
348                 /* if the file is going to stay open, then we
349                    need to set the desired access properly */
350                 desiredAccess = 0;
351                 if (oflags & FMODE_READ)
352                         desiredAccess |= GENERIC_READ; /* is this too little? */
353                 if (oflags & FMODE_WRITE)
354                         desiredAccess |= GENERIC_WRITE;
355
356                 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
357                         disposition = FILE_CREATE;
358                 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
359                         disposition = FILE_OVERWRITE_IF;
360                 else if ((oflags & O_CREAT) == O_CREAT)
361                         disposition = FILE_OPEN_IF;
362                 else
363                         cFYI(1, "Create flag not set in create function");
364         }
365
366         /* BB add processing to set equivalent of mode - e.g. via CreateX with
367            ACLs */
368
369         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
370         if (buf == NULL) {
371                 kfree(full_path);
372                 FreeXid(xid);
373                 return -ENOMEM;
374         }
375
376         /*
377          * if we're not using unix extensions, see if we need to set
378          * ATTR_READONLY on the create call
379          */
380         if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
381                 create_options |= CREATE_OPTION_READONLY;
382
383         if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
384                 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
385                          desiredAccess, create_options,
386                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
387                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
388         else
389                 rc = -EIO; /* no NT SMB support fall into legacy open below */
390
391         if (rc == -EIO) {
392                 /* old server, retry the open legacy style */
393                 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
394                         desiredAccess, create_options,
395                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
396                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
397         }
398         if (rc) {
399                 cFYI(1, "cifs_create returned 0x%x", rc);
400                 goto cifs_create_out;
401         }
402
403         /* If Open reported that we actually created a file
404            then we now have to set the mode if possible */
405         if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
406                 struct cifs_unix_set_info_args args = {
407                                 .mode   = mode,
408                                 .ctime  = NO_CHANGE_64,
409                                 .atime  = NO_CHANGE_64,
410                                 .mtime  = NO_CHANGE_64,
411                                 .device = 0,
412                 };
413
414                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
415                         args.uid = (__u64) current_fsuid();
416                         if (inode->i_mode & S_ISGID)
417                                 args.gid = (__u64) inode->i_gid;
418                         else
419                                 args.gid = (__u64) current_fsgid();
420                 } else {
421                         args.uid = NO_CHANGE_64;
422                         args.gid = NO_CHANGE_64;
423                 }
424                 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
425                                         cifs_sb->local_nls,
426                                         cifs_sb->mnt_cifs_flags &
427                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
428         } else {
429                 /* BB implement mode setting via Windows security
430                    descriptors e.g. */
431                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
432
433                 /* Could set r/o dos attribute if mode & 0222 == 0 */
434         }
435
436 cifs_create_get_file_info:
437         /* server might mask mode so we have to query for it */
438         if (tcon->unix_ext)
439                 rc = cifs_get_inode_info_unix(&newinode, full_path,
440                                               inode->i_sb, xid);
441         else {
442                 rc = cifs_get_inode_info(&newinode, full_path, buf,
443                                          inode->i_sb, xid, &fileHandle);
444                 if (newinode) {
445                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
446                                 newinode->i_mode = mode;
447                         if ((oplock & CIFS_CREATE_ACTION) &&
448                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
449                                 newinode->i_uid = current_fsuid();
450                                 if (inode->i_mode & S_ISGID)
451                                         newinode->i_gid = inode->i_gid;
452                                 else
453                                         newinode->i_gid = current_fsgid();
454                         }
455                 }
456         }
457
458 cifs_create_set_dentry:
459         if (rc == 0)
460                 setup_cifs_dentry(tcon, direntry, newinode);
461         else
462                 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
463
464         if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
465                 struct cifsFileInfo *pfile_info;
466                 /*
467                  * cifs_fill_filedata() takes care of setting cifsFileInfo
468                  * pointer to file->private_data.
469                  */
470                 pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL,
471                                                nd->path.mnt, oflags);
472                 if (pfile_info == NULL)
473                         rc = -ENOMEM;
474         } else {
475                 CIFSSMBClose(xid, tcon, fileHandle);
476         }
477
478 cifs_create_out:
479         kfree(buf);
480         kfree(full_path);
481         FreeXid(xid);
482         return rc;
483 }
484
485 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
486                 dev_t device_number)
487 {
488         int rc = -EPERM;
489         int xid;
490         struct cifs_sb_info *cifs_sb;
491         struct cifsTconInfo *pTcon;
492         char *full_path = NULL;
493         struct inode *newinode = NULL;
494
495         if (!old_valid_dev(device_number))
496                 return -EINVAL;
497
498         xid = GetXid();
499
500         cifs_sb = CIFS_SB(inode->i_sb);
501         pTcon = cifs_sb->tcon;
502
503         full_path = build_path_from_dentry(direntry);
504         if (full_path == NULL)
505                 rc = -ENOMEM;
506         else if (pTcon->unix_ext) {
507                 struct cifs_unix_set_info_args args = {
508                         .mode   = mode & ~current_umask(),
509                         .ctime  = NO_CHANGE_64,
510                         .atime  = NO_CHANGE_64,
511                         .mtime  = NO_CHANGE_64,
512                         .device = device_number,
513                 };
514                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
515                         args.uid = (__u64) current_fsuid();
516                         args.gid = (__u64) current_fsgid();
517                 } else {
518                         args.uid = NO_CHANGE_64;
519                         args.gid = NO_CHANGE_64;
520                 }
521                 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
522                                             cifs_sb->local_nls,
523                                             cifs_sb->mnt_cifs_flags &
524                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
525
526                 if (!rc) {
527                         rc = cifs_get_inode_info_unix(&newinode, full_path,
528                                                 inode->i_sb, xid);
529                         if (pTcon->nocase)
530                                 direntry->d_op = &cifs_ci_dentry_ops;
531                         else
532                                 direntry->d_op = &cifs_dentry_ops;
533                         if (rc == 0)
534                                 d_instantiate(direntry, newinode);
535                 }
536         } else {
537                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
538                         int oplock = 0;
539                         u16 fileHandle;
540                         FILE_ALL_INFO *buf;
541
542                         cFYI(1, "sfu compat create special file");
543
544                         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
545                         if (buf == NULL) {
546                                 kfree(full_path);
547                                 rc = -ENOMEM;
548                                 FreeXid(xid);
549                                 return rc;
550                         }
551
552                         rc = CIFSSMBOpen(xid, pTcon, full_path,
553                                          FILE_CREATE, /* fail if exists */
554                                          GENERIC_WRITE /* BB would
555                                           WRITE_OWNER | WRITE_DAC be better? */,
556                                          /* Create a file and set the
557                                             file attribute to SYSTEM */
558                                          CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
559                                          &fileHandle, &oplock, buf,
560                                          cifs_sb->local_nls,
561                                          cifs_sb->mnt_cifs_flags &
562                                             CIFS_MOUNT_MAP_SPECIAL_CHR);
563
564                         /* BB FIXME - add handling for backlevel servers
565                            which need legacy open and check for all
566                            calls to SMBOpen for fallback to SMBLeagcyOpen */
567                         if (!rc) {
568                                 /* BB Do not bother to decode buf since no
569                                    local inode yet to put timestamps in,
570                                    but we can reuse it safely */
571                                 unsigned int bytes_written;
572                                 struct win_dev *pdev;
573                                 pdev = (struct win_dev *)buf;
574                                 if (S_ISCHR(mode)) {
575                                         memcpy(pdev->type, "IntxCHR", 8);
576                                         pdev->major =
577                                               cpu_to_le64(MAJOR(device_number));
578                                         pdev->minor =
579                                               cpu_to_le64(MINOR(device_number));
580                                         rc = CIFSSMBWrite(xid, pTcon,
581                                                 fileHandle,
582                                                 sizeof(struct win_dev),
583                                                 0, &bytes_written, (char *)pdev,
584                                                 NULL, 0);
585                                 } else if (S_ISBLK(mode)) {
586                                         memcpy(pdev->type, "IntxBLK", 8);
587                                         pdev->major =
588                                               cpu_to_le64(MAJOR(device_number));
589                                         pdev->minor =
590                                               cpu_to_le64(MINOR(device_number));
591                                         rc = CIFSSMBWrite(xid, pTcon,
592                                                 fileHandle,
593                                                 sizeof(struct win_dev),
594                                                 0, &bytes_written, (char *)pdev,
595                                                 NULL, 0);
596                                 } /* else if(S_ISFIFO */
597                                 CIFSSMBClose(xid, pTcon, fileHandle);
598                                 d_drop(direntry);
599                         }
600                         kfree(buf);
601                         /* add code here to set EAs */
602                 }
603         }
604
605         kfree(full_path);
606         FreeXid(xid);
607         return rc;
608 }
609
610 struct dentry *
611 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
612             struct nameidata *nd)
613 {
614         int xid;
615         int rc = 0; /* to get around spurious gcc warning, set to zero here */
616         __u32 oplock = 0;
617         __u16 fileHandle = 0;
618         bool posix_open = false;
619         struct cifs_sb_info *cifs_sb;
620         struct cifsTconInfo *pTcon;
621         struct cifsFileInfo *cfile;
622         struct inode *newInode = NULL;
623         char *full_path = NULL;
624         struct file *filp;
625
626         xid = GetXid();
627
628         cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
629               parent_dir_inode, direntry->d_name.name, direntry);
630
631         /* check whether path exists */
632
633         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
634         pTcon = cifs_sb->tcon;
635
636         /*
637          * Don't allow the separator character in a path component.
638          * The VFS will not allow "/", but "\" is allowed by posix.
639          */
640         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
641                 int i;
642                 for (i = 0; i < direntry->d_name.len; i++)
643                         if (direntry->d_name.name[i] == '\\') {
644                                 cFYI(1, "Invalid file name");
645                                 FreeXid(xid);
646                                 return ERR_PTR(-EINVAL);
647                         }
648         }
649
650         /*
651          * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
652          * the VFS handle the create.
653          */
654         if (nd && (nd->flags & LOOKUP_EXCL)) {
655                 d_instantiate(direntry, NULL);
656                 return NULL;
657         }
658
659         /* can not grab the rename sem here since it would
660         deadlock in the cases (beginning of sys_rename itself)
661         in which we already have the sb rename sem */
662         full_path = build_path_from_dentry(direntry);
663         if (full_path == NULL) {
664                 FreeXid(xid);
665                 return ERR_PTR(-ENOMEM);
666         }
667
668         if (direntry->d_inode != NULL) {
669                 cFYI(1, "non-NULL inode in lookup");
670         } else {
671                 cFYI(1, "NULL inode in lookup");
672         }
673         cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
674
675         /* Posix open is only called (at lookup time) for file create now.
676          * For opens (rather than creates), because we do not know if it
677          * is a file or directory yet, and current Samba no longer allows
678          * us to do posix open on dirs, we could end up wasting an open call
679          * on what turns out to be a dir. For file opens, we wait to call posix
680          * open till cifs_open.  It could be added here (lookup) in the future
681          * but the performance tradeoff of the extra network request when EISDIR
682          * or EACCES is returned would have to be weighed against the 50%
683          * reduction in network traffic in the other paths.
684          */
685         if (pTcon->unix_ext) {
686                 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
687                      (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
688                      (nd->intent.open.flags & O_CREAT)) {
689                         rc = cifs_posix_open(full_path, &newInode,
690                                         parent_dir_inode->i_sb,
691                                         nd->intent.open.create_mode,
692                                         nd->intent.open.flags, &oplock,
693                                         &fileHandle, xid);
694                         /*
695                          * The check below works around a bug in POSIX
696                          * open in samba versions 3.3.1 and earlier where
697                          * open could incorrectly fail with invalid parameter.
698                          * If either that or op not supported returned, follow
699                          * the normal lookup.
700                          */
701                         if ((rc == 0) || (rc == -ENOENT))
702                                 posix_open = true;
703                         else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
704                                 pTcon->broken_posix_open = true;
705                 }
706                 if (!posix_open)
707                         rc = cifs_get_inode_info_unix(&newInode, full_path,
708                                                 parent_dir_inode->i_sb, xid);
709         } else
710                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
711                                 parent_dir_inode->i_sb, xid, NULL);
712
713         if ((rc == 0) && (newInode != NULL)) {
714                 if (pTcon->nocase)
715                         direntry->d_op = &cifs_ci_dentry_ops;
716                 else
717                         direntry->d_op = &cifs_dentry_ops;
718                 d_add(direntry, newInode);
719                 if (posix_open) {
720                         cfile = cifs_new_fileinfo(newInode, fileHandle, NULL,
721                                                   nd->path.mnt,
722                                                   nd->intent.open.flags);
723                         if (cfile == NULL) {
724                                 CIFSSMBClose(xid, pTcon, fileHandle);
725                                 rc = -ENOMEM;
726                                 goto lookup_out;
727                         }
728                         filp = lookup_instantiate_filp(nd, direntry, NULL);
729                 }
730                 /* since paths are not looked up by component - the parent
731                    directories are presumed to be good here */
732                 renew_parental_timestamps(direntry);
733
734         } else if (rc == -ENOENT) {
735                 rc = 0;
736                 direntry->d_time = jiffies;
737                 if (pTcon->nocase)
738                         direntry->d_op = &cifs_ci_dentry_ops;
739                 else
740                         direntry->d_op = &cifs_dentry_ops;
741                 d_add(direntry, NULL);
742         /*      if it was once a directory (but how can we tell?) we could do
743                 shrink_dcache_parent(direntry); */
744         } else if (rc != -EACCES) {
745                 cERROR(1, "Unexpected lookup error %d", rc);
746                 /* We special case check for Access Denied - since that
747                 is a common return code */
748         }
749
750 lookup_out:
751         kfree(full_path);
752         FreeXid(xid);
753         return ERR_PTR(rc);
754 }
755
756 static int
757 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
758 {
759         int isValid = 1;
760
761         if (direntry->d_inode) {
762                 if (cifs_revalidate_dentry(direntry))
763                         return 0;
764         } else {
765                 cFYI(1, "neg dentry 0x%p name = %s",
766                          direntry, direntry->d_name.name);
767                 if (time_after(jiffies, direntry->d_time + HZ) ||
768                         !lookupCacheEnabled) {
769                         d_drop(direntry);
770                         isValid = 0;
771                 }
772         }
773
774         return isValid;
775 }
776
777 /* static int cifs_d_delete(struct dentry *direntry)
778 {
779         int rc = 0;
780
781         cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
782
783         return rc;
784 }     */
785
786 const struct dentry_operations cifs_dentry_ops = {
787         .d_revalidate = cifs_d_revalidate,
788 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
789 };
790
791 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
792 {
793         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
794         unsigned long hash;
795         int i;
796
797         hash = init_name_hash();
798         for (i = 0; i < q->len; i++)
799                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
800                                          hash);
801         q->hash = end_name_hash(hash);
802
803         return 0;
804 }
805
806 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
807                            struct qstr *b)
808 {
809         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
810
811         if ((a->len == b->len) &&
812             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
813                 /*
814                  * To preserve case, don't let an existing negative dentry's
815                  * case take precedence.  If a is not a negative dentry, this
816                  * should have no side effects
817                  */
818                 memcpy((void *)a->name, b->name, a->len);
819                 return 0;
820         }
821         return 1;
822 }
823
824 const struct dentry_operations cifs_ci_dentry_ops = {
825         .d_revalidate = cifs_d_revalidate,
826         .d_hash = cifs_ci_hash,
827         .d_compare = cifs_ci_compare,
828 };