atomic_t: Remove volatile from atomic_t definition
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / cifs / inode.c
blob29b9ea244c8132e241f1f9e6749be2003a8f196c
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/slab.h>
24 #include <linux/pagemap.h>
25 #include <asm/div64.h>
26 #include "cifsfs.h"
27 #include "cifspdu.h"
28 #include "cifsglob.h"
29 #include "cifsproto.h"
30 #include "cifs_debug.h"
31 #include "cifs_fs_sb.h"
34 static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
36 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
38 switch (inode->i_mode & S_IFMT) {
39 case S_IFREG:
40 inode->i_op = &cifs_file_inode_ops;
41 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
42 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
43 inode->i_fop = &cifs_file_direct_nobrl_ops;
44 else
45 inode->i_fop = &cifs_file_direct_ops;
46 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
47 inode->i_fop = &cifs_file_nobrl_ops;
48 else { /* not direct, send byte range locks */
49 inode->i_fop = &cifs_file_ops;
53 /* check if server can support readpages */
54 if (cifs_sb->tcon->ses->server->maxBuf <
55 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
56 inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
57 else
58 inode->i_data.a_ops = &cifs_addr_ops;
59 break;
60 case S_IFDIR:
61 #ifdef CONFIG_CIFS_DFS_UPCALL
62 if (is_dfs_referral) {
63 inode->i_op = &cifs_dfs_referral_inode_operations;
64 } else {
65 #else /* NO DFS support, treat as a directory */
67 #endif
68 inode->i_op = &cifs_dir_inode_ops;
69 inode->i_fop = &cifs_dir_ops;
71 break;
72 case S_IFLNK:
73 inode->i_op = &cifs_symlink_inode_ops;
74 break;
75 default:
76 init_special_inode(inode, inode->i_mode, inode->i_rdev);
77 break;
81 /* check inode attributes against fattr. If they don't match, tag the
82 * inode for cache invalidation
84 static void
85 cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
87 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
89 cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid));
91 if (inode->i_state & I_NEW) {
92 cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid));
93 return;
96 /* don't bother with revalidation if we have an oplock */
97 if (cifs_i->clientCanCacheRead) {
98 cFYI(1, ("%s: inode %llu is oplocked", __func__,
99 cifs_i->uniqueid));
100 return;
103 /* revalidate if mtime or size have changed */
104 if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
105 cifs_i->server_eof == fattr->cf_eof) {
106 cFYI(1, ("%s: inode %llu is unchanged", __func__,
107 cifs_i->uniqueid));
108 return;
111 cFYI(1, ("%s: invalidating inode %llu mapping", __func__,
112 cifs_i->uniqueid));
113 cifs_i->invalid_mapping = true;
116 /* populate an inode with info from a cifs_fattr struct */
117 void
118 cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
120 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
121 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
122 unsigned long oldtime = cifs_i->time;
124 cifs_revalidate_cache(inode, fattr);
126 inode->i_atime = fattr->cf_atime;
127 inode->i_mtime = fattr->cf_mtime;
128 inode->i_ctime = fattr->cf_ctime;
129 inode->i_rdev = fattr->cf_rdev;
130 inode->i_nlink = fattr->cf_nlink;
131 inode->i_uid = fattr->cf_uid;
132 inode->i_gid = fattr->cf_gid;
134 /* if dynperm is set, don't clobber existing mode */
135 if (inode->i_state & I_NEW ||
136 !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM))
137 inode->i_mode = fattr->cf_mode;
139 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
140 cifs_i->uniqueid = fattr->cf_uniqueid;
142 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
143 cifs_i->time = 0;
144 else
145 cifs_i->time = jiffies;
147 cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
148 oldtime, cifs_i->time));
150 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
152 cifs_i->server_eof = fattr->cf_eof;
154 * Can't safely change the file size here if the client is writing to
155 * it due to potential races.
157 spin_lock(&inode->i_lock);
158 if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
159 i_size_write(inode, fattr->cf_eof);
162 * i_blocks is not related to (i_size / i_blksize),
163 * but instead 512 byte (2**9) size is required for
164 * calculating num blocks.
166 inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9;
168 spin_unlock(&inode->i_lock);
170 cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
173 /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
174 void
175 cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
176 struct cifs_sb_info *cifs_sb)
178 memset(fattr, 0, sizeof(*fattr));
179 fattr->cf_uniqueid = le64_to_cpu(info->UniqueId);
180 fattr->cf_bytes = le64_to_cpu(info->NumOfBytes);
181 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
183 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
184 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastModificationTime);
185 fattr->cf_ctime = cifs_NTtimeToUnix(info->LastStatusChange);
186 fattr->cf_mode = le64_to_cpu(info->Permissions);
189 * Since we set the inode type below we need to mask off
190 * to avoid strange results if bits set above.
192 fattr->cf_mode &= ~S_IFMT;
193 switch (le32_to_cpu(info->Type)) {
194 case UNIX_FILE:
195 fattr->cf_mode |= S_IFREG;
196 fattr->cf_dtype = DT_REG;
197 break;
198 case UNIX_SYMLINK:
199 fattr->cf_mode |= S_IFLNK;
200 fattr->cf_dtype = DT_LNK;
201 break;
202 case UNIX_DIR:
203 fattr->cf_mode |= S_IFDIR;
204 fattr->cf_dtype = DT_DIR;
205 break;
206 case UNIX_CHARDEV:
207 fattr->cf_mode |= S_IFCHR;
208 fattr->cf_dtype = DT_CHR;
209 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
210 le64_to_cpu(info->DevMinor) & MINORMASK);
211 break;
212 case UNIX_BLOCKDEV:
213 fattr->cf_mode |= S_IFBLK;
214 fattr->cf_dtype = DT_BLK;
215 fattr->cf_rdev = MKDEV(le64_to_cpu(info->DevMajor),
216 le64_to_cpu(info->DevMinor) & MINORMASK);
217 break;
218 case UNIX_FIFO:
219 fattr->cf_mode |= S_IFIFO;
220 fattr->cf_dtype = DT_FIFO;
221 break;
222 case UNIX_SOCKET:
223 fattr->cf_mode |= S_IFSOCK;
224 fattr->cf_dtype = DT_SOCK;
225 break;
226 default:
227 /* safest to call it a file if we do not know */
228 fattr->cf_mode |= S_IFREG;
229 fattr->cf_dtype = DT_REG;
230 cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
231 break;
234 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
235 fattr->cf_uid = cifs_sb->mnt_uid;
236 else
237 fattr->cf_uid = le64_to_cpu(info->Uid);
239 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
240 fattr->cf_gid = cifs_sb->mnt_gid;
241 else
242 fattr->cf_gid = le64_to_cpu(info->Gid);
244 fattr->cf_nlink = le64_to_cpu(info->Nlinks);
248 * Fill a cifs_fattr struct with fake inode info.
250 * Needed to setup cifs_fattr data for the directory which is the
251 * junction to the new submount (ie to setup the fake directory
252 * which represents a DFS referral).
254 static void
255 cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
257 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
259 cFYI(1, ("creating fake fattr for DFS referral"));
261 memset(fattr, 0, sizeof(*fattr));
262 fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
263 fattr->cf_uid = cifs_sb->mnt_uid;
264 fattr->cf_gid = cifs_sb->mnt_gid;
265 fattr->cf_atime = CURRENT_TIME;
266 fattr->cf_ctime = CURRENT_TIME;
267 fattr->cf_mtime = CURRENT_TIME;
268 fattr->cf_nlink = 2;
269 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
272 int cifs_get_file_info_unix(struct file *filp)
274 int rc;
275 int xid;
276 FILE_UNIX_BASIC_INFO find_data;
277 struct cifs_fattr fattr;
278 struct inode *inode = filp->f_path.dentry->d_inode;
279 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
280 struct cifsTconInfo *tcon = cifs_sb->tcon;
281 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
283 xid = GetXid();
284 rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data);
285 if (!rc) {
286 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
287 } else if (rc == -EREMOTE) {
288 cifs_create_dfs_fattr(&fattr, inode->i_sb);
289 rc = 0;
292 cifs_fattr_to_inode(inode, &fattr);
293 FreeXid(xid);
294 return rc;
297 int cifs_get_inode_info_unix(struct inode **pinode,
298 const unsigned char *full_path,
299 struct super_block *sb, int xid)
301 int rc;
302 FILE_UNIX_BASIC_INFO find_data;
303 struct cifs_fattr fattr;
304 struct cifsTconInfo *tcon;
305 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
307 tcon = cifs_sb->tcon;
308 cFYI(1, ("Getting info on %s", full_path));
310 /* could have done a find first instead but this returns more info */
311 rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
312 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
313 CIFS_MOUNT_MAP_SPECIAL_CHR);
315 if (!rc) {
316 cifs_unix_basic_to_fattr(&fattr, &find_data, cifs_sb);
317 } else if (rc == -EREMOTE) {
318 cifs_create_dfs_fattr(&fattr, sb);
319 rc = 0;
320 } else {
321 return rc;
324 if (*pinode == NULL) {
325 /* get new inode */
326 *pinode = cifs_iget(sb, &fattr);
327 if (!*pinode)
328 rc = -ENOMEM;
329 } else {
330 /* we already have inode, update it */
331 cifs_fattr_to_inode(*pinode, &fattr);
334 return rc;
337 static int
338 cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
339 struct cifs_sb_info *cifs_sb, int xid)
341 int rc;
342 int oplock = 0;
343 __u16 netfid;
344 struct cifsTconInfo *pTcon = cifs_sb->tcon;
345 char buf[24];
346 unsigned int bytes_read;
347 char *pbuf;
349 pbuf = buf;
351 fattr->cf_mode &= ~S_IFMT;
353 if (fattr->cf_eof == 0) {
354 fattr->cf_mode |= S_IFIFO;
355 fattr->cf_dtype = DT_FIFO;
356 return 0;
357 } else if (fattr->cf_eof < 8) {
358 fattr->cf_mode |= S_IFREG;
359 fattr->cf_dtype = DT_REG;
360 return -EINVAL; /* EOPNOTSUPP? */
363 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
364 CREATE_NOT_DIR, &netfid, &oplock, NULL,
365 cifs_sb->local_nls,
366 cifs_sb->mnt_cifs_flags &
367 CIFS_MOUNT_MAP_SPECIAL_CHR);
368 if (rc == 0) {
369 int buf_type = CIFS_NO_BUFFER;
370 /* Read header */
371 rc = CIFSSMBRead(xid, pTcon, netfid,
372 24 /* length */, 0 /* offset */,
373 &bytes_read, &pbuf, &buf_type);
374 if ((rc == 0) && (bytes_read >= 8)) {
375 if (memcmp("IntxBLK", pbuf, 8) == 0) {
376 cFYI(1, ("Block device"));
377 fattr->cf_mode |= S_IFBLK;
378 fattr->cf_dtype = DT_BLK;
379 if (bytes_read == 24) {
380 /* we have enough to decode dev num */
381 __u64 mjr; /* major */
382 __u64 mnr; /* minor */
383 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
384 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
385 fattr->cf_rdev = MKDEV(mjr, mnr);
387 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
388 cFYI(1, ("Char device"));
389 fattr->cf_mode |= S_IFCHR;
390 fattr->cf_dtype = DT_CHR;
391 if (bytes_read == 24) {
392 /* we have enough to decode dev num */
393 __u64 mjr; /* major */
394 __u64 mnr; /* minor */
395 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
396 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
397 fattr->cf_rdev = MKDEV(mjr, mnr);
399 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
400 cFYI(1, ("Symlink"));
401 fattr->cf_mode |= S_IFLNK;
402 fattr->cf_dtype = DT_LNK;
403 } else {
404 fattr->cf_mode |= S_IFREG; /* file? */
405 fattr->cf_dtype = DT_REG;
406 rc = -EOPNOTSUPP;
408 } else {
409 fattr->cf_mode |= S_IFREG; /* then it is a file */
410 fattr->cf_dtype = DT_REG;
411 rc = -EOPNOTSUPP; /* or some unknown SFU type */
413 CIFSSMBClose(xid, pTcon, netfid);
415 return rc;
418 #define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
421 * Fetch mode bits as provided by SFU.
423 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
425 static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
426 struct cifs_sb_info *cifs_sb, int xid)
428 #ifdef CONFIG_CIFS_XATTR
429 ssize_t rc;
430 char ea_value[4];
431 __u32 mode;
433 rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS",
434 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
435 cifs_sb->mnt_cifs_flags &
436 CIFS_MOUNT_MAP_SPECIAL_CHR);
437 if (rc < 0)
438 return (int)rc;
439 else if (rc > 3) {
440 mode = le32_to_cpu(*((__le32 *)ea_value));
441 fattr->cf_mode &= ~SFBITS_MASK;
442 cFYI(1, ("special bits 0%o org mode 0%o", mode,
443 fattr->cf_mode));
444 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
445 cFYI(1, ("special mode bits 0%o", mode));
448 return 0;
449 #else
450 return -EOPNOTSUPP;
451 #endif
454 /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
455 static void
456 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
457 struct cifs_sb_info *cifs_sb, bool adjust_tz)
459 memset(fattr, 0, sizeof(*fattr));
460 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
461 if (info->DeletePending)
462 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
464 if (info->LastAccessTime)
465 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
466 else
467 fattr->cf_atime = CURRENT_TIME;
469 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
470 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
472 if (adjust_tz) {
473 fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
474 fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
477 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
478 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
480 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
481 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
482 fattr->cf_dtype = DT_DIR;
483 } else {
484 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
485 fattr->cf_dtype = DT_REG;
487 /* clear write bits if ATTR_READONLY is set */
488 if (fattr->cf_cifsattrs & ATTR_READONLY)
489 fattr->cf_mode &= ~(S_IWUGO);
492 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
494 fattr->cf_uid = cifs_sb->mnt_uid;
495 fattr->cf_gid = cifs_sb->mnt_gid;
498 int cifs_get_file_info(struct file *filp)
500 int rc;
501 int xid;
502 FILE_ALL_INFO find_data;
503 struct cifs_fattr fattr;
504 struct inode *inode = filp->f_path.dentry->d_inode;
505 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
506 struct cifsTconInfo *tcon = cifs_sb->tcon;
507 struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
509 xid = GetXid();
510 rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
511 if (rc == -EOPNOTSUPP || rc == -EINVAL) {
513 * FIXME: legacy server -- fall back to path-based call?
514 * for now, just skip revalidating and mark inode for
515 * immediate reval.
517 rc = 0;
518 CIFS_I(inode)->time = 0;
519 goto cgfi_exit;
520 } else if (rc == -EREMOTE) {
521 cifs_create_dfs_fattr(&fattr, inode->i_sb);
522 rc = 0;
523 } else if (rc)
524 goto cgfi_exit;
527 * don't bother with SFU junk here -- just mark inode as needing
528 * revalidation.
530 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
531 fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
532 fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
533 cifs_fattr_to_inode(inode, &fattr);
534 cgfi_exit:
535 FreeXid(xid);
536 return rc;
539 int cifs_get_inode_info(struct inode **pinode,
540 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
541 struct super_block *sb, int xid, const __u16 *pfid)
543 int rc = 0, tmprc;
544 struct cifsTconInfo *pTcon;
545 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
546 char *buf = NULL;
547 bool adjustTZ = false;
548 struct cifs_fattr fattr;
550 pTcon = cifs_sb->tcon;
551 cFYI(1, ("Getting info on %s", full_path));
553 if ((pfindData == NULL) && (*pinode != NULL)) {
554 if (CIFS_I(*pinode)->clientCanCacheRead) {
555 cFYI(1, ("No need to revalidate cached inode sizes"));
556 return rc;
560 /* if file info not passed in then get it from server */
561 if (pfindData == NULL) {
562 buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
563 if (buf == NULL)
564 return -ENOMEM;
565 pfindData = (FILE_ALL_INFO *)buf;
567 /* could do find first instead but this returns more info */
568 rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
569 0 /* not legacy */,
570 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
571 CIFS_MOUNT_MAP_SPECIAL_CHR);
572 /* BB optimize code so we do not make the above call
573 when server claims no NT SMB support and the above call
574 failed at least once - set flag in tcon or mount */
575 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
576 rc = SMBQueryInformation(xid, pTcon, full_path,
577 pfindData, cifs_sb->local_nls,
578 cifs_sb->mnt_cifs_flags &
579 CIFS_MOUNT_MAP_SPECIAL_CHR);
580 adjustTZ = true;
584 if (!rc) {
585 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
586 cifs_sb, adjustTZ);
587 } else if (rc == -EREMOTE) {
588 cifs_create_dfs_fattr(&fattr, sb);
589 rc = 0;
590 } else {
591 goto cgii_exit;
595 * If an inode wasn't passed in, then get the inode number
597 * Is an i_ino of zero legal? Can we use that to check if the server
598 * supports returning inode numbers? Are there other sanity checks we
599 * can use to ensure that the server is really filling in that field?
601 * We can not use the IndexNumber field by default from Windows or
602 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
603 * CIFS spec claims that this value is unique within the scope of a
604 * share, and the windows docs hint that it's actually unique
605 * per-machine.
607 * There may be higher info levels that work but are there Windows
608 * server or network appliances for which IndexNumber field is not
609 * guaranteed unique?
611 if (*pinode == NULL) {
612 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
613 int rc1 = 0;
615 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
616 full_path, &fattr.cf_uniqueid,
617 cifs_sb->local_nls,
618 cifs_sb->mnt_cifs_flags &
619 CIFS_MOUNT_MAP_SPECIAL_CHR);
620 if (rc1 || !fattr.cf_uniqueid) {
621 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
622 fattr.cf_uniqueid = iunique(sb, ROOT_I);
623 cifs_autodisable_serverino(cifs_sb);
625 } else {
626 fattr.cf_uniqueid = iunique(sb, ROOT_I);
628 } else {
629 fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
632 /* query for SFU type info if supported and needed */
633 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
634 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
635 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
636 if (tmprc)
637 cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
640 #ifdef CONFIG_CIFS_EXPERIMENTAL
641 /* fill in 0777 bits from ACL */
642 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
643 cFYI(1, ("Getting mode bits from ACL"));
644 cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
646 #endif
648 /* fill in remaining high mode bits e.g. SUID, VTX */
649 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
650 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
652 if (!*pinode) {
653 *pinode = cifs_iget(sb, &fattr);
654 if (!*pinode)
655 rc = -ENOMEM;
656 } else {
657 cifs_fattr_to_inode(*pinode, &fattr);
660 cgii_exit:
661 kfree(buf);
662 return rc;
665 static const struct inode_operations cifs_ipc_inode_ops = {
666 .lookup = cifs_lookup,
669 char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
671 int pplen = cifs_sb->prepathlen;
672 int dfsplen;
673 char *full_path = NULL;
675 /* if no prefix path, simply set path to the root of share to "" */
676 if (pplen == 0) {
677 full_path = kmalloc(1, GFP_KERNEL);
678 if (full_path)
679 full_path[0] = 0;
680 return full_path;
683 if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
684 dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
685 else
686 dfsplen = 0;
688 full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
689 if (full_path == NULL)
690 return full_path;
692 if (dfsplen) {
693 strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
694 /* switch slash direction in prepath depending on whether
695 * windows or posix style path names
697 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
698 int i;
699 for (i = 0; i < dfsplen; i++) {
700 if (full_path[i] == '\\')
701 full_path[i] = '/';
705 strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
706 full_path[dfsplen + pplen] = 0; /* add trailing null */
707 return full_path;
710 static int
711 cifs_find_inode(struct inode *inode, void *opaque)
713 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
715 if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
716 return 0;
719 * uh oh -- it's a directory. We can't use it since hardlinked dirs are
720 * verboten. Disable serverino and return it as if it were found, the
721 * caller can discard it, generate a uniqueid and retry the find
723 if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) {
724 fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
725 cifs_autodisable_serverino(CIFS_SB(inode->i_sb));
728 return 1;
731 static int
732 cifs_init_inode(struct inode *inode, void *opaque)
734 struct cifs_fattr *fattr = (struct cifs_fattr *) opaque;
736 CIFS_I(inode)->uniqueid = fattr->cf_uniqueid;
737 return 0;
740 /* Given fattrs, get a corresponding inode */
741 struct inode *
742 cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
744 unsigned long hash;
745 struct inode *inode;
747 retry_iget5_locked:
748 cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
750 /* hash down to 32-bits on 32-bit arch */
751 hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
753 inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr);
754 if (inode) {
755 /* was there a problematic inode number collision? */
756 if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) {
757 iput(inode);
758 fattr->cf_uniqueid = iunique(sb, ROOT_I);
759 fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION;
760 goto retry_iget5_locked;
763 cifs_fattr_to_inode(inode, fattr);
764 if (sb->s_flags & MS_NOATIME)
765 inode->i_flags |= S_NOATIME | S_NOCMTIME;
766 if (inode->i_state & I_NEW) {
767 inode->i_ino = hash;
768 unlock_new_inode(inode);
772 return inode;
775 /* gets root inode */
776 struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
778 int xid;
779 struct cifs_sb_info *cifs_sb;
780 struct inode *inode = NULL;
781 long rc;
782 char *full_path;
784 cifs_sb = CIFS_SB(sb);
785 full_path = cifs_build_path_to_root(cifs_sb);
786 if (full_path == NULL)
787 return ERR_PTR(-ENOMEM);
789 xid = GetXid();
790 if (cifs_sb->tcon->unix_ext)
791 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
792 else
793 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
794 xid, NULL);
796 if (!inode)
797 return ERR_PTR(-ENOMEM);
799 if (rc && cifs_sb->tcon->ipc) {
800 cFYI(1, ("ipc connection - fake read inode"));
801 inode->i_mode |= S_IFDIR;
802 inode->i_nlink = 2;
803 inode->i_op = &cifs_ipc_inode_ops;
804 inode->i_fop = &simple_dir_operations;
805 inode->i_uid = cifs_sb->mnt_uid;
806 inode->i_gid = cifs_sb->mnt_gid;
807 } else if (rc) {
808 kfree(full_path);
809 _FreeXid(xid);
810 iget_failed(inode);
811 return ERR_PTR(rc);
815 kfree(full_path);
816 /* can not call macro FreeXid here since in a void func
817 * TODO: This is no longer true
819 _FreeXid(xid);
820 return inode;
823 static int
824 cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
825 char *full_path, __u32 dosattr)
827 int rc;
828 int oplock = 0;
829 __u16 netfid;
830 __u32 netpid;
831 bool set_time = false;
832 struct cifsFileInfo *open_file;
833 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
834 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
835 struct cifsTconInfo *pTcon = cifs_sb->tcon;
836 FILE_BASIC_INFO info_buf;
838 if (attrs == NULL)
839 return -EINVAL;
841 if (attrs->ia_valid & ATTR_ATIME) {
842 set_time = true;
843 info_buf.LastAccessTime =
844 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
845 } else
846 info_buf.LastAccessTime = 0;
848 if (attrs->ia_valid & ATTR_MTIME) {
849 set_time = true;
850 info_buf.LastWriteTime =
851 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
852 } else
853 info_buf.LastWriteTime = 0;
856 * Samba throws this field away, but windows may actually use it.
857 * Do not set ctime unless other time stamps are changed explicitly
858 * (i.e. by utimes()) since we would then have a mix of client and
859 * server times.
861 if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
862 cFYI(1, ("CIFS - CTIME changed"));
863 info_buf.ChangeTime =
864 cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
865 } else
866 info_buf.ChangeTime = 0;
868 info_buf.CreationTime = 0; /* don't change */
869 info_buf.Attributes = cpu_to_le32(dosattr);
872 * If the file is already open for write, just use that fileid
874 open_file = find_writable_file(cifsInode);
875 if (open_file) {
876 netfid = open_file->netfid;
877 netpid = open_file->pid;
878 goto set_via_filehandle;
882 * NT4 apparently returns success on this call, but it doesn't
883 * really work.
885 if (!(pTcon->ses->flags & CIFS_SES_NT4)) {
886 rc = CIFSSMBSetPathInfo(xid, pTcon, full_path,
887 &info_buf, cifs_sb->local_nls,
888 cifs_sb->mnt_cifs_flags &
889 CIFS_MOUNT_MAP_SPECIAL_CHR);
890 if (rc == 0) {
891 cifsInode->cifsAttrs = dosattr;
892 goto out;
893 } else if (rc != -EOPNOTSUPP && rc != -EINVAL)
894 goto out;
897 cFYI(1, ("calling SetFileInfo since SetPathInfo for "
898 "times not supported by this server"));
899 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
900 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
901 CREATE_NOT_DIR, &netfid, &oplock,
902 NULL, cifs_sb->local_nls,
903 cifs_sb->mnt_cifs_flags &
904 CIFS_MOUNT_MAP_SPECIAL_CHR);
906 if (rc != 0) {
907 if (rc == -EIO)
908 rc = -EINVAL;
909 goto out;
912 netpid = current->tgid;
914 set_via_filehandle:
915 rc = CIFSSMBSetFileInfo(xid, pTcon, &info_buf, netfid, netpid);
916 if (!rc)
917 cifsInode->cifsAttrs = dosattr;
919 if (open_file == NULL)
920 CIFSSMBClose(xid, pTcon, netfid);
921 else
922 cifsFileInfo_put(open_file);
923 out:
924 return rc;
928 * open the given file (if it isn't already), set the DELETE_ON_CLOSE bit
929 * and rename it to a random name that hopefully won't conflict with
930 * anything else.
932 static int
933 cifs_rename_pending_delete(char *full_path, struct dentry *dentry, int xid)
935 int oplock = 0;
936 int rc;
937 __u16 netfid;
938 struct inode *inode = dentry->d_inode;
939 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
940 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
941 struct cifsTconInfo *tcon = cifs_sb->tcon;
942 __u32 dosattr, origattr;
943 FILE_BASIC_INFO *info_buf = NULL;
945 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN,
946 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR,
947 &netfid, &oplock, NULL, cifs_sb->local_nls,
948 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
949 if (rc != 0)
950 goto out;
952 origattr = cifsInode->cifsAttrs;
953 if (origattr == 0)
954 origattr |= ATTR_NORMAL;
956 dosattr = origattr & ~ATTR_READONLY;
957 if (dosattr == 0)
958 dosattr |= ATTR_NORMAL;
959 dosattr |= ATTR_HIDDEN;
961 /* set ATTR_HIDDEN and clear ATTR_READONLY, but only if needed */
962 if (dosattr != origattr) {
963 info_buf = kzalloc(sizeof(*info_buf), GFP_KERNEL);
964 if (info_buf == NULL) {
965 rc = -ENOMEM;
966 goto out_close;
968 info_buf->Attributes = cpu_to_le32(dosattr);
969 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
970 current->tgid);
971 /* although we would like to mark the file hidden
972 if that fails we will still try to rename it */
973 if (rc != 0)
974 cifsInode->cifsAttrs = dosattr;
975 else
976 dosattr = origattr; /* since not able to change them */
979 /* rename the file */
980 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls,
981 cifs_sb->mnt_cifs_flags &
982 CIFS_MOUNT_MAP_SPECIAL_CHR);
983 if (rc != 0) {
984 rc = -ETXTBSY;
985 goto undo_setattr;
988 /* try to set DELETE_ON_CLOSE */
989 if (!cifsInode->delete_pending) {
990 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid,
991 current->tgid);
993 * some samba versions return -ENOENT when we try to set the
994 * file disposition here. Likely a samba bug, but work around
995 * it for now. This means that some cifsXXX files may hang
996 * around after they shouldn't.
998 * BB: remove this hack after more servers have the fix
1000 if (rc == -ENOENT)
1001 rc = 0;
1002 else if (rc != 0) {
1003 rc = -ETXTBSY;
1004 goto undo_rename;
1006 cifsInode->delete_pending = true;
1009 out_close:
1010 CIFSSMBClose(xid, tcon, netfid);
1011 out:
1012 kfree(info_buf);
1013 return rc;
1016 * reset everything back to the original state. Don't bother
1017 * dealing with errors here since we can't do anything about
1018 * them anyway.
1020 undo_rename:
1021 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name,
1022 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1023 CIFS_MOUNT_MAP_SPECIAL_CHR);
1024 undo_setattr:
1025 if (dosattr != origattr) {
1026 info_buf->Attributes = cpu_to_le32(origattr);
1027 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid,
1028 current->tgid))
1029 cifsInode->cifsAttrs = origattr;
1032 goto out_close;
1037 * If dentry->d_inode is null (usually meaning the cached dentry
1038 * is a negative dentry) then we would attempt a standard SMB delete, but
1039 * if that fails we can not attempt the fall back mechanisms on EACCESS
1040 * but will return the EACCESS to the caller. Note that the VFS does not call
1041 * unlink on negative dentries currently.
1043 int cifs_unlink(struct inode *dir, struct dentry *dentry)
1045 int rc = 0;
1046 int xid;
1047 char *full_path = NULL;
1048 struct inode *inode = dentry->d_inode;
1049 struct cifsInodeInfo *cifs_inode;
1050 struct super_block *sb = dir->i_sb;
1051 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
1052 struct cifsTconInfo *tcon = cifs_sb->tcon;
1053 struct iattr *attrs = NULL;
1054 __u32 dosattr = 0, origattr = 0;
1056 cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
1058 xid = GetXid();
1060 /* Unlink can be called from rename so we can not take the
1061 * sb->s_vfs_rename_mutex here */
1062 full_path = build_path_from_dentry(dentry);
1063 if (full_path == NULL) {
1064 rc = -ENOMEM;
1065 FreeXid(xid);
1066 return rc;
1069 if ((tcon->ses->capabilities & CAP_UNIX) &&
1070 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1071 le64_to_cpu(tcon->fsUnixInfo.Capability))) {
1072 rc = CIFSPOSIXDelFile(xid, tcon, full_path,
1073 SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
1074 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1075 cFYI(1, ("posix del rc %d", rc));
1076 if ((rc == 0) || (rc == -ENOENT))
1077 goto psx_del_no_retry;
1080 retry_std_delete:
1081 rc = CIFSSMBDelFile(xid, tcon, full_path, cifs_sb->local_nls,
1082 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1084 psx_del_no_retry:
1085 if (!rc) {
1086 if (inode)
1087 drop_nlink(inode);
1088 } else if (rc == -ENOENT) {
1089 d_drop(dentry);
1090 } else if (rc == -ETXTBSY) {
1091 rc = cifs_rename_pending_delete(full_path, dentry, xid);
1092 if (rc == 0)
1093 drop_nlink(inode);
1094 } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
1095 attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
1096 if (attrs == NULL) {
1097 rc = -ENOMEM;
1098 goto out_reval;
1101 /* try to reset dos attributes */
1102 cifs_inode = CIFS_I(inode);
1103 origattr = cifs_inode->cifsAttrs;
1104 if (origattr == 0)
1105 origattr |= ATTR_NORMAL;
1106 dosattr = origattr & ~ATTR_READONLY;
1107 if (dosattr == 0)
1108 dosattr |= ATTR_NORMAL;
1109 dosattr |= ATTR_HIDDEN;
1111 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
1112 if (rc != 0)
1113 goto out_reval;
1115 goto retry_std_delete;
1118 /* undo the setattr if we errored out and it's needed */
1119 if (rc != 0 && dosattr != 0)
1120 cifs_set_file_info(inode, attrs, xid, full_path, origattr);
1122 out_reval:
1123 if (inode) {
1124 cifs_inode = CIFS_I(inode);
1125 cifs_inode->time = 0; /* will force revalidate to get info
1126 when needed */
1127 inode->i_ctime = current_fs_time(sb);
1129 dir->i_ctime = dir->i_mtime = current_fs_time(sb);
1130 cifs_inode = CIFS_I(dir);
1131 CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
1133 kfree(full_path);
1134 kfree(attrs);
1135 FreeXid(xid);
1136 return rc;
1139 int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
1141 int rc = 0, tmprc;
1142 int xid;
1143 struct cifs_sb_info *cifs_sb;
1144 struct cifsTconInfo *pTcon;
1145 char *full_path = NULL;
1146 struct inode *newinode = NULL;
1147 struct cifs_fattr fattr;
1149 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
1151 xid = GetXid();
1153 cifs_sb = CIFS_SB(inode->i_sb);
1154 pTcon = cifs_sb->tcon;
1156 full_path = build_path_from_dentry(direntry);
1157 if (full_path == NULL) {
1158 rc = -ENOMEM;
1159 FreeXid(xid);
1160 return rc;
1163 if ((pTcon->ses->capabilities & CAP_UNIX) &&
1164 (CIFS_UNIX_POSIX_PATH_OPS_CAP &
1165 le64_to_cpu(pTcon->fsUnixInfo.Capability))) {
1166 u32 oplock = 0;
1167 FILE_UNIX_BASIC_INFO *pInfo =
1168 kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
1169 if (pInfo == NULL) {
1170 rc = -ENOMEM;
1171 goto mkdir_out;
1174 mode &= ~current_umask();
1175 rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT,
1176 mode, NULL /* netfid */, pInfo, &oplock,
1177 full_path, cifs_sb->local_nls,
1178 cifs_sb->mnt_cifs_flags &
1179 CIFS_MOUNT_MAP_SPECIAL_CHR);
1180 if (rc == -EOPNOTSUPP) {
1181 kfree(pInfo);
1182 goto mkdir_retry_old;
1183 } else if (rc) {
1184 cFYI(1, ("posix mkdir returned 0x%x", rc));
1185 d_drop(direntry);
1186 } else {
1187 if (pInfo->Type == cpu_to_le32(-1)) {
1188 /* no return info, go query for it */
1189 kfree(pInfo);
1190 goto mkdir_get_info;
1192 /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need
1193 to set uid/gid */
1194 inc_nlink(inode);
1195 if (pTcon->nocase)
1196 direntry->d_op = &cifs_ci_dentry_ops;
1197 else
1198 direntry->d_op = &cifs_dentry_ops;
1200 cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
1201 newinode = cifs_iget(inode->i_sb, &fattr);
1202 if (!newinode) {
1203 kfree(pInfo);
1204 goto mkdir_get_info;
1207 d_instantiate(direntry, newinode);
1209 #ifdef CONFIG_CIFS_DEBUG2
1210 cFYI(1, ("instantiated dentry %p %s to inode %p",
1211 direntry, direntry->d_name.name, newinode));
1213 if (newinode->i_nlink != 2)
1214 cFYI(1, ("unexpected number of links %d",
1215 newinode->i_nlink));
1216 #endif
1218 kfree(pInfo);
1219 goto mkdir_out;
1221 mkdir_retry_old:
1222 /* BB add setting the equivalent of mode via CreateX w/ACLs */
1223 rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
1224 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1225 if (rc) {
1226 cFYI(1, ("cifs_mkdir returned 0x%x", rc));
1227 d_drop(direntry);
1228 } else {
1229 mkdir_get_info:
1230 inc_nlink(inode);
1231 if (pTcon->unix_ext)
1232 rc = cifs_get_inode_info_unix(&newinode, full_path,
1233 inode->i_sb, xid);
1234 else
1235 rc = cifs_get_inode_info(&newinode, full_path, NULL,
1236 inode->i_sb, xid, NULL);
1238 if (pTcon->nocase)
1239 direntry->d_op = &cifs_ci_dentry_ops;
1240 else
1241 direntry->d_op = &cifs_dentry_ops;
1242 d_instantiate(direntry, newinode);
1243 /* setting nlink not necessary except in cases where we
1244 * failed to get it from the server or was set bogus */
1245 if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
1246 direntry->d_inode->i_nlink = 2;
1248 mode &= ~current_umask();
1249 /* must turn on setgid bit if parent dir has it */
1250 if (inode->i_mode & S_ISGID)
1251 mode |= S_ISGID;
1253 if (pTcon->unix_ext) {
1254 struct cifs_unix_set_info_args args = {
1255 .mode = mode,
1256 .ctime = NO_CHANGE_64,
1257 .atime = NO_CHANGE_64,
1258 .mtime = NO_CHANGE_64,
1259 .device = 0,
1261 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
1262 args.uid = (__u64)current_fsuid();
1263 if (inode->i_mode & S_ISGID)
1264 args.gid = (__u64)inode->i_gid;
1265 else
1266 args.gid = (__u64)current_fsgid();
1267 } else {
1268 args.uid = NO_CHANGE_64;
1269 args.gid = NO_CHANGE_64;
1271 CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args,
1272 cifs_sb->local_nls,
1273 cifs_sb->mnt_cifs_flags &
1274 CIFS_MOUNT_MAP_SPECIAL_CHR);
1275 } else {
1276 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) &&
1277 (mode & S_IWUGO) == 0) {
1278 FILE_BASIC_INFO pInfo;
1279 struct cifsInodeInfo *cifsInode;
1280 u32 dosattrs;
1282 memset(&pInfo, 0, sizeof(pInfo));
1283 cifsInode = CIFS_I(newinode);
1284 dosattrs = cifsInode->cifsAttrs|ATTR_READONLY;
1285 pInfo.Attributes = cpu_to_le32(dosattrs);
1286 tmprc = CIFSSMBSetPathInfo(xid, pTcon,
1287 full_path, &pInfo,
1288 cifs_sb->local_nls,
1289 cifs_sb->mnt_cifs_flags &
1290 CIFS_MOUNT_MAP_SPECIAL_CHR);
1291 if (tmprc == 0)
1292 cifsInode->cifsAttrs = dosattrs;
1294 if (direntry->d_inode) {
1295 if (cifs_sb->mnt_cifs_flags &
1296 CIFS_MOUNT_DYNPERM)
1297 direntry->d_inode->i_mode =
1298 (mode | S_IFDIR);
1300 if (cifs_sb->mnt_cifs_flags &
1301 CIFS_MOUNT_SET_UID) {
1302 direntry->d_inode->i_uid =
1303 current_fsuid();
1304 if (inode->i_mode & S_ISGID)
1305 direntry->d_inode->i_gid =
1306 inode->i_gid;
1307 else
1308 direntry->d_inode->i_gid =
1309 current_fsgid();
1314 mkdir_out:
1315 kfree(full_path);
1316 FreeXid(xid);
1317 return rc;
1320 int cifs_rmdir(struct inode *inode, struct dentry *direntry)
1322 int rc = 0;
1323 int xid;
1324 struct cifs_sb_info *cifs_sb;
1325 struct cifsTconInfo *pTcon;
1326 char *full_path = NULL;
1327 struct cifsInodeInfo *cifsInode;
1329 cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
1331 xid = GetXid();
1333 cifs_sb = CIFS_SB(inode->i_sb);
1334 pTcon = cifs_sb->tcon;
1336 full_path = build_path_from_dentry(direntry);
1337 if (full_path == NULL) {
1338 rc = -ENOMEM;
1339 FreeXid(xid);
1340 return rc;
1343 rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls,
1344 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
1346 if (!rc) {
1347 drop_nlink(inode);
1348 spin_lock(&direntry->d_inode->i_lock);
1349 i_size_write(direntry->d_inode, 0);
1350 clear_nlink(direntry->d_inode);
1351 spin_unlock(&direntry->d_inode->i_lock);
1354 cifsInode = CIFS_I(direntry->d_inode);
1355 cifsInode->time = 0; /* force revalidate to go get info when
1356 needed */
1358 cifsInode = CIFS_I(inode);
1359 cifsInode->time = 0; /* force revalidate to get parent dir info
1360 since cached search results now invalid */
1362 direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
1363 current_fs_time(inode->i_sb);
1365 kfree(full_path);
1366 FreeXid(xid);
1367 return rc;
1370 static int
1371 cifs_do_rename(int xid, struct dentry *from_dentry, const char *fromPath,
1372 struct dentry *to_dentry, const char *toPath)
1374 struct cifs_sb_info *cifs_sb = CIFS_SB(from_dentry->d_sb);
1375 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1376 __u16 srcfid;
1377 int oplock, rc;
1379 /* try path-based rename first */
1380 rc = CIFSSMBRename(xid, pTcon, fromPath, toPath, cifs_sb->local_nls,
1381 cifs_sb->mnt_cifs_flags &
1382 CIFS_MOUNT_MAP_SPECIAL_CHR);
1385 * don't bother with rename by filehandle unless file is busy and
1386 * source Note that cross directory moves do not work with
1387 * rename by filehandle to various Windows servers.
1389 if (rc == 0 || rc != -ETXTBSY)
1390 return rc;
1392 /* open the file to be renamed -- we need DELETE perms */
1393 rc = CIFSSMBOpen(xid, pTcon, fromPath, FILE_OPEN, DELETE,
1394 CREATE_NOT_DIR, &srcfid, &oplock, NULL,
1395 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1396 CIFS_MOUNT_MAP_SPECIAL_CHR);
1398 if (rc == 0) {
1399 rc = CIFSSMBRenameOpenFile(xid, pTcon, srcfid,
1400 (const char *) to_dentry->d_name.name,
1401 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1402 CIFS_MOUNT_MAP_SPECIAL_CHR);
1404 CIFSSMBClose(xid, pTcon, srcfid);
1407 return rc;
1410 int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
1411 struct inode *target_dir, struct dentry *target_dentry)
1413 char *fromName = NULL;
1414 char *toName = NULL;
1415 struct cifs_sb_info *cifs_sb_source;
1416 struct cifs_sb_info *cifs_sb_target;
1417 struct cifsTconInfo *tcon;
1418 FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
1419 FILE_UNIX_BASIC_INFO *info_buf_target;
1420 int xid, rc, tmprc;
1422 cifs_sb_target = CIFS_SB(target_dir->i_sb);
1423 cifs_sb_source = CIFS_SB(source_dir->i_sb);
1424 tcon = cifs_sb_source->tcon;
1426 xid = GetXid();
1429 * BB: this might be allowed if same server, but different share.
1430 * Consider adding support for this
1432 if (tcon != cifs_sb_target->tcon) {
1433 rc = -EXDEV;
1434 goto cifs_rename_exit;
1438 * we already have the rename sem so we do not need to
1439 * grab it again here to protect the path integrity
1441 fromName = build_path_from_dentry(source_dentry);
1442 if (fromName == NULL) {
1443 rc = -ENOMEM;
1444 goto cifs_rename_exit;
1447 toName = build_path_from_dentry(target_dentry);
1448 if (toName == NULL) {
1449 rc = -ENOMEM;
1450 goto cifs_rename_exit;
1453 rc = cifs_do_rename(xid, source_dentry, fromName,
1454 target_dentry, toName);
1456 if (rc == -EEXIST && tcon->unix_ext) {
1458 * Are src and dst hardlinks of same inode? We can
1459 * only tell with unix extensions enabled
1461 info_buf_source =
1462 kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
1463 GFP_KERNEL);
1464 if (info_buf_source == NULL) {
1465 rc = -ENOMEM;
1466 goto cifs_rename_exit;
1469 info_buf_target = info_buf_source + 1;
1470 tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
1471 info_buf_source,
1472 cifs_sb_source->local_nls,
1473 cifs_sb_source->mnt_cifs_flags &
1474 CIFS_MOUNT_MAP_SPECIAL_CHR);
1475 if (tmprc != 0)
1476 goto unlink_target;
1478 tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
1479 toName, info_buf_target,
1480 cifs_sb_target->local_nls,
1481 /* remap based on source sb */
1482 cifs_sb_source->mnt_cifs_flags &
1483 CIFS_MOUNT_MAP_SPECIAL_CHR);
1485 if (tmprc == 0 && (info_buf_source->UniqueId ==
1486 info_buf_target->UniqueId)) {
1487 /* same file, POSIX says that this is a noop */
1488 rc = 0;
1489 goto cifs_rename_exit;
1491 } /* else ... BB we could add the same check for Windows by
1492 checking the UniqueId via FILE_INTERNAL_INFO */
1494 unlink_target:
1495 /* Try unlinking the target dentry if it's not negative */
1496 if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
1497 tmprc = cifs_unlink(target_dir, target_dentry);
1498 if (tmprc)
1499 goto cifs_rename_exit;
1501 rc = cifs_do_rename(xid, source_dentry, fromName,
1502 target_dentry, toName);
1505 cifs_rename_exit:
1506 kfree(info_buf_source);
1507 kfree(fromName);
1508 kfree(toName);
1509 FreeXid(xid);
1510 return rc;
1513 static bool
1514 cifs_inode_needs_reval(struct inode *inode)
1516 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1518 if (cifs_i->clientCanCacheRead)
1519 return false;
1521 if (!lookupCacheEnabled)
1522 return true;
1524 if (cifs_i->time == 0)
1525 return true;
1527 /* FIXME: the actimeo should be tunable */
1528 if (time_after_eq(jiffies, cifs_i->time + HZ))
1529 return true;
1531 return false;
1534 /* check invalid_mapping flag and zap the cache if it's set */
1535 static void
1536 cifs_invalidate_mapping(struct inode *inode)
1538 int rc;
1539 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
1541 cifs_i->invalid_mapping = false;
1543 /* write back any cached data */
1544 if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
1545 rc = filemap_write_and_wait(inode->i_mapping);
1546 if (rc)
1547 cifs_i->write_behind_rc = rc;
1549 invalidate_remote_inode(inode);
1552 int cifs_revalidate_file(struct file *filp)
1554 int rc = 0;
1555 struct inode *inode = filp->f_path.dentry->d_inode;
1557 if (!cifs_inode_needs_reval(inode))
1558 goto check_inval;
1560 if (CIFS_SB(inode->i_sb)->tcon->unix_ext)
1561 rc = cifs_get_file_info_unix(filp);
1562 else
1563 rc = cifs_get_file_info(filp);
1565 check_inval:
1566 if (CIFS_I(inode)->invalid_mapping)
1567 cifs_invalidate_mapping(inode);
1569 return rc;
1572 /* revalidate a dentry's inode attributes */
1573 int cifs_revalidate_dentry(struct dentry *dentry)
1575 int xid;
1576 int rc = 0;
1577 char *full_path = NULL;
1578 struct inode *inode = dentry->d_inode;
1579 struct super_block *sb = dentry->d_sb;
1581 if (inode == NULL)
1582 return -ENOENT;
1584 xid = GetXid();
1586 if (!cifs_inode_needs_reval(inode))
1587 goto check_inval;
1589 /* can not safely grab the rename sem here if rename calls revalidate
1590 since that would deadlock */
1591 full_path = build_path_from_dentry(dentry);
1592 if (full_path == NULL) {
1593 rc = -ENOMEM;
1594 goto check_inval;
1597 cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
1598 "jiffies %ld", full_path, inode, inode->i_count.counter,
1599 dentry, dentry->d_time, jiffies));
1601 if (CIFS_SB(sb)->tcon->unix_ext)
1602 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
1603 else
1604 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
1605 xid, NULL);
1607 check_inval:
1608 if (CIFS_I(inode)->invalid_mapping)
1609 cifs_invalidate_mapping(inode);
1611 kfree(full_path);
1612 FreeXid(xid);
1613 return rc;
1616 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
1617 struct kstat *stat)
1619 int err = cifs_revalidate_dentry(dentry);
1620 if (!err) {
1621 generic_fillattr(dentry->d_inode, stat);
1622 stat->blksize = CIFS_MAX_MSGSIZE;
1623 stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
1625 return err;
1628 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
1630 pgoff_t index = from >> PAGE_CACHE_SHIFT;
1631 unsigned offset = from & (PAGE_CACHE_SIZE - 1);
1632 struct page *page;
1633 int rc = 0;
1635 page = grab_cache_page(mapping, index);
1636 if (!page)
1637 return -ENOMEM;
1639 zero_user_segment(page, offset, PAGE_CACHE_SIZE);
1640 unlock_page(page);
1641 page_cache_release(page);
1642 return rc;
1645 static int cifs_vmtruncate(struct inode *inode, loff_t offset)
1647 loff_t oldsize;
1648 int err;
1650 spin_lock(&inode->i_lock);
1651 err = inode_newsize_ok(inode, offset);
1652 if (err) {
1653 spin_unlock(&inode->i_lock);
1654 goto out;
1657 oldsize = inode->i_size;
1658 i_size_write(inode, offset);
1659 spin_unlock(&inode->i_lock);
1660 truncate_pagecache(inode, oldsize, offset);
1661 if (inode->i_op->truncate)
1662 inode->i_op->truncate(inode);
1663 out:
1664 return err;
1667 static int
1668 cifs_set_file_size(struct inode *inode, struct iattr *attrs,
1669 int xid, char *full_path)
1671 int rc;
1672 struct cifsFileInfo *open_file;
1673 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1674 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1675 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1678 * To avoid spurious oplock breaks from server, in the case of
1679 * inodes that we already have open, avoid doing path based
1680 * setting of file size if we can do it by handle.
1681 * This keeps our caching token (oplock) and avoids timeouts
1682 * when the local oplock break takes longer to flush
1683 * writebehind data than the SMB timeout for the SetPathInfo
1684 * request would allow
1686 open_file = find_writable_file(cifsInode);
1687 if (open_file) {
1688 __u16 nfid = open_file->netfid;
1689 __u32 npid = open_file->pid;
1690 rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
1691 npid, false);
1692 cifsFileInfo_put(open_file);
1693 cFYI(1, ("SetFSize for attrs rc = %d", rc));
1694 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1695 unsigned int bytes_written;
1696 rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
1697 &bytes_written, NULL, NULL, 1);
1698 cFYI(1, ("Wrt seteof rc %d", rc));
1700 } else
1701 rc = -EINVAL;
1703 if (rc != 0) {
1704 /* Set file size by pathname rather than by handle
1705 either because no valid, writeable file handle for
1706 it was found or because there was an error setting
1707 it by handle */
1708 rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
1709 false, cifs_sb->local_nls,
1710 cifs_sb->mnt_cifs_flags &
1711 CIFS_MOUNT_MAP_SPECIAL_CHR);
1712 cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
1713 if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
1714 __u16 netfid;
1715 int oplock = 0;
1717 rc = SMBLegacyOpen(xid, pTcon, full_path,
1718 FILE_OPEN, GENERIC_WRITE,
1719 CREATE_NOT_DIR, &netfid, &oplock, NULL,
1720 cifs_sb->local_nls,
1721 cifs_sb->mnt_cifs_flags &
1722 CIFS_MOUNT_MAP_SPECIAL_CHR);
1723 if (rc == 0) {
1724 unsigned int bytes_written;
1725 rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
1726 attrs->ia_size,
1727 &bytes_written, NULL,
1728 NULL, 1);
1729 cFYI(1, ("wrt seteof rc %d", rc));
1730 CIFSSMBClose(xid, pTcon, netfid);
1735 if (rc == 0) {
1736 cifsInode->server_eof = attrs->ia_size;
1737 rc = cifs_vmtruncate(inode, attrs->ia_size);
1738 cifs_truncate_page(inode->i_mapping, inode->i_size);
1741 return rc;
1744 static int
1745 cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1747 int rc;
1748 int xid;
1749 char *full_path = NULL;
1750 struct inode *inode = direntry->d_inode;
1751 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1752 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1753 struct cifsTconInfo *pTcon = cifs_sb->tcon;
1754 struct cifs_unix_set_info_args *args = NULL;
1755 struct cifsFileInfo *open_file;
1757 cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
1758 direntry->d_name.name, attrs->ia_valid));
1760 xid = GetXid();
1762 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1763 /* check if we have permission to change attrs */
1764 rc = inode_change_ok(inode, attrs);
1765 if (rc < 0)
1766 goto out;
1767 else
1768 rc = 0;
1771 full_path = build_path_from_dentry(direntry);
1772 if (full_path == NULL) {
1773 rc = -ENOMEM;
1774 goto out;
1778 * Attempt to flush data before changing attributes. We need to do
1779 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1780 * ownership or mode then we may also need to do this. Here, we take
1781 * the safe way out and just do the flush on all setattr requests. If
1782 * the flush returns error, store it to report later and continue.
1784 * BB: This should be smarter. Why bother flushing pages that
1785 * will be truncated anyway? Also, should we error out here if
1786 * the flush returns error?
1788 rc = filemap_write_and_wait(inode->i_mapping);
1789 if (rc != 0) {
1790 cifsInode->write_behind_rc = rc;
1791 rc = 0;
1794 if (attrs->ia_valid & ATTR_SIZE) {
1795 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1796 if (rc != 0)
1797 goto out;
1800 /* skip mode change if it's just for clearing setuid/setgid */
1801 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1802 attrs->ia_valid &= ~ATTR_MODE;
1804 args = kmalloc(sizeof(*args), GFP_KERNEL);
1805 if (args == NULL) {
1806 rc = -ENOMEM;
1807 goto out;
1810 /* set up the struct */
1811 if (attrs->ia_valid & ATTR_MODE)
1812 args->mode = attrs->ia_mode;
1813 else
1814 args->mode = NO_CHANGE_64;
1816 if (attrs->ia_valid & ATTR_UID)
1817 args->uid = attrs->ia_uid;
1818 else
1819 args->uid = NO_CHANGE_64;
1821 if (attrs->ia_valid & ATTR_GID)
1822 args->gid = attrs->ia_gid;
1823 else
1824 args->gid = NO_CHANGE_64;
1826 if (attrs->ia_valid & ATTR_ATIME)
1827 args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
1828 else
1829 args->atime = NO_CHANGE_64;
1831 if (attrs->ia_valid & ATTR_MTIME)
1832 args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
1833 else
1834 args->mtime = NO_CHANGE_64;
1836 if (attrs->ia_valid & ATTR_CTIME)
1837 args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
1838 else
1839 args->ctime = NO_CHANGE_64;
1841 args->device = 0;
1842 open_file = find_writable_file(cifsInode);
1843 if (open_file) {
1844 u16 nfid = open_file->netfid;
1845 u32 npid = open_file->pid;
1846 rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid);
1847 cifsFileInfo_put(open_file);
1848 } else {
1849 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args,
1850 cifs_sb->local_nls,
1851 cifs_sb->mnt_cifs_flags &
1852 CIFS_MOUNT_MAP_SPECIAL_CHR);
1855 if (!rc) {
1856 rc = inode_setattr(inode, attrs);
1858 /* force revalidate when any of these times are set since some
1859 of the fs types (eg ext3, fat) do not have fine enough
1860 time granularity to match protocol, and we do not have a
1861 a way (yet) to query the server fs's time granularity (and
1862 whether it rounds times down).
1864 if (!rc && (attrs->ia_valid & (ATTR_MTIME | ATTR_CTIME)))
1865 cifsInode->time = 0;
1867 out:
1868 kfree(args);
1869 kfree(full_path);
1870 FreeXid(xid);
1871 return rc;
1874 static int
1875 cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1877 int xid;
1878 struct inode *inode = direntry->d_inode;
1879 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1880 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1881 char *full_path = NULL;
1882 int rc = -EACCES;
1883 __u32 dosattr = 0;
1884 __u64 mode = NO_CHANGE_64;
1886 xid = GetXid();
1888 cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
1889 direntry->d_name.name, attrs->ia_valid));
1891 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1892 /* check if we have permission to change attrs */
1893 rc = inode_change_ok(inode, attrs);
1894 if (rc < 0) {
1895 FreeXid(xid);
1896 return rc;
1897 } else
1898 rc = 0;
1901 full_path = build_path_from_dentry(direntry);
1902 if (full_path == NULL) {
1903 rc = -ENOMEM;
1904 FreeXid(xid);
1905 return rc;
1909 * Attempt to flush data before changing attributes. We need to do
1910 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1911 * ownership or mode then we may also need to do this. Here, we take
1912 * the safe way out and just do the flush on all setattr requests. If
1913 * the flush returns error, store it to report later and continue.
1915 * BB: This should be smarter. Why bother flushing pages that
1916 * will be truncated anyway? Also, should we error out here if
1917 * the flush returns error?
1919 rc = filemap_write_and_wait(inode->i_mapping);
1920 if (rc != 0) {
1921 cifsInode->write_behind_rc = rc;
1922 rc = 0;
1925 if (attrs->ia_valid & ATTR_SIZE) {
1926 rc = cifs_set_file_size(inode, attrs, xid, full_path);
1927 if (rc != 0)
1928 goto cifs_setattr_exit;
1932 * Without unix extensions we can't send ownership changes to the
1933 * server, so silently ignore them. This is consistent with how
1934 * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With
1935 * CIFSACL support + proper Windows to Unix idmapping, we may be
1936 * able to support this in the future.
1938 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
1939 attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
1941 /* skip mode change if it's just for clearing setuid/setgid */
1942 if (attrs->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
1943 attrs->ia_valid &= ~ATTR_MODE;
1945 if (attrs->ia_valid & ATTR_MODE) {
1946 cFYI(1, ("Mode changed to 0%o", attrs->ia_mode));
1947 mode = attrs->ia_mode;
1950 if (attrs->ia_valid & ATTR_MODE) {
1951 rc = 0;
1952 #ifdef CONFIG_CIFS_EXPERIMENTAL
1953 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
1954 rc = mode_to_acl(inode, full_path, mode);
1955 else
1956 #endif
1957 if (((mode & S_IWUGO) == 0) &&
1958 (cifsInode->cifsAttrs & ATTR_READONLY) == 0) {
1960 dosattr = cifsInode->cifsAttrs | ATTR_READONLY;
1962 /* fix up mode if we're not using dynperm */
1963 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
1964 attrs->ia_mode = inode->i_mode & ~S_IWUGO;
1965 } else if ((mode & S_IWUGO) &&
1966 (cifsInode->cifsAttrs & ATTR_READONLY)) {
1968 dosattr = cifsInode->cifsAttrs & ~ATTR_READONLY;
1969 /* Attributes of 0 are ignored */
1970 if (dosattr == 0)
1971 dosattr |= ATTR_NORMAL;
1973 /* reset local inode permissions to normal */
1974 if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1975 attrs->ia_mode &= ~(S_IALLUGO);
1976 if (S_ISDIR(inode->i_mode))
1977 attrs->ia_mode |=
1978 cifs_sb->mnt_dir_mode;
1979 else
1980 attrs->ia_mode |=
1981 cifs_sb->mnt_file_mode;
1983 } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) {
1984 /* ignore mode change - ATTR_READONLY hasn't changed */
1985 attrs->ia_valid &= ~ATTR_MODE;
1989 if (attrs->ia_valid & (ATTR_MTIME|ATTR_ATIME|ATTR_CTIME) ||
1990 ((attrs->ia_valid & ATTR_MODE) && dosattr)) {
1991 rc = cifs_set_file_info(inode, attrs, xid, full_path, dosattr);
1992 /* BB: check for rc = -EOPNOTSUPP and switch to legacy mode */
1994 /* Even if error on time set, no sense failing the call if
1995 the server would set the time to a reasonable value anyway,
1996 and this check ensures that we are not being called from
1997 sys_utimes in which case we ought to fail the call back to
1998 the user when the server rejects the call */
1999 if ((rc) && (attrs->ia_valid &
2000 (ATTR_MODE | ATTR_GID | ATTR_UID | ATTR_SIZE)))
2001 rc = 0;
2004 /* do not need local check to inode_check_ok since the server does
2005 that */
2006 if (!rc)
2007 rc = inode_setattr(inode, attrs);
2008 cifs_setattr_exit:
2009 kfree(full_path);
2010 FreeXid(xid);
2011 return rc;
2015 cifs_setattr(struct dentry *direntry, struct iattr *attrs)
2017 struct inode *inode = direntry->d_inode;
2018 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2019 struct cifsTconInfo *pTcon = cifs_sb->tcon;
2021 if (pTcon->unix_ext)
2022 return cifs_setattr_unix(direntry, attrs);
2024 return cifs_setattr_nounix(direntry, attrs);
2026 /* BB: add cifs_setattr_legacy for really old servers */
2029 #if 0
2030 void cifs_delete_inode(struct inode *inode)
2032 cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
2033 /* may have to add back in if and when safe distributed caching of
2034 directories added e.g. via FindNotify */
2036 #endif