aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-07-09 01:46:37 -0400
committerSteve French <sfrench@us.ibm.com>2009-07-09 19:05:48 -0400
commit0b8f18e358384a52c1ed7fa7129c08e7eaf86bb6 (patch)
treeba5292a38d8910c6b3a3303a3c7f88491e1708af /fs
parentb77863bfa153e886f9f8faf1a791ba57a36efed0 (diff)
cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget
cifs: convert cifs_get_inode_info and non-posix readdir to use cifs_iget Rather than allocating an inode and filling it out, have cifs_get_inode_info fill out a cifs_fattr and call cifs_iget. This means a pretty hefty reorganization of cifs_get_inode_info. For the readdir codepath, add a couple of new functions for filling out cifs_fattr's from different FindFile response infolevels. Finally, remove cifs_new_inode since there are no more callers. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/cifs/cifsacl.c26
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifsproto.h6
-rw-r--r--fs/cifs/inode.c397
-rw-r--r--fs/cifs/readdir.c350
5 files changed, 252 insertions, 529 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 1403b5d86a73..6941c22398a6 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -327,7 +327,7 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
327 327
328static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, 328static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
329 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid, 329 struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
330 struct inode *inode) 330 struct cifs_fattr *fattr)
331{ 331{
332 int i; 332 int i;
333 int num_aces = 0; 333 int num_aces = 0;
@@ -340,7 +340,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
340 if (!pdacl) { 340 if (!pdacl) {
341 /* no DACL in the security descriptor, set 341 /* no DACL in the security descriptor, set
342 all the permissions for user/group/other */ 342 all the permissions for user/group/other */
343 inode->i_mode |= S_IRWXUGO; 343 fattr->cf_mode |= S_IRWXUGO;
344 return; 344 return;
345 } 345 }
346 346
@@ -357,7 +357,7 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
357 /* reset rwx permissions for user/group/other. 357 /* reset rwx permissions for user/group/other.
358 Also, if num_aces is 0 i.e. DACL has no ACEs, 358 Also, if num_aces is 0 i.e. DACL has no ACEs,
359 user/group/other have no permissions */ 359 user/group/other have no permissions */
360 inode->i_mode &= ~(S_IRWXUGO); 360 fattr->cf_mode &= ~(S_IRWXUGO);
361 361
362 acl_base = (char *)pdacl; 362 acl_base = (char *)pdacl;
363 acl_size = sizeof(struct cifs_acl); 363 acl_size = sizeof(struct cifs_acl);
@@ -379,17 +379,17 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
379 if (compare_sids(&(ppace[i]->sid), pownersid)) 379 if (compare_sids(&(ppace[i]->sid), pownersid))
380 access_flags_to_mode(ppace[i]->access_req, 380 access_flags_to_mode(ppace[i]->access_req,
381 ppace[i]->type, 381 ppace[i]->type,
382 &(inode->i_mode), 382 &fattr->cf_mode,
383 &user_mask); 383 &user_mask);
384 if (compare_sids(&(ppace[i]->sid), pgrpsid)) 384 if (compare_sids(&(ppace[i]->sid), pgrpsid))
385 access_flags_to_mode(ppace[i]->access_req, 385 access_flags_to_mode(ppace[i]->access_req,
386 ppace[i]->type, 386 ppace[i]->type,
387 &(inode->i_mode), 387 &fattr->cf_mode,
388 &group_mask); 388 &group_mask);
389 if (compare_sids(&(ppace[i]->sid), &sid_everyone)) 389 if (compare_sids(&(ppace[i]->sid), &sid_everyone))
390 access_flags_to_mode(ppace[i]->access_req, 390 access_flags_to_mode(ppace[i]->access_req,
391 ppace[i]->type, 391 ppace[i]->type,
392 &(inode->i_mode), 392 &fattr->cf_mode,
393 &other_mask); 393 &other_mask);
394 394
395/* memcpy((void *)(&(cifscred->aces[i])), 395/* memcpy((void *)(&(cifscred->aces[i])),
@@ -464,7 +464,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
464 464
465/* Convert CIFS ACL to POSIX form */ 465/* Convert CIFS ACL to POSIX form */
466static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, 466static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
467 struct inode *inode) 467 struct cifs_fattr *fattr)
468{ 468{
469 int rc; 469 int rc;
470 struct cifs_sid *owner_sid_ptr, *group_sid_ptr; 470 struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
@@ -472,7 +472,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
472 char *end_of_acl = ((char *)pntsd) + acl_len; 472 char *end_of_acl = ((char *)pntsd) + acl_len;
473 __u32 dacloffset; 473 __u32 dacloffset;
474 474
475 if ((inode == NULL) || (pntsd == NULL)) 475 if (pntsd == NULL)
476 return -EIO; 476 return -EIO;
477 477
478 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + 478 owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
@@ -497,7 +497,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
497 497
498 if (dacloffset) 498 if (dacloffset)
499 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, 499 parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
500 group_sid_ptr, inode); 500 group_sid_ptr, fattr);
501 else 501 else
502 cFYI(1, ("no ACL")); /* BB grant all or default perms? */ 502 cFYI(1, ("no ACL")); /* BB grant all or default perms? */
503 503
@@ -508,7 +508,6 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
508 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, 508 memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
509 sizeof(struct cifs_sid)); */ 509 sizeof(struct cifs_sid)); */
510 510
511
512 return 0; 511 return 0;
513} 512}
514 513
@@ -671,8 +670,9 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
671} 670}
672 671
673/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 672/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
674void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, 673void
675 const char *path, const __u16 *pfid) 674cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
675 struct inode *inode, const char *path, const __u16 *pfid)
676{ 676{
677 struct cifs_ntsd *pntsd = NULL; 677 struct cifs_ntsd *pntsd = NULL;
678 u32 acllen = 0; 678 u32 acllen = 0;
@@ -687,7 +687,7 @@ void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode,
687 687
688 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 688 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
689 if (pntsd) 689 if (pntsd)
690 rc = parse_sec_desc(pntsd, acllen, inode); 690 rc = parse_sec_desc(pntsd, acllen, fattr);
691 if (rc) 691 if (rc)
692 cFYI(1, ("parse sec desc failed rc = %d", rc)); 692 cFYI(1, ("parse sec desc failed rc = %d", rc));
693 693
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index e6435cba8113..8bcf5a4bcded 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -479,6 +479,8 @@ struct dfs_info3_param {
479 */ 479 */
480 480
481#define CIFS_FATTR_DFS_REFERRAL 0x1 481#define CIFS_FATTR_DFS_REFERRAL 0x1
482#define CIFS_FATTR_DELETE_PENDING 0x2
483#define CIFS_FATTR_NEED_REVAL 0x4
482 484
483struct cifs_fattr { 485struct cifs_fattr {
484 u32 cf_flags; 486 u32 cf_flags;
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 37c11c08c529..da8fbf565991 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -102,7 +102,6 @@ extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
102 FILE_UNIX_BASIC_INFO *info, 102 FILE_UNIX_BASIC_INFO *info,
103 struct cifs_sb_info *cifs_sb); 103 struct cifs_sb_info *cifs_sb);
104extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr); 104extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
105extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
106extern struct inode *cifs_iget(struct super_block *sb, 105extern struct inode *cifs_iget(struct super_block *sb,
107 struct cifs_fattr *fattr); 106 struct cifs_fattr *fattr);
108 107
@@ -113,8 +112,9 @@ extern int cifs_get_inode_info(struct inode **pinode,
113extern int cifs_get_inode_info_unix(struct inode **pinode, 112extern int cifs_get_inode_info_unix(struct inode **pinode,
114 const unsigned char *search_path, 113 const unsigned char *search_path,
115 struct super_block *sb, int xid); 114 struct super_block *sb, int xid);
116extern void acl_to_uid_mode(struct cifs_sb_info *cifs_sb, struct inode *inode, 115extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb,
117 const char *path, const __u16 *pfid); 116 struct cifs_fattr *fattr, struct inode *inode,
117 const char *path, const __u16 *pfid);
118extern int mode_to_acl(struct inode *inode, const char *path, __u64); 118extern int mode_to_acl(struct inode *inode, const char *path, __u64);
119 119
120extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, 120extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 55b616bb381e..a807397f444e 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,23 +82,34 @@ void
82cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) 82cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
83{ 83{
84 struct cifsInodeInfo *cifs_i = CIFS_I(inode); 84 struct cifsInodeInfo *cifs_i = CIFS_I(inode);
85 unsigned long now = jiffies; 85 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
86 unsigned long oldtime = cifs_i->time;
86 87
87 inode->i_atime = fattr->cf_atime; 88 inode->i_atime = fattr->cf_atime;
88 inode->i_mtime = fattr->cf_mtime; 89 inode->i_mtime = fattr->cf_mtime;
89 inode->i_ctime = fattr->cf_ctime; 90 inode->i_ctime = fattr->cf_ctime;
90 inode->i_mode = fattr->cf_mode;
91 inode->i_rdev = fattr->cf_rdev; 91 inode->i_rdev = fattr->cf_rdev;
92 inode->i_nlink = fattr->cf_nlink; 92 inode->i_nlink = fattr->cf_nlink;
93 inode->i_uid = fattr->cf_uid; 93 inode->i_uid = fattr->cf_uid;
94 inode->i_gid = fattr->cf_gid; 94 inode->i_gid = fattr->cf_gid;
95 95
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;
100
96 cifs_i->cifsAttrs = fattr->cf_cifsattrs; 101 cifs_i->cifsAttrs = fattr->cf_cifsattrs;
97 cifs_i->uniqueid = fattr->cf_uniqueid; 102 cifs_i->uniqueid = fattr->cf_uniqueid;
98 103
104 if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
105 cifs_i->time = 0;
106 else
107 cifs_i->time = jiffies;
108
99 cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, 109 cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
100 cifs_i->time, now)); 110 oldtime, cifs_i->time));
101 cifs_i->time = now; 111
112 cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
102 113
103 /* 114 /*
104 * Can't safely change the file size here if the client is writing to 115 * Can't safely change the file size here if the client is writing to
@@ -219,49 +230,6 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
219 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL; 230 fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
220} 231}
221 232
222/**
223 * cifs_new inode - create new inode, initialize, and hash it
224 * @sb - pointer to superblock
225 * @inum - if valid pointer and serverino is enabled, replace i_ino with val
226 *
227 * Create a new inode, initialize it for CIFS and hash it. Returns the new
228 * inode or NULL if one couldn't be allocated.
229 *
230 * If the share isn't mounted with "serverino" or inum is a NULL pointer then
231 * we'll just use the inode number assigned by new_inode(). Note that this can
232 * mean i_ino collisions since the i_ino assigned by new_inode is not
233 * guaranteed to be unique.
234 */
235struct inode *
236cifs_new_inode(struct super_block *sb, __u64 *inum)
237{
238 struct inode *inode;
239
240 inode = new_inode(sb);
241 if (inode == NULL)
242 return NULL;
243
244 /*
245 * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
246 * stop passing inum as ptr. Are there sanity checks we can use to
247 * ensure that the server is really filling in that field? Also,
248 * if serverino is disabled, perhaps we should be using iunique()?
249 */
250 if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
251 inode->i_ino = (unsigned long) *inum;
252
253 /*
254 * must set this here instead of cifs_alloc_inode since VFS will
255 * clobber i_flags
256 */
257 if (sb->s_flags & MS_NOATIME)
258 inode->i_flags |= S_NOATIME | S_NOCMTIME;
259
260 insert_inode_hash(inode);
261
262 return inode;
263}
264
265int cifs_get_inode_info_unix(struct inode **pinode, 233int cifs_get_inode_info_unix(struct inode **pinode,
266 const unsigned char *full_path, 234 const unsigned char *full_path,
267 struct super_block *sb, int xid) 235 struct super_block *sb, int xid)
@@ -302,9 +270,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
302 return rc; 270 return rc;
303} 271}
304 272
305static int decode_sfu_inode(struct inode *inode, __u64 size, 273static int
306 const unsigned char *path, 274cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
307 struct cifs_sb_info *cifs_sb, int xid) 275 struct cifs_sb_info *cifs_sb, int xid)
308{ 276{
309 int rc; 277 int rc;
310 int oplock = 0; 278 int oplock = 0;
@@ -316,10 +284,15 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
316 284
317 pbuf = buf; 285 pbuf = buf;
318 286
319 if (size == 0) { 287 fattr->cf_mode &= ~S_IFMT;
320 inode->i_mode |= S_IFIFO; 288
289 if (fattr->cf_eof == 0) {
290 fattr->cf_mode |= S_IFIFO;
291 fattr->cf_dtype = DT_FIFO;
321 return 0; 292 return 0;
322 } else if (size < 8) { 293 } else if (fattr->cf_eof < 8) {
294 fattr->cf_mode |= S_IFREG;
295 fattr->cf_dtype = DT_REG;
323 return -EINVAL; /* EOPNOTSUPP? */ 296 return -EINVAL; /* EOPNOTSUPP? */
324 } 297 }
325 298
@@ -331,42 +304,46 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
331 if (rc == 0) { 304 if (rc == 0) {
332 int buf_type = CIFS_NO_BUFFER; 305 int buf_type = CIFS_NO_BUFFER;
333 /* Read header */ 306 /* Read header */
334 rc = CIFSSMBRead(xid, pTcon, 307 rc = CIFSSMBRead(xid, pTcon, netfid,
335 netfid,
336 24 /* length */, 0 /* offset */, 308 24 /* length */, 0 /* offset */,
337 &bytes_read, &pbuf, &buf_type); 309 &bytes_read, &pbuf, &buf_type);
338 if ((rc == 0) && (bytes_read >= 8)) { 310 if ((rc == 0) && (bytes_read >= 8)) {
339 if (memcmp("IntxBLK", pbuf, 8) == 0) { 311 if (memcmp("IntxBLK", pbuf, 8) == 0) {
340 cFYI(1, ("Block device")); 312 cFYI(1, ("Block device"));
341 inode->i_mode |= S_IFBLK; 313 fattr->cf_mode |= S_IFBLK;
314 fattr->cf_dtype = DT_BLK;
342 if (bytes_read == 24) { 315 if (bytes_read == 24) {
343 /* we have enough to decode dev num */ 316 /* we have enough to decode dev num */
344 __u64 mjr; /* major */ 317 __u64 mjr; /* major */
345 __u64 mnr; /* minor */ 318 __u64 mnr; /* minor */
346 mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); 319 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
347 mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); 320 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
348 inode->i_rdev = MKDEV(mjr, mnr); 321 fattr->cf_rdev = MKDEV(mjr, mnr);
349 } 322 }
350 } else if (memcmp("IntxCHR", pbuf, 8) == 0) { 323 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
351 cFYI(1, ("Char device")); 324 cFYI(1, ("Char device"));
352 inode->i_mode |= S_IFCHR; 325 fattr->cf_mode |= S_IFCHR;
326 fattr->cf_dtype = DT_CHR;
353 if (bytes_read == 24) { 327 if (bytes_read == 24) {
354 /* we have enough to decode dev num */ 328 /* we have enough to decode dev num */
355 __u64 mjr; /* major */ 329 __u64 mjr; /* major */
356 __u64 mnr; /* minor */ 330 __u64 mnr; /* minor */
357 mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); 331 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
358 mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); 332 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
359 inode->i_rdev = MKDEV(mjr, mnr); 333 fattr->cf_rdev = MKDEV(mjr, mnr);
360 } 334 }
361 } else if (memcmp("IntxLNK", pbuf, 7) == 0) { 335 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
362 cFYI(1, ("Symlink")); 336 cFYI(1, ("Symlink"));
363 inode->i_mode |= S_IFLNK; 337 fattr->cf_mode |= S_IFLNK;
338 fattr->cf_dtype = DT_LNK;
364 } else { 339 } else {
365 inode->i_mode |= S_IFREG; /* file? */ 340 fattr->cf_mode |= S_IFREG; /* file? */
341 fattr->cf_dtype = DT_REG;
366 rc = -EOPNOTSUPP; 342 rc = -EOPNOTSUPP;
367 } 343 }
368 } else { 344 } else {
369 inode->i_mode |= S_IFREG; /* then it is a file */ 345 fattr->cf_mode |= S_IFREG; /* then it is a file */
346 fattr->cf_dtype = DT_REG;
370 rc = -EOPNOTSUPP; /* or some unknown SFU type */ 347 rc = -EOPNOTSUPP; /* or some unknown SFU type */
371 } 348 }
372 CIFSSMBClose(xid, pTcon, netfid); 349 CIFSSMBClose(xid, pTcon, netfid);
@@ -376,9 +353,13 @@ static int decode_sfu_inode(struct inode *inode, __u64 size,
376 353
377#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */ 354#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
378 355
379static int get_sfu_mode(struct inode *inode, 356/*
380 const unsigned char *path, 357 * Fetch mode bits as provided by SFU.
381 struct cifs_sb_info *cifs_sb, int xid) 358 *
359 * FIXME: Doesn't this clobber the type bit we got from cifs_sfu_type ?
360 */
361static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
362 struct cifs_sb_info *cifs_sb, int xid)
382{ 363{
383#ifdef CONFIG_CIFS_XATTR 364#ifdef CONFIG_CIFS_XATTR
384 ssize_t rc; 365 ssize_t rc;
@@ -386,68 +367,80 @@ static int get_sfu_mode(struct inode *inode,
386 __u32 mode; 367 __u32 mode;
387 368
388 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", 369 rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
389 ea_value, 4 /* size of buf */, cifs_sb->local_nls, 370 ea_value, 4 /* size of buf */, cifs_sb->local_nls,
390 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 371 cifs_sb->mnt_cifs_flags &
372 CIFS_MOUNT_MAP_SPECIAL_CHR);
391 if (rc < 0) 373 if (rc < 0)
392 return (int)rc; 374 return (int)rc;
393 else if (rc > 3) { 375 else if (rc > 3) {
394 mode = le32_to_cpu(*((__le32 *)ea_value)); 376 mode = le32_to_cpu(*((__le32 *)ea_value));
395 inode->i_mode &= ~SFBITS_MASK; 377 fattr->cf_mode &= ~SFBITS_MASK;
396 cFYI(1, ("special bits 0%o org mode 0%o", mode, inode->i_mode)); 378 cFYI(1, ("special bits 0%o org mode 0%o", mode,
397 inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode; 379 fattr->cf_mode));
380 fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
398 cFYI(1, ("special mode bits 0%o", mode)); 381 cFYI(1, ("special mode bits 0%o", mode));
399 return 0;
400 } else {
401 return 0;
402 } 382 }
383
384 return 0;
403#else 385#else
404 return -EOPNOTSUPP; 386 return -EOPNOTSUPP;
405#endif 387#endif
406} 388}
407 389
408/* 390/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
409 * Needed to setup inode data for the directory which is the 391void
410 * junction to the new submount (ie to setup the fake directory 392cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
411 * which represents a DFS referral) 393 struct cifs_sb_info *cifs_sb, bool adjust_tz)
412 */
413static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat,
414 struct super_block *sb)
415{ 394{
416 memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); 395 memset(fattr, 0, sizeof(*fattr));
417 396 fattr->cf_cifsattrs = le32_to_cpu(info->Attributes);
418/* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); 397 if (info->DeletePending)
419 __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); 398 fattr->cf_flags |= CIFS_FATTR_DELETE_PENDING;
420 __u8 pfnd_dat->DeletePending = 0; 399
421 __u8 pfnd_data->Directory = 0; 400 if (info->LastAccessTime)
422 __le32 pfnd_dat->EASize = 0; 401 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
423 __u64 pfnd_dat->IndexNumber = 0; 402 else
424 __u64 pfnd_dat->IndexNumber1 = 0; */ 403 fattr->cf_atime = CURRENT_TIME;
425 pfnd_dat->CreationTime = 404
426 cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 405 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
427 pfnd_dat->LastAccessTime = 406 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
428 cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 407
429 pfnd_dat->LastWriteTime = 408 if (adjust_tz) {
430 cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 409 fattr->cf_ctime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
431 pfnd_dat->ChangeTime = 410 fattr->cf_mtime.tv_sec += cifs_sb->tcon->ses->server->timeAdj;
432 cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); 411 }
433 pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY); 412
434 pfnd_dat->NumberOfLinks = cpu_to_le32(2); 413 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
414 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
415
416 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
417 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
418 fattr->cf_dtype = DT_DIR;
419 } else {
420 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
421 fattr->cf_dtype = DT_REG;
422 }
423
424 /* clear write bits if ATTR_READONLY is set */
425 if (fattr->cf_cifsattrs & ATTR_READONLY)
426 fattr->cf_mode &= ~(S_IWUGO);
427
428 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
429
430 fattr->cf_uid = cifs_sb->mnt_uid;
431 fattr->cf_gid = cifs_sb->mnt_gid;
435} 432}
436 433
437int cifs_get_inode_info(struct inode **pinode, 434int cifs_get_inode_info(struct inode **pinode,
438 const unsigned char *full_path, FILE_ALL_INFO *pfindData, 435 const unsigned char *full_path, FILE_ALL_INFO *pfindData,
439 struct super_block *sb, int xid, const __u16 *pfid) 436 struct super_block *sb, int xid, const __u16 *pfid)
440{ 437{
441 int rc = 0; 438 int rc = 0, tmprc;
442 __u32 attr;
443 struct cifsInodeInfo *cifsInfo;
444 struct cifsTconInfo *pTcon; 439 struct cifsTconInfo *pTcon;
445 struct inode *inode;
446 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 440 struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
447 char *buf = NULL; 441 char *buf = NULL;
448 bool adjustTZ = false; 442 bool adjustTZ = false;
449 bool is_dfs_referral = false; 443 struct cifs_fattr fattr;
450 umode_t default_mode;
451 444
452 pTcon = cifs_sb->tcon; 445 pTcon = cifs_sb->tcon;
453 cFYI(1, ("Getting info on %s", full_path)); 446 cFYI(1, ("Getting info on %s", full_path));
@@ -482,163 +475,82 @@ int cifs_get_inode_info(struct inode **pinode,
482 adjustTZ = true; 475 adjustTZ = true;
483 } 476 }
484 } 477 }
485 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 478
486 if (rc == -EREMOTE) { 479 if (!rc) {
487 is_dfs_referral = true; 480 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *) pfindData,
488 fill_fake_finddata(pfindData, sb); 481 cifs_sb, adjustTZ);
482 } else if (rc == -EREMOTE) {
483 cifs_create_dfs_fattr(&fattr, sb);
489 rc = 0; 484 rc = 0;
490 } else if (rc) 485 } else {
491 goto cgii_exit; 486 goto cgii_exit;
487 }
492 488
493 attr = le32_to_cpu(pfindData->Attributes); 489 /*
494 490 * If an inode wasn't passed in, then get the inode number
495 /* get new inode */ 491 *
492 * Is an i_ino of zero legal? Can we use that to check if the server
493 * supports returning inode numbers? Are there other sanity checks we
494 * can use to ensure that the server is really filling in that field?
495 *
496 * We can not use the IndexNumber field by default from Windows or
497 * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA
498 * CIFS spec claims that this value is unique within the scope of a
499 * share, and the windows docs hint that it's actually unique
500 * per-machine.
501 *
502 * There may be higher info levels that work but are there Windows
503 * server or network appliances for which IndexNumber field is not
504 * guaranteed unique?
505 */
496 if (*pinode == NULL) { 506 if (*pinode == NULL) {
497 __u64 inode_num;
498 __u64 *pinum = &inode_num;
499
500 /* Is an i_ino of zero legal? Can we use that to check
501 if the server supports returning inode numbers? Are
502 there other sanity checks we can use to ensure that
503 the server is really filling in that field? */
504
505 /* We can not use the IndexNumber field by default from
506 Windows or Samba (in ALL_INFO buf) but we can request
507 it explicitly. It may not be unique presumably if
508 the server has multiple devices mounted under one share */
509
510 /* There may be higher info levels that work but are
511 there Windows server or network appliances for which
512 IndexNumber field is not guaranteed unique? */
513
514 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 507 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
515 int rc1 = 0; 508 int rc1 = 0;
516 509
517 rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 510 rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
518 full_path, pinum, 511 full_path, &fattr.cf_uniqueid,
519 cifs_sb->local_nls, 512 cifs_sb->local_nls,
520 cifs_sb->mnt_cifs_flags & 513 cifs_sb->mnt_cifs_flags &
521 CIFS_MOUNT_MAP_SPECIAL_CHR); 514 CIFS_MOUNT_MAP_SPECIAL_CHR);
522 if (rc1) { 515 if (rc1) {
523 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
524 pinum = NULL;
525 /* BB EOPNOSUPP disable SERVER_INUM? */ 516 /* BB EOPNOSUPP disable SERVER_INUM? */
517 cFYI(1, ("GetSrvInodeNum rc %d", rc1));
518 fattr.cf_uniqueid = iunique(sb, ROOT_I);
526 } 519 }
527 } else { 520 } else {
528 pinum = NULL; 521 fattr.cf_uniqueid = iunique(sb, ROOT_I);
529 } 522 }
530
531 *pinode = cifs_new_inode(sb, pinum);
532 if (*pinode == NULL) {
533 rc = -ENOMEM;
534 goto cgii_exit;
535 }
536 }
537 inode = *pinode;
538 cifsInfo = CIFS_I(inode);
539 cifsInfo->cifsAttrs = attr;
540 cifsInfo->delete_pending = pfindData->DeletePending ? true : false;
541 cFYI(1, ("Old time %ld", cifsInfo->time));
542 cifsInfo->time = jiffies;
543 cFYI(1, ("New time %ld", cifsInfo->time));
544
545 /* blksize needs to be multiple of two. So safer to default to
546 blksize and blkbits set in superblock so 2**blkbits and blksize
547 will match rather than setting to:
548 (pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
549
550 /* Linux can not store file creation time so ignore it */
551 if (pfindData->LastAccessTime)
552 inode->i_atime = cifs_NTtimeToUnix(pfindData->LastAccessTime);
553 else /* do not need to use current_fs_time - time not stored */
554 inode->i_atime = CURRENT_TIME;
555 inode->i_mtime = cifs_NTtimeToUnix(pfindData->LastWriteTime);
556 inode->i_ctime = cifs_NTtimeToUnix(pfindData->ChangeTime);
557 cFYI(DBG2, ("Attributes came in as 0x%x", attr));
558 if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
559 inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
560 inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
561 }
562
563 /* get default inode mode */
564 if (attr & ATTR_DIRECTORY)
565 default_mode = cifs_sb->mnt_dir_mode;
566 else
567 default_mode = cifs_sb->mnt_file_mode;
568
569 /* set permission bits */
570 if (atomic_read(&cifsInfo->inUse) == 0 ||
571 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
572 inode->i_mode = default_mode;
573 else {
574 /* just reenable write bits if !ATTR_READONLY */
575 if ((inode->i_mode & S_IWUGO) == 0 &&
576 (attr & ATTR_READONLY) == 0)
577 inode->i_mode |= (S_IWUGO & default_mode);
578
579 inode->i_mode &= ~S_IFMT;
580 }
581 /* clear write bits if ATTR_READONLY is set */
582 if (attr & ATTR_READONLY)
583 inode->i_mode &= ~S_IWUGO;
584
585 /* set inode type */
586 if ((attr & ATTR_SYSTEM) &&
587 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
588 /* no need to fix endianness on 0 */
589 if (pfindData->EndOfFile == 0)
590 inode->i_mode |= S_IFIFO;
591 else if (decode_sfu_inode(inode,
592 le64_to_cpu(pfindData->EndOfFile),
593 full_path, cifs_sb, xid))
594 cFYI(1, ("unknown SFU file type\n"));
595 } else { 523 } else {
596 if (attr & ATTR_DIRECTORY) 524 fattr.cf_uniqueid = CIFS_I(*pinode)->uniqueid;
597 inode->i_mode |= S_IFDIR;
598 else
599 inode->i_mode |= S_IFREG;
600 } 525 }
601 526
602 cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); 527 /* query for SFU type info if supported and needed */
603 spin_lock(&inode->i_lock); 528 if (fattr.cf_cifsattrs & ATTR_SYSTEM &&
604 if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { 529 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
605 /* can not safely shrink the file size here if the 530 tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
606 client is writing to it due to potential races */ 531 if (tmprc)
607 i_size_write(inode, cifsInfo->server_eof); 532 cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
608
609 /* 512 bytes (2**9) is the fake blocksize that must be
610 used for this calculation */
611 inode->i_blocks = (512 - 1 + le64_to_cpu(
612 pfindData->AllocationSize)) >> 9;
613 } 533 }
614 spin_unlock(&inode->i_lock);
615 534
616 inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
617
618 /* BB fill in uid and gid here? with help from winbind?
619 or retrieve from NTFS stream extended attribute */
620#ifdef CONFIG_CIFS_EXPERIMENTAL 535#ifdef CONFIG_CIFS_EXPERIMENTAL
621 /* fill in 0777 bits from ACL */ 536 /* fill in 0777 bits from ACL */
622 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 537 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
623 cFYI(1, ("Getting mode bits from ACL")); 538 cFYI(1, ("Getting mode bits from ACL"));
624 acl_to_uid_mode(cifs_sb, inode, full_path, pfid); 539 cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
625 } 540 }
626#endif 541#endif
627 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
628 /* fill in remaining high mode bits e.g. SUID, VTX */
629 get_sfu_mode(inode, full_path, cifs_sb, xid);
630 } else if (atomic_read(&cifsInfo->inUse) == 0) {
631 inode->i_uid = cifs_sb->mnt_uid;
632 inode->i_gid = cifs_sb->mnt_gid;
633 /* set so we do not keep refreshing these fields with
634 bad data after user has changed them in memory */
635 atomic_set(&cifsInfo->inUse, 1);
636 }
637
638 cifs_set_ops(inode, is_dfs_referral);
639
640 542
543 /* fill in remaining high mode bits e.g. SUID, VTX */
544 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
545 cifs_sfu_mode(&fattr, full_path, cifs_sb, xid);
641 546
547 if (!*pinode) {
548 *pinode = cifs_iget(sb, &fattr);
549 if (!*pinode)
550 rc = -ENOMEM;
551 } else {
552 cifs_fattr_to_inode(*pinode, &fattr);
553 }
642 554
643cgii_exit: 555cgii_exit:
644 kfree(buf); 556 kfree(buf);
@@ -753,21 +665,14 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
753 return ERR_PTR(-ENOMEM); 665 return ERR_PTR(-ENOMEM);
754 666
755 xid = GetXid(); 667 xid = GetXid();
756 if (cifs_sb->tcon->unix_ext) { 668 if (cifs_sb->tcon->unix_ext)
757 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); 669 rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
758 if (!inode) 670 else
759 return ERR_PTR(-ENOMEM); 671 rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
760 } else {
761 inode = iget_locked(sb, ino);
762 if (!inode)
763 return ERR_PTR(-ENOMEM);
764 if (!(inode->i_state & I_NEW))
765 return inode;
766
767 rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
768 xid, NULL); 672 xid, NULL);
769 unlock_new_inode(inode); 673
770 } 674 if (!inode)
675 return ERR_PTR(-ENOMEM);
771 676
772 if (rc && cifs_sb->tcon->ipc) { 677 if (rc && cifs_sb->tcon->ipc) {
773 cFYI(1, ("ipc connection - fake read inode")); 678 cFYI(1, ("ipc connection - fake read inode"));
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 231aa6953f83..f823a4a208a7 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -112,239 +112,74 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
112 return dentry; 112 return dentry;
113} 113}
114 114
115/* Returns 1 if new inode created, 2 if both dentry and inode were */ 115static void
116/* Might check in the future if inode number changed so we can rehash inode */ 116cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
117static int
118construct_dentry(struct qstr *qstring, struct file *file,
119 struct inode **ptmp_inode, struct dentry **pnew_dentry,
120 __u64 *inum)
121{ 117{
122 struct dentry *tmp_dentry = NULL; 118 fattr->cf_uid = cifs_sb->mnt_uid;
123 struct super_block *sb = file->f_path.dentry->d_sb; 119 fattr->cf_gid = cifs_sb->mnt_gid;
124 int rc = 0;
125 120
126 cFYI(1, ("For %s", qstring->name)); 121 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
127 122 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
128 tmp_dentry = d_lookup(file->f_path.dentry, qstring); 123 fattr->cf_dtype = DT_DIR;
129 if (tmp_dentry) {
130 /* BB: overwrite old name? i.e. tmp_dentry->d_name and
131 * tmp_dentry->d_name.len??
132 */
133 cFYI(0, ("existing dentry with inode 0x%p",
134 tmp_dentry->d_inode));
135 *ptmp_inode = tmp_dentry->d_inode;
136 if (*ptmp_inode == NULL) {
137 *ptmp_inode = cifs_new_inode(sb, inum);
138 if (*ptmp_inode == NULL)
139 return rc;
140 rc = 1;
141 }
142 } else { 124 } else {
143 tmp_dentry = d_alloc(file->f_path.dentry, qstring); 125 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
144 if (tmp_dentry == NULL) { 126 fattr->cf_dtype = DT_REG;
145 cERROR(1, ("Failed allocating dentry"));
146 *ptmp_inode = NULL;
147 return rc;
148 }
149
150 if (CIFS_SB(sb)->tcon->nocase)
151 tmp_dentry->d_op = &cifs_ci_dentry_ops;
152 else
153 tmp_dentry->d_op = &cifs_dentry_ops;
154
155 *ptmp_inode = cifs_new_inode(sb, inum);
156 if (*ptmp_inode == NULL)
157 return rc;
158 rc = 2;
159 }
160
161 tmp_dentry->d_time = jiffies;
162 *pnew_dentry = tmp_dentry;
163 return rc;
164}
165
166static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
167 char *buf, unsigned int *pobject_type, int isNewInode)
168{
169 loff_t local_size;
170 struct timespec local_mtime;
171
172 struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
173 struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
174 __u32 attr;
175 __u64 allocation_size;
176 __u64 end_of_file;
177 umode_t default_mode;
178
179 /* save mtime and size */
180 local_mtime = tmp_inode->i_mtime;
181 local_size = tmp_inode->i_size;
182
183 if (new_buf_type) {
184 FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
185
186 attr = le32_to_cpu(pfindData->ExtFileAttributes);
187 allocation_size = le64_to_cpu(pfindData->AllocationSize);
188 end_of_file = le64_to_cpu(pfindData->EndOfFile);
189 tmp_inode->i_atime =
190 cifs_NTtimeToUnix(pfindData->LastAccessTime);
191 tmp_inode->i_mtime =
192 cifs_NTtimeToUnix(pfindData->LastWriteTime);
193 tmp_inode->i_ctime =
194 cifs_NTtimeToUnix(pfindData->ChangeTime);
195 } else { /* legacy, OS2 and DOS style */
196 int offset = cifs_sb->tcon->ses->server->timeAdj;
197 FIND_FILE_STANDARD_INFO *pfindData =
198 (FIND_FILE_STANDARD_INFO *)buf;
199
200 tmp_inode->i_mtime = cnvrtDosUnixTm(pfindData->LastWriteDate,
201 pfindData->LastWriteTime,
202 offset);
203 tmp_inode->i_atime = cnvrtDosUnixTm(pfindData->LastAccessDate,
204 pfindData->LastAccessTime,
205 offset);
206 tmp_inode->i_ctime = cnvrtDosUnixTm(pfindData->LastWriteDate,
207 pfindData->LastWriteTime,
208 offset);
209 attr = le16_to_cpu(pfindData->Attributes);
210 allocation_size = le32_to_cpu(pfindData->AllocationSize);
211 end_of_file = le32_to_cpu(pfindData->DataSize);
212 }
213
214 /* Linux can not store file creation time unfortunately so ignore it */
215
216 cifsInfo->cifsAttrs = attr;
217#ifdef CONFIG_CIFS_EXPERIMENTAL
218 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
219 /* get more accurate mode via ACL - so force inode refresh */
220 cifsInfo->time = 0;
221 } else
222#endif /* CONFIG_CIFS_EXPERIMENTAL */
223 cifsInfo->time = jiffies;
224
225 /* treat dos attribute of read-only as read-only mode bit e.g. 555? */
226 /* 2767 perms - indicate mandatory locking */
227 /* BB fill in uid and gid here? with help from winbind?
228 or retrieve from NTFS stream extended attribute */
229 if (atomic_read(&cifsInfo->inUse) == 0) {
230 tmp_inode->i_uid = cifs_sb->mnt_uid;
231 tmp_inode->i_gid = cifs_sb->mnt_gid;
232 } 127 }
233 128
234 if (attr & ATTR_DIRECTORY) 129 if (fattr->cf_cifsattrs & ATTR_READONLY)
235 default_mode = cifs_sb->mnt_dir_mode; 130 fattr->cf_mode &= ~S_IWUGO;
236 else
237 default_mode = cifs_sb->mnt_file_mode;
238
239 /* set initial permissions */
240 if ((atomic_read(&cifsInfo->inUse) == 0) ||
241 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
242 tmp_inode->i_mode = default_mode;
243 else {
244 /* just reenable write bits if !ATTR_READONLY */
245 if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
246 (attr & ATTR_READONLY) == 0)
247 tmp_inode->i_mode |= (S_IWUGO & default_mode);
248
249 tmp_inode->i_mode &= ~S_IFMT;
250 }
251
252 /* clear write bits if ATTR_READONLY is set */
253 if (attr & ATTR_READONLY)
254 tmp_inode->i_mode &= ~S_IWUGO;
255 131
256 /* set inode type */ 132 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL &&
257 if ((attr & ATTR_SYSTEM) && 133 fattr->cf_cifsattrs & ATTR_SYSTEM) {
258 (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) { 134 if (fattr->cf_eof == 0) {
259 if (end_of_file == 0) { 135 fattr->cf_mode &= ~S_IFMT;
260 tmp_inode->i_mode |= S_IFIFO; 136 fattr->cf_mode |= S_IFIFO;
261 *pobject_type = DT_FIFO; 137 fattr->cf_dtype = DT_FIFO;
262 } else { 138 } else {
263 /* 139 /*
264 * trying to get the type can be slow, so just call 140 * trying to get the type and mode via SFU can be slow,
265 * this a regular file for now, and mark for reval 141 * so just call those regular files for now, and mark
142 * for reval
266 */ 143 */
267 tmp_inode->i_mode |= S_IFREG; 144 fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
268 *pobject_type = DT_REG;
269 cifsInfo->time = 0;
270 }
271 } else {
272 if (attr & ATTR_DIRECTORY) {
273 tmp_inode->i_mode |= S_IFDIR;
274 *pobject_type = DT_DIR;
275 } else {
276 tmp_inode->i_mode |= S_IFREG;
277 *pobject_type = DT_REG;
278 } 145 }
279 } 146 }
147}
280 148
281 /* can not fill in nlink here as in qpathinfo version and Unx search */ 149void
282 if (atomic_read(&cifsInfo->inUse) == 0) 150cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
283 atomic_set(&cifsInfo->inUse, 1); 151 struct cifs_sb_info *cifs_sb)
152{
153 memset(fattr, 0, sizeof(*fattr));
154 fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
155 fattr->cf_eof = le64_to_cpu(info->EndOfFile);
156 fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
157 fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
158 fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
159 fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
160
161 cifs_fill_common_info(fattr, cifs_sb);
162}
284 163
285 cifsInfo->server_eof = end_of_file; 164void
286 spin_lock(&tmp_inode->i_lock); 165cifs_std_info_to_fattr(struct cifs_fattr *fattr, FIND_FILE_STANDARD_INFO *info,
287 if (is_size_safe_to_change(cifsInfo, end_of_file)) { 166 struct cifs_sb_info *cifs_sb)
288 /* can not safely change the file size here if the 167{
289 client is writing to it due to potential races */ 168 int offset = cifs_sb->tcon->ses->server->timeAdj;
290 i_size_write(tmp_inode, end_of_file);
291 169
292 /* 512 bytes (2**9) is the fake blocksize that must be used */ 170 memset(fattr, 0, sizeof(*fattr));
293 /* for this calculation, even though the reported blocksize is larger */ 171 fattr->cf_atime = cnvrtDosUnixTm(info->LastAccessDate,
294 tmp_inode->i_blocks = (512 - 1 + allocation_size) >> 9; 172 info->LastAccessTime, offset);
295 } 173 fattr->cf_ctime = cnvrtDosUnixTm(info->LastWriteDate,
296 spin_unlock(&tmp_inode->i_lock); 174 info->LastWriteTime, offset);
297 175 fattr->cf_mtime = cnvrtDosUnixTm(info->LastWriteDate,
298 if (allocation_size < end_of_file) 176 info->LastWriteTime, offset);
299 cFYI(1, ("May be sparse file, allocation less than file size")); 177
300 cFYI(1, ("File Size %ld and blocks %llu", 178 fattr->cf_cifsattrs = le16_to_cpu(info->Attributes);
301 (unsigned long)tmp_inode->i_size, 179 fattr->cf_bytes = le32_to_cpu(info->AllocationSize);
302 (unsigned long long)tmp_inode->i_blocks)); 180 fattr->cf_eof = le32_to_cpu(info->DataSize);
303 if (S_ISREG(tmp_inode->i_mode)) { 181
304 cFYI(1, ("File inode")); 182 cifs_fill_common_info(fattr, cifs_sb);
305 tmp_inode->i_op = &cifs_file_inode_ops;
306 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
307 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
308 tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
309 else
310 tmp_inode->i_fop = &cifs_file_direct_ops;
311 } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
312 tmp_inode->i_fop = &cifs_file_nobrl_ops;
313 else
314 tmp_inode->i_fop = &cifs_file_ops;
315
316 if ((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
317 (cifs_sb->tcon->ses->server->maxBuf <
318 PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
319 tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
320 else
321 tmp_inode->i_data.a_ops = &cifs_addr_ops;
322
323 if (isNewInode)
324 return; /* No sense invalidating pages for new inode
325 since have not started caching readahead file
326 data yet */
327
328 if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) &&
329 (local_size == tmp_inode->i_size)) {
330 cFYI(1, ("inode exists but unchanged"));
331 } else {
332 /* file may have changed on server */
333 cFYI(1, ("invalidate inode, readdir detected change"));
334 invalidate_remote_inode(tmp_inode);
335 }
336 } else if (S_ISDIR(tmp_inode->i_mode)) {
337 cFYI(1, ("Directory inode"));
338 tmp_inode->i_op = &cifs_dir_inode_ops;
339 tmp_inode->i_fop = &cifs_dir_ops;
340 } else if (S_ISLNK(tmp_inode->i_mode)) {
341 cFYI(1, ("Symbolic Link inode"));
342 tmp_inode->i_op = &cifs_symlink_inode_ops;
343 } else {
344 cFYI(1, ("Init special inode"));
345 init_special_inode(tmp_inode, tmp_inode->i_mode,
346 tmp_inode->i_rdev);
347 }
348} 183}
349 184
350/* BB eventually need to add the following helper function to 185/* BB eventually need to add the following helper function to
@@ -846,11 +681,10 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
846 int rc = 0; 681 int rc = 0;
847 struct qstr qstring; 682 struct qstr qstring;
848 struct cifsFileInfo *pCifsF; 683 struct cifsFileInfo *pCifsF;
849 unsigned int obj_type; 684 u64 inum;
850 __u64 inum;
851 ino_t ino; 685 ino_t ino;
686 struct super_block *sb;
852 struct cifs_sb_info *cifs_sb; 687 struct cifs_sb_info *cifs_sb;
853 struct inode *tmp_inode;
854 struct dentry *tmp_dentry; 688 struct dentry *tmp_dentry;
855 struct cifs_fattr fattr; 689 struct cifs_fattr fattr;
856 690
@@ -870,71 +704,53 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
870 if (rc != 0) 704 if (rc != 0)
871 return 0; 705 return 0;
872 706
873 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); 707 sb = file->f_path.dentry->d_sb;
708 cifs_sb = CIFS_SB(sb);
874 709
875 qstring.name = scratch_buf; 710 qstring.name = scratch_buf;
876 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, 711 rc = cifs_get_name_from_search_buf(&qstring, pfindEntry,
877 pCifsF->srch_inf.info_level, 712 pCifsF->srch_inf.info_level,
878 pCifsF->srch_inf.unicode, cifs_sb, 713 pCifsF->srch_inf.unicode, cifs_sb,
879 max_len, 714 max_len, &inum /* returned */);
880 &inum /* returned */);
881 715
882 if (rc) 716 if (rc)
883 return rc; 717 return rc;
884 718
885 /* only these two infolevels return valid inode numbers */ 719 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
886 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
887 cifs_unix_basic_to_fattr(&fattr, 720 cifs_unix_basic_to_fattr(&fattr,
888 &((FILE_UNIX_INFO *) pfindEntry)->basic, 721 &((FILE_UNIX_INFO *) pfindEntry)->basic,
889 cifs_sb); 722 cifs_sb);
890 tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, 723 else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
891 &fattr); 724 cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *)
892 obj_type = fattr.cf_dtype; 725 pfindEntry, cifs_sb);
893 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); 726 else
894 } else { 727 cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *)
895 if (pCifsF->srch_inf.info_level == 728 pfindEntry, cifs_sb);
896 SMB_FIND_FILE_ID_FULL_DIR_INFO)
897 rc = construct_dentry(&qstring, file, &tmp_inode,
898 &tmp_dentry, &inum);
899 else
900 rc = construct_dentry(&qstring, file, &tmp_inode,
901 &tmp_dentry, NULL);
902
903 if ((tmp_inode == NULL) || (tmp_dentry == NULL)) {
904 rc = -ENOMEM;
905 goto out;
906 }
907
908 /* we pass in rc below, indicating whether it is a new inode,
909 * so we can figure out whether to invalidate the inode cached
910 * data if the file has changed
911 */
912 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
913 fill_in_inode(tmp_inode, 0, pfindEntry, &obj_type, rc);
914 else
915 fill_in_inode(tmp_inode, 1, pfindEntry, &obj_type, rc);
916 729
917 /* new inode - needs to be tied to dentry */ 730 /* FIXME: make _to_fattr functions fill this out */
918 if (rc) { 731 if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
919 d_instantiate(tmp_dentry, tmp_inode); 732 fattr.cf_uniqueid = inum;
920 if (rc == 2) 733 else
921 d_rehash(tmp_dentry); 734 fattr.cf_uniqueid = iunique(sb, ROOT_I);
922 }
923 735
924 ino = cifs_uniqueid_to_ino_t(tmp_inode->i_ino); 736 ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
925 } 737 tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr);
926 738
927 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, 739 rc = filldir(direntry, qstring.name, qstring.len, file->f_pos,
928 ino, obj_type); 740 ino, fattr.cf_dtype);
741
742 /*
743 * we can not return filldir errors to the caller since they are
744 * "normal" when the stat blocksize is too small - we return remapped
745 * error instead
746 *
747 * FIXME: This looks bogus. filldir returns -EOVERFLOW in the above
748 * case already. Why should we be clobbering other errors from it?
749 */
929 if (rc) { 750 if (rc) {
930 cFYI(1, ("filldir rc = %d", rc)); 751 cFYI(1, ("filldir rc = %d", rc));
931 /* we can not return filldir errors to the caller
932 since they are "normal" when the stat blocksize
933 is too small - we return remapped error instead */
934 rc = -EOVERFLOW; 752 rc = -EOVERFLOW;
935 } 753 }
936
937out:
938 dput(tmp_dentry); 754 dput(tmp_dentry);
939 return rc; 755 return rc;
940} 756}