aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
committerDave Kleikamp <shaggy@austin.ibm.com>2006-01-24 15:34:47 -0500
commit0a0fc0ddbe732779366ab6b1b879f62195e65967 (patch)
tree7b42490a676cf39ae0691b6859ecf7fd410f229b /fs/cifs/inode.c
parent4d5dbd0945d9e0833dd7964a3d6ee33157f7cc7a (diff)
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
Merge with /home/shaggy/git/linus-clean/
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c268
1 files changed, 216 insertions, 52 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 923d071163b2..59359911f481 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
41 char *tmp_path; 41 char *tmp_path;
42 42
43 pTcon = cifs_sb->tcon; 43 pTcon = cifs_sb->tcon;
44 cFYI(1, (" Getting info on %s ", search_path)); 44 cFYI(1, ("Getting info on %s ", search_path));
45 /* could have done a find first instead but this returns more info */ 45 /* could have done a find first instead but this returns more info */
46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 46 rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 47 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
97 inode = *pinode; 97 inode = *pinode;
98 cifsInfo = CIFS_I(inode); 98 cifsInfo = CIFS_I(inode);
99 99
100 cFYI(1, (" Old time %ld ", cifsInfo->time)); 100 cFYI(1, ("Old time %ld ", cifsInfo->time));
101 cifsInfo->time = jiffies; 101 cifsInfo->time = jiffies;
102 cFYI(1, (" New time %ld ", cifsInfo->time)); 102 cFYI(1, ("New time %ld ", cifsInfo->time));
103 /* this is ok to set on every inode revalidate */ 103 /* this is ok to set on every inode revalidate */
104 atomic_set(&cifsInfo->inUse,1); 104 atomic_set(&cifsInfo->inUse,1);
105 105
@@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
111 inode->i_ctime = 111 inode->i_ctime =
112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange)); 112 cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
113 inode->i_mode = le64_to_cpu(findData.Permissions); 113 inode->i_mode = le64_to_cpu(findData.Permissions);
114 /* since we set the inode type below we need to mask off
115 to avoid strange results if bits set above */
116 inode->i_mode &= ~S_IFMT;
114 if (type == UNIX_FILE) { 117 if (type == UNIX_FILE) {
115 inode->i_mode |= S_IFREG; 118 inode->i_mode |= S_IFREG;
116 } else if (type == UNIX_SYMLINK) { 119 } else if (type == UNIX_SYMLINK) {
@@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
129 inode->i_mode |= S_IFIFO; 132 inode->i_mode |= S_IFIFO;
130 } else if (type == UNIX_SOCKET) { 133 } else if (type == UNIX_SOCKET) {
131 inode->i_mode |= S_IFSOCK; 134 inode->i_mode |= S_IFSOCK;
135 } else {
136 /* safest to call it a file if we do not know */
137 inode->i_mode |= S_IFREG;
138 cFYI(1,("unknown type %d",type));
132 } 139 }
133 inode->i_uid = le64_to_cpu(findData.Uid); 140 inode->i_uid = le64_to_cpu(findData.Uid);
134 inode->i_gid = le64_to_cpu(findData.Gid); 141 inode->i_gid = le64_to_cpu(findData.Gid);
@@ -155,34 +162,39 @@ int cifs_get_inode_info_unix(struct inode **pinode,
155 } 162 }
156 163
157 if (num_of_bytes < end_of_file) 164 if (num_of_bytes < end_of_file)
158 cFYI(1, ("allocation size less than end of file ")); 165 cFYI(1, ("allocation size less than end of file"));
159 cFYI(1, 166 cFYI(1,
160 ("Size %ld and blocks %ld", 167 ("Size %ld and blocks %ld",
161 (unsigned long) inode->i_size, inode->i_blocks)); 168 (unsigned long) inode->i_size, inode->i_blocks));
162 if (S_ISREG(inode->i_mode)) { 169 if (S_ISREG(inode->i_mode)) {
163 cFYI(1, (" File inode ")); 170 cFYI(1, ("File inode"));
164 inode->i_op = &cifs_file_inode_ops; 171 inode->i_op = &cifs_file_inode_ops;
165 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 172 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
166 inode->i_fop = &cifs_file_direct_ops; 173 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
167 else 174 inode->i_fop =
175 &cifs_file_direct_nobrl_ops;
176 else
177 inode->i_fop = &cifs_file_direct_ops;
178 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
179 inode->i_fop = &cifs_file_nobrl_ops;
180 else /* not direct, send byte range locks */
168 inode->i_fop = &cifs_file_ops; 181 inode->i_fop = &cifs_file_ops;
169 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 182
170 inode->i_fop->lock = NULL;
171 inode->i_data.a_ops = &cifs_addr_ops; 183 inode->i_data.a_ops = &cifs_addr_ops;
172 /* check if server can support readpages */ 184 /* check if server can support readpages */
173 if(pTcon->ses->server->maxBuf < 185 if(pTcon->ses->server->maxBuf <
174 4096 + MAX_CIFS_HDR_SIZE) 186 4096 + MAX_CIFS_HDR_SIZE)
175 inode->i_data.a_ops->readpages = NULL; 187 inode->i_data.a_ops->readpages = NULL;
176 } else if (S_ISDIR(inode->i_mode)) { 188 } else if (S_ISDIR(inode->i_mode)) {
177 cFYI(1, (" Directory inode")); 189 cFYI(1, ("Directory inode"));
178 inode->i_op = &cifs_dir_inode_ops; 190 inode->i_op = &cifs_dir_inode_ops;
179 inode->i_fop = &cifs_dir_ops; 191 inode->i_fop = &cifs_dir_ops;
180 } else if (S_ISLNK(inode->i_mode)) { 192 } else if (S_ISLNK(inode->i_mode)) {
181 cFYI(1, (" Symbolic Link inode ")); 193 cFYI(1, ("Symbolic Link inode"));
182 inode->i_op = &cifs_symlink_inode_ops; 194 inode->i_op = &cifs_symlink_inode_ops;
183 /* tmp_inode->i_fop = */ /* do not need to set to anything */ 195 /* tmp_inode->i_fop = */ /* do not need to set to anything */
184 } else { 196 } else {
185 cFYI(1, (" Init special inode ")); 197 cFYI(1, ("Init special inode"));
186 init_special_inode(inode, inode->i_mode, 198 init_special_inode(inode, inode->i_mode,
187 inode->i_rdev); 199 inode->i_rdev);
188 } 200 }
@@ -190,6 +202,112 @@ int cifs_get_inode_info_unix(struct inode **pinode,
190 return rc; 202 return rc;
191} 203}
192 204
205static int decode_sfu_inode(struct inode * inode, __u64 size,
206 const unsigned char *path,
207 struct cifs_sb_info *cifs_sb, int xid)
208{
209 int rc;
210 int oplock = FALSE;
211 __u16 netfid;
212 struct cifsTconInfo *pTcon = cifs_sb->tcon;
213 char buf[24];
214 unsigned int bytes_read;
215 char * pbuf;
216
217 pbuf = buf;
218
219 if(size == 0) {
220 inode->i_mode |= S_IFIFO;
221 return 0;
222 } else if (size < 8) {
223 return -EINVAL; /* EOPNOTSUPP? */
224 }
225
226 rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
227 CREATE_NOT_DIR, &netfid, &oplock, NULL,
228 cifs_sb->local_nls,
229 cifs_sb->mnt_cifs_flags &
230 CIFS_MOUNT_MAP_SPECIAL_CHR);
231 if (rc==0) {
232 int buf_type = CIFS_NO_BUFFER;
233 /* Read header */
234 rc = CIFSSMBRead(xid, pTcon,
235 netfid,
236 24 /* length */, 0 /* offset */,
237 &bytes_read, &pbuf, &buf_type);
238 if((rc == 0) && (bytes_read >= 8)) {
239 if(memcmp("IntxBLK", pbuf, 8) == 0) {
240 cFYI(1,("Block device"));
241 inode->i_mode |= S_IFBLK;
242 if(bytes_read == 24) {
243 /* we have enough to decode dev num */
244 __u64 mjr; /* major */
245 __u64 mnr; /* minor */
246 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
247 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
248 inode->i_rdev = MKDEV(mjr, mnr);
249 }
250 } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
251 cFYI(1,("Char device"));
252 inode->i_mode |= S_IFCHR;
253 if(bytes_read == 24) {
254 /* we have enough to decode dev num */
255 __u64 mjr; /* major */
256 __u64 mnr; /* minor */
257 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
258 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
259 inode->i_rdev = MKDEV(mjr, mnr);
260 }
261 } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
262 cFYI(1,("Symlink"));
263 inode->i_mode |= S_IFLNK;
264 } else {
265 inode->i_mode |= S_IFREG; /* file? */
266 rc = -EOPNOTSUPP;
267 }
268 } else {
269 inode->i_mode |= S_IFREG; /* then it is a file */
270 rc = -EOPNOTSUPP; /* or some unknown SFU type */
271 }
272 CIFSSMBClose(xid, pTcon, netfid);
273 }
274 return rc;
275
276}
277
278#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
279
280static int get_sfu_uid_mode(struct inode * inode,
281 const unsigned char *path,
282 struct cifs_sb_info *cifs_sb, int xid)
283{
284#ifdef CONFIG_CIFS_XATTR
285 ssize_t rc;
286 char ea_value[4];
287 __u32 mode;
288
289 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
290 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
291 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
292 if(rc < 0)
293 return (int)rc;
294 else if (rc > 3) {
295 mode = le32_to_cpu(*((__le32 *)ea_value));
296 inode->i_mode &= ~SFBITS_MASK;
297 cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
298 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
299 cFYI(1,("special mode bits 0%o", mode));
300 return 0;
301 } else {
302 return 0;
303 }
304#else
305 return -EOPNOTSUPP;
306#endif
307
308
309}
310
193int cifs_get_inode_info(struct inode **pinode, 311int cifs_get_inode_info(struct inode **pinode,
194 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 312 const unsigned char *search_path, FILE_ALL_INFO *pfindData,
195 struct super_block *sb, int xid) 313 struct super_block *sb, int xid)
@@ -202,7 +320,7 @@ int cifs_get_inode_info(struct inode **pinode,
202 char *buf = NULL; 320 char *buf = NULL;
203 321
204 pTcon = cifs_sb->tcon; 322 pTcon = cifs_sb->tcon;
205 cFYI(1,("Getting info on %s ", search_path)); 323 cFYI(1,("Getting info on %s", search_path));
206 324
207 if ((pfindData == NULL) && (*pinode != NULL)) { 325 if ((pfindData == NULL) && (*pinode != NULL)) {
208 if (CIFS_I(*pinode)->clientCanCacheRead) { 326 if (CIFS_I(*pinode)->clientCanCacheRead) {
@@ -303,9 +421,9 @@ int cifs_get_inode_info(struct inode **pinode,
303 inode = *pinode; 421 inode = *pinode;
304 cifsInfo = CIFS_I(inode); 422 cifsInfo = CIFS_I(inode);
305 cifsInfo->cifsAttrs = attr; 423 cifsInfo->cifsAttrs = attr;
306 cFYI(1, (" Old time %ld ", cifsInfo->time)); 424 cFYI(1, ("Old time %ld ", cifsInfo->time));
307 cifsInfo->time = jiffies; 425 cifsInfo->time = jiffies;
308 cFYI(1, (" New time %ld ", cifsInfo->time)); 426 cFYI(1, ("New time %ld ", cifsInfo->time));
309 427
310 /* blksize needs to be multiple of two. So safer to default to 428 /* blksize needs to be multiple of two. So safer to default to
311 blksize and blkbits set in superblock so 2**blkbits and blksize 429 blksize and blkbits set in superblock so 2**blkbits and blksize
@@ -319,13 +437,15 @@ int cifs_get_inode_info(struct inode **pinode,
319 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime)); 437 cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
320 inode->i_ctime = 438 inode->i_ctime =
321 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime)); 439 cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
322 cFYI(0, (" Attributes came in as 0x%x ", attr)); 440 cFYI(0, ("Attributes came in as 0x%x ", attr));
323 441
324 /* set default mode. will override for dirs below */ 442 /* set default mode. will override for dirs below */
325 if (atomic_read(&cifsInfo->inUse) == 0) 443 if (atomic_read(&cifsInfo->inUse) == 0)
326 /* new inode, can safely set these fields */ 444 /* new inode, can safely set these fields */
327 inode->i_mode = cifs_sb->mnt_file_mode; 445 inode->i_mode = cifs_sb->mnt_file_mode;
328 446 else /* since we set the inode type below we need to mask off
447 to avoid strange results if type changes and both get orred in */
448 inode->i_mode &= ~S_IFMT;
329/* if (attr & ATTR_REPARSE) */ 449/* if (attr & ATTR_REPARSE) */
330 /* We no longer handle these as symlinks because we could not 450 /* We no longer handle these as symlinks because we could not
331 follow them due to the absolute path with drive letter */ 451 follow them due to the absolute path with drive letter */
@@ -340,10 +460,16 @@ int cifs_get_inode_info(struct inode **pinode,
340 (pfindData->EndOfFile == 0)) { 460 (pfindData->EndOfFile == 0)) {
341 inode->i_mode = cifs_sb->mnt_file_mode; 461 inode->i_mode = cifs_sb->mnt_file_mode;
342 inode->i_mode |= S_IFIFO; 462 inode->i_mode |= S_IFIFO;
343/* BB Finish for SFU style symlinks and devies */ 463/* BB Finish for SFU style symlinks and devices */
344/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 464 } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
345 (cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */ 465 (cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
346 466 if (decode_sfu_inode(inode,
467 le64_to_cpu(pfindData->EndOfFile),
468 search_path,
469 cifs_sb, xid)) {
470 cFYI(1,("Unrecognized sfu inode type"));
471 }
472 cFYI(1,("sfu mode 0%o",inode->i_mode));
347 } else { 473 } else {
348 inode->i_mode |= S_IFREG; 474 inode->i_mode |= S_IFREG;
349 /* treat the dos attribute of read-only as read-only 475 /* treat the dos attribute of read-only as read-only
@@ -368,7 +494,10 @@ int cifs_get_inode_info(struct inode **pinode,
368 494
369 /* BB fill in uid and gid here? with help from winbind? 495 /* BB fill in uid and gid here? with help from winbind?
370 or retrieve from NTFS stream extended attribute */ 496 or retrieve from NTFS stream extended attribute */
371 if (atomic_read(&cifsInfo->inUse) == 0) { 497 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
498 /* fill in uid, gid, mode from server ACL */
499 get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
500 } else if (atomic_read(&cifsInfo->inUse) == 0) {
372 inode->i_uid = cifs_sb->mnt_uid; 501 inode->i_uid = cifs_sb->mnt_uid;
373 inode->i_gid = cifs_sb->mnt_gid; 502 inode->i_gid = cifs_sb->mnt_gid;
374 /* set so we do not keep refreshing these fields with 503 /* set so we do not keep refreshing these fields with
@@ -377,24 +506,29 @@ int cifs_get_inode_info(struct inode **pinode,
377 } 506 }
378 507
379 if (S_ISREG(inode->i_mode)) { 508 if (S_ISREG(inode->i_mode)) {
380 cFYI(1, (" File inode ")); 509 cFYI(1, ("File inode"));
381 inode->i_op = &cifs_file_inode_ops; 510 inode->i_op = &cifs_file_inode_ops;
382 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 511 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
383 inode->i_fop = &cifs_file_direct_ops; 512 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
384 else 513 inode->i_fop =
514 &cifs_file_direct_nobrl_ops;
515 else
516 inode->i_fop = &cifs_file_direct_ops;
517 } else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
518 inode->i_fop = &cifs_file_nobrl_ops;
519 else /* not direct, send byte range locks */
385 inode->i_fop = &cifs_file_ops; 520 inode->i_fop = &cifs_file_ops;
386 if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 521
387 inode->i_fop->lock = NULL;
388 inode->i_data.a_ops = &cifs_addr_ops; 522 inode->i_data.a_ops = &cifs_addr_ops;
389 if(pTcon->ses->server->maxBuf < 523 if(pTcon->ses->server->maxBuf <
390 4096 + MAX_CIFS_HDR_SIZE) 524 4096 + MAX_CIFS_HDR_SIZE)
391 inode->i_data.a_ops->readpages = NULL; 525 inode->i_data.a_ops->readpages = NULL;
392 } else if (S_ISDIR(inode->i_mode)) { 526 } else if (S_ISDIR(inode->i_mode)) {
393 cFYI(1, (" Directory inode ")); 527 cFYI(1, ("Directory inode"));
394 inode->i_op = &cifs_dir_inode_ops; 528 inode->i_op = &cifs_dir_inode_ops;
395 inode->i_fop = &cifs_dir_ops; 529 inode->i_fop = &cifs_dir_ops;
396 } else if (S_ISLNK(inode->i_mode)) { 530 } else if (S_ISLNK(inode->i_mode)) {
397 cFYI(1, (" Symbolic Link inode ")); 531 cFYI(1, ("Symbolic Link inode"));
398 inode->i_op = &cifs_symlink_inode_ops; 532 inode->i_op = &cifs_symlink_inode_ops;
399 } else { 533 } else {
400 init_special_inode(inode, inode->i_mode, 534 init_special_inode(inode, inode->i_mode,
@@ -431,7 +565,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
431 struct cifsInodeInfo *cifsInode; 565 struct cifsInodeInfo *cifsInode;
432 FILE_BASIC_INFO *pinfo_buf; 566 FILE_BASIC_INFO *pinfo_buf;
433 567
434 cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode)); 568 cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
435 569
436 xid = GetXid(); 570 xid = GetXid();
437 571
@@ -577,7 +711,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
577 char *full_path = NULL; 711 char *full_path = NULL;
578 struct inode *newinode = NULL; 712 struct inode *newinode = NULL;
579 713
580 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); 714 cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
581 715
582 xid = GetXid(); 716 xid = GetXid();
583 717
@@ -617,8 +751,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
617 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 751 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
618 CIFSSMBUnixSetPerms(xid, pTcon, full_path, 752 CIFSSMBUnixSetPerms(xid, pTcon, full_path,
619 mode, 753 mode,
620 (__u64)current->euid, 754 (__u64)current->fsuid,
621 (__u64)current->egid, 755 (__u64)current->fsgid,
622 0 /* dev_t */, 756 0 /* dev_t */,
623 cifs_sb->local_nls, 757 cifs_sb->local_nls,
624 cifs_sb->mnt_cifs_flags & 758 cifs_sb->mnt_cifs_flags &
@@ -635,6 +769,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
635 /* BB to be implemented via Windows secrty descriptors 769 /* BB to be implemented via Windows secrty descriptors
636 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, 770 eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
637 -1, -1, local_nls); */ 771 -1, -1, local_nls); */
772 if(direntry->d_inode) {
773 direntry->d_inode->i_mode = mode;
774 direntry->d_inode->i_mode |= S_IFDIR;
775 if(cifs_sb->mnt_cifs_flags &
776 CIFS_MOUNT_SET_UID) {
777 direntry->d_inode->i_uid =
778 current->fsuid;
779 direntry->d_inode->i_gid =
780 current->fsgid;
781 }
782 }
638 } 783 }
639 } 784 }
640 kfree(full_path); 785 kfree(full_path);
@@ -651,7 +796,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
651 char *full_path = NULL; 796 char *full_path = NULL;
652 struct cifsInodeInfo *cifsInode; 797 struct cifsInodeInfo *cifsInode;
653 798
654 cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode)); 799 cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
655 800
656 xid = GetXid(); 801 xid = GetXid();
657 802
@@ -896,9 +1041,9 @@ int cifs_revalidate(struct dentry *direntry)
896 } 1041 }
897 1042
898 /* can not grab this sem since kernel filesys locking documentation 1043 /* can not grab this sem since kernel filesys locking documentation
899 indicates i_sem may be taken by the kernel on lookup and rename 1044 indicates i_mutex may be taken by the kernel on lookup and rename
900 which could deadlock if we grab the i_sem here as well */ 1045 which could deadlock if we grab the i_mutex here as well */
901/* down(&direntry->d_inode->i_sem);*/ 1046/* mutex_lock(&direntry->d_inode->i_mutex);*/
902 /* need to write out dirty pages here */ 1047 /* need to write out dirty pages here */
903 if (direntry->d_inode->i_mapping) { 1048 if (direntry->d_inode->i_mapping) {
904 /* do we need to lock inode until after invalidate completes 1049 /* do we need to lock inode until after invalidate completes
@@ -906,17 +1051,23 @@ int cifs_revalidate(struct dentry *direntry)
906 filemap_fdatawrite(direntry->d_inode->i_mapping); 1051 filemap_fdatawrite(direntry->d_inode->i_mapping);
907 } 1052 }
908 if (invalidate_inode) { 1053 if (invalidate_inode) {
909 if (direntry->d_inode->i_mapping) 1054 /* shrink_dcache not necessary now that cifs dentry ops
910 filemap_fdatawait(direntry->d_inode->i_mapping); 1055 are exported for negative dentries */
911 /* may eventually have to do this for open files too */ 1056/* if(S_ISDIR(direntry->d_inode->i_mode))
912 if (list_empty(&(cifsInode->openFileList))) { 1057 shrink_dcache_parent(direntry); */
913 /* Has changed on server - flush read ahead pages */ 1058 if (S_ISREG(direntry->d_inode->i_mode)) {
914 cFYI(1, ("Invalidating read ahead data on " 1059 if (direntry->d_inode->i_mapping)
915 "closed file")); 1060 filemap_fdatawait(direntry->d_inode->i_mapping);
916 invalidate_remote_inode(direntry->d_inode); 1061 /* may eventually have to do this for open files too */
1062 if (list_empty(&(cifsInode->openFileList))) {
1063 /* changed on server - flush read ahead pages */
1064 cFYI(1, ("Invalidating read ahead data on "
1065 "closed file"));
1066 invalidate_remote_inode(direntry->d_inode);
1067 }
917 } 1068 }
918 } 1069 }
919/* up(&direntry->d_inode->i_sem); */ 1070/* mutex_unlock(&direntry->d_inode->i_mutex); */
920 1071
921 kfree(full_path); 1072 kfree(full_path);
922 FreeXid(xid); 1073 FreeXid(xid);
@@ -970,11 +1121,22 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
970 1121
971 xid = GetXid(); 1122 xid = GetXid();
972 1123
973 cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ", 1124 cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
974 direntry->d_name.name, attrs->ia_valid)); 1125 direntry->d_name.name, attrs->ia_valid));
1126
975 cifs_sb = CIFS_SB(direntry->d_inode->i_sb); 1127 cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
976 pTcon = cifs_sb->tcon; 1128 pTcon = cifs_sb->tcon;
977 1129
1130 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
1131 /* check if we have permission to change attrs */
1132 rc = inode_change_ok(direntry->d_inode, attrs);
1133 if(rc < 0) {
1134 FreeXid(xid);
1135 return rc;
1136 } else
1137 rc = 0;
1138 }
1139
978 down(&direntry->d_sb->s_vfs_rename_sem); 1140 down(&direntry->d_sb->s_vfs_rename_sem);
979 full_path = build_path_from_dentry(direntry); 1141 full_path = build_path_from_dentry(direntry);
980 up(&direntry->d_sb->s_vfs_rename_sem); 1142 up(&direntry->d_sb->s_vfs_rename_sem);
@@ -987,8 +1149,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
987 /* BB check if we need to refresh inode from server now ? BB */ 1149 /* BB check if we need to refresh inode from server now ? BB */
988 1150
989 /* need to flush data before changing file size on server */ 1151 /* need to flush data before changing file size on server */
990 filemap_fdatawrite(direntry->d_inode->i_mapping); 1152 filemap_write_and_wait(direntry->d_inode->i_mapping);
991 filemap_fdatawait(direntry->d_inode->i_mapping);
992 1153
993 if (attrs->ia_valid & ATTR_SIZE) { 1154 if (attrs->ia_valid & ATTR_SIZE) {
994 /* To avoid spurious oplock breaks from server, in the case of 1155 /* To avoid spurious oplock breaks from server, in the case of
@@ -1014,7 +1175,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1014 1 /* 45 seconds */); 1175 1 /* 45 seconds */);
1015 cFYI(1,("Wrt seteof rc %d", rc)); 1176 cFYI(1,("Wrt seteof rc %d", rc));
1016 } 1177 }
1017 } 1178 } else
1179 rc = -EINVAL;
1180
1018 if (rc != 0) { 1181 if (rc != 0) {
1019 /* Set file size by pathname rather than by handle 1182 /* Set file size by pathname rather than by handle
1020 either because no valid, writeable file handle for 1183 either because no valid, writeable file handle for
@@ -1086,6 +1249,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
1086 cifs_sb->mnt_cifs_flags & 1249 cifs_sb->mnt_cifs_flags &
1087 CIFS_MOUNT_MAP_SPECIAL_CHR); 1250 CIFS_MOUNT_MAP_SPECIAL_CHR);
1088 else if (attrs->ia_valid & ATTR_MODE) { 1251 else if (attrs->ia_valid & ATTR_MODE) {
1252 rc = 0;
1089 if ((mode & S_IWUGO) == 0) /* not writeable */ { 1253 if ((mode & S_IWUGO) == 0) /* not writeable */ {
1090 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) 1254 if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
1091 time_buf.Attributes = 1255 time_buf.Attributes =