]> bbs.cooldavid.org Git - net-next-2.6.git/blob - fs/cifs/dir.c
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[net-next-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 <linux/file.h>
29 #include "cifsfs.h"
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsproto.h"
33 #include "cifs_debug.h"
34 #include "cifs_fs_sb.h"
35
36 static void
37 renew_parental_timestamps(struct dentry *direntry)
38 {
39         /* BB check if there is a way to get the kernel to do this or if we
40            really need this */
41         do {
42                 direntry->d_time = jiffies;
43                 direntry = direntry->d_parent;
44         } while (!IS_ROOT(direntry));
45 }
46
47 /* Note: caller must free return buffer */
48 char *
49 build_path_from_dentry(struct dentry *direntry)
50 {
51         struct dentry *temp;
52         int namelen;
53         int pplen;
54         int dfsplen;
55         char *full_path;
56         char dirsep;
57         struct cifs_sb_info *cifs_sb;
58
59         if (direntry == NULL)
60                 return NULL;  /* not much we can do if dentry is freed and
61                 we need to reopen the file after it was closed implicitly
62                 when the server crashed */
63
64         cifs_sb = CIFS_SB(direntry->d_sb);
65         dirsep = CIFS_DIR_SEP(cifs_sb);
66         pplen = cifs_sb->prepathlen;
67         if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
68                 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
69         else
70                 dfsplen = 0;
71 cifs_bp_rename_retry:
72         namelen = pplen + dfsplen;
73         for (temp = direntry; !IS_ROOT(temp);) {
74                 namelen += (1 + temp->d_name.len);
75                 temp = temp->d_parent;
76                 if (temp == NULL) {
77                         cERROR(1, "corrupt dentry");
78                         return NULL;
79                 }
80         }
81
82         full_path = kmalloc(namelen+1, GFP_KERNEL);
83         if (full_path == NULL)
84                 return full_path;
85         full_path[namelen] = 0; /* trailing null */
86         for (temp = direntry; !IS_ROOT(temp);) {
87                 namelen -= 1 + temp->d_name.len;
88                 if (namelen < 0) {
89                         break;
90                 } else {
91                         full_path[namelen] = dirsep;
92                         strncpy(full_path + namelen + 1, temp->d_name.name,
93                                 temp->d_name.len);
94                         cFYI(0, "name: %s", full_path + namelen);
95                 }
96                 temp = temp->d_parent;
97                 if (temp == NULL) {
98                         cERROR(1, "corrupt dentry");
99                         kfree(full_path);
100                         return NULL;
101                 }
102         }
103         if (namelen != pplen + dfsplen) {
104                 cERROR(1, "did not end path lookup where expected namelen is %d",
105                         namelen);
106                 /* presumably this is only possible if racing with a rename
107                 of one of the parent directories  (we can not lock the dentries
108                 above us to prevent this, but retrying should be harmless) */
109                 kfree(full_path);
110                 goto cifs_bp_rename_retry;
111         }
112         /* DIR_SEP already set for byte  0 / vs \ but not for
113            subsequent slashes in prepath which currently must
114            be entered the right way - not sure if there is an alternative
115            since the '\' is a valid posix character so we can not switch
116            those safely to '/' if any are found in the middle of the prepath */
117         /* BB test paths to Windows with '/' in the midst of prepath */
118
119         if (dfsplen) {
120                 strncpy(full_path, 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         INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break);
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         file->private_data = pCifsFile;
183
184         return pCifsFile;
185 }
186
187 int cifs_posix_open(char *full_path, struct inode **pinode,
188                         struct super_block *sb, int mode, int oflags,
189                         __u32 *poplock, __u16 *pnetfid, int xid)
190 {
191         int rc;
192         FILE_UNIX_BASIC_INFO *presp_data;
193         __u32 posix_flags = 0;
194         struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
195         struct cifs_fattr fattr;
196
197         cFYI(1, "posix open %s", full_path);
198
199         presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
200         if (presp_data == NULL)
201                 return -ENOMEM;
202
203 /* So far cifs posix extensions can only map the following flags.
204    There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
205    so far we do not seem to need them, and we can treat them as local only */
206         if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
207                 (FMODE_READ | FMODE_WRITE))
208                 posix_flags = SMB_O_RDWR;
209         else if (oflags & FMODE_READ)
210                 posix_flags = SMB_O_RDONLY;
211         else if (oflags & FMODE_WRITE)
212                 posix_flags = SMB_O_WRONLY;
213         if (oflags & O_CREAT)
214                 posix_flags |= SMB_O_CREAT;
215         if (oflags & O_EXCL)
216                 posix_flags |= SMB_O_EXCL;
217         if (oflags & O_TRUNC)
218                 posix_flags |= SMB_O_TRUNC;
219         /* be safe and imply O_SYNC for O_DSYNC */
220         if (oflags & O_DSYNC)
221                 posix_flags |= SMB_O_SYNC;
222         if (oflags & O_DIRECTORY)
223                 posix_flags |= SMB_O_DIRECTORY;
224         if (oflags & O_NOFOLLOW)
225                 posix_flags |= SMB_O_NOFOLLOW;
226         if (oflags & O_DIRECT)
227                 posix_flags |= SMB_O_DIRECT;
228
229         mode &= ~current_umask();
230         rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
231                         pnetfid, presp_data, poplock, full_path,
232                         cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
233                                         CIFS_MOUNT_MAP_SPECIAL_CHR);
234         if (rc)
235                 goto posix_open_ret;
236
237         if (presp_data->Type == cpu_to_le32(-1))
238                 goto posix_open_ret; /* open ok, caller does qpathinfo */
239
240         if (!pinode)
241                 goto posix_open_ret; /* caller does not need info */
242
243         cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb);
244
245         /* get new inode and set it up */
246         if (*pinode == NULL) {
247                 cifs_fill_uniqueid(sb, &fattr);
248                 *pinode = cifs_iget(sb, &fattr);
249                 if (!*pinode) {
250                         rc = -ENOMEM;
251                         goto posix_open_ret;
252                 }
253         } else {
254                 cifs_fattr_to_inode(*pinode, &fattr);
255         }
256
257 posix_open_ret:
258         kfree(presp_data);
259         return rc;
260 }
261
262 static void setup_cifs_dentry(struct cifsTconInfo *tcon,
263                               struct dentry *direntry,
264                               struct inode *newinode)
265 {
266         if (tcon->nocase)
267                 direntry->d_op = &cifs_ci_dentry_ops;
268         else
269                 direntry->d_op = &cifs_dentry_ops;
270         d_instantiate(direntry, newinode);
271 }
272
273 /* Inode operations in similar order to how they appear in Linux file fs.h */
274
275 int
276 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
277                 struct nameidata *nd)
278 {
279         int rc = -ENOENT;
280         int xid;
281         int create_options = CREATE_NOT_DIR;
282         __u32 oplock = 0;
283         int oflags;
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                 goto cifs_create_out;
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 | SMB_O_CREAT;
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,
323                         inode->i_sb, 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                         if (newinode == NULL) /* query inode info */
331                                 goto cifs_create_get_file_info;
332                         else /* success, no need to query */
333                                 goto cifs_create_set_dentry;
334                 } else if ((rc != -EIO) && (rc != -EREMOTE) &&
335                          (rc != -EOPNOTSUPP) && (rc != -EINVAL))
336                         goto cifs_create_out;
337                 /* else fallthrough to retry, using older open call, this is
338                    case where server does not support this SMB level, and
339                    falsely claims capability (also get here for DFS case
340                    which should be rare for path not covered on files) */
341         }
342
343         if (nd && (nd->flags & LOOKUP_OPEN)) {
344                 /* if the file is going to stay open, then we
345                    need to set the desired access properly */
346                 desiredAccess = 0;
347                 if (oflags & FMODE_READ)
348                         desiredAccess |= GENERIC_READ; /* is this too little? */
349                 if (oflags & FMODE_WRITE)
350                         desiredAccess |= GENERIC_WRITE;
351
352                 if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
353                         disposition = FILE_CREATE;
354                 else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
355                         disposition = FILE_OVERWRITE_IF;
356                 else if ((oflags & O_CREAT) == O_CREAT)
357                         disposition = FILE_OPEN_IF;
358                 else
359                         cFYI(1, "Create flag not set in create function");
360         }
361
362         /* BB add processing to set equivalent of mode - e.g. via CreateX with
363            ACLs */
364
365         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
366         if (buf == NULL) {
367                 rc = -ENOMEM;
368                 goto cifs_create_out;
369         }
370
371         /*
372          * if we're not using unix extensions, see if we need to set
373          * ATTR_READONLY on the create call
374          */
375         if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
376                 create_options |= CREATE_OPTION_READONLY;
377
378         if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
379                 rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
380                          desiredAccess, create_options,
381                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
382                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
383         else
384                 rc = -EIO; /* no NT SMB support fall into legacy open below */
385
386         if (rc == -EIO) {
387                 /* old server, retry the open legacy style */
388                 rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
389                         desiredAccess, create_options,
390                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
391                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
392         }
393         if (rc) {
394                 cFYI(1, "cifs_create returned 0x%x", rc);
395                 goto cifs_create_out;
396         }
397
398         /* If Open reported that we actually created a file
399            then we now have to set the mode if possible */
400         if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
401                 struct cifs_unix_set_info_args args = {
402                                 .mode   = mode,
403                                 .ctime  = NO_CHANGE_64,
404                                 .atime  = NO_CHANGE_64,
405                                 .mtime  = NO_CHANGE_64,
406                                 .device = 0,
407                 };
408
409                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
410                         args.uid = (__u64) current_fsuid();
411                         if (inode->i_mode & S_ISGID)
412                                 args.gid = (__u64) inode->i_gid;
413                         else
414                                 args.gid = (__u64) current_fsgid();
415                 } else {
416                         args.uid = NO_CHANGE_64;
417                         args.gid = NO_CHANGE_64;
418                 }
419                 CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
420                                         cifs_sb->local_nls,
421                                         cifs_sb->mnt_cifs_flags &
422                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
423         } else {
424                 /* BB implement mode setting via Windows security
425                    descriptors e.g. */
426                 /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
427
428                 /* Could set r/o dos attribute if mode & 0222 == 0 */
429         }
430
431 cifs_create_get_file_info:
432         /* server might mask mode so we have to query for it */
433         if (tcon->unix_ext)
434                 rc = cifs_get_inode_info_unix(&newinode, full_path,
435                                               inode->i_sb, xid);
436         else {
437                 rc = cifs_get_inode_info(&newinode, full_path, buf,
438                                          inode->i_sb, xid, &fileHandle);
439                 if (newinode) {
440                         if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
441                                 newinode->i_mode = mode;
442                         if ((oplock & CIFS_CREATE_ACTION) &&
443                             (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
444                                 newinode->i_uid = current_fsuid();
445                                 if (inode->i_mode & S_ISGID)
446                                         newinode->i_gid = inode->i_gid;
447                                 else
448                                         newinode->i_gid = current_fsgid();
449                         }
450                 }
451         }
452
453 cifs_create_set_dentry:
454         if (rc == 0)
455                 setup_cifs_dentry(tcon, direntry, newinode);
456         else
457                 cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
458
459         if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
460                 struct cifsFileInfo *pfile_info;
461                 struct file *filp;
462
463                 filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
464                 if (IS_ERR(filp)) {
465                         rc = PTR_ERR(filp);
466                         CIFSSMBClose(xid, tcon, fileHandle);
467                         goto cifs_create_out;
468                 }
469
470                 pfile_info = cifs_new_fileinfo(newinode, fileHandle, filp,
471                                                nd->path.mnt, oflags);
472                 if (pfile_info == NULL) {
473                         fput(filp);
474                         CIFSSMBClose(xid, tcon, fileHandle);
475                         rc = -ENOMEM;
476                 }
477         } else {
478                 CIFSSMBClose(xid, tcon, fileHandle);
479         }
480
481 cifs_create_out:
482         kfree(buf);
483         kfree(full_path);
484         FreeXid(xid);
485         return rc;
486 }
487
488 int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
489                 dev_t device_number)
490 {
491         int rc = -EPERM;
492         int xid;
493         struct cifs_sb_info *cifs_sb;
494         struct cifsTconInfo *pTcon;
495         char *full_path = NULL;
496         struct inode *newinode = NULL;
497         int oplock = 0;
498         u16 fileHandle;
499         FILE_ALL_INFO *buf = NULL;
500         unsigned int bytes_written;
501         struct win_dev *pdev;
502
503         if (!old_valid_dev(device_number))
504                 return -EINVAL;
505
506         xid = GetXid();
507
508         cifs_sb = CIFS_SB(inode->i_sb);
509         pTcon = cifs_sb->tcon;
510
511         full_path = build_path_from_dentry(direntry);
512         if (full_path == NULL) {
513                 rc = -ENOMEM;
514                 goto mknod_out;
515         }
516
517         if (pTcon->unix_ext) {
518                 struct cifs_unix_set_info_args args = {
519                         .mode   = mode & ~current_umask(),
520                         .ctime  = NO_CHANGE_64,
521                         .atime  = NO_CHANGE_64,
522                         .mtime  = NO_CHANGE_64,
523                         .device = device_number,
524                 };
525                 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
526                         args.uid = (__u64) current_fsuid();
527                         args.gid = (__u64) current_fsgid();
528                 } else {
529                         args.uid = NO_CHANGE_64;
530                         args.gid = NO_CHANGE_64;
531                 }
532                 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
533                                             cifs_sb->local_nls,
534                                             cifs_sb->mnt_cifs_flags &
535                                                 CIFS_MOUNT_MAP_SPECIAL_CHR);
536                 if (rc)
537                         goto mknod_out;
538
539                 rc = cifs_get_inode_info_unix(&newinode, full_path,
540                                                 inode->i_sb, xid);
541                 if (pTcon->nocase)
542                         direntry->d_op = &cifs_ci_dentry_ops;
543                 else
544                         direntry->d_op = &cifs_dentry_ops;
545
546                 if (rc == 0)
547                         d_instantiate(direntry, newinode);
548                 goto mknod_out;
549         }
550
551         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
552                 goto mknod_out;
553
554
555         cFYI(1, "sfu compat create special file");
556
557         buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
558         if (buf == NULL) {
559                 kfree(full_path);
560                 rc = -ENOMEM;
561                 FreeXid(xid);
562                 return rc;
563         }
564
565         /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */
566         rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
567                          GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
568                          &fileHandle, &oplock, buf, cifs_sb->local_nls,
569                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
570         if (rc)
571                 goto mknod_out;
572
573         /* BB Do not bother to decode buf since no local inode yet to put
574          * timestamps in, but we can reuse it safely */
575
576         pdev = (struct win_dev *)buf;
577         if (S_ISCHR(mode)) {
578                 memcpy(pdev->type, "IntxCHR", 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_ISBLK(mode)) {
589                 memcpy(pdev->type, "IntxBLK", 8);
590                 pdev->major =
591                       cpu_to_le64(MAJOR(device_number));
592                 pdev->minor =
593                       cpu_to_le64(MINOR(device_number));
594                 rc = CIFSSMBWrite(xid, pTcon,
595                         fileHandle,
596                         sizeof(struct win_dev),
597                         0, &bytes_written, (char *)pdev,
598                         NULL, 0);
599         } /* else if (S_ISFIFO) */
600         CIFSSMBClose(xid, pTcon, fileHandle);
601         d_drop(direntry);
602
603         /* FIXME: add code here to set EAs */
604
605 mknod_out:
606         kfree(full_path);
607         kfree(buf);
608         FreeXid(xid);
609         return rc;
610 }
611
612 struct dentry *
613 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
614             struct nameidata *nd)
615 {
616         int xid;
617         int rc = 0; /* to get around spurious gcc warning, set to zero here */
618         __u32 oplock = 0;
619         __u16 fileHandle = 0;
620         bool posix_open = false;
621         struct cifs_sb_info *cifs_sb;
622         struct cifsTconInfo *pTcon;
623         struct cifsFileInfo *cfile;
624         struct inode *newInode = NULL;
625         char *full_path = NULL;
626         struct file *filp;
627
628         xid = GetXid();
629
630         cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
631               parent_dir_inode, direntry->d_name.name, direntry);
632
633         /* check whether path exists */
634
635         cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
636         pTcon = cifs_sb->tcon;
637
638         /*
639          * Don't allow the separator character in a path component.
640          * The VFS will not allow "/", but "\" is allowed by posix.
641          */
642         if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
643                 int i;
644                 for (i = 0; i < direntry->d_name.len; i++)
645                         if (direntry->d_name.name[i] == '\\') {
646                                 cFYI(1, "Invalid file name");
647                                 FreeXid(xid);
648                                 return ERR_PTR(-EINVAL);
649                         }
650         }
651
652         /*
653          * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
654          * the VFS handle the create.
655          */
656         if (nd && (nd->flags & LOOKUP_EXCL)) {
657                 d_instantiate(direntry, NULL);
658                 return NULL;
659         }
660
661         /* can not grab the rename sem here since it would
662         deadlock in the cases (beginning of sys_rename itself)
663         in which we already have the sb rename sem */
664         full_path = build_path_from_dentry(direntry);
665         if (full_path == NULL) {
666                 FreeXid(xid);
667                 return ERR_PTR(-ENOMEM);
668         }
669
670         if (direntry->d_inode != NULL) {
671                 cFYI(1, "non-NULL inode in lookup");
672         } else {
673                 cFYI(1, "NULL inode in lookup");
674         }
675         cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
676
677         /* Posix open is only called (at lookup time) for file create now.
678          * For opens (rather than creates), because we do not know if it
679          * is a file or directory yet, and current Samba no longer allows
680          * us to do posix open on dirs, we could end up wasting an open call
681          * on what turns out to be a dir. For file opens, we wait to call posix
682          * open till cifs_open.  It could be added here (lookup) in the future
683          * but the performance tradeoff of the extra network request when EISDIR
684          * or EACCES is returned would have to be weighed against the 50%
685          * reduction in network traffic in the other paths.
686          */
687         if (pTcon->unix_ext) {
688                 if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
689                      (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
690                      (nd->intent.open.flags & O_CREAT)) {
691                         rc = cifs_posix_open(full_path, &newInode,
692                                         parent_dir_inode->i_sb,
693                                         nd->intent.open.create_mode,
694                                         nd->intent.open.flags, &oplock,
695                                         &fileHandle, xid);
696                         /*
697                          * The check below works around a bug in POSIX
698                          * open in samba versions 3.3.1 and earlier where
699                          * open could incorrectly fail with invalid parameter.
700                          * If either that or op not supported returned, follow
701                          * the normal lookup.
702                          */
703                         if ((rc == 0) || (rc == -ENOENT))
704                                 posix_open = true;
705                         else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
706                                 pTcon->broken_posix_open = true;
707                 }
708                 if (!posix_open)
709                         rc = cifs_get_inode_info_unix(&newInode, full_path,
710                                                 parent_dir_inode->i_sb, xid);
711         } else
712                 rc = cifs_get_inode_info(&newInode, full_path, NULL,
713                                 parent_dir_inode->i_sb, xid, NULL);
714
715         if ((rc == 0) && (newInode != NULL)) {
716                 if (pTcon->nocase)
717                         direntry->d_op = &cifs_ci_dentry_ops;
718                 else
719                         direntry->d_op = &cifs_dentry_ops;
720                 d_add(direntry, newInode);
721                 if (posix_open) {
722                         filp = lookup_instantiate_filp(nd, direntry,
723                                                        generic_file_open);
724                         if (IS_ERR(filp)) {
725                                 rc = PTR_ERR(filp);
726                                 CIFSSMBClose(xid, pTcon, fileHandle);
727                                 goto lookup_out;
728                         }
729
730                         cfile = cifs_new_fileinfo(newInode, fileHandle, filp,
731                                                   nd->path.mnt,
732                                                   nd->intent.open.flags);
733                         if (cfile == NULL) {
734                                 fput(filp);
735                                 CIFSSMBClose(xid, pTcon, fileHandle);
736                                 rc = -ENOMEM;
737                                 goto lookup_out;
738                         }
739                 }
740                 /* since paths are not looked up by component - the parent
741                    directories are presumed to be good here */
742                 renew_parental_timestamps(direntry);
743
744         } else if (rc == -ENOENT) {
745                 rc = 0;
746                 direntry->d_time = jiffies;
747                 if (pTcon->nocase)
748                         direntry->d_op = &cifs_ci_dentry_ops;
749                 else
750                         direntry->d_op = &cifs_dentry_ops;
751                 d_add(direntry, NULL);
752         /*      if it was once a directory (but how can we tell?) we could do
753                 shrink_dcache_parent(direntry); */
754         } else if (rc != -EACCES) {
755                 cERROR(1, "Unexpected lookup error %d", rc);
756                 /* We special case check for Access Denied - since that
757                 is a common return code */
758         }
759
760 lookup_out:
761         kfree(full_path);
762         FreeXid(xid);
763         return ERR_PTR(rc);
764 }
765
766 static int
767 cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
768 {
769         int isValid = 1;
770
771         if (direntry->d_inode) {
772                 if (cifs_revalidate_dentry(direntry))
773                         return 0;
774         } else {
775                 cFYI(1, "neg dentry 0x%p name = %s",
776                          direntry, direntry->d_name.name);
777                 if (time_after(jiffies, direntry->d_time + HZ) ||
778                         !lookupCacheEnabled) {
779                         d_drop(direntry);
780                         isValid = 0;
781                 }
782         }
783
784         return isValid;
785 }
786
787 /* static int cifs_d_delete(struct dentry *direntry)
788 {
789         int rc = 0;
790
791         cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
792
793         return rc;
794 }     */
795
796 const struct dentry_operations cifs_dentry_ops = {
797         .d_revalidate = cifs_d_revalidate,
798 /* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
799 };
800
801 static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
802 {
803         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
804         unsigned long hash;
805         int i;
806
807         hash = init_name_hash();
808         for (i = 0; i < q->len; i++)
809                 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
810                                          hash);
811         q->hash = end_name_hash(hash);
812
813         return 0;
814 }
815
816 static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
817                            struct qstr *b)
818 {
819         struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
820
821         if ((a->len == b->len) &&
822             (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
823                 /*
824                  * To preserve case, don't let an existing negative dentry's
825                  * case take precedence.  If a is not a negative dentry, this
826                  * should have no side effects
827                  */
828                 memcpy((void *)a->name, b->name, a->len);
829                 return 0;
830         }
831         return 1;
832 }
833
834 const struct dentry_operations cifs_ci_dentry_ops = {
835         .d_revalidate = cifs_d_revalidate,
836         .d_hash = cifs_ci_hash,
837         .d_compare = cifs_ci_compare,
838 };