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