[CIFS] pSesInfo->sesSem is used as mutex. Rename it to session_mutex and
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / cifs / inode.c
blob8bdbc818164cbc87df5455c92b1d61ac2f915c90
1 /*
2 * fs/cifs/inode.c
4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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"
33 static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
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;
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 */
66 #endif
67 inode->i_op = &cifs_dir_inode_ops;
68 inode->i_fop = &cifs_dir_ops;
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;
80 /* populate an inode with info from a cifs_fattr struct */
81 void
82 cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
84 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
85 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
86 unsigned long oldtime = cifs_i->time;
88 inode->i_atime = fattr->cf_atime;
89 inode->i_mtime = fattr->cf_mtime;
90 inode->i_ctime = fattr->cf_ctime;
91 inode->i_rdev = fattr->cf_rdev;
92 inode->i_nlink = fattr->cf_nlink;
93 inode->i_uid = fattr->cf_uid;
94 inode->i_gid = fattr->cf_gid;
96 /* if dynperm is set, don't clobber existing mode */
97 if (inode->i_state & I_NEW ||
98 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
99 inode->i_mode = fattr->cf_mode;
101 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
102 cifs_i->uniqueid = fattr->cf_uniqueid;
104 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
105 cifs_i->time = 0;
106 else
107 cifs_i->time = jiffies;
109 cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
110 oldtime, cifs_i->time));
112 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
114 cifs_i->server_eof = fattr->cf_eof;
116 * Can't safely change the file size here if the client is writing to
117 * it due to potential races.
119 spin_lock(&inode->i_lock);
120 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
121 i_size_write(inode, fattr->cf_eof);
124 * i_blocks is not related to (i_size / i_blksize),
125 * but instead 512 byte (2**9) size is required for
126 * calculating num blocks.
128 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
130 spin_unlock(&inode->i_lock);
132 cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
135 /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
136 void
137 cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
138 struct cifs_sb_info *cifs_sb)
140 memset(fattr, 0, sizeof(*fattr));
141 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
142 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
143 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
145 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
146 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
147 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
148 fattr->cf_mode = le64_to_cpu(info->Permissions);
151 * Since we set the inode type below we need to mask off
152 * to avoid strange results if bits set above.
154 fattr->cf_mode &= ~S_IFMT;
155 switch (le32_to_cpu(info->Type)) {
156 case UNIX_FILE:
157 fattr->cf_mode |= S_IFREG;
158 fattr->cf_dtype = DT_REG;
159 break;
160 case UNIX_SYMLINK:
161 fattr->cf_mode |= S_IFLNK;
162 fattr->cf_dtype = DT_LNK;
163 break;
164 case UNIX_DIR:
165 fattr->cf_mode |= S_IFDIR;
166 fattr->cf_dtype = DT_DIR;
167 break;
168 case UNIX_CHARDEV:
169 fattr->cf_mode |= S_IFCHR;
170 fattr->cf_dtype = DT_CHR;
171 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
172 le64_to_cpu(info->DevMinor) & MINORMASK);
173 break;
174 case UNIX_BLOCKDEV:
175 fattr->cf_mode |= S_IFBLK;
176 fattr->cf_dtype = DT_BLK;
177 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
178 le64_to_cpu(info->DevMinor) & MINORMASK);
179 break;
180 case UNIX_FIFO:
181 fattr->cf_mode |= S_IFIFO;
182 fattr->cf_dtype = DT_FIFO;
183 break;
184 case UNIX_SOCKET:
185 fattr->cf_mode |= S_IFSOCK;
186 fattr->cf_dtype = DT_SOCK;
187 break;
188 default:
189 /* safest to call it a file if we do not know */
190 fattr->cf_mode |= S_IFREG;
191 fattr->cf_dtype = DT_REG;
192 cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
193 break;
196 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
197 fattr->cf_uid = cifs_sb->mnt_uid;
198 else
199 fattr->cf_uid = le64_to_cpu(info->Uid);
201 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
202 fattr->cf_gid = cifs_sb->mnt_gid;
203 else
204 fattr->cf_gid = le64_to_cpu(info->Gid);
206 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
210 * Fill a cifs_fattr struct with fake inode info.
212 * Needed to setup cifs_fattr data for the directory which is the
213 * junction to the new submount (ie to setup the fake directory
214 * which represents a DFS referral).
216 static void
217 cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
219 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
221 cFYI(1, ("creating fake fattr for DFS referral"));
223 memset(fattr, 0, sizeof(*fattr));
224 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
225 fattr->cf_uid = cifs_sb->mnt_uid;
226 fattr->cf_gid = cifs_sb->mnt_gid;
227 fattr->cf_atime = CURRENT_TIME;
228 fattr->cf_ctime = CURRENT_TIME;
229 fattr->cf_mtime = CURRENT_TIME;
230 fattr->cf_nlink = 2;
231 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
234 int cifs_get_inode_info_unix(struct inode **pinode,
235 const unsigned char *full_path,
236 struct super_block *sb, int xid)
238 int rc;
239 FILE_UNIX_BASIC_INFO find_data;
240 struct cifs_fattr fattr;
241 struct cifsTconInfo *tcon;
242 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
244 tcon = cifs_sb->tcon;
245 cFYI(1, ("Getting info on %s", full_path));
247 /* could have done a find first instead but this returns more info */
248 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
249 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
250 CIFS_MOUNT_MAP_SPECIAL_CHR);
252 if (!rc) {
253 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
254 } else if (rc == -EREMOTE) {
255 cifs_create_dfs_fattr(&fattr, sb);
256 rc = 0;
257 } else {
258 return rc;
261 if (*pinode == NULL) {
262 /* get new inode */
263 *pinode = cifs_iget(sb, &fattr);
264 if (!*pinode)
265 rc = -ENOMEM;
266 } else {
267 /* we already have inode, update it */
268 cifs_fattr_to_inode(*pinode, &fattr);
271 return rc;
274 static int
275 cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
276 struct cifs_sb_info *cifs_sb, int xid)
278 int rc;
279 int oplock = 0;
280 __u16 netfid;
281 struct cifsTconInfo *pTcon = cifs_sb->tcon;
282 char buf[24];
283 unsigned int bytes_read;
284 char *pbuf;
286 pbuf = buf;
288 fattr->cf_mode &= ~S_IFMT;
290 if (fattr->cf_eof == 0) {
291 fattr->cf_mode |= S_IFIFO;
292 fattr->cf_dtype = DT_FIFO;
293 return 0;
294 } else if (fattr->cf_eof < 8) {
295 fattr->cf_mode |= S_IFREG;
296 fattr->cf_dtype = DT_REG;
297 return -EINVAL; /* EOPNOTSUPP? */
300 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
301 CREATE_NOT_DIR, &netfid, &oplock, NULL,
302 cifs_sb->local_nls,
303 cifs_sb->mnt_cifs_flags &
304 CIFS_MOUNT_MAP_SPECIAL_CHR);
305 if (rc == 0) {
306 int buf_type = CIFS_NO_BUFFER;
307 /* Read header */
308 rc = CIFSSMBRead(xid, pTcon, netfid,
309 24 /* length */, 0 /* offset */,
310 &bytes_read, &pbuf, &buf_type);
311 if ((rc == 0) && (bytes_read >= 8)) {
312 if (memcmp("IntxBLK", pbuf, 8) == 0) {
313 cFYI(1, ("Block device"));
314 fattr->cf_mode |= S_IFBLK;
315 fattr->cf_dtype = DT_BLK;
316 if (bytes_read == 24) {
317 /* we have enough to decode dev num */
318 __u64 mjr; /* major */
319 __u64 mnr; /* minor */
320 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
321 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
322 fattr->cf_rdev = MKDEV(mjr, mnr);
324 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
325 cFYI(1, ("Char device"));
326 fattr->cf_mode |= S_IFCHR;
327 fattr->cf_dtype = DT_CHR;
328 if (bytes_read == 24) {
329 /* we have enough to decode dev num */
330 __u64 mjr; /* major */
331 __u64 mnr; /* minor */
332 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
333 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
334 fattr->cf_rdev = MKDEV(mjr, mnr);
336 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
337 cFYI(1, ("Symlink"));
338 fattr->cf_mode |= S_IFLNK;
339 fattr->cf_dtype = DT_LNK;
340 } else {
341 fattr->cf_mode |= S_IFREG; /* file? */
342 fattr->cf_dtype = DT_REG;
343 rc = -EOPNOTSUPP;
345 } else {
346 fattr->cf_mode |= S_IFREG; /* then it is a file */
347 fattr->cf_dtype = DT_REG;
348 rc = -EOPNOTSUPP; /* or some unknown SFU type */
350 CIFSSMBClose(xid, pTcon, netfid);
352 return rc;
355 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
358 * Fetch mode bits as provided by SFU.
360 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
362 static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
363 struct cifs_sb_info *cifs_sb, int xid)
365 #ifdef CONFIG_CIFS_XATTR
366 ssize_t rc;
367 char ea_value[4];
368 __u32 mode;
370 rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
371 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
372 cifs_sb->mnt_cifs_flags &
373 CIFS_MOUNT_MAP_SPECIAL_CHR);
374 if (rc < 0)
375 return (int)rc;
376 else if (rc > 3) {
377 mode = le32_to_cpu(*((__le32 *)ea_value));
378 fattr->cf_mode &= ~SFBITS_MASK;
379 cFYI(1, ("special bits 0%o org mode 0%o", mode,
380 fattr->cf_mode));
381 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
382 cFYI(1, ("special mode bits 0%o", mode));
385 return 0;
386 #else
387 return -EOPNOTSUPP;
388 #endif
391 /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
392 static void
393 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
394 struct cifs_sb_info *cifs_sb, bool adjust_tz)
396 memset(fattr, 0, sizeof(*fattr));
397 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
398 if (info->DeletePending)
399 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
401 if (info->LastAccessTime)
402 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
403 else
404 fattr->cf_atime = CURRENT_TIME;
406 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
407 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
409 if (adjust_tz) {
410 fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
411 fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
414 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
415 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
417 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
418 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
419 fattr->cf_dtype = DT_DIR;
420 } else {
421 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
422 fattr->cf_dtype = DT_REG;
424 /* clear write bits if ATTR_READONLY is set */
425 if (fattr->cf_cifsattrs & ATTR_READONLY)
426 fattr->cf_mode &= ~(S_IWUGO);
429 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
431 fattr->cf_uid = cifs_sb->mnt_uid;
432 fattr->cf_gid = cifs_sb->mnt_gid;
435 int cifs_get_inode_info(struct inode **pinode,
436 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
437 struct super_block *sb, int xid, const __u16 *pfid)
439 int rc = 0, tmprc;
440 struct cifsTconInfo *pTcon;
441 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
442 char *buf = NULL;
443 bool adjustTZ = false;
444 struct cifs_fattr fattr;
446 pTcon = cifs_sb->tcon;
447 cFYI(1, ("Getting info on %s", full_path));
449 if ((pfindData == NULL) && (*pinode != NULL)) {
450 if (CIFS_I(*pinode)->clientCanCacheRead) {
451 cFYI(1, ("No need to revalidate cached inode sizes"));
452 return rc;
456 /* if file info not passed in then get it from server */
457 if (pfindData == NULL) {
458 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
459 if (buf == NULL)
460 return -ENOMEM;
461 pfindData = (FILE_ALL_INFO *)buf;
463 /* could do find first instead but this returns more info */
464 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
465 0 /* not legacy */,
466 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
467 CIFS_MOUNT_MAP_SPECIAL_CHR);
468 /* BB optimize code so we do not make the above call
469 when server claims no NT SMB support and the above call
470 failed at least once - set flag in tcon or mount */
471 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
472 rc = SMBQueryInformation(xid, pTcon, full_path,
473 pfindData, cifs_sb->local_nls,
474 cifs_sb->mnt_cifs_flags &
475 CIFS_MOUNT_MAP_SPECIAL_CHR);
476 adjustTZ = true;
480 if (!rc) {
481 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
482 cifs_sb, adjustTZ);
483 } else if (rc == -EREMOTE) {
484 cifs_create_dfs_fattr(&fattr, sb);
485 rc = 0;
486 } else {
487 goto cgii_exit;
491 * If an inode wasn't passed in, then get the inode number
493 * Is an i_ino of zero legal? Can we use that to check if the server
494 * supports returning inode numbers? Are there other sanity checks we
495 * can use to ensure that the server is really filling in that field?
497 * We can not use the IndexNumber field by default from Windows or
498 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
499 * CIFS spec claims that this value is unique within the scope of a
500 * share, and the windows docs hint that it's actually unique
501 * per-machine.
503 * There may be higher info levels that work but are there Windows
504 * server or network appliances for which IndexNumber field is not
505 * guaranteed unique?
507 if (*pinode == NULL) {
508 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
509 int rc1 = 0;
511 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
512 full_path, &fattr.cf_uniqueid,
513 cifs_sb->local_nls,
514 cifs_sb->mnt_cifs_flags &
515 CIFS_MOUNT_MAP_SPECIAL_CHR);
516 if (rc1 || !fattr.cf_uniqueid) {
517 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
518 fattr.cf_uniqueid = iunique(sb, ROOT_I);
519 cifs_autodisable_serverino(cifs_sb);
521 } else {
522 fattr.cf_uniqueid = iunique(sb, ROOT_I);
524 } else {
525 fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
528 /* query for SFU type info if supported and needed */
529 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
530 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
531 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
532 if (tmprc)
533 cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
536 #ifdef CONFIG_CIFS_EXPERIMENTAL
537 /* fill in 0777 bits from ACL */
538 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
539 cFYI(1, ("Getting mode bits from ACL"));
540 cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
542 #endif
544 /* fill in remaining high mode bits e.g. SUID, VTX */
545 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
546 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
548 if (!*pinode) {
549 *pinode = cifs_iget(sb, &fattr);
550 if (!*pinode)
551 rc = -ENOMEM;
552 } else {
553 cifs_fattr_to_inode(*pinode, &fattr);
556 cgii_exit:
557 kfree(buf);
558 return rc;
561 static const struct inode_operations cifs_ipc_inode_ops = {
562 .lookup = cifs_lookup,
565 char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
567 int pplen = cifs_sb->prepathlen;
568 int dfsplen;
569 char *full_path = NULL;
571 /* if no prefix path, simply set path to the root of share to "" */
572 if (pplen == 0) {
573 full_path = kmalloc(1, GFP_KERNEL);
574 if (full_path)
575 full_path[0] = 0;
576 return full_path;
579 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
580 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
581 else
582 dfsplen = 0;
584 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
585 if (full_path == NULL)
586 return full_path;
588 if (dfsplen) {
589 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
590 /* switch slash direction in prepath depending on whether
591 * windows or posix style path names
593 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
594 int i;
595 for (i = 0; i < dfsplen; i++) {
596 if (full_path[i] == '\\')
597 full_path[i] = '/';
601 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
602 full_path[dfsplen + pplen] = 0; /* add trailing null */
603 return full_path;
606 static int
607 cifs_find_inode(struct inode *inode, void *opaque)
609 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
611 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
612 return 0;
614 return 1;
617 static int
618 cifs_init_inode(struct inode *inode, void *opaque)
620 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
622 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
623 return 0;
626 /* Given fattrs, get a corresponding inode */
627 struct inode *
628 cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
630 unsigned long hash;
631 struct inode *inode;
633 cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
635 /* hash down to 32-bits on 32-bit arch */
636 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
638 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
640 /* we have fattrs in hand, update the inode */
641 if (inode) {
642 cifs_fattr_to_inode(inode, fattr);
643 if (sb->s_flags & MS_NOATIME)
644 inode->i_flags |= S_NOATIME | S_NOCMTIME;
645 if (inode->i_state & I_NEW) {
646 inode->i_ino = hash;
647 unlock_new_inode(inode);
651 return inode;
654 /* gets root inode */
655 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
657 int xid;
658 struct cifs_sb_info *cifs_sb;
659 struct inode *inode = NULL;
660 long rc;
661 char *full_path;
663 cifs_sb = CIFS_SB(sb);
664 full_path = cifs_build_path_to_root(cifs_sb);
665 if (full_path == NULL)
666 return ERR_PTR(-ENOMEM);
668 xid = GetXid();
669 if (cifs_sb->tcon->unix_ext)
670 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
671 else
672 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
673 xid, NULL);
675 if (!inode)
676 return ERR_PTR(-ENOMEM);
678 if (rc && cifs_sb->tcon->ipc) {
679 cFYI(1, ("ipc connection - fake read inode"));
680 inode->i_mode |= S_IFDIR;
681 inode->i_nlink = 2;
682 inode->i_op = &cifs_ipc_inode_ops;
683 inode->i_fop = &simple_dir_operations;
684 inode->i_uid = cifs_sb->mnt_uid;
685 inode->i_gid = cifs_sb->mnt_gid;
686 } else if (rc) {
687 kfree(full_path);
688 _FreeXid(xid);
689 iget_failed(inode);
690 return ERR_PTR(rc);
694 kfree(full_path);
695 /* can not call macro FreeXid here since in a void func
696 * TODO: This is no longer true
698 _FreeXid(xid);
699 return inode;
702 static int
703 cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
704 char *full_path, __u32 dosattr)
706 int rc;
707 int oplock = 0;
708 __u16 netfid;
709 __u32 netpid;
710 bool set_time = false;
711 struct cifsFileInfo *open_file;
712 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
713 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
714 struct cifsTconInfo *pTcon = cifs_sb->tcon;
715 FILE_BASIC_INFO info_buf;
717 if (attrs == NULL)
718 return -EINVAL;
720 if (attrs->ia_valid & ATTR_ATIME) {
721 set_time = true;
722 info_buf.LastAccessTime =
723 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
724 } else
725 info_buf.LastAccessTime = 0;
727 if (attrs->ia_valid & ATTR_MTIME) {
728 set_time = true;
729 info_buf.LastWriteTime =
730 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
731 } else
732 info_buf.LastWriteTime = 0;
735 * Samba throws this field away, but windows may actually use it.
736 * Do not set ctime unless other time stamps are changed explicitly
737 * (i.e. by utimes()) since we would then have a mix of client and
738 * server times.
740 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
741 cFYI(1, ("CIFS - CTIME changed"));
742 info_buf.ChangeTime =
743 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
744 } else
745 info_buf.ChangeTime = 0;
747 info_buf.CreationTime = 0; /* don't change */
748 info_buf.Attributes = cpu_to_le32(dosattr);
751 * If the file is already open for write, just use that fileid
753 open_file = find_writable_file(cifsInode);
754 if (open_file) {
755 netfid = open_file->netfid;
756 netpid = open_file->pid;
757 goto set_via_filehandle;
761 * NT4 apparently returns success on this call, but it doesn't
762 * really work.
764 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
765 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
766 &info_buf, cifs_sb->local_nls,
767 cifs_sb->mnt_cifs_flags &
768 CIFS_MOUNT_MAP_SPECIAL_CHR);
769 if (rc == 0) {
770 cifsInode->cifsAttrs = dosattr;
771 goto out;
772 } else if (rc != -EOPNOTSUPP && rc != -EINVAL)
773 goto out;
776 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
777 "times not supported by this server"));
778 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
779 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
780 CREATE_NOT_DIR, &netfid, &oplock,
781 NULL, cifs_sb->local_nls,
782 cifs_sb->mnt_cifs_flags &
783 CIFS_MOUNT_MAP_SPECIAL_CHR);
785 if (rc != 0) {
786 if (rc == -EIO)
787 rc = -EINVAL;
788 goto out;
791 netpid = current->tgid;
793 set_via_filehandle:
794 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
795 if (!rc)
796 cifsInode->cifsAttrs = dosattr;
798 if (open_file == NULL)
799 CIFSSMBClose(xid, pTcon, netfid);
800 else
801 cifsFileInfo_put(open_file);
802 out:
803 return rc;
807 * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
808 * and rename it to a random name that hopefully won't conflict with
809 * anything else.
811 static int
812 cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
814 int oplock = 0;
815 int rc;
816 __u16 netfid;
817 struct inode *inode = dentry->d_inode;
818 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
819 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
820 struct cifsTconInfo *tcon = cifs_sb->tcon;
821 __u32 dosattr, origattr;
822 FILE_BASIC_INFO *info_buf = NULL;
824 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
825 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
826 &netfid, &oplock, NULL, cifs_sb->local_nls,
827 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
828 if (rc != 0)
829 goto out;
831 origattr = cifsInode->cifsAttrs;
832 if (origattr == 0)
833 origattr |= ATTR_NORMAL;
835 dosattr = origattr & ~ATTR_READONLY;
836 if (dosattr == 0)
837 dosattr |= ATTR_NORMAL;
838 dosattr |= ATTR_HIDDEN;
840 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
841 if (dosattr != origattr) {
842 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
843 if (info_buf == NULL) {
844 rc = -ENOMEM;
845 goto out_close;
847 info_buf->Attributes = cpu_to_le32(dosattr);
848 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
849 current->tgid);
850 /* although we would like to mark the file hidden
851 if that fails we will still try to rename it */
852 if (rc != 0)
853 cifsInode->cifsAttrs = dosattr;
854 else
855 dosattr = origattr; /* since not able to change them */
858 /* rename the file */
859 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
860 cifs_sb->mnt_cifs_flags &
861 CIFS_MOUNT_MAP_SPECIAL_CHR);
862 if (rc != 0) {
863 rc = -ETXTBSY;
864 goto undo_setattr;
867 /* try to set DELETE_ON_CLOSE */
868 if (!cifsInode->delete_pending) {
869 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
870 current->tgid);
872 * some samba versions return -ENOENT when we try to set the
873 * file disposition here. Likely a samba bug, but work around
874 * it for now. This means that some cifsXXX files may hang
875 * around after they shouldn't.
877 * BB: remove this hack after more servers have the fix
879 if (rc == -ENOENT)
880 rc = 0;
881 else if (rc != 0) {
882 rc = -ETXTBSY;
883 goto undo_rename;
885 cifsInode->delete_pending = true;
888 out_close:
889 CIFSSMBClose(xid, tcon, netfid);
890 out:
891 kfree(info_buf);
892 return rc;
895 * reset everything back to the original state. Don't bother
896 * dealing with errors here since we can't do anything about
897 * them anyway.
899 undo_rename:
900 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
901 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
902 CIFS_MOUNT_MAP_SPECIAL_CHR);
903 undo_setattr:
904 if (dosattr != origattr) {
905 info_buf->Attributes = cpu_to_le32(origattr);
906 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
907 current->tgid))
908 cifsInode->cifsAttrs = origattr;
911 goto out_close;
916 * If dentry->d_inode is null (usually meaning the cached dentry
917 * is a negative dentry) then we would attempt a standard SMB delete, but
918 * if that fails we can not attempt the fall back mechanisms on EACCESS
919 * but will return the EACCESS to the caller. Note that the VFS does not call
920 * unlink on negative dentries currently.
922 int cifs_unlink(struct inode *dir, struct dentry *dentry)
924 int rc = 0;
925 int xid;
926 char *full_path = NULL;
927 struct inode *inode = dentry->d_inode;
928 struct cifsInodeInfo *cifs_inode;
929 struct super_block *sb = dir->i_sb;
930 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
931 struct cifsTconInfo *tcon = cifs_sb->tcon;
932 struct iattr *attrs = NULL;
933 __u32 dosattr = 0, origattr = 0;
935 cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
937 xid = GetXid();
939 /* Unlink can be called from rename so we can not take the
940 * sb->s_vfs_rename_mutex here */
941 full_path = build_path_from_dentry(dentry);
942 if (full_path == NULL) {
943 rc = -ENOMEM;
944 FreeXid(xid);
945 return rc;
948 if ((tcon->ses->capabilities & CAP_UNIX) &&
949 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
950 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
951 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
952 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
953 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
954 cFYI(1, ("posix del rc %d", rc));
955 if ((rc == 0) || (rc == -ENOENT))
956 goto psx_del_no_retry;
959 retry_std_delete:
960 rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
961 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
963 psx_del_no_retry:
964 if (!rc) {
965 if (inode)
966 drop_nlink(inode);
967 } else if (rc == -ENOENT) {
968 d_drop(dentry);
969 } else if (rc == -ETXTBSY) {
970 rc = cifs_rename_pending_delete(full_path, dentry, xid);
971 if (rc == 0)
972 drop_nlink(inode);
973 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
974 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
975 if (attrs == NULL) {
976 rc = -ENOMEM;
977 goto out_reval;
980 /* try to reset dos attributes */
981 cifs_inode = CIFS_I(inode);
982 origattr = cifs_inode->cifsAttrs;
983 if (origattr == 0)
984 origattr |= ATTR_NORMAL;
985 dosattr = origattr & ~ATTR_READONLY;
986 if (dosattr == 0)
987 dosattr |= ATTR_NORMAL;
988 dosattr |= ATTR_HIDDEN;
990 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
991 if (rc != 0)
992 goto out_reval;
994 goto retry_std_delete;
997 /* undo the setattr if we errored out and it's needed */
998 if (rc != 0 && dosattr != 0)
999 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1001 out_reval:
1002 if (inode) {
1003 cifs_inode = CIFS_I(inode);
1004 cifs_inode->time = 0; /* will force revalidate to get info
1005 when needed */
1006 inode->i_ctime = current_fs_time(sb);
1008 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
1009 cifs_inode = CIFS_I(dir);
1010 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
1012 kfree(full_path);
1013 kfree(attrs);
1014 FreeXid(xid);
1015 return rc;
1018 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1020 int rc = 0, tmprc;
1021 int xid;
1022 struct cifs_sb_info *cifs_sb;
1023 struct cifsTconInfo *pTcon;
1024 char *full_path = NULL;
1025 struct inode *newinode = NULL;
1026 struct cifs_fattr fattr;
1028 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
1030 xid = GetXid();
1032 cifs_sb = CIFS_SB(inode->i_sb);
1033 pTcon = cifs_sb->tcon;
1035 full_path = build_path_from_dentry(direntry);
1036 if (full_path == NULL) {
1037 rc = -ENOMEM;
1038 FreeXid(xid);
1039 return rc;
1042 if ((pTcon->ses->capabilities & CAP_UNIX) &&
1043 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1044 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
1045 u32 oplock = 0;
1046 FILE_UNIX_BASIC_INFO *pInfo =
1047 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1048 if (pInfo == NULL) {
1049 rc = -ENOMEM;
1050 goto mkdir_out;
1053 mode &= ~current_umask();
1054 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1055 mode, NULL /* netfid */, pInfo, &oplock,
1056 full_path, cifs_sb->local_nls,
1057 cifs_sb->mnt_cifs_flags &
1058 CIFS_MOUNT_MAP_SPECIAL_CHR);
1059 if (rc == -EOPNOTSUPP) {
1060 kfree(pInfo);
1061 goto mkdir_retry_old;
1062 } else if (rc) {
1063 cFYI(1, ("posix mkdir returned 0x%x", rc));
1064 d_drop(direntry);
1065 } else {
1066 if (pInfo->Type == cpu_to_le32(-1)) {
1067 /* no return info, go query for it */
1068 kfree(pInfo);
1069 goto mkdir_get_info;
1071 /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
1072 to set uid/gid */
1073 inc_nlink(inode);
1074 if (pTcon->nocase)
1075 direntry->d_op = &cifs_ci_dentry_ops;
1076 else
1077 direntry->d_op = &cifs_dentry_ops;
1079 cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
1080 newinode = cifs_iget(inode->i_sb, &fattr);
1081 if (!newinode) {
1082 kfree(pInfo);
1083 goto mkdir_get_info;
1086 d_instantiate(direntry, newinode);
1088 #ifdef CONFIG_CIFS_DEBUG2
1089 cFYI(1, ("instantiated dentry %p %s to inode %p",
1090 direntry, direntry->d_name.name, newinode));
1092 if (newinode->i_nlink != 2)
1093 cFYI(1, ("unexpected number of links %d",
1094 newinode->i_nlink));
1095 #endif
1097 kfree(pInfo);
1098 goto mkdir_out;
1100 mkdir_retry_old:
1101 /* BB add setting the equivalent of mode via CreateX w/ACLs */
1102 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1103 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1104 if (rc) {
1105 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
1106 d_drop(direntry);
1107 } else {
1108 mkdir_get_info:
1109 inc_nlink(inode);
1110 if (pTcon->unix_ext)
1111 rc = cifs_get_inode_info_unix(&newinode, full_path,
1112 inode->i_sb, xid);
1113 else
1114 rc = cifs_get_inode_info(&newinode, full_path, NULL,
1115 inode->i_sb, xid, NULL);
1117 if (pTcon->nocase)
1118 direntry->d_op = &cifs_ci_dentry_ops;
1119 else
1120 direntry->d_op = &cifs_dentry_ops;
1121 d_instantiate(direntry, newinode);
1122 /* setting nlink not necessary except in cases where we
1123 * failed to get it from the server or was set bogus */
1124 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1125 direntry->d_inode->i_nlink = 2;
1127 mode &= ~current_umask();
1128 /* must turn on setgid bit if parent dir has it */
1129 if (inode->i_mode & S_ISGID)
1130 mode |= S_ISGID;
1132 if (pTcon->unix_ext) {
1133 struct cifs_unix_set_info_args args = {
1134 .mode = mode,
1135 .ctime = NO_CHANGE_64,
1136 .atime = NO_CHANGE_64,
1137 .mtime = NO_CHANGE_64,
1138 .device = 0,
1140 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1141 args.uid = (__u64)current_fsuid();
1142 if (inode->i_mode & S_ISGID)
1143 args.gid = (__u64)inode->i_gid;
1144 else
1145 args.gid = (__u64)current_fsgid();
1146 } else {
1147 args.uid = NO_CHANGE_64;
1148 args.gid = NO_CHANGE_64;
1150 CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
1151 cifs_sb->local_nls,
1152 cifs_sb->mnt_cifs_flags &
1153 CIFS_MOUNT_MAP_SPECIAL_CHR);
1154 } else {
1155 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1156 (mode & S_IWUGO) == 0) {
1157 FILE_BASIC_INFO pInfo;
1158 struct cifsInodeInfo *cifsInode;
1159 u32 dosattrs;
1161 memset(&pInfo, 0, sizeof(pInfo));
1162 cifsInode = CIFS_I(newinode);
1163 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1164 pInfo.Attributes = cpu_to_le32(dosattrs);
1165 tmprc = CIFSSMBSetPathInfo(xid, pTcon,
1166 full_path, &pInfo,
1167 cifs_sb->local_nls,
1168 cifs_sb->mnt_cifs_flags &
1169 CIFS_MOUNT_MAP_SPECIAL_CHR);
1170 if (tmprc == 0)
1171 cifsInode->cifsAttrs = dosattrs;
1173 if (direntry->d_inode) {
1174 if (cifs_sb->mnt_cifs_flags &
1175 CIFS_MOUNT_DYNPERM)
1176 direntry->d_inode->i_mode =
1177 (mode | S_IFDIR);
1179 if (cifs_sb->mnt_cifs_flags &
1180 CIFS_MOUNT_SET_UID) {
1181 direntry->d_inode->i_uid =
1182 current_fsuid();
1183 if (inode->i_mode & S_ISGID)
1184 direntry->d_inode->i_gid =
1185 inode->i_gid;
1186 else
1187 direntry->d_inode->i_gid =
1188 current_fsgid();
1193 mkdir_out:
1194 kfree(full_path);
1195 FreeXid(xid);
1196 return rc;
1199 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1201 int rc = 0;
1202 int xid;
1203 struct cifs_sb_info *cifs_sb;
1204 struct cifsTconInfo *pTcon;
1205 char *full_path = NULL;
1206 struct cifsInodeInfo *cifsInode;
1208 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
1210 xid = GetXid();
1212 cifs_sb = CIFS_SB(inode->i_sb);
1213 pTcon = cifs_sb->tcon;
1215 full_path = build_path_from_dentry(direntry);
1216 if (full_path == NULL) {
1217 rc = -ENOMEM;
1218 FreeXid(xid);
1219 return rc;
1222 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1223 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1225 if (!rc) {
1226 drop_nlink(inode);
1227 spin_lock(&direntry->d_inode->i_lock);
1228 i_size_write(direntry->d_inode, 0);
1229 clear_nlink(direntry->d_inode);
1230 spin_unlock(&direntry->d_inode->i_lock);
1233 cifsInode = CIFS_I(direntry->d_inode);
1234 cifsInode->time = 0; /* force revalidate to go get info when
1235 needed */
1237 cifsInode = CIFS_I(inode);
1238 cifsInode->time = 0; /* force revalidate to get parent dir info
1239 since cached search results now invalid */
1241 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1242 current_fs_time(inode->i_sb);
1244 kfree(full_path);
1245 FreeXid(xid);
1246 return rc;
1249 static int
1250 cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1251 struct dentry *to_dentry, const char *toPath)
1253 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
1254 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1255 __u16 srcfid;
1256 int oplock, rc;
1258 /* try path-based rename first */
1259 rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
1260 cifs_sb->mnt_cifs_flags &
1261 CIFS_MOUNT_MAP_SPECIAL_CHR);
1264 * don't bother with rename by filehandle unless file is busy and
1265 * source Note that cross directory moves do not work with
1266 * rename by filehandle to various Windows servers.
1268 if (rc == 0 || rc != -ETXTBSY)
1269 return rc;
1271 /* open the file to be renamed -- we need DELETE perms */
1272 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
1273 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1274 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1275 CIFS_MOUNT_MAP_SPECIAL_CHR);
1277 if (rc == 0) {
1278 rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
1279 (const char *) to_dentry->d_name.name,
1280 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1281 CIFS_MOUNT_MAP_SPECIAL_CHR);
1283 CIFSSMBClose(xid, pTcon, srcfid);
1286 return rc;
1289 int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1290 struct inode *target_dir, struct dentry *target_dentry)
1292 char *fromName = NULL;
1293 char *toName = NULL;
1294 struct cifs_sb_info *cifs_sb_source;
1295 struct cifs_sb_info *cifs_sb_target;
1296 struct cifsTconInfo *tcon;
1297 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1298 FILE_UNIX_BASIC_INFO *info_buf_target;
1299 int xid, rc, tmprc;
1301 cifs_sb_target = CIFS_SB(target_dir->i_sb);
1302 cifs_sb_source = CIFS_SB(source_dir->i_sb);
1303 tcon = cifs_sb_source->tcon;
1305 xid = GetXid();
1308 * BB: this might be allowed if same server, but different share.
1309 * Consider adding support for this
1311 if (tcon != cifs_sb_target->tcon) {
1312 rc = -EXDEV;
1313 goto cifs_rename_exit;
1317 * we already have the rename sem so we do not need to
1318 * grab it again here to protect the path integrity
1320 fromName = build_path_from_dentry(source_dentry);
1321 if (fromName == NULL) {
1322 rc = -ENOMEM;
1323 goto cifs_rename_exit;
1326 toName = build_path_from_dentry(target_dentry);
1327 if (toName == NULL) {
1328 rc = -ENOMEM;
1329 goto cifs_rename_exit;
1332 rc = cifs_do_rename(xid, source_dentry, fromName,
1333 target_dentry, toName);
1335 if (rc == -EEXIST && tcon->unix_ext) {
1337 * Are src and dst hardlinks of same inode? We can
1338 * only tell with unix extensions enabled
1340 info_buf_source =
1341 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1342 GFP_KERNEL);
1343 if (info_buf_source == NULL) {
1344 rc = -ENOMEM;
1345 goto cifs_rename_exit;
1348 info_buf_target = info_buf_source + 1;
1349 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
1350 info_buf_source,
1351 cifs_sb_source->local_nls,
1352 cifs_sb_source->mnt_cifs_flags &
1353 CIFS_MOUNT_MAP_SPECIAL_CHR);
1354 if (tmprc != 0)
1355 goto unlink_target;
1357 tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
1358 toName, info_buf_target,
1359 cifs_sb_target->local_nls,
1360 /* remap based on source sb */
1361 cifs_sb_source->mnt_cifs_flags &
1362 CIFS_MOUNT_MAP_SPECIAL_CHR);
1364 if (tmprc == 0 && (info_buf_source->UniqueId ==
1365 info_buf_target->UniqueId)) {
1366 /* same file, POSIX says that this is a noop */
1367 rc = 0;
1368 goto cifs_rename_exit;
1370 } /* else ... BB we could add the same check for Windows by
1371 checking the UniqueId via FILE_INTERNAL_INFO */
1373 unlink_target:
1374 /* Try unlinking the target dentry if it's not negative */
1375 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
1376 tmprc = cifs_unlink(target_dir, target_dentry);
1377 if (tmprc)
1378 goto cifs_rename_exit;
1380 rc = cifs_do_rename(xid, source_dentry, fromName,
1381 target_dentry, toName);
1384 cifs_rename_exit:
1385 kfree(info_buf_source);
1386 kfree(fromName);
1387 kfree(toName);
1388 FreeXid(xid);
1389 return rc;
1392 int cifs_revalidate(struct dentry *direntry)
1394 int xid;
1395 int rc = 0, wbrc = 0;
1396 char *full_path;
1397 struct cifs_sb_info *cifs_sb;
1398 struct cifsInodeInfo *cifsInode;
1399 loff_t local_size;
1400 struct timespec local_mtime;
1401 bool invalidate_inode = false;
1403 if (direntry->d_inode == NULL)
1404 return -ENOENT;
1406 cifsInode = CIFS_I(direntry->d_inode);
1408 if (cifsInode == NULL)
1409 return -ENOENT;
1411 /* no sense revalidating inode info on file that no one can write */
1412 if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
1413 return rc;
1415 xid = GetXid();
1417 cifs_sb = CIFS_SB(direntry->d_sb);
1419 /* can not safely grab the rename sem here if rename calls revalidate
1420 since that would deadlock */
1421 full_path = build_path_from_dentry(direntry);
1422 if (full_path == NULL) {
1423 rc = -ENOMEM;
1424 FreeXid(xid);
1425 return rc;
1427 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1428 "jiffies %ld", full_path, direntry->d_inode,
1429 direntry->d_inode->i_count.counter, direntry,
1430 direntry->d_time, jiffies));
1432 if (cifsInode->time == 0) {
1433 /* was set to zero previously to force revalidate */
1434 } else if (time_before(jiffies, cifsInode->time + HZ) &&
1435 lookupCacheEnabled) {
1436 if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
1437 (direntry->d_inode->i_nlink == 1)) {
1438 kfree(full_path);
1439 FreeXid(xid);
1440 return rc;
1441 } else {
1442 cFYI(1, ("Have to revalidate file due to hardlinks"));
1446 /* save mtime and size */
1447 local_mtime = direntry->d_inode->i_mtime;
1448 local_size = direntry->d_inode->i_size;
1450 if (cifs_sb->tcon->unix_ext) {
1451 rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
1452 direntry->d_sb, xid);
1453 if (rc) {
1454 cFYI(1, ("error on getting revalidate info %d", rc));
1455 /* if (rc != -ENOENT)
1456 rc = 0; */ /* BB should we cache info on
1457 certain errors? */
1459 } else {
1460 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
1461 direntry->d_sb, xid, NULL);
1462 if (rc) {
1463 cFYI(1, ("error on getting revalidate info %d", rc));
1464 /* if (rc != -ENOENT)
1465 rc = 0; */ /* BB should we cache info on
1466 certain errors? */
1469 /* should we remap certain errors, access denied?, to zero */
1471 /* if not oplocked, we invalidate inode pages if mtime or file size
1472 had changed on server */
1474 if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
1475 (local_size == direntry->d_inode->i_size)) {
1476 cFYI(1, ("cifs_revalidate - inode unchanged"));
1477 } else {
1478 /* file may have changed on server */
1479 if (cifsInode->clientCanCacheRead) {
1480 /* no need to invalidate inode pages since we were the
1481 only ones who could have modified the file and the
1482 server copy is staler than ours */
1483 } else {
1484 invalidate_inode = true;
1488 /* can not grab this sem since kernel filesys locking documentation
1489 indicates i_mutex may be taken by the kernel on lookup and rename
1490 which could deadlock if we grab the i_mutex here as well */
1491 /* mutex_lock(&direntry->d_inode->i_mutex);*/
1492 /* need to write out dirty pages here */
1493 if (direntry->d_inode->i_mapping) {
1494 /* do we need to lock inode until after invalidate completes
1495 below? */
1496 wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping);
1497 if (wbrc)
1498 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1500 if (invalidate_inode) {
1501 /* shrink_dcache not necessary now that cifs dentry ops
1502 are exported for negative dentries */
1503 /* if (S_ISDIR(direntry->d_inode->i_mode))
1504 shrink_dcache_parent(direntry); */
1505 if (S_ISREG(direntry->d_inode->i_mode)) {
1506 if (direntry->d_inode->i_mapping) {
1507 wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
1508 if (wbrc)
1509 CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
1511 /* may eventually have to do this for open files too */
1512 if (list_empty(&(cifsInode->openFileList))) {
1513 /* changed on server - flush read ahead pages */
1514 cFYI(1, ("Invalidating read ahead data on "
1515 "closed file"));
1516 invalidate_remote_inode(direntry->d_inode);
1520 /* mutex_unlock(&direntry->d_inode->i_mutex); */
1522 kfree(full_path);
1523 FreeXid(xid);
1524 return rc;
1527 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1528 struct kstat *stat)
1530 int err = cifs_revalidate(dentry);
1531 if (!err) {
1532 generic_fillattr(dentry->d_inode, stat);
1533 stat->blksize = CIFS_MAX_MSGSIZE;
1534 stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
1536 return err;
1539 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1541 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1542 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1543 struct page *page;
1544 int rc = 0;
1546 page = grab_cache_page(mapping, index);
1547 if (!page)
1548 return -ENOMEM;
1550 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
1551 unlock_page(page);
1552 page_cache_release(page);
1553 return rc;
1556 static int cifs_vmtruncate(struct inode *inode, loff_t offset)
1558 loff_t oldsize;
1559 int err;
1561 spin_lock(&inode->i_lock);
1562 err = inode_newsize_ok(inode, offset);
1563 if (err) {
1564 spin_unlock(&inode->i_lock);
1565 goto out;
1568 oldsize = inode->i_size;
1569 i_size_write(inode, offset);
1570 spin_unlock(&inode->i_lock);
1571 truncate_pagecache(inode, oldsize, offset);
1572 if (inode->i_op->truncate)
1573 inode->i_op->truncate(inode);
1574 out:
1575 return err;
1578 static int
1579 cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1580 int xid, char *full_path)
1582 int rc;
1583 struct cifsFileInfo *open_file;
1584 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1585 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1586 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1589 * To avoid spurious oplock breaks from server, in the case of
1590 * inodes that we already have open, avoid doing path based
1591 * setting of file size if we can do it by handle.
1592 * This keeps our caching token (oplock) and avoids timeouts
1593 * when the local oplock break takes longer to flush
1594 * writebehind data than the SMB timeout for the SetPathInfo
1595 * request would allow
1597 open_file = find_writable_file(cifsInode);
1598 if (open_file) {
1599 __u16 nfid = open_file->netfid;
1600 __u32 npid = open_file->pid;
1601 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
1602 npid, false);
1603 cifsFileInfo_put(open_file);
1604 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1605 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1606 unsigned int bytes_written;
1607 rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
1608 &bytes_written, NULL, NULL, 1);
1609 cFYI(1, ("Wrt seteof rc %d", rc));
1611 } else
1612 rc = -EINVAL;
1614 if (rc != 0) {
1615 /* Set file size by pathname rather than by handle
1616 either because no valid, writeable file handle for
1617 it was found or because there was an error setting
1618 it by handle */
1619 rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
1620 false, cifs_sb->local_nls,
1621 cifs_sb->mnt_cifs_flags &
1622 CIFS_MOUNT_MAP_SPECIAL_CHR);
1623 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1624 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1625 __u16 netfid;
1626 int oplock = 0;
1628 rc = SMBLegacyOpen(xid, pTcon, full_path,
1629 FILE_OPEN, GENERIC_WRITE,
1630 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1631 cifs_sb->local_nls,
1632 cifs_sb->mnt_cifs_flags &
1633 CIFS_MOUNT_MAP_SPECIAL_CHR);
1634 if (rc == 0) {
1635 unsigned int bytes_written;
1636 rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
1637 attrs->ia_size,
1638 &bytes_written, NULL,
1639 NULL, 1);
1640 cFYI(1, ("wrt seteof rc %d", rc));
1641 CIFSSMBClose(xid, pTcon, netfid);
1646 if (rc == 0) {
1647 cifsInode->server_eof = attrs->ia_size;
1648 rc = cifs_vmtruncate(inode, attrs->ia_size);
1649 cifs_truncate_page(inode->i_mapping, inode->i_size);
1652 return rc;
1655 static int
1656 cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1658 int rc;
1659 int xid;
1660 char *full_path = NULL;
1661 struct inode *inode = direntry->d_inode;
1662 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1663 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1664 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1665 struct cifs_unix_set_info_args *args = NULL;
1666 struct cifsFileInfo *open_file;
1668 cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
1669 direntry->d_name.name, attrs->ia_valid));
1671 xid = GetXid();
1673 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1674 /* check if we have permission to change attrs */
1675 rc = inode_change_ok(inode, attrs);
1676 if (rc < 0)
1677 goto out;
1678 else
1679 rc = 0;
1682 full_path = build_path_from_dentry(direntry);
1683 if (full_path == NULL) {
1684 rc = -ENOMEM;
1685 goto out;
1689 * Attempt to flush data before changing attributes. We need to do
1690 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1691 * ownership or mode then we may also need to do this. Here, we take
1692 * the safe way out and just do the flush on all setattr requests. If
1693 * the flush returns error, store it to report later and continue.
1695 * BB: This should be smarter. Why bother flushing pages that
1696 * will be truncated anyway? Also, should we error out here if
1697 * the flush returns error?
1699 rc = filemap_write_and_wait(inode->i_mapping);
1700 if (rc != 0) {
1701 cifsInode->write_behind_rc = rc;
1702 rc = 0;
1705 if (attrs->ia_valid & ATTR_SIZE) {
1706 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1707 if (rc != 0)
1708 goto out;
1711 /* skip mode change if it's just for clearing setuid/setgid */
1712 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1713 attrs->ia_valid &= ~ATTR_MODE;
1715 args = kmalloc(sizeof(*args), GFP_KERNEL);
1716 if (args == NULL) {
1717 rc = -ENOMEM;
1718 goto out;
1721 /* set up the struct */
1722 if (attrs->ia_valid & ATTR_MODE)
1723 args->mode = attrs->ia_mode;
1724 else
1725 args->mode = NO_CHANGE_64;
1727 if (attrs->ia_valid & ATTR_UID)
1728 args->uid = attrs->ia_uid;
1729 else
1730 args->uid = NO_CHANGE_64;
1732 if (attrs->ia_valid & ATTR_GID)
1733 args->gid = attrs->ia_gid;
1734 else
1735 args->gid = NO_CHANGE_64;
1737 if (attrs->ia_valid & ATTR_ATIME)
1738 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
1739 else
1740 args->atime = NO_CHANGE_64;
1742 if (attrs->ia_valid & ATTR_MTIME)
1743 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
1744 else
1745 args->mtime = NO_CHANGE_64;
1747 if (attrs->ia_valid & ATTR_CTIME)
1748 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
1749 else
1750 args->ctime = NO_CHANGE_64;
1752 args->device = 0;
1753 open_file = find_writable_file(cifsInode);
1754 if (open_file) {
1755 u16 nfid = open_file->netfid;
1756 u32 npid = open_file->pid;
1757 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
1758 cifsFileInfo_put(open_file);
1759 } else {
1760 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
1761 cifs_sb->local_nls,
1762 cifs_sb->mnt_cifs_flags &
1763 CIFS_MOUNT_MAP_SPECIAL_CHR);
1766 if (!rc) {
1767 rc = inode_setattr(inode, attrs);
1769 /* force revalidate when any of these times are set since some
1770 of the fs types (eg ext3, fat) do not have fine enough
1771 time granularity to match protocol, and we do not have a
1772 a way (yet) to query the server fs's time granularity (and
1773 whether it rounds times down).
1775 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
1776 cifsInode->time = 0;
1778 out:
1779 kfree(args);
1780 kfree(full_path);
1781 FreeXid(xid);
1782 return rc;
1785 static int
1786 cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1788 int xid;
1789 struct inode *inode = direntry->d_inode;
1790 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1791 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1792 char *full_path = NULL;
1793 int rc = -EACCES;
1794 __u32 dosattr = 0;
1795 __u64 mode = NO_CHANGE_64;
1797 xid = GetXid();
1799 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1800 direntry->d_name.name, attrs->ia_valid));
1802 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1803 /* check if we have permission to change attrs */
1804 rc = inode_change_ok(inode, attrs);
1805 if (rc < 0) {
1806 FreeXid(xid);
1807 return rc;
1808 } else
1809 rc = 0;
1812 full_path = build_path_from_dentry(direntry);
1813 if (full_path == NULL) {
1814 rc = -ENOMEM;
1815 FreeXid(xid);
1816 return rc;
1820 * Attempt to flush data before changing attributes. We need to do
1821 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1822 * ownership or mode then we may also need to do this. Here, we take
1823 * the safe way out and just do the flush on all setattr requests. If
1824 * the flush returns error, store it to report later and continue.
1826 * BB: This should be smarter. Why bother flushing pages that
1827 * will be truncated anyway? Also, should we error out here if
1828 * the flush returns error?
1830 rc = filemap_write_and_wait(inode->i_mapping);
1831 if (rc != 0) {
1832 cifsInode->write_behind_rc = rc;
1833 rc = 0;
1836 if (attrs->ia_valid & ATTR_SIZE) {
1837 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1838 if (rc != 0)
1839 goto cifs_setattr_exit;
1843 * Without unix extensions we can't send ownership changes to the
1844 * server, so silently ignore them. This is consistent with how
1845 * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With
1846 * CIFSACL support + proper Windows to Unix idmapping, we may be
1847 * able to support this in the future.
1849 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
1850 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1852 /* skip mode change if it's just for clearing setuid/setgid */
1853 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1854 attrs->ia_valid &= ~ATTR_MODE;
1856 if (attrs->ia_valid & ATTR_MODE) {
1857 cFYI(1, ("Mode changed to 0%o", attrs->ia_mode));
1858 mode = attrs->ia_mode;
1861 if (attrs->ia_valid & ATTR_MODE) {
1862 rc = 0;
1863 #ifdef CONFIG_CIFS_EXPERIMENTAL
1864 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
1865 rc = mode_to_acl(inode, full_path, mode);
1866 else
1867 #endif
1868 if (((mode & S_IWUGO) == 0) &&
1869 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1871 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
1873 /* fix up mode if we're not using dynperm */
1874 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
1875 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
1876 } else if ((mode & S_IWUGO) &&
1877 (cifsInode->cifsAttrs & ATTR_READONLY)) {
1879 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
1880 /* Attributes of 0 are ignored */
1881 if (dosattr == 0)
1882 dosattr |= ATTR_NORMAL;
1884 /* reset local inode permissions to normal */
1885 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1886 attrs->ia_mode &= ~(S_IALLUGO);
1887 if (S_ISDIR(inode->i_mode))
1888 attrs->ia_mode |=
1889 cifs_sb->mnt_dir_mode;
1890 else
1891 attrs->ia_mode |=
1892 cifs_sb->mnt_file_mode;
1894 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1895 /* ignore mode change - ATTR_READONLY hasn't changed */
1896 attrs->ia_valid &= ~ATTR_MODE;
1900 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
1901 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
1902 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
1903 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
1905 /* Even if error on time set, no sense failing the call if
1906 the server would set the time to a reasonable value anyway,
1907 and this check ensures that we are not being called from
1908 sys_utimes in which case we ought to fail the call back to
1909 the user when the server rejects the call */
1910 if ((rc) && (attrs->ia_valid &
1911 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
1912 rc = 0;
1915 /* do not need local check to inode_check_ok since the server does
1916 that */
1917 if (!rc)
1918 rc = inode_setattr(inode, attrs);
1919 cifs_setattr_exit:
1920 kfree(full_path);
1921 FreeXid(xid);
1922 return rc;
1926 cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1928 struct inode *inode = direntry->d_inode;
1929 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1930 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1932 if (pTcon->unix_ext)
1933 return cifs_setattr_unix(direntry, attrs);
1935 return cifs_setattr_nounix(direntry, attrs);
1937 /* BB: add cifs_setattr_legacy for really old servers */
1940 #if 0
1941 void cifs_delete_inode(struct inode *inode)
1943 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
1944 /* may have to add back in if and when safe distributed caching of
1945 directories added e.g. via FindNotify */
1947 #endif