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