linux/fs/cifs/inode.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/inode.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2002,2007
   5 *   Author(s): Steve French (sfrench@us.ibm.com)
   6 *
   7 *   This library is free software; you can redistribute it and/or modify
   8 *   it under the terms of the GNU Lesser General Public License as published
   9 *   by the Free Software Foundation; either version 2.1 of the License, or
  10 *   (at your option) any later version.
  11 *
  12 *   This library is distributed in the hope that it will be useful,
  13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  15 *   the GNU Lesser General Public License for more details.
  16 *
  17 *   You should have received a copy of the GNU Lesser General Public License
  18 *   along with this library; if not, write to the Free Software
  19 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21#include <linux/fs.h>
  22#include <linux/stat.h>
  23#include <linux/pagemap.h>
  24#include <asm/div64.h>
  25#include "cifsfs.h"
  26#include "cifspdu.h"
  27#include "cifsglob.h"
  28#include "cifsproto.h"
  29#include "cifs_debug.h"
  30#include "cifs_fs_sb.h"
  31
  32int cifs_get_inode_info_unix(struct inode **pinode,
  33        const unsigned char *search_path, struct super_block *sb, int xid)
  34{
  35        int rc = 0;
  36        FILE_UNIX_BASIC_INFO findData;
  37        struct cifsTconInfo *pTcon;
  38        struct inode *inode;
  39        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
  40        char *tmp_path;
  41
  42        pTcon = cifs_sb->tcon;
  43        cFYI(1, ("Getting info on %s", search_path));
  44        /* could have done a find first instead but this returns more info */
  45        rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
  46                                  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
  47                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
  48/*      dump_mem("\nUnixQPathInfo return data", &findData,
  49                 sizeof(findData)); */
  50        if (rc) {
  51                if (rc == -EREMOTE) {
  52                        tmp_path =
  53                            kmalloc(strnlen(pTcon->treeName,
  54                                            MAX_TREE_SIZE + 1) +
  55                                    strnlen(search_path, MAX_PATHCONF) + 1,
  56                                    GFP_KERNEL);
  57                        if (tmp_path == NULL) {
  58                                return -ENOMEM;
  59                        }
  60                        /* have to skip first of the double backslash of
  61                           UNC name */
  62                        strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
  63                        strncat(tmp_path, search_path, MAX_PATHCONF);
  64                        rc = connect_to_dfs_path(xid, pTcon->ses,
  65                                                 /* treename + */ tmp_path,
  66                                                 cifs_sb->local_nls,
  67                                                 cifs_sb->mnt_cifs_flags &
  68                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
  69                        kfree(tmp_path);
  70
  71                        /* BB fix up inode etc. */
  72                } else if (rc) {
  73                        return rc;
  74                }
  75        } else {
  76                struct cifsInodeInfo *cifsInfo;
  77                __u32 type = le32_to_cpu(findData.Type);
  78                __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
  79                __u64 end_of_file = le64_to_cpu(findData.EndOfFile);
  80
  81                /* get new inode */
  82                if (*pinode == NULL) {
  83                        *pinode = new_inode(sb);
  84                        if (*pinode == NULL)
  85                                return -ENOMEM;
  86                        /* Is an i_ino of zero legal? */
  87                        /* Are there sanity checks we can use to ensure that
  88                           the server is really filling in that field? */
  89                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
  90                                (*pinode)->i_ino =
  91                                        (unsigned long)findData.UniqueId;
  92                        } /* note ino incremented to unique num in new_inode */
  93                        if (sb->s_flags & MS_NOATIME)
  94                                (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
  95
  96                        insert_inode_hash(*pinode);
  97                }
  98
  99                inode = *pinode;
 100                cifsInfo = CIFS_I(inode);
 101
 102                cFYI(1, ("Old time %ld", cifsInfo->time));
 103                cifsInfo->time = jiffies;
 104                cFYI(1, ("New time %ld", cifsInfo->time));
 105                /* this is ok to set on every inode revalidate */
 106                atomic_set(&cifsInfo->inUse, 1);
 107
 108                inode->i_atime =
 109                    cifs_NTtimeToUnix(le64_to_cpu(findData.LastAccessTime));
 110                inode->i_mtime =
 111                    cifs_NTtimeToUnix(le64_to_cpu
 112                                (findData.LastModificationTime));
 113                inode->i_ctime =
 114                    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
 115                inode->i_mode = le64_to_cpu(findData.Permissions);
 116                /* since we set the inode type below we need to mask off
 117                   to avoid strange results if bits set above */
 118                inode->i_mode &= ~S_IFMT;
 119                if (type == UNIX_FILE) {
 120                        inode->i_mode |= S_IFREG;
 121                } else if (type == UNIX_SYMLINK) {
 122                        inode->i_mode |= S_IFLNK;
 123                } else if (type == UNIX_DIR) {
 124                        inode->i_mode |= S_IFDIR;
 125                } else if (type == UNIX_CHARDEV) {
 126                        inode->i_mode |= S_IFCHR;
 127                        inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 128                                le64_to_cpu(findData.DevMinor) & MINORMASK);
 129                } else if (type == UNIX_BLOCKDEV) {
 130                        inode->i_mode |= S_IFBLK;
 131                        inode->i_rdev = MKDEV(le64_to_cpu(findData.DevMajor),
 132                                le64_to_cpu(findData.DevMinor) & MINORMASK);
 133                } else if (type == UNIX_FIFO) {
 134                        inode->i_mode |= S_IFIFO;
 135                } else if (type == UNIX_SOCKET) {
 136                        inode->i_mode |= S_IFSOCK;
 137                } else {
 138                        /* safest to call it a file if we do not know */
 139                        inode->i_mode |= S_IFREG;
 140                        cFYI(1, ("unknown type %d", type));
 141                }
 142
 143                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
 144                        inode->i_uid = cifs_sb->mnt_uid;
 145                else
 146                        inode->i_uid = le64_to_cpu(findData.Uid);
 147
 148                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
 149                        inode->i_gid = cifs_sb->mnt_gid;
 150                else
 151                        inode->i_gid = le64_to_cpu(findData.Gid);
 152
 153                inode->i_nlink = le64_to_cpu(findData.Nlinks);
 154
 155                spin_lock(&inode->i_lock);
 156                if (is_size_safe_to_change(cifsInfo, end_of_file)) {
 157                /* can not safely change the file size here if the
 158                   client is writing to it due to potential races */
 159                        i_size_write(inode, end_of_file);
 160
 161                /* blksize needs to be multiple of two. So safer to default to
 162                blksize and blkbits set in superblock so 2**blkbits and blksize
 163                will match rather than setting to:
 164                (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 165
 166                /* This seems incredibly stupid but it turns out that i_blocks
 167                   is not related to (i_size / i_blksize), instead 512 byte size
 168                   is required for calculating num blocks */
 169
 170                /* 512 bytes (2**9) is the fake blocksize that must be used */
 171                /* for this calculation */
 172                        inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 173                }
 174                spin_unlock(&inode->i_lock);
 175
 176                if (num_of_bytes < end_of_file)
 177                        cFYI(1, ("allocation size less than end of file"));
 178                cFYI(1, ("Size %ld and blocks %llu",
 179                        (unsigned long) inode->i_size,
 180                        (unsigned long long)inode->i_blocks));
 181                if (S_ISREG(inode->i_mode)) {
 182                        cFYI(1, ("File inode"));
 183                        inode->i_op = &cifs_file_inode_ops;
 184                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
 185                                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 186                                        inode->i_fop =
 187                                                &cifs_file_direct_nobrl_ops;
 188                                else
 189                                        inode->i_fop = &cifs_file_direct_ops;
 190                        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 191                                inode->i_fop = &cifs_file_nobrl_ops;
 192                        else /* not direct, send byte range locks */
 193                                inode->i_fop = &cifs_file_ops;
 194
 195                        /* check if server can support readpages */
 196                        if (pTcon->ses->server->maxBuf <
 197                            PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
 198                                inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
 199                        else
 200                                inode->i_data.a_ops = &cifs_addr_ops;
 201                } else if (S_ISDIR(inode->i_mode)) {
 202                        cFYI(1, ("Directory inode"));
 203                        inode->i_op = &cifs_dir_inode_ops;
 204                        inode->i_fop = &cifs_dir_ops;
 205                } else if (S_ISLNK(inode->i_mode)) {
 206                        cFYI(1, ("Symbolic Link inode"));
 207                        inode->i_op = &cifs_symlink_inode_ops;
 208                /* tmp_inode->i_fop = */ /* do not need to set to anything */
 209                } else {
 210                        cFYI(1, ("Init special inode"));
 211                        init_special_inode(inode, inode->i_mode,
 212                                           inode->i_rdev);
 213                }
 214        }
 215        return rc;
 216}
 217
 218static int decode_sfu_inode(struct inode *inode, __u64 size,
 219                            const unsigned char *path,
 220                            struct cifs_sb_info *cifs_sb, int xid)
 221{
 222        int rc;
 223        int oplock = FALSE;
 224        __u16 netfid;
 225        struct cifsTconInfo *pTcon = cifs_sb->tcon;
 226        char buf[24];
 227        unsigned int bytes_read;
 228        char *pbuf;
 229
 230        pbuf = buf;
 231
 232        if (size == 0) {
 233                inode->i_mode |= S_IFIFO;
 234                return 0;
 235        } else if (size < 8) {
 236                return -EINVAL;  /* EOPNOTSUPP? */
 237        }
 238
 239        rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
 240                         CREATE_NOT_DIR, &netfid, &oplock, NULL,
 241                         cifs_sb->local_nls,
 242                         cifs_sb->mnt_cifs_flags &
 243                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 244        if (rc == 0) {
 245                int buf_type = CIFS_NO_BUFFER;
 246                        /* Read header */
 247                rc = CIFSSMBRead(xid, pTcon,
 248                                 netfid,
 249                                 24 /* length */, 0 /* offset */,
 250                                 &bytes_read, &pbuf, &buf_type);
 251                if ((rc == 0) && (bytes_read >= 8)) {
 252                        if (memcmp("IntxBLK", pbuf, 8) == 0) {
 253                                cFYI(1, ("Block device"));
 254                                inode->i_mode |= S_IFBLK;
 255                                if (bytes_read == 24) {
 256                                        /* we have enough to decode dev num */
 257                                        __u64 mjr; /* major */
 258                                        __u64 mnr; /* minor */
 259                                        mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
 260                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
 261                                        inode->i_rdev = MKDEV(mjr, mnr);
 262                                }
 263                        } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
 264                                cFYI(1, ("Char device"));
 265                                inode->i_mode |= S_IFCHR;
 266                                if (bytes_read == 24) {
 267                                        /* we have enough to decode dev num */
 268                                        __u64 mjr; /* major */
 269                                        __u64 mnr; /* minor */
 270                                        mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
 271                                        mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
 272                                        inode->i_rdev = MKDEV(mjr, mnr);
 273                                }
 274                        } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
 275                                cFYI(1, ("Symlink"));
 276                                inode->i_mode |= S_IFLNK;
 277                        } else {
 278                                inode->i_mode |= S_IFREG; /* file? */
 279                                rc = -EOPNOTSUPP;
 280                        }
 281                } else {
 282                        inode->i_mode |= S_IFREG; /* then it is a file */
 283                        rc = -EOPNOTSUPP; /* or some unknown SFU type */
 284                }
 285                CIFSSMBClose(xid, pTcon, netfid);
 286        }
 287        return rc;
 288}
 289
 290#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID)  /* SETFILEBITS valid bits */
 291
 292static int get_sfu_mode(struct inode *inode,
 293                        const unsigned char *path,
 294                        struct cifs_sb_info *cifs_sb, int xid)
 295{
 296#ifdef CONFIG_CIFS_XATTR
 297        ssize_t rc;
 298        char ea_value[4];
 299        __u32 mode;
 300
 301        rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
 302                        ea_value, 4 /* size of buf */, cifs_sb->local_nls,
 303                cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 304        if (rc < 0)
 305                return (int)rc;
 306        else if (rc > 3) {
 307                mode = le32_to_cpu(*((__le32 *)ea_value));
 308                inode->i_mode &= ~SFBITS_MASK;
 309                cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode));
 310                inode->i_mode = (mode &  SFBITS_MASK) | inode->i_mode;
 311                cFYI(1, ("special mode bits 0%o", mode));
 312                return 0;
 313        } else {
 314                return 0;
 315        }
 316#else
 317        return -EOPNOTSUPP;
 318#endif
 319}
 320
 321int cifs_get_inode_info(struct inode **pinode,
 322        const unsigned char *search_path, FILE_ALL_INFO *pfindData,
 323        struct super_block *sb, int xid)
 324{
 325        int rc = 0;
 326        struct cifsTconInfo *pTcon;
 327        struct inode *inode;
 328        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 329        char *tmp_path;
 330        char *buf = NULL;
 331        int adjustTZ = FALSE;
 332
 333        pTcon = cifs_sb->tcon;
 334        cFYI(1, ("Getting info on %s", search_path));
 335
 336        if ((pfindData == NULL) && (*pinode != NULL)) {
 337                if (CIFS_I(*pinode)->clientCanCacheRead) {
 338                        cFYI(1, ("No need to revalidate cached inode sizes"));
 339                        return rc;
 340                }
 341        }
 342
 343        /* if file info not passed in then get it from server */
 344        if (pfindData == NULL) {
 345                buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
 346                if (buf == NULL)
 347                        return -ENOMEM;
 348                pfindData = (FILE_ALL_INFO *)buf;
 349                /* could do find first instead but this returns more info */
 350                rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
 351                              0 /* not legacy */,
 352                              cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 353                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 354                /* BB optimize code so we do not make the above call
 355                when server claims no NT SMB support and the above call
 356                failed at least once - set flag in tcon or mount */
 357                if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
 358                        rc = SMBQueryInformation(xid, pTcon, search_path,
 359                                        pfindData, cifs_sb->local_nls,
 360                                        cifs_sb->mnt_cifs_flags &
 361                                          CIFS_MOUNT_MAP_SPECIAL_CHR);
 362                        adjustTZ = TRUE;
 363                }
 364        }
 365        /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
 366        if (rc) {
 367                if (rc == -EREMOTE) {
 368                        tmp_path =
 369                            kmalloc(strnlen
 370                                    (pTcon->treeName,
 371                                     MAX_TREE_SIZE + 1) +
 372                                    strnlen(search_path, MAX_PATHCONF) + 1,
 373                                    GFP_KERNEL);
 374                        if (tmp_path == NULL) {
 375                                kfree(buf);
 376                                return -ENOMEM;
 377                        }
 378
 379                        strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
 380                        strncat(tmp_path, search_path, MAX_PATHCONF);
 381                        rc = connect_to_dfs_path(xid, pTcon->ses,
 382                                                 /* treename + */ tmp_path,
 383                                                 cifs_sb->local_nls,
 384                                                 cifs_sb->mnt_cifs_flags &
 385                                                   CIFS_MOUNT_MAP_SPECIAL_CHR);
 386                        kfree(tmp_path);
 387                        /* BB fix up inode etc. */
 388                } else if (rc) {
 389                        kfree(buf);
 390                        return rc;
 391                }
 392        } else {
 393                struct cifsInodeInfo *cifsInfo;
 394                __u32 attr = le32_to_cpu(pfindData->Attributes);
 395
 396                /* get new inode */
 397                if (*pinode == NULL) {
 398                        *pinode = new_inode(sb);
 399                        if (*pinode == NULL) {
 400                                kfree(buf);
 401                                return -ENOMEM;
 402                        }
 403                        /* Is an i_ino of zero legal? Can we use that to check
 404                           if the server supports returning inode numbers?  Are
 405                           there other sanity checks we can use to ensure that
 406                           the server is really filling in that field? */
 407
 408                        /* We can not use the IndexNumber field by default from
 409                           Windows or Samba (in ALL_INFO buf) but we can request
 410                           it explicitly.  It may not be unique presumably if
 411                           the server has multiple devices mounted under one
 412                           share */
 413
 414                        /* There may be higher info levels that work but are
 415                           there Windows server or network appliances for which
 416                           IndexNumber field is not guaranteed unique? */
 417
 418                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 419                                int rc1 = 0;
 420                                __u64 inode_num;
 421
 422                                rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
 423                                        search_path, &inode_num,
 424                                        cifs_sb->local_nls,
 425                                        cifs_sb->mnt_cifs_flags &
 426                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 427                                if (rc1) {
 428                                        cFYI(1, ("GetSrvInodeNum rc %d", rc1));
 429                                        /* BB EOPNOSUPP disable SERVER_INUM? */
 430                                } else /* do we need cast or hash to ino? */
 431                                        (*pinode)->i_ino = inode_num;
 432                        } /* else ino incremented to unique num in new_inode*/
 433                        if (sb->s_flags & MS_NOATIME)
 434                                (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
 435                        insert_inode_hash(*pinode);
 436                }
 437                inode = *pinode;
 438                cifsInfo = CIFS_I(inode);
 439                cifsInfo->cifsAttrs = attr;
 440                cFYI(1, ("Old time %ld", cifsInfo->time));
 441                cifsInfo->time = jiffies;
 442                cFYI(1, ("New time %ld", cifsInfo->time));
 443
 444                /* blksize needs to be multiple of two. So safer to default to
 445                blksize and blkbits set in superblock so 2**blkbits and blksize
 446                will match rather than setting to:
 447                (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 448
 449                /* Linux can not store file creation time so ignore it */
 450                if (pfindData->LastAccessTime)
 451                        inode->i_atime = cifs_NTtimeToUnix
 452                                (le64_to_cpu(pfindData->LastAccessTime));
 453                else /* do not need to use current_fs_time - time not stored */
 454                        inode->i_atime = CURRENT_TIME;
 455                inode->i_mtime =
 456                    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
 457                inode->i_ctime =
 458                    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
 459                cFYI(0, ("Attributes came in as 0x%x", attr));
 460                if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
 461                        inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
 462                        inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
 463                }
 464
 465                /* set default mode. will override for dirs below */
 466                if (atomic_read(&cifsInfo->inUse) == 0)
 467                        /* new inode, can safely set these fields */
 468                        inode->i_mode = cifs_sb->mnt_file_mode;
 469                else /* since we set the inode type below we need to mask off
 470                     to avoid strange results if type changes and both
 471                     get orred in */
 472                        inode->i_mode &= ~S_IFMT;
 473/*              if (attr & ATTR_REPARSE)  */
 474                /* We no longer handle these as symlinks because we could not
 475                   follow them due to the absolute path with drive letter */
 476                if (attr & ATTR_DIRECTORY) {
 477                /* override default perms since we do not do byte range locking
 478                   on dirs */
 479                        inode->i_mode = cifs_sb->mnt_dir_mode;
 480                        inode->i_mode |= S_IFDIR;
 481                } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
 482                           (cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
 483                           /* No need to le64 convert size of zero */
 484                           (pfindData->EndOfFile == 0)) {
 485                        inode->i_mode = cifs_sb->mnt_file_mode;
 486                        inode->i_mode |= S_IFIFO;
 487/* BB Finish for SFU style symlinks and devices */
 488                } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
 489                           (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
 490                        if (decode_sfu_inode(inode,
 491                                         le64_to_cpu(pfindData->EndOfFile),
 492                                         search_path,
 493                                         cifs_sb, xid)) {
 494                                cFYI(1, ("Unrecognized sfu inode type"));
 495                        }
 496                        cFYI(1, ("sfu mode 0%o", inode->i_mode));
 497                } else {
 498                        inode->i_mode |= S_IFREG;
 499                        /* treat the dos attribute of read-only as read-only
 500                           mode e.g. 555 */
 501                        if (cifsInfo->cifsAttrs & ATTR_READONLY)
 502                                inode->i_mode &= ~(S_IWUGO);
 503                        else if ((inode->i_mode & S_IWUGO) == 0)
 504                                /* the ATTR_READONLY flag may have been */
 505                                /* changed on server -- set any w bits  */
 506                                /* allowed by mnt_file_mode             */
 507                                inode->i_mode |= (S_IWUGO &
 508                                                  cifs_sb->mnt_file_mode);
 509                /* BB add code here -
 510                   validate if device or weird share or device type? */
 511                }
 512
 513                spin_lock(&inode->i_lock);
 514                if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) {
 515                        /* can not safely shrink the file size here if the
 516                           client is writing to it due to potential races */
 517                        i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
 518
 519                        /* 512 bytes (2**9) is the fake blocksize that must be
 520                           used for this calculation */
 521                        inode->i_blocks = (512 - 1 + le64_to_cpu(
 522                                           pfindData->AllocationSize)) >> 9;
 523                }
 524                spin_unlock(&inode->i_lock);
 525
 526                inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
 527
 528                /* BB fill in uid and gid here? with help from winbind?
 529                   or retrieve from NTFS stream extended attribute */
 530#ifdef CONFIG_CIFS_EXPERIMENTAL
 531                /* fill in 0777 bits from ACL */
 532                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
 533                        cFYI(1, ("Getting mode bits from ACL"));
 534                        acl_to_uid_mode(inode, search_path);
 535                }
 536#endif
 537                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
 538                        /* fill in remaining high mode bits e.g. SUID, VTX */
 539                        get_sfu_mode(inode, search_path, cifs_sb, xid);
 540                } else if (atomic_read(&cifsInfo->inUse) == 0) {
 541                        inode->i_uid = cifs_sb->mnt_uid;
 542                        inode->i_gid = cifs_sb->mnt_gid;
 543                        /* set so we do not keep refreshing these fields with
 544                           bad data after user has changed them in memory */
 545                        atomic_set(&cifsInfo->inUse, 1);
 546                }
 547
 548                if (S_ISREG(inode->i_mode)) {
 549                        cFYI(1, ("File inode"));
 550                        inode->i_op = &cifs_file_inode_ops;
 551                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
 552                                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 553                                        inode->i_fop =
 554                                                &cifs_file_direct_nobrl_ops;
 555                                else
 556                                        inode->i_fop = &cifs_file_direct_ops;
 557                        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 558                                inode->i_fop = &cifs_file_nobrl_ops;
 559                        else /* not direct, send byte range locks */
 560                                inode->i_fop = &cifs_file_ops;
 561
 562                        if (pTcon->ses->server->maxBuf <
 563                             PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
 564                                inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
 565                        else
 566                                inode->i_data.a_ops = &cifs_addr_ops;
 567                } else if (S_ISDIR(inode->i_mode)) {
 568                        cFYI(1, ("Directory inode"));
 569                        inode->i_op = &cifs_dir_inode_ops;
 570                        inode->i_fop = &cifs_dir_ops;
 571                } else if (S_ISLNK(inode->i_mode)) {
 572                        cFYI(1, ("Symbolic Link inode"));
 573                        inode->i_op = &cifs_symlink_inode_ops;
 574                } else {
 575                        init_special_inode(inode, inode->i_mode,
 576                                           inode->i_rdev);
 577                }
 578        }
 579        kfree(buf);
 580        return rc;
 581}
 582
 583static const struct inode_operations cifs_ipc_inode_ops = {
 584        .lookup = cifs_lookup,
 585};
 586
 587/* gets root inode */
 588void cifs_read_inode(struct inode *inode)
 589{
 590        int xid, rc;
 591        struct cifs_sb_info *cifs_sb;
 592
 593        cifs_sb = CIFS_SB(inode->i_sb);
 594        xid = GetXid();
 595
 596        if (cifs_sb->tcon->unix_ext)
 597                rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
 598        else
 599                rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
 600        if (rc && cifs_sb->tcon->ipc) {
 601                cFYI(1, ("ipc connection - fake read inode"));
 602                inode->i_mode |= S_IFDIR;
 603                inode->i_nlink = 2;
 604                inode->i_op = &cifs_ipc_inode_ops;
 605                inode->i_fop = &simple_dir_operations;
 606                inode->i_uid = cifs_sb->mnt_uid;
 607                inode->i_gid = cifs_sb->mnt_gid;
 608        }
 609
 610        /* can not call macro FreeXid here since in a void func */
 611        _FreeXid(xid);
 612}
 613
 614int cifs_unlink(struct inode *inode, struct dentry *direntry)
 615{
 616        int rc = 0;
 617        int xid;
 618        struct cifs_sb_info *cifs_sb;
 619        struct cifsTconInfo *pTcon;
 620        char *full_path = NULL;
 621        struct cifsInodeInfo *cifsInode;
 622        FILE_BASIC_INFO *pinfo_buf;
 623
 624        cFYI(1, ("cifs_unlink, inode = 0x%p", inode));
 625
 626        xid = GetXid();
 627
 628        if (inode)
 629                cifs_sb = CIFS_SB(inode->i_sb);
 630        else
 631                cifs_sb = CIFS_SB(direntry->d_sb);
 632        pTcon = cifs_sb->tcon;
 633
 634        /* Unlink can be called from rename so we can not grab the sem here
 635           since we deadlock otherwise */
 636/*      mutex_lock(&direntry->d_sb->s_vfs_rename_mutex);*/
 637        full_path = build_path_from_dentry(direntry);
 638/*      mutex_unlock(&direntry->d_sb->s_vfs_rename_mutex);*/
 639        if (full_path == NULL) {
 640                FreeXid(xid);
 641                return -ENOMEM;
 642        }
 643
 644        if ((pTcon->ses->capabilities & CAP_UNIX) &&
 645                (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 646                        le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
 647                rc = CIFSPOSIXDelFile(xid, pTcon, full_path,
 648                        SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
 649                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 650                cFYI(1, ("posix del rc %d", rc));
 651                if ((rc == 0) || (rc == -ENOENT))
 652                        goto psx_del_no_retry;
 653        }
 654
 655        rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls,
 656                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 657psx_del_no_retry:
 658        if (!rc) {
 659                if (direntry->d_inode)
 660                        drop_nlink(direntry->d_inode);
 661        } else if (rc == -ENOENT) {
 662                d_drop(direntry);
 663        } else if (rc == -ETXTBSY) {
 664                int oplock = FALSE;
 665                __u16 netfid;
 666
 667                rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE,
 668                                 CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE,
 669                                 &netfid, &oplock, NULL, cifs_sb->local_nls,
 670                                 cifs_sb->mnt_cifs_flags &
 671                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 672                if (rc == 0) {
 673                        CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL,
 674                                              cifs_sb->local_nls,
 675                                              cifs_sb->mnt_cifs_flags &
 676                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 677                        CIFSSMBClose(xid, pTcon, netfid);
 678                        if (direntry->d_inode)
 679                                drop_nlink(direntry->d_inode);
 680                }
 681        } else if (rc == -EACCES) {
 682                /* try only if r/o attribute set in local lookup data? */
 683                pinfo_buf = kzalloc(sizeof(FILE_BASIC_INFO), GFP_KERNEL);
 684                if (pinfo_buf) {
 685                        /* ATTRS set to normal clears r/o bit */
 686                        pinfo_buf->Attributes = cpu_to_le32(ATTR_NORMAL);
 687                        if (!(pTcon->ses->flags & CIFS_SES_NT4))
 688                                rc = CIFSSMBSetTimes(xid, pTcon, full_path,
 689                                                     pinfo_buf,
 690                                                     cifs_sb->local_nls,
 691                                                     cifs_sb->mnt_cifs_flags &
 692                                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 693                        else
 694                                rc = -EOPNOTSUPP;
 695
 696                        if (rc == -EOPNOTSUPP) {
 697                                int oplock = FALSE;
 698                                __u16 netfid;
 699                        /*      rc = CIFSSMBSetAttrLegacy(xid, pTcon,
 700                                                          full_path,
 701                                                          (__u16)ATTR_NORMAL,
 702                                                          cifs_sb->local_nls);
 703                           For some strange reason it seems that NT4 eats the
 704                           old setattr call without actually setting the
 705                           attributes so on to the third attempted workaround
 706                           */
 707
 708                        /* BB could scan to see if we already have it open
 709                           and pass in pid of opener to function */
 710                                rc = CIFSSMBOpen(xid, pTcon, full_path,
 711                                                 FILE_OPEN, SYNCHRONIZE |
 712                                                 FILE_WRITE_ATTRIBUTES, 0,
 713                                                 &netfid, &oplock, NULL,
 714                                                 cifs_sb->local_nls,
 715                                                 cifs_sb->mnt_cifs_flags &
 716                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
 717                                if (rc == 0) {
 718                                        rc = CIFSSMBSetFileTimes(xid, pTcon,
 719                                                                 pinfo_buf,
 720                                                                 netfid);
 721                                        CIFSSMBClose(xid, pTcon, netfid);
 722                                }
 723                        }
 724                        kfree(pinfo_buf);
 725                }
 726                if (rc == 0) {
 727                        rc = CIFSSMBDelFile(xid, pTcon, full_path,
 728                                            cifs_sb->local_nls,
 729                                            cifs_sb->mnt_cifs_flags &
 730                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
 731                        if (!rc) {
 732                                if (direntry->d_inode)
 733                                        drop_nlink(direntry->d_inode);
 734                        } else if (rc == -ETXTBSY) {
 735                                int oplock = FALSE;
 736                                __u16 netfid;
 737
 738                                rc = CIFSSMBOpen(xid, pTcon, full_path,
 739                                                 FILE_OPEN, DELETE,
 740                                                 CREATE_NOT_DIR |
 741                                                 CREATE_DELETE_ON_CLOSE,
 742                                                 &netfid, &oplock, NULL,
 743                                                 cifs_sb->local_nls,
 744                                                 cifs_sb->mnt_cifs_flags &
 745                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
 746                                if (rc == 0) {
 747                                        CIFSSMBRenameOpenFile(xid, pTcon,
 748                                                netfid, NULL,
 749                                                cifs_sb->local_nls,
 750                                                cifs_sb->mnt_cifs_flags &
 751                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
 752                                        CIFSSMBClose(xid, pTcon, netfid);
 753                                        if (direntry->d_inode)
 754                                                drop_nlink(direntry->d_inode);
 755                                }
 756                        /* BB if rc = -ETXTBUSY goto the rename logic BB */
 757                        }
 758                }
 759        }
 760        if (direntry->d_inode) {
 761                cifsInode = CIFS_I(direntry->d_inode);
 762                cifsInode->time = 0;    /* will force revalidate to get info
 763                                           when needed */
 764                direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
 765        }
 766        if (inode) {
 767                inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
 768                cifsInode = CIFS_I(inode);
 769                cifsInode->time = 0;    /* force revalidate of dir as well */
 770        }
 771
 772        kfree(full_path);
 773        FreeXid(xid);
 774        return rc;
 775}
 776
 777static void posix_fill_in_inode(struct inode *tmp_inode,
 778        FILE_UNIX_BASIC_INFO *pData, int *pobject_type, int isNewInode)
 779{
 780        loff_t local_size;
 781        struct timespec local_mtime;
 782
 783        struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 784        struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
 785
 786        __u32 type = le32_to_cpu(pData->Type);
 787        __u64 num_of_bytes = le64_to_cpu(pData->NumOfBytes);
 788        __u64 end_of_file = le64_to_cpu(pData->EndOfFile);
 789        cifsInfo->time = jiffies;
 790        atomic_inc(&cifsInfo->inUse);
 791
 792        /* save mtime and size */
 793        local_mtime = tmp_inode->i_mtime;
 794        local_size  = tmp_inode->i_size;
 795
 796        tmp_inode->i_atime =
 797            cifs_NTtimeToUnix(le64_to_cpu(pData->LastAccessTime));
 798        tmp_inode->i_mtime =
 799            cifs_NTtimeToUnix(le64_to_cpu(pData->LastModificationTime));
 800        tmp_inode->i_ctime =
 801            cifs_NTtimeToUnix(le64_to_cpu(pData->LastStatusChange));
 802
 803        tmp_inode->i_mode = le64_to_cpu(pData->Permissions);
 804        /* since we set the inode type below we need to mask off type
 805           to avoid strange results if bits above were corrupt */
 806        tmp_inode->i_mode &= ~S_IFMT;
 807        if (type == UNIX_FILE) {
 808                *pobject_type = DT_REG;
 809                tmp_inode->i_mode |= S_IFREG;
 810        } else if (type == UNIX_SYMLINK) {
 811                *pobject_type = DT_LNK;
 812                tmp_inode->i_mode |= S_IFLNK;
 813        } else if (type == UNIX_DIR) {
 814                *pobject_type = DT_DIR;
 815                tmp_inode->i_mode |= S_IFDIR;
 816        } else if (type == UNIX_CHARDEV) {
 817                *pobject_type = DT_CHR;
 818                tmp_inode->i_mode |= S_IFCHR;
 819                tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
 820                                le64_to_cpu(pData->DevMinor) & MINORMASK);
 821        } else if (type == UNIX_BLOCKDEV) {
 822                *pobject_type = DT_BLK;
 823                tmp_inode->i_mode |= S_IFBLK;
 824                tmp_inode->i_rdev = MKDEV(le64_to_cpu(pData->DevMajor),
 825                                le64_to_cpu(pData->DevMinor) & MINORMASK);
 826        } else if (type == UNIX_FIFO) {
 827                *pobject_type = DT_FIFO;
 828                tmp_inode->i_mode |= S_IFIFO;
 829        } else if (type == UNIX_SOCKET) {
 830                *pobject_type = DT_SOCK;
 831                tmp_inode->i_mode |= S_IFSOCK;
 832        } else {
 833                /* safest to just call it a file */
 834                *pobject_type = DT_REG;
 835                tmp_inode->i_mode |= S_IFREG;
 836                cFYI(1, ("unknown inode type %d", type));
 837        }
 838
 839#ifdef CONFIG_CIFS_DEBUG2
 840        cFYI(1, ("object type: %d", type));
 841#endif
 842        tmp_inode->i_uid = le64_to_cpu(pData->Uid);
 843        tmp_inode->i_gid = le64_to_cpu(pData->Gid);
 844        tmp_inode->i_nlink = le64_to_cpu(pData->Nlinks);
 845
 846        spin_lock(&tmp_inode->i_lock);
 847        if (is_size_safe_to_change(cifsInfo, end_of_file)) {
 848                /* can not safely change the file size here if the
 849                client is writing to it due to potential races */
 850                i_size_write(tmp_inode, end_of_file);
 851
 852        /* 512 bytes (2**9) is the fake blocksize that must be used */
 853        /* for this calculation, not the real blocksize */
 854                tmp_inode->i_blocks = (512 - 1 + num_of_bytes) >> 9;
 855        }
 856        spin_unlock(&tmp_inode->i_lock);
 857
 858        if (S_ISREG(tmp_inode->i_mode)) {
 859                cFYI(1, ("File inode"));
 860                tmp_inode->i_op = &cifs_file_inode_ops;
 861
 862                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
 863                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 864                                tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
 865                        else
 866                                tmp_inode->i_fop = &cifs_file_direct_ops;
 867
 868                } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
 869                        tmp_inode->i_fop = &cifs_file_nobrl_ops;
 870                else
 871                        tmp_inode->i_fop = &cifs_file_ops;
 872
 873                if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
 874                   (cifs_sb->tcon->ses->server->maxBuf <
 875                        PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
 876                        tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
 877                else
 878                        tmp_inode->i_data.a_ops = &cifs_addr_ops;
 879
 880                if (isNewInode)
 881                        return; /* No sense invalidating pages for new inode
 882                                   since we we have not started caching
 883                                   readahead file data yet */
 884
 885                if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
 886                        (local_size == tmp_inode->i_size)) {
 887                        cFYI(1, ("inode exists but unchanged"));
 888                } else {
 889                        /* file may have changed on server */
 890                        cFYI(1, ("invalidate inode, readdir detected change"));
 891                        invalidate_remote_inode(tmp_inode);
 892                }
 893        } else if (S_ISDIR(tmp_inode->i_mode)) {
 894                cFYI(1, ("Directory inode"));
 895                tmp_inode->i_op = &cifs_dir_inode_ops;
 896                tmp_inode->i_fop = &cifs_dir_ops;
 897        } else if (S_ISLNK(tmp_inode->i_mode)) {
 898                cFYI(1, ("Symbolic Link inode"));
 899                tmp_inode->i_op = &cifs_symlink_inode_ops;
 900/* tmp_inode->i_fop = *//* do not need to set to anything */
 901        } else {
 902                cFYI(1, ("Special inode"));
 903                init_special_inode(tmp_inode, tmp_inode->i_mode,
 904                                   tmp_inode->i_rdev);
 905        }
 906}
 907
 908int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
 909{
 910        int rc = 0;
 911        int xid;
 912        struct cifs_sb_info *cifs_sb;
 913        struct cifsTconInfo *pTcon;
 914        char *full_path = NULL;
 915        struct inode *newinode = NULL;
 916
 917        cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
 918
 919        xid = GetXid();
 920
 921        cifs_sb = CIFS_SB(inode->i_sb);
 922        pTcon = cifs_sb->tcon;
 923
 924        full_path = build_path_from_dentry(direntry);
 925        if (full_path == NULL) {
 926                FreeXid(xid);
 927                return -ENOMEM;
 928        }
 929
 930        if ((pTcon->ses->capabilities & CAP_UNIX) &&
 931                (CIFS_UNIX_POSIX_PATH_OPS_CAP &
 932                        le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
 933                u32 oplock = 0;
 934                FILE_UNIX_BASIC_INFO * pInfo =
 935                        kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
 936                if (pInfo == NULL) {
 937                        rc = -ENOMEM;
 938                        goto mkdir_out;
 939                }
 940
 941                mode &= ~current->fs->umask;
 942                rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
 943                                mode, NULL /* netfid */, pInfo, &oplock,
 944                                full_path, cifs_sb->local_nls,
 945                                cifs_sb->mnt_cifs_flags &
 946                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 947                if (rc == -EOPNOTSUPP) {
 948                        kfree(pInfo);
 949                        goto mkdir_retry_old;
 950                } else if (rc) {
 951                        cFYI(1, ("posix mkdir returned 0x%x", rc));
 952                        d_drop(direntry);
 953                } else {
 954                        int obj_type;
 955                        if (pInfo->Type == cpu_to_le32(-1)) {
 956                                /* no return info, go query for it */
 957                                kfree(pInfo);
 958                                goto mkdir_get_info;
 959                        }
 960/*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
 961        to set uid/gid */
 962                        inc_nlink(inode);
 963                        if (pTcon->nocase)
 964                                direntry->d_op = &cifs_ci_dentry_ops;
 965                        else
 966                                direntry->d_op = &cifs_dentry_ops;
 967
 968                        newinode = new_inode(inode->i_sb);
 969                        if (newinode == NULL) {
 970                                kfree(pInfo);
 971                                goto mkdir_get_info;
 972                        }
 973                        /* Is an i_ino of zero legal? */
 974                        /* Are there sanity checks we can use to ensure that
 975                           the server is really filling in that field? */
 976                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 977                                newinode->i_ino =
 978                                        (unsigned long)pInfo->UniqueId;
 979                        } /* note ino incremented to unique num in new_inode */
 980                        if (inode->i_sb->s_flags & MS_NOATIME)
 981                                newinode->i_flags |= S_NOATIME | S_NOCMTIME;
 982                        newinode->i_nlink = 2;
 983
 984                        insert_inode_hash(newinode);
 985                        d_instantiate(direntry, newinode);
 986
 987                        /* we already checked in POSIXCreate whether
 988                           frame was long enough */
 989                        posix_fill_in_inode(direntry->d_inode,
 990                                        pInfo, &obj_type, 1 /* NewInode */);
 991#ifdef CONFIG_CIFS_DEBUG2
 992                        cFYI(1, ("instantiated dentry %p %s to inode %p",
 993                                direntry, direntry->d_name.name, newinode));
 994
 995                        if (newinode->i_nlink != 2)
 996                                cFYI(1, ("unexpected number of links %d",
 997                                        newinode->i_nlink));
 998#endif
 999                }
1000                kfree(pInfo);
1001                goto mkdir_out;
1002        }
1003mkdir_retry_old:
1004        /* BB add setting the equivalent of mode via CreateX w/ACLs */
1005        rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1006                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1007        if (rc) {
1008                cFYI(1, ("cifs_mkdir returned 0x%x", rc));
1009                d_drop(direntry);
1010        } else {
1011mkdir_get_info:
1012                inc_nlink(inode);
1013                if (pTcon->unix_ext)
1014                        rc = cifs_get_inode_info_unix(&newinode, full_path,
1015                                                      inode->i_sb, xid);
1016                else
1017                        rc = cifs_get_inode_info(&newinode, full_path, NULL,
1018                                                 inode->i_sb, xid);
1019
1020                if (pTcon->nocase)
1021                        direntry->d_op = &cifs_ci_dentry_ops;
1022                else
1023                        direntry->d_op = &cifs_dentry_ops;
1024                d_instantiate(direntry, newinode);
1025                 /* setting nlink not necessary except in cases where we
1026                  * failed to get it from the server or was set bogus */
1027                if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1028                                direntry->d_inode->i_nlink = 2;
1029                if (pTcon->unix_ext) {
1030                        mode &= ~current->fs->umask;
1031                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1032                                CIFSSMBUnixSetPerms(xid, pTcon, full_path,
1033                                                    mode,
1034                                                    (__u64)current->fsuid,
1035                                                    (__u64)current->fsgid,
1036                                                    0 /* dev_t */,
1037                                                    cifs_sb->local_nls,
1038                                                    cifs_sb->mnt_cifs_flags &
1039                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
1040                        } else {
1041                                CIFSSMBUnixSetPerms(xid, pTcon, full_path,
1042                                                    mode, (__u64)-1,
1043                                                    (__u64)-1, 0 /* dev_t */,
1044                                                    cifs_sb->local_nls,
1045                                                    cifs_sb->mnt_cifs_flags &
1046                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
1047                        }
1048                } else {
1049                        /* BB to be implemented via Windows secrty descriptors
1050                           eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
1051                                                 -1, -1, local_nls); */
1052                        if (direntry->d_inode) {
1053                                direntry->d_inode->i_mode = mode;
1054                                direntry->d_inode->i_mode |= S_IFDIR;
1055                                if (cifs_sb->mnt_cifs_flags &
1056                                     CIFS_MOUNT_SET_UID) {
1057                                        direntry->d_inode->i_uid =
1058                                                current->fsuid;
1059                                        direntry->d_inode->i_gid =
1060                                                current->fsgid;
1061                                }
1062                        }
1063                }
1064        }
1065mkdir_out:
1066        kfree(full_path);
1067        FreeXid(xid);
1068        return rc;
1069}
1070
1071int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1072{
1073        int rc = 0;
1074        int xid;
1075        struct cifs_sb_info *cifs_sb;
1076        struct cifsTconInfo *pTcon;
1077        char *full_path = NULL;
1078        struct cifsInodeInfo *cifsInode;
1079
1080        cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
1081
1082        xid = GetXid();
1083
1084        cifs_sb = CIFS_SB(inode->i_sb);
1085        pTcon = cifs_sb->tcon;
1086
1087        full_path = build_path_from_dentry(direntry);
1088        if (full_path == NULL) {
1089                FreeXid(xid);
1090                return -ENOMEM;
1091        }
1092
1093        rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1094                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1095
1096        if (!rc) {
1097                drop_nlink(inode);
1098                spin_lock(&direntry->d_inode->i_lock);
1099                i_size_write(direntry->d_inode, 0);
1100                clear_nlink(direntry->d_inode);
1101                spin_unlock(&direntry->d_inode->i_lock);
1102        }
1103
1104        cifsInode = CIFS_I(direntry->d_inode);
1105        cifsInode->time = 0;    /* force revalidate to go get info when
1106                                   needed */
1107        direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1108                current_fs_time(inode->i_sb);
1109
1110        kfree(full_path);
1111        FreeXid(xid);
1112        return rc;
1113}
1114
1115int cifs_rename(struct inode *source_inode, struct dentry *source_direntry,
1116        struct inode *target_inode, struct dentry *target_direntry)
1117{
1118        char *fromName;
1119        char *toName;
1120        struct cifs_sb_info *cifs_sb_source;
1121        struct cifs_sb_info *cifs_sb_target;
1122        struct cifsTconInfo *pTcon;
1123        int xid;
1124        int rc = 0;
1125
1126        xid = GetXid();
1127
1128        cifs_sb_target = CIFS_SB(target_inode->i_sb);
1129        cifs_sb_source = CIFS_SB(source_inode->i_sb);
1130        pTcon = cifs_sb_source->tcon;
1131
1132        if (pTcon != cifs_sb_target->tcon) {
1133                FreeXid(xid);
1134                return -EXDEV;  /* BB actually could be allowed if same server,
1135                                   but different share.
1136                                   Might eventually add support for this */
1137        }
1138
1139        /* we already  have the rename sem so we do not need to grab it again
1140           here to protect the path integrity */
1141        fromName = build_path_from_dentry(source_direntry);
1142        toName = build_path_from_dentry(target_direntry);
1143        if ((fromName == NULL) || (toName == NULL)) {
1144                rc = -ENOMEM;
1145                goto cifs_rename_exit;
1146        }
1147
1148        rc = CIFSSMBRename(xid, pTcon, fromName, toName,
1149                           cifs_sb_source->local_nls,
1150                           cifs_sb_source->mnt_cifs_flags &
1151                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1152        if (rc == -EEXIST) {
1153                /* check if they are the same file because rename of hardlinked
1154                   files is a noop */
1155                FILE_UNIX_BASIC_INFO *info_buf_source;
1156                FILE_UNIX_BASIC_INFO *info_buf_target;
1157
1158                info_buf_source =
1159                        kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1160                if (info_buf_source != NULL) {
1161                        info_buf_target = info_buf_source + 1;
1162                        if (pTcon->unix_ext)
1163                                rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName,
1164                                        info_buf_source,
1165                                        cifs_sb_source->local_nls,
1166                                        cifs_sb_source->mnt_cifs_flags &
1167                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1168                        /* else rc is still EEXIST so will fall through to
1169                           unlink the target and retry rename */
1170                        if (rc == 0) {
1171                                rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName,
1172                                                info_buf_target,
1173                                                cifs_sb_target->local_nls,
1174                                                /* remap based on source sb */
1175                                                cifs_sb_source->mnt_cifs_flags &
1176                                                    CIFS_MOUNT_MAP_SPECIAL_CHR);
1177                        }
1178                        if ((rc == 0) &&
1179                            (info_buf_source->UniqueId ==
1180                             info_buf_target->UniqueId)) {
1181                        /* do not rename since the files are hardlinked which
1182                           is a noop */
1183                        } else {
1184                        /* we either can not tell the files are hardlinked
1185                           (as with Windows servers) or files are not
1186                           hardlinked so delete the target manually before
1187                           renaming to follow POSIX rather than Windows
1188                           semantics */
1189                                cifs_unlink(target_inode, target_direntry);
1190                                rc = CIFSSMBRename(xid, pTcon, fromName,
1191                                                   toName,
1192                                                   cifs_sb_source->local_nls,
1193                                                   cifs_sb_source->mnt_cifs_flags
1194                                                   & CIFS_MOUNT_MAP_SPECIAL_CHR);
1195                        }
1196                        kfree(info_buf_source);
1197                } /* if we can not get memory just leave rc as EEXIST */
1198        }
1199
1200        if (rc) {
1201                cFYI(1, ("rename rc %d", rc));
1202        }
1203
1204        if ((rc == -EIO) || (rc == -EEXIST)) {
1205                int oplock = FALSE;
1206                __u16 netfid;
1207
1208                /* BB FIXME Is Generic Read correct for rename? */
1209                /* if renaming directory - we should not say CREATE_NOT_DIR,
1210                   need to test renaming open directory, also GENERIC_READ
1211                   might not right be right access to request */
1212                rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ,
1213                                 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1214                                 cifs_sb_source->local_nls,
1215                                 cifs_sb_source->mnt_cifs_flags &
1216                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
1217                if (rc == 0) {
1218                        rc = CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName,
1219                                              cifs_sb_source->local_nls,
1220                                              cifs_sb_source->mnt_cifs_flags &
1221                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1222                        CIFSSMBClose(xid, pTcon, netfid);
1223                }
1224        }
1225
1226cifs_rename_exit:
1227        kfree(fromName);
1228        kfree(toName);
1229        FreeXid(xid);
1230        return rc;
1231}
1232
1233int cifs_revalidate(struct dentry *direntry)
1234{
1235        int xid;
1236        int rc = 0, wbrc = 0;
1237        char *full_path;
1238        struct cifs_sb_info *cifs_sb;
1239        struct cifsInodeInfo *cifsInode;
1240        loff_t local_size;
1241        struct timespec local_mtime;
1242        int invalidate_inode = FALSE;
1243
1244        if (direntry->d_inode == NULL)
1245                return -ENOENT;
1246
1247        cifsInode = CIFS_I(direntry->d_inode);
1248
1249        if (cifsInode == NULL)
1250                return -ENOENT;
1251
1252        /* no sense revalidating inode info on file that no one can write */
1253        if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
1254                return rc;
1255
1256        xid = GetXid();
1257
1258        cifs_sb = CIFS_SB(direntry->d_sb);
1259
1260        /* can not safely grab the rename sem here if rename calls revalidate
1261           since that would deadlock */
1262        full_path = build_path_from_dentry(direntry);
1263        if (full_path == NULL) {
1264                FreeXid(xid);
1265                return -ENOMEM;
1266        }
1267        cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1268                 "jiffies %ld", full_path, direntry->d_inode,
1269                 direntry->d_inode->i_count.counter, direntry,
1270                 direntry->d_time, jiffies));
1271
1272        if (cifsInode->time == 0) {
1273                /* was set to zero previously to force revalidate */
1274        } else if (time_before(jiffies, cifsInode->time + HZ) &&
1275                   lookupCacheEnabled) {
1276                if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
1277                    (direntry->d_inode->i_nlink == 1)) {
1278                        kfree(full_path);
1279                        FreeXid(xid);
1280                        return rc;
1281                } else {
1282                        cFYI(1, ("Have to revalidate file due to hardlinks"));
1283                }
1284        }
1285
1286        /* save mtime and size */
1287        local_mtime = direntry->d_inode->i_mtime;
1288        local_size = direntry->d_inode->i_size;
1289
1290        if (cifs_sb->tcon->unix_ext) {
1291                rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
1292                                              direntry->d_sb, xid);
1293                if (rc) {
1294                        cFYI(1, ("error on getting revalidate info %d", rc));
1295/*                      if (rc != -ENOENT)
1296                                rc = 0; */      /* BB should we cache info on
1297                                                   certain errors? */
1298                }
1299        } else {
1300                rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
1301                                         direntry->d_sb, xid);
1302                if (rc) {
1303                        cFYI(1, ("error on getting revalidate info %d", rc));
1304/*                      if (rc != -ENOENT)
1305                                rc = 0; */      /* BB should we cache info on
1306                                                   certain errors? */
1307                }
1308        }
1309        /* should we remap certain errors, access denied?, to zero */
1310
1311        /* if not oplocked, we invalidate inode pages if mtime or file size
1312           had changed on server */
1313
1314        if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
1315            (local_size == direntry->d_inode->i_size)) {
1316                cFYI(1, ("cifs_revalidate - inode unchanged"));
1317        } else {
1318                /* file may have changed on server */
1319                if (cifsInode->clientCanCacheRead) {
1320                        /* no need to invalidate inode pages since we were the
1321                           only ones who could have modified the file and the
1322                           server copy is staler than ours */
1323                } else {
1324                        invalidate_inode = TRUE;
1325                }
1326        }
1327
1328        /* can not grab this sem since kernel filesys locking documentation
1329           indicates i_mutex may be taken by the kernel on lookup and rename
1330           which could deadlock if we grab the i_mutex here as well */
1331/*      mutex_lock(&direntry->d_inode->i_mutex);*/
1332        /* need to write out dirty pages here  */
1333        if (direntry->d_inode->i_mapping) {
1334                /* do we need to lock inode until after invalidate completes
1335                   below? */
1336                wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping);
1337                if (wbrc)
1338                        CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1339        }
1340        if (invalidate_inode) {
1341        /* shrink_dcache not necessary now that cifs dentry ops
1342        are exported for negative dentries */
1343/*              if (S_ISDIR(direntry->d_inode->i_mode))
1344                        shrink_dcache_parent(direntry); */
1345                if (S_ISREG(direntry->d_inode->i_mode)) {
1346                        if (direntry->d_inode->i_mapping)
1347                                wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
1348                                if (wbrc)
1349                                        CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1350                        /* may eventually have to do this for open files too */
1351                        if (list_empty(&(cifsInode->openFileList))) {
1352                                /* changed on server - flush read ahead pages */
1353                                cFYI(1, ("Invalidating read ahead data on "
1354                                         "closed file"));
1355                                invalidate_remote_inode(direntry->d_inode);
1356                        }
1357                }
1358        }
1359/*      mutex_unlock(&direntry->d_inode->i_mutex); */
1360
1361        kfree(full_path);
1362        FreeXid(xid);
1363        return rc;
1364}
1365
1366int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1367        struct kstat *stat)
1368{
1369        int err = cifs_revalidate(dentry);
1370        if (!err) {
1371                generic_fillattr(dentry->d_inode, stat);
1372                stat->blksize = CIFS_MAX_MSGSIZE;
1373        }
1374        return err;
1375}
1376
1377static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1378{
1379        pgoff_t index = from >> PAGE_CACHE_SHIFT;
1380        unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1381        struct page *page;
1382        int rc = 0;
1383
1384        page = grab_cache_page(mapping, index);
1385        if (!page)
1386                return -ENOMEM;
1387
1388        zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
1389        unlock_page(page);
1390        page_cache_release(page);
1391        return rc;
1392}
1393
1394static int cifs_vmtruncate(struct inode *inode, loff_t offset)
1395{
1396        struct address_space *mapping = inode->i_mapping;
1397        unsigned long limit;
1398
1399        spin_lock(&inode->i_lock);
1400        if (inode->i_size < offset)
1401                goto do_expand;
1402        /*
1403         * truncation of in-use swapfiles is disallowed - it would cause
1404         * subsequent swapout to scribble on the now-freed blocks.
1405         */
1406        if (IS_SWAPFILE(inode)) {
1407                spin_unlock(&inode->i_lock);
1408                goto out_busy;
1409        }
1410        i_size_write(inode, offset);
1411        spin_unlock(&inode->i_lock);
1412        /*
1413         * unmap_mapping_range is called twice, first simply for efficiency
1414         * so that truncate_inode_pages does fewer single-page unmaps. However
1415         * after this first call, and before truncate_inode_pages finishes,
1416         * it is possible for private pages to be COWed, which remain after
1417         * truncate_inode_pages finishes, hence the second unmap_mapping_range
1418         * call must be made for correctness.
1419         */
1420        unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1421        truncate_inode_pages(mapping, offset);
1422        unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
1423        goto out_truncate;
1424
1425do_expand:
1426        limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
1427        if (limit != RLIM_INFINITY && offset > limit) {
1428                spin_unlock(&inode->i_lock);
1429                goto out_sig;
1430        }
1431        if (offset > inode->i_sb->s_maxbytes) {
1432                spin_unlock(&inode->i_lock);
1433                goto out_big;
1434        }
1435        i_size_write(inode, offset);
1436        spin_unlock(&inode->i_lock);
1437out_truncate:
1438        if (inode->i_op && inode->i_op->truncate)
1439                inode->i_op->truncate(inode);
1440        return 0;
1441out_sig:
1442        send_sig(SIGXFSZ, current, 0);
1443out_big:
1444        return -EFBIG;
1445out_busy:
1446        return -ETXTBSY;
1447}
1448
1449int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1450{
1451        int xid;
1452        struct cifs_sb_info *cifs_sb;
1453        struct cifsTconInfo *pTcon;
1454        char *full_path = NULL;
1455        int rc = -EACCES;
1456        struct cifsFileInfo *open_file = NULL;
1457        FILE_BASIC_INFO time_buf;
1458        int set_time = FALSE;
1459        int set_dosattr = FALSE;
1460        __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
1461        __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
1462        __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
1463        struct cifsInodeInfo *cifsInode;
1464
1465        xid = GetXid();
1466
1467        cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1468                 direntry->d_name.name, attrs->ia_valid));
1469
1470        cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
1471        pTcon = cifs_sb->tcon;
1472
1473        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1474                /* check if we have permission to change attrs */
1475                rc = inode_change_ok(direntry->d_inode, attrs);
1476                if (rc < 0) {
1477                        FreeXid(xid);
1478                        return rc;
1479                } else
1480                        rc = 0;
1481        }
1482
1483        full_path = build_path_from_dentry(direntry);
1484        if (full_path == NULL) {
1485                FreeXid(xid);
1486                return -ENOMEM;
1487        }
1488        cifsInode = CIFS_I(direntry->d_inode);
1489
1490        /* BB check if we need to refresh inode from server now ? BB */
1491
1492        if (attrs->ia_valid & ATTR_SIZE) {
1493                /*
1494                   Flush data before changing file size on server. If the
1495                   flush returns error, store it to report later and continue.
1496                   BB: This should be smarter. Why bother flushing pages that
1497                   will be truncated anyway? Also, should we error out here if
1498                   the flush returns error?
1499                 */
1500                rc = filemap_write_and_wait(direntry->d_inode->i_mapping);
1501                if (rc != 0) {
1502                        CIFS_I(direntry->d_inode)->write_behind_rc = rc;
1503                        rc = 0;
1504                }
1505
1506                /* To avoid spurious oplock breaks from server, in the case of
1507                   inodes that we already have open, avoid doing path based
1508                   setting of file size if we can do it by handle.
1509                   This keeps our caching token (oplock) and avoids timeouts
1510                   when the local oplock break takes longer to flush
1511                   writebehind data than the SMB timeout for the SetPathInfo
1512                   request would allow */
1513
1514                open_file = find_writable_file(cifsInode);
1515                if (open_file) {
1516                        __u16 nfid = open_file->netfid;
1517                        __u32 npid = open_file->pid;
1518                        rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
1519                                                nfid, npid, FALSE);
1520                        atomic_dec(&open_file->wrtPending);
1521                        cFYI(1, ("SetFSize for attrs rc = %d", rc));
1522                        if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1523                                unsigned int bytes_written;
1524                                rc = CIFSSMBWrite(xid, pTcon,
1525                                                  nfid, 0, attrs->ia_size,
1526                                                  &bytes_written, NULL, NULL,
1527                                                  1 /* 45 seconds */);
1528                                cFYI(1, ("Wrt seteof rc %d", rc));
1529                        }
1530                } else
1531                        rc = -EINVAL;
1532
1533                if (rc != 0) {
1534                        /* Set file size by pathname rather than by handle
1535                           either because no valid, writeable file handle for
1536                           it was found or because there was an error setting
1537                           it by handle */
1538                        rc = CIFSSMBSetEOF(xid, pTcon, full_path,
1539                                           attrs->ia_size, FALSE,
1540                                           cifs_sb->local_nls,
1541                                           cifs_sb->mnt_cifs_flags &
1542                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1543                        cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1544                        if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1545                                __u16 netfid;
1546                                int oplock = FALSE;
1547
1548                                rc = SMBLegacyOpen(xid, pTcon, full_path,
1549                                        FILE_OPEN,
1550                                        SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1551                                        CREATE_NOT_DIR, &netfid, &oplock,
1552                                        NULL, cifs_sb->local_nls,
1553                                        cifs_sb->mnt_cifs_flags &
1554                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1555                                if (rc == 0) {
1556                                        unsigned int bytes_written;
1557                                        rc = CIFSSMBWrite(xid, pTcon,
1558                                                        netfid, 0,
1559                                                        attrs->ia_size,
1560                                                        &bytes_written, NULL,
1561                                                        NULL, 1 /* 45 sec */);
1562                                        cFYI(1, ("wrt seteof rc %d", rc));
1563                                        CIFSSMBClose(xid, pTcon, netfid);
1564                                }
1565
1566                        }
1567                }
1568
1569                /* Server is ok setting allocation size implicitly - no need
1570                   to call:
1571                CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, TRUE,
1572                         cifs_sb->local_nls);
1573                   */
1574
1575                if (rc == 0) {
1576                        rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size);
1577                        cifs_truncate_page(direntry->d_inode->i_mapping,
1578                                           direntry->d_inode->i_size);
1579                } else
1580                        goto cifs_setattr_exit;
1581        }
1582        if (attrs->ia_valid & ATTR_UID) {
1583                cFYI(1, ("UID changed to %d", attrs->ia_uid));
1584                uid = attrs->ia_uid;
1585        }
1586        if (attrs->ia_valid & ATTR_GID) {
1587                cFYI(1, ("GID changed to %d", attrs->ia_gid));
1588                gid = attrs->ia_gid;
1589        }
1590
1591        time_buf.Attributes = 0;
1592
1593        /* skip mode change if it's just for clearing setuid/setgid */
1594        if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1595                attrs->ia_valid &= ~ATTR_MODE;
1596
1597        if (attrs->ia_valid & ATTR_MODE) {
1598                cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode));
1599                mode = attrs->ia_mode;
1600        }
1601
1602        if ((pTcon->unix_ext)
1603            && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID)))
1604                rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid,
1605                                         0 /* dev_t */, cifs_sb->local_nls,
1606                                         cifs_sb->mnt_cifs_flags &
1607                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1608        else if (attrs->ia_valid & ATTR_MODE) {
1609                rc = 0;
1610                if ((mode & S_IWUGO) == 0) /* not writeable */ {
1611                        if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1612                                set_dosattr = TRUE;
1613                                time_buf.Attributes =
1614                                        cpu_to_le32(cifsInode->cifsAttrs |
1615                                                    ATTR_READONLY);
1616                        }
1617                } else if (cifsInode->cifsAttrs & ATTR_READONLY) {
1618                        /* If file is readonly on server, we would
1619                        not be able to write to it - so if any write
1620                        bit is enabled for user or group or other we
1621                        need to at least try to remove r/o dos attr */
1622                        set_dosattr = TRUE;
1623                        time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs &
1624                                            (~ATTR_READONLY));
1625                        /* Windows ignores set to zero */
1626                        if (time_buf.Attributes == 0)
1627                                time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL);
1628                }
1629                /* BB to be implemented -
1630                   via Windows security descriptors or streams */
1631                /* CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, uid, gid,
1632                                      cifs_sb->local_nls); */
1633        }
1634
1635        if (attrs->ia_valid & ATTR_ATIME) {
1636                set_time = TRUE;
1637                time_buf.LastAccessTime =
1638                    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
1639        } else
1640                time_buf.LastAccessTime = 0;
1641
1642        if (attrs->ia_valid & ATTR_MTIME) {
1643                set_time = TRUE;
1644                time_buf.LastWriteTime =
1645                    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
1646        } else
1647                time_buf.LastWriteTime = 0;
1648        /* Do not set ctime explicitly unless other time
1649           stamps are changed explicitly (i.e. by utime()
1650           since we would then have a mix of client and
1651           server times */
1652
1653        if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
1654                set_time = TRUE;
1655                /* Although Samba throws this field away
1656                it may be useful to Windows - but we do
1657                not want to set ctime unless some other
1658                timestamp is changing */
1659                cFYI(1, ("CIFS - CTIME changed"));
1660                time_buf.ChangeTime =
1661                    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
1662        } else
1663                time_buf.ChangeTime = 0;
1664
1665        if (set_time || set_dosattr) {
1666                time_buf.CreationTime = 0;      /* do not change */
1667                /* In the future we should experiment - try setting timestamps
1668                   via Handle (SetFileInfo) instead of by path */
1669                if (!(pTcon->ses->flags & CIFS_SES_NT4))
1670                        rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf,
1671                                             cifs_sb->local_nls,
1672                                             cifs_sb->mnt_cifs_flags &
1673                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1674                else
1675                        rc = -EOPNOTSUPP;
1676
1677                if (rc == -EOPNOTSUPP) {
1678                        int oplock = FALSE;
1679                        __u16 netfid;
1680
1681                        cFYI(1, ("calling SetFileInfo since SetPathInfo for "
1682                                 "times not supported by this server"));
1683                        /* BB we could scan to see if we already have it open
1684                           and pass in pid of opener to function */
1685                        rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
1686                                         SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
1687                                         CREATE_NOT_DIR, &netfid, &oplock,
1688                                         NULL, cifs_sb->local_nls,
1689                                         cifs_sb->mnt_cifs_flags &
1690                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
1691                        if (rc == 0) {
1692                                rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf,
1693                                                         netfid);
1694                                CIFSSMBClose(xid, pTcon, netfid);
1695                        } else {
1696                        /* BB For even older servers we could convert time_buf
1697                           into old DOS style which uses two second
1698                           granularity */
1699
1700                        /* rc = CIFSSMBSetTimesLegacy(xid, pTcon, full_path,
1701                                        &time_buf, cifs_sb->local_nls); */
1702                        }
1703                }
1704                /* Even if error on time set, no sense failing the call if
1705                the server would set the time to a reasonable value anyway,
1706                and this check ensures that we are not being called from
1707                sys_utimes in which case we ought to fail the call back to
1708                the user when the server rejects the call */
1709                if ((rc) && (attrs->ia_valid &
1710                         (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1711                        rc = 0;
1712        }
1713
1714        /* do not need local check to inode_check_ok since the server does
1715           that */
1716        if (!rc)
1717                rc = inode_setattr(direntry->d_inode, attrs);
1718cifs_setattr_exit:
1719        kfree(full_path);
1720        FreeXid(xid);
1721        return rc;
1722}
1723
1724#if 0
1725void cifs_delete_inode(struct inode *inode)
1726{
1727        cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1728        /* may have to add back in if and when safe distributed caching of
1729           directories added e.g. via FindNotify */
1730}
1731#endif
1732