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