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