linux/fs/cifs/dir.c
<<
>>
Prefs
   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
  36static void
  37renew_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 */
  48char *
  49build_path_from_dentry(struct dentry *direntry)
  50{
  51        struct dentry *temp;
  52        int namelen;
  53        int dfsplen;
  54        char *full_path;
  55        char dirsep;
  56        struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
  57        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
  58        unsigned seq;
  59
  60        dirsep = CIFS_DIR_SEP(cifs_sb);
  61        if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
  62                dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
  63        else
  64                dfsplen = 0;
  65cifs_bp_rename_retry:
  66        namelen = dfsplen;
  67        seq = read_seqbegin(&rename_lock);
  68        rcu_read_lock();
  69        for (temp = direntry; !IS_ROOT(temp);) {
  70                namelen += (1 + temp->d_name.len);
  71                temp = temp->d_parent;
  72                if (temp == NULL) {
  73                        cERROR(1, "corrupt dentry");
  74                        rcu_read_unlock();
  75                        return NULL;
  76                }
  77        }
  78        rcu_read_unlock();
  79
  80        full_path = kmalloc(namelen+1, GFP_KERNEL);
  81        if (full_path == NULL)
  82                return full_path;
  83        full_path[namelen] = 0; /* trailing null */
  84        rcu_read_lock();
  85        for (temp = direntry; !IS_ROOT(temp);) {
  86                spin_lock(&temp->d_lock);
  87                namelen -= 1 + temp->d_name.len;
  88                if (namelen < 0) {
  89                        spin_unlock(&temp->d_lock);
  90                        break;
  91                } else {
  92                        full_path[namelen] = dirsep;
  93                        strncpy(full_path + namelen + 1, temp->d_name.name,
  94                                temp->d_name.len);
  95                        cFYI(0, "name: %s", full_path + namelen);
  96                }
  97                spin_unlock(&temp->d_lock);
  98                temp = temp->d_parent;
  99                if (temp == NULL) {
 100                        cERROR(1, "corrupt dentry");
 101                        rcu_read_unlock();
 102                        kfree(full_path);
 103                        return NULL;
 104                }
 105        }
 106        rcu_read_unlock();
 107        if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
 108                cFYI(1, "did not end path lookup where expected. namelen=%d "
 109                        "dfsplen=%d", namelen, dfsplen);
 110                /* presumably this is only possible if racing with a rename
 111                of one of the parent directories  (we can not lock the dentries
 112                above us to prevent this, but retrying should be harmless) */
 113                kfree(full_path);
 114                goto cifs_bp_rename_retry;
 115        }
 116        /* DIR_SEP already set for byte  0 / vs \ but not for
 117           subsequent slashes in prepath which currently must
 118           be entered the right way - not sure if there is an alternative
 119           since the '\' is a valid posix character so we can not switch
 120           those safely to '/' if any are found in the middle of the prepath */
 121        /* BB test paths to Windows with '/' in the midst of prepath */
 122
 123        if (dfsplen) {
 124                strncpy(full_path, tcon->treeName, dfsplen);
 125                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
 126                        int i;
 127                        for (i = 0; i < dfsplen; i++) {
 128                                if (full_path[i] == '\\')
 129                                        full_path[i] = '/';
 130                        }
 131                }
 132        }
 133        return full_path;
 134}
 135
 136/* Inode operations in similar order to how they appear in Linux file fs.h */
 137
 138int
 139cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
 140                struct nameidata *nd)
 141{
 142        int rc = -ENOENT;
 143        int xid;
 144        int create_options = CREATE_NOT_DIR;
 145        __u32 oplock = 0;
 146        int oflags;
 147        /*
 148         * BB below access is probably too much for mknod to request
 149         *    but we have to do query and setpathinfo so requesting
 150         *    less could fail (unless we want to request getatr and setatr
 151         *    permissions (only).  At least for POSIX we do not have to
 152         *    request so much.
 153         */
 154        int desiredAccess = GENERIC_READ | GENERIC_WRITE;
 155        __u16 fileHandle;
 156        struct cifs_sb_info *cifs_sb;
 157        struct tcon_link *tlink;
 158        struct cifs_tcon *tcon;
 159        char *full_path = NULL;
 160        FILE_ALL_INFO *buf = NULL;
 161        struct inode *newinode = NULL;
 162        int disposition = FILE_OVERWRITE_IF;
 163
 164        xid = GetXid();
 165
 166        cifs_sb = CIFS_SB(inode->i_sb);
 167        tlink = cifs_sb_tlink(cifs_sb);
 168        if (IS_ERR(tlink)) {
 169                FreeXid(xid);
 170                return PTR_ERR(tlink);
 171        }
 172        tcon = tlink_tcon(tlink);
 173
 174        if (enable_oplocks)
 175                oplock = REQ_OPLOCK;
 176
 177        if (nd)
 178                oflags = nd->intent.open.file->f_flags;
 179        else
 180                oflags = O_RDONLY | O_CREAT;
 181
 182        full_path = build_path_from_dentry(direntry);
 183        if (full_path == NULL) {
 184                rc = -ENOMEM;
 185                goto cifs_create_out;
 186        }
 187
 188        if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
 189            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 190                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
 191                rc = cifs_posix_open(full_path, &newinode,
 192                        inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
 193                /* EIO could indicate that (posix open) operation is not
 194                   supported, despite what server claimed in capability
 195                   negotiation.  EREMOTE indicates DFS junction, which is not
 196                   handled in posix open */
 197
 198                if (rc == 0) {
 199                        if (newinode == NULL) /* query inode info */
 200                                goto cifs_create_get_file_info;
 201                        else /* success, no need to query */
 202                                goto cifs_create_set_dentry;
 203                } else if ((rc != -EIO) && (rc != -EREMOTE) &&
 204                         (rc != -EOPNOTSUPP) && (rc != -EINVAL))
 205                        goto cifs_create_out;
 206                /* else fallthrough to retry, using older open call, this is
 207                   case where server does not support this SMB level, and
 208                   falsely claims capability (also get here for DFS case
 209                   which should be rare for path not covered on files) */
 210        }
 211
 212        if (nd) {
 213                /* if the file is going to stay open, then we
 214                   need to set the desired access properly */
 215                desiredAccess = 0;
 216                if (OPEN_FMODE(oflags) & FMODE_READ)
 217                        desiredAccess |= GENERIC_READ; /* is this too little? */
 218                if (OPEN_FMODE(oflags) & FMODE_WRITE)
 219                        desiredAccess |= GENERIC_WRITE;
 220
 221                if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
 222                        disposition = FILE_CREATE;
 223                else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
 224                        disposition = FILE_OVERWRITE_IF;
 225                else if ((oflags & O_CREAT) == O_CREAT)
 226                        disposition = FILE_OPEN_IF;
 227                else
 228                        cFYI(1, "Create flag not set in create function");
 229        }
 230
 231        /* BB add processing to set equivalent of mode - e.g. via CreateX with
 232           ACLs */
 233
 234        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
 235        if (buf == NULL) {
 236                rc = -ENOMEM;
 237                goto cifs_create_out;
 238        }
 239
 240        /*
 241         * if we're not using unix extensions, see if we need to set
 242         * ATTR_READONLY on the create call
 243         */
 244        if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
 245                create_options |= CREATE_OPTION_READONLY;
 246
 247        if (backup_cred(cifs_sb))
 248                create_options |= CREATE_OPEN_BACKUP_INTENT;
 249
 250        if (tcon->ses->capabilities & CAP_NT_SMBS)
 251                rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
 252                         desiredAccess, create_options,
 253                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
 254                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 255        else
 256                rc = -EIO; /* no NT SMB support fall into legacy open below */
 257
 258        if (rc == -EIO) {
 259                /* old server, retry the open legacy style */
 260                rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
 261                        desiredAccess, create_options,
 262                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
 263                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 264        }
 265        if (rc) {
 266                cFYI(1, "cifs_create returned 0x%x", rc);
 267                goto cifs_create_out;
 268        }
 269
 270        /* If Open reported that we actually created a file
 271           then we now have to set the mode if possible */
 272        if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
 273                struct cifs_unix_set_info_args args = {
 274                                .mode   = mode,
 275                                .ctime  = NO_CHANGE_64,
 276                                .atime  = NO_CHANGE_64,
 277                                .mtime  = NO_CHANGE_64,
 278                                .device = 0,
 279                };
 280
 281                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 282                        args.uid = (__u64) current_fsuid();
 283                        if (inode->i_mode & S_ISGID)
 284                                args.gid = (__u64) inode->i_gid;
 285                        else
 286                                args.gid = (__u64) current_fsgid();
 287                } else {
 288                        args.uid = NO_CHANGE_64;
 289                        args.gid = NO_CHANGE_64;
 290                }
 291                CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
 292                                        current->tgid);
 293        } else {
 294                /* BB implement mode setting via Windows security
 295                   descriptors e.g. */
 296                /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
 297
 298                /* Could set r/o dos attribute if mode & 0222 == 0 */
 299        }
 300
 301cifs_create_get_file_info:
 302        /* server might mask mode so we have to query for it */
 303        if (tcon->unix_ext)
 304                rc = cifs_get_inode_info_unix(&newinode, full_path,
 305                                              inode->i_sb, xid);
 306        else {
 307                rc = cifs_get_inode_info(&newinode, full_path, buf,
 308                                         inode->i_sb, xid, &fileHandle);
 309                if (newinode) {
 310                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
 311                                newinode->i_mode = mode;
 312                        if ((oplock & CIFS_CREATE_ACTION) &&
 313                            (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
 314                                newinode->i_uid = current_fsuid();
 315                                if (inode->i_mode & S_ISGID)
 316                                        newinode->i_gid = inode->i_gid;
 317                                else
 318                                        newinode->i_gid = current_fsgid();
 319                        }
 320                }
 321        }
 322
 323cifs_create_set_dentry:
 324        if (rc == 0)
 325                d_instantiate(direntry, newinode);
 326        else
 327                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
 328
 329        if (newinode && nd) {
 330                struct cifsFileInfo *pfile_info;
 331                struct file *filp;
 332
 333                filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
 334                if (IS_ERR(filp)) {
 335                        rc = PTR_ERR(filp);
 336                        CIFSSMBClose(xid, tcon, fileHandle);
 337                        goto cifs_create_out;
 338                }
 339
 340                pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
 341                if (pfile_info == NULL) {
 342                        fput(filp);
 343                        CIFSSMBClose(xid, tcon, fileHandle);
 344                        rc = -ENOMEM;
 345                }
 346        } else {
 347                CIFSSMBClose(xid, tcon, fileHandle);
 348        }
 349
 350cifs_create_out:
 351        kfree(buf);
 352        kfree(full_path);
 353        cifs_put_tlink(tlink);
 354        FreeXid(xid);
 355        return rc;
 356}
 357
 358int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
 359                dev_t device_number)
 360{
 361        int rc = -EPERM;
 362        int xid;
 363        int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
 364        struct cifs_sb_info *cifs_sb;
 365        struct tcon_link *tlink;
 366        struct cifs_tcon *pTcon;
 367        struct cifs_io_parms io_parms;
 368        char *full_path = NULL;
 369        struct inode *newinode = NULL;
 370        int oplock = 0;
 371        u16 fileHandle;
 372        FILE_ALL_INFO *buf = NULL;
 373        unsigned int bytes_written;
 374        struct win_dev *pdev;
 375
 376        if (!old_valid_dev(device_number))
 377                return -EINVAL;
 378
 379        cifs_sb = CIFS_SB(inode->i_sb);
 380        tlink = cifs_sb_tlink(cifs_sb);
 381        if (IS_ERR(tlink))
 382                return PTR_ERR(tlink);
 383
 384        pTcon = tlink_tcon(tlink);
 385
 386        xid = GetXid();
 387
 388        full_path = build_path_from_dentry(direntry);
 389        if (full_path == NULL) {
 390                rc = -ENOMEM;
 391                goto mknod_out;
 392        }
 393
 394        if (pTcon->unix_ext) {
 395                struct cifs_unix_set_info_args args = {
 396                        .mode   = mode & ~current_umask(),
 397                        .ctime  = NO_CHANGE_64,
 398                        .atime  = NO_CHANGE_64,
 399                        .mtime  = NO_CHANGE_64,
 400                        .device = device_number,
 401                };
 402                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 403                        args.uid = (__u64) current_fsuid();
 404                        args.gid = (__u64) current_fsgid();
 405                } else {
 406                        args.uid = NO_CHANGE_64;
 407                        args.gid = NO_CHANGE_64;
 408                }
 409                rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
 410                                            cifs_sb->local_nls,
 411                                            cifs_sb->mnt_cifs_flags &
 412                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 413                if (rc)
 414                        goto mknod_out;
 415
 416                rc = cifs_get_inode_info_unix(&newinode, full_path,
 417                                                inode->i_sb, xid);
 418
 419                if (rc == 0)
 420                        d_instantiate(direntry, newinode);
 421                goto mknod_out;
 422        }
 423
 424        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
 425                goto mknod_out;
 426
 427
 428        cFYI(1, "sfu compat create special file");
 429
 430        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
 431        if (buf == NULL) {
 432                kfree(full_path);
 433                rc = -ENOMEM;
 434                FreeXid(xid);
 435                return rc;
 436        }
 437
 438        if (backup_cred(cifs_sb))
 439                create_options |= CREATE_OPEN_BACKUP_INTENT;
 440
 441        rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE,
 442                         GENERIC_WRITE, create_options,
 443                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
 444                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 445        if (rc)
 446                goto mknod_out;
 447
 448        /* BB Do not bother to decode buf since no local inode yet to put
 449         * timestamps in, but we can reuse it safely */
 450
 451        pdev = (struct win_dev *)buf;
 452        io_parms.netfid = fileHandle;
 453        io_parms.pid = current->tgid;
 454        io_parms.tcon = pTcon;
 455        io_parms.offset = 0;
 456        io_parms.length = sizeof(struct win_dev);
 457        if (S_ISCHR(mode)) {
 458                memcpy(pdev->type, "IntxCHR", 8);
 459                pdev->major =
 460                      cpu_to_le64(MAJOR(device_number));
 461                pdev->minor =
 462                      cpu_to_le64(MINOR(device_number));
 463                rc = CIFSSMBWrite(xid, &io_parms,
 464                        &bytes_written, (char *)pdev,
 465                        NULL, 0);
 466        } else if (S_ISBLK(mode)) {
 467                memcpy(pdev->type, "IntxBLK", 8);
 468                pdev->major =
 469                      cpu_to_le64(MAJOR(device_number));
 470                pdev->minor =
 471                      cpu_to_le64(MINOR(device_number));
 472                rc = CIFSSMBWrite(xid, &io_parms,
 473                        &bytes_written, (char *)pdev,
 474                        NULL, 0);
 475        } /* else if (S_ISFIFO) */
 476        CIFSSMBClose(xid, pTcon, fileHandle);
 477        d_drop(direntry);
 478
 479        /* FIXME: add code here to set EAs */
 480
 481mknod_out:
 482        kfree(full_path);
 483        kfree(buf);
 484        FreeXid(xid);
 485        cifs_put_tlink(tlink);
 486        return rc;
 487}
 488
 489struct dentry *
 490cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
 491            struct nameidata *nd)
 492{
 493        int xid;
 494        int rc = 0; /* to get around spurious gcc warning, set to zero here */
 495        __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0;
 496        __u16 fileHandle = 0;
 497        bool posix_open = false;
 498        struct cifs_sb_info *cifs_sb;
 499        struct tcon_link *tlink;
 500        struct cifs_tcon *pTcon;
 501        struct cifsFileInfo *cfile;
 502        struct inode *newInode = NULL;
 503        char *full_path = NULL;
 504        struct file *filp;
 505
 506        xid = GetXid();
 507
 508        cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
 509              parent_dir_inode, direntry->d_name.name, direntry);
 510
 511        /* check whether path exists */
 512
 513        cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
 514        tlink = cifs_sb_tlink(cifs_sb);
 515        if (IS_ERR(tlink)) {
 516                FreeXid(xid);
 517                return (struct dentry *)tlink;
 518        }
 519        pTcon = tlink_tcon(tlink);
 520
 521        /*
 522         * Don't allow the separator character in a path component.
 523         * The VFS will not allow "/", but "\" is allowed by posix.
 524         */
 525        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
 526                int i;
 527                for (i = 0; i < direntry->d_name.len; i++)
 528                        if (direntry->d_name.name[i] == '\\') {
 529                                cFYI(1, "Invalid file name");
 530                                rc = -EINVAL;
 531                                goto lookup_out;
 532                        }
 533        }
 534
 535        /*
 536         * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
 537         * the VFS handle the create.
 538         */
 539        if (nd && (nd->flags & LOOKUP_EXCL)) {
 540                d_instantiate(direntry, NULL);
 541                rc = 0;
 542                goto lookup_out;
 543        }
 544
 545        /* can not grab the rename sem here since it would
 546        deadlock in the cases (beginning of sys_rename itself)
 547        in which we already have the sb rename sem */
 548        full_path = build_path_from_dentry(direntry);
 549        if (full_path == NULL) {
 550                rc = -ENOMEM;
 551                goto lookup_out;
 552        }
 553
 554        if (direntry->d_inode != NULL) {
 555                cFYI(1, "non-NULL inode in lookup");
 556        } else {
 557                cFYI(1, "NULL inode in lookup");
 558        }
 559        cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
 560
 561        /* Posix open is only called (at lookup time) for file create now.
 562         * For opens (rather than creates), because we do not know if it
 563         * is a file or directory yet, and current Samba no longer allows
 564         * us to do posix open on dirs, we could end up wasting an open call
 565         * on what turns out to be a dir. For file opens, we wait to call posix
 566         * open till cifs_open.  It could be added here (lookup) in the future
 567         * but the performance tradeoff of the extra network request when EISDIR
 568         * or EACCES is returned would have to be weighed against the 50%
 569         * reduction in network traffic in the other paths.
 570         */
 571        if (pTcon->unix_ext) {
 572                if (nd && !(nd->flags & LOOKUP_DIRECTORY) &&
 573                     (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
 574                     (nd->intent.open.file->f_flags & O_CREAT)) {
 575                        rc = cifs_posix_open(full_path, &newInode,
 576                                        parent_dir_inode->i_sb,
 577                                        nd->intent.open.create_mode,
 578                                        nd->intent.open.file->f_flags, &oplock,
 579                                        &fileHandle, xid);
 580                        /*
 581                         * The check below works around a bug in POSIX
 582                         * open in samba versions 3.3.1 and earlier where
 583                         * open could incorrectly fail with invalid parameter.
 584                         * If either that or op not supported returned, follow
 585                         * the normal lookup.
 586                         */
 587                        switch (rc) {
 588                        case 0:
 589                                /*
 590                                 * The server may allow us to open things like
 591                                 * FIFOs, but the client isn't set up to deal
 592                                 * with that. If it's not a regular file, just
 593                                 * close it and proceed as if it were a normal
 594                                 * lookup.
 595                                 */
 596                                if (newInode && !S_ISREG(newInode->i_mode)) {
 597                                        CIFSSMBClose(xid, pTcon, fileHandle);
 598                                        break;
 599                                }
 600                        case -ENOENT:
 601                                posix_open = true;
 602                        case -EOPNOTSUPP:
 603                                break;
 604                        default:
 605                                pTcon->broken_posix_open = true;
 606                        }
 607                }
 608                if (!posix_open)
 609                        rc = cifs_get_inode_info_unix(&newInode, full_path,
 610                                                parent_dir_inode->i_sb, xid);
 611        } else
 612                rc = cifs_get_inode_info(&newInode, full_path, NULL,
 613                                parent_dir_inode->i_sb, xid, NULL);
 614
 615        if ((rc == 0) && (newInode != NULL)) {
 616                d_add(direntry, newInode);
 617                if (posix_open) {
 618                        filp = lookup_instantiate_filp(nd, direntry,
 619                                                       generic_file_open);
 620                        if (IS_ERR(filp)) {
 621                                rc = PTR_ERR(filp);
 622                                CIFSSMBClose(xid, pTcon, fileHandle);
 623                                goto lookup_out;
 624                        }
 625
 626                        cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
 627                                                  oplock);
 628                        if (cfile == NULL) {
 629                                fput(filp);
 630                                CIFSSMBClose(xid, pTcon, fileHandle);
 631                                rc = -ENOMEM;
 632                                goto lookup_out;
 633                        }
 634                }
 635                /* since paths are not looked up by component - the parent
 636                   directories are presumed to be good here */
 637                renew_parental_timestamps(direntry);
 638
 639        } else if (rc == -ENOENT) {
 640                rc = 0;
 641                direntry->d_time = jiffies;
 642                d_add(direntry, NULL);
 643        /*      if it was once a directory (but how can we tell?) we could do
 644                shrink_dcache_parent(direntry); */
 645        } else if (rc != -EACCES) {
 646                cERROR(1, "Unexpected lookup error %d", rc);
 647                /* We special case check for Access Denied - since that
 648                is a common return code */
 649        }
 650
 651lookup_out:
 652        kfree(full_path);
 653        cifs_put_tlink(tlink);
 654        FreeXid(xid);
 655        return ERR_PTR(rc);
 656}
 657
 658static int
 659cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
 660{
 661        if (nd && (nd->flags & LOOKUP_RCU))
 662                return -ECHILD;
 663
 664        if (direntry->d_inode) {
 665                if (cifs_revalidate_dentry(direntry))
 666                        return 0;
 667                else {
 668                        /*
 669                         * Forcibly invalidate automounting directory inodes
 670                         * (remote DFS directories) so to have them
 671                         * instantiated again for automount
 672                         */
 673                        if (IS_AUTOMOUNT(direntry->d_inode))
 674                                return 0;
 675                        return 1;
 676                }
 677        }
 678
 679        /*
 680         * This may be nfsd (or something), anyway, we can't see the
 681         * intent of this. So, since this can be for creation, drop it.
 682         */
 683        if (!nd)
 684                return 0;
 685
 686        /*
 687         * Drop the negative dentry, in order to make sure to use the
 688         * case sensitive name which is specified by user if this is
 689         * for creation.
 690         */
 691        if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
 692                return 0;
 693
 694        if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
 695                return 0;
 696
 697        return 1;
 698}
 699
 700/* static int cifs_d_delete(struct dentry *direntry)
 701{
 702        int rc = 0;
 703
 704        cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name);
 705
 706        return rc;
 707}     */
 708
 709const struct dentry_operations cifs_dentry_ops = {
 710        .d_revalidate = cifs_d_revalidate,
 711        .d_automount = cifs_dfs_d_automount,
 712/* d_delete:       cifs_d_delete,      */ /* not needed except for debugging */
 713};
 714
 715static int cifs_ci_hash(const struct dentry *dentry, const struct inode *inode,
 716                struct qstr *q)
 717{
 718        struct nls_table *codepage = CIFS_SB(dentry->d_sb)->local_nls;
 719        unsigned long hash;
 720        int i;
 721
 722        hash = init_name_hash();
 723        for (i = 0; i < q->len; i++)
 724                hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
 725                                         hash);
 726        q->hash = end_name_hash(hash);
 727
 728        return 0;
 729}
 730
 731static int cifs_ci_compare(const struct dentry *parent,
 732                const struct inode *pinode,
 733                const struct dentry *dentry, const struct inode *inode,
 734                unsigned int len, const char *str, const struct qstr *name)
 735{
 736        struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
 737
 738        if ((name->len == len) &&
 739            (nls_strnicmp(codepage, name->name, str, len) == 0))
 740                return 0;
 741        return 1;
 742}
 743
 744const struct dentry_operations cifs_ci_dentry_ops = {
 745        .d_revalidate = cifs_d_revalidate,
 746        .d_hash = cifs_ci_hash,
 747        .d_compare = cifs_ci_compare,
 748        .d_automount = cifs_dfs_d_automount,
 749};
 750