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