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