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