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