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