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