Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
[CIFS] Fix mem leak on dfs referral
[CIFS] file create with acl support enabled is slow
[CIFS] Fix mtime on cp -p when file data cached but written out too late
[CIFS] Fix build problem
[CIFS] cifs: replace remaining __FUNCTION__ occurrences
[CIFS] DFS patch that connects inode with dfs handling ops

+130 -102
+9 -9
fs/cifs/cifs_dfs_ref.c
··· 74 pSep = memchr(UNC+2, '\\', len-2); 75 if (!pSep) { 76 cERROR(1, ("%s: no server name end in node name: %s", 77 - __FUNCTION__, node_name)); 78 kfree(UNC); 79 return NULL; 80 } ··· 84 pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); 85 if (!pSep) { 86 cERROR(1, ("%s:2 cant find share name in node name: %s", 87 - __FUNCTION__, node_name)); 88 kfree(UNC); 89 return NULL; 90 } ··· 127 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 128 if (rc != 0) { 129 cERROR(1, ("%s: Failed to resolve server part of %s to IP", 130 - __FUNCTION__, *devname)); 131 mountdata = ERR_PTR(rc); 132 goto compose_mount_options_out; 133 } ··· 181 } 182 } 183 184 - /*cFYI(1,("%s: parent mountdata: %s", __FUNCTION__,sb_mountdata));*/ 185 - /*cFYI(1, ("%s: submount mountdata: %s", __FUNCTION__, mountdata ));*/ 186 187 compose_mount_options_out: 188 kfree(srvIP); ··· 302 int rc = 0; 303 struct vfsmount *mnt = ERR_PTR(-ENOENT); 304 305 - cFYI(1, ("in %s", __FUNCTION__)); 306 BUG_ON(IS_ROOT(dentry)); 307 308 xid = GetXid(); ··· 336 len = strlen(referrals[i].node_name); 337 if (len < 2) { 338 cERROR(1, ("%s: Net Address path too short: %s", 339 - __FUNCTION__, referrals[i].node_name)); 340 rc = -EINVAL; 341 goto out_err; 342 } ··· 344 nd->path.dentry, 345 referrals[i].node_name); 346 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", 347 - __FUNCTION__, 348 referrals[i].node_name, mnt)); 349 350 /* complete mount procedure if we accured submount */ ··· 365 FreeXid(xid); 366 free_dfs_info_array(referrals, num_referrals); 367 kfree(full_path); 368 - cFYI(1, ("leaving %s" , __FUNCTION__)); 369 return ERR_PTR(rc); 370 out_err: 371 path_put(&nd->path);
··· 74 pSep = memchr(UNC+2, '\\', len-2); 75 if (!pSep) { 76 cERROR(1, ("%s: no server name end in node name: %s", 77 + __func__, node_name)); 78 kfree(UNC); 79 return NULL; 80 } ··· 84 pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); 85 if (!pSep) { 86 cERROR(1, ("%s:2 cant find share name in node name: %s", 87 + __func__, node_name)); 88 kfree(UNC); 89 return NULL; 90 } ··· 127 rc = dns_resolve_server_name_to_ip(*devname, &srvIP); 128 if (rc != 0) { 129 cERROR(1, ("%s: Failed to resolve server part of %s to IP", 130 + __func__, *devname)); 131 mountdata = ERR_PTR(rc); 132 goto compose_mount_options_out; 133 } ··· 181 } 182 } 183 184 + /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ 185 + /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ 186 187 compose_mount_options_out: 188 kfree(srvIP); ··· 302 int rc = 0; 303 struct vfsmount *mnt = ERR_PTR(-ENOENT); 304 305 + cFYI(1, ("in %s", __func__)); 306 BUG_ON(IS_ROOT(dentry)); 307 308 xid = GetXid(); ··· 336 len = strlen(referrals[i].node_name); 337 if (len < 2) { 338 cERROR(1, ("%s: Net Address path too short: %s", 339 + __func__, referrals[i].node_name)); 340 rc = -EINVAL; 341 goto out_err; 342 } ··· 344 nd->path.dentry, 345 referrals[i].node_name); 346 cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", 347 + __func__, 348 referrals[i].node_name, mnt)); 349 350 /* complete mount procedure if we accured submount */ ··· 365 FreeXid(xid); 366 free_dfs_info_array(referrals, num_referrals); 367 kfree(full_path); 368 + cFYI(1, ("leaving %s" , __func__)); 369 return ERR_PTR(rc); 370 out_err: 371 path_put(&nd->path);
+15 -10
fs/cifs/cifsacl.c
··· 1 /* 2 * fs/cifs/cifsacl.c 3 * 4 - * Copyright (C) International Business Machines Corp., 2007 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 * Contains the routines for mapping CIFS/NTFS ACLs ··· 556 557 /* Retrieve an ACL from the server */ 558 static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, 559 - const char *path) 560 { 561 - struct cifsFileInfo *open_file; 562 int unlock_file = FALSE; 563 int xid; 564 int rc = -EIO; ··· 573 return NULL; 574 575 xid = GetXid(); 576 - open_file = find_readable_file(CIFS_I(inode)); 577 sb = inode->i_sb; 578 if (sb == NULL) { 579 FreeXid(xid); ··· 588 if (open_file) { 589 unlock_file = TRUE; 590 fid = open_file->netfid; 591 - } else { 592 int oplock = FALSE; 593 /* open file */ 594 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, ··· 604 605 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 606 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); 607 - if (unlock_file == TRUE) 608 atomic_dec(&open_file->wrtPending); 609 - else 610 CIFSSMBClose(xid, cifs_sb->tcon, fid); 611 612 FreeXid(xid); 613 return pntsd; ··· 669 } 670 671 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 672 - void acl_to_uid_mode(struct inode *inode, const char *path) 673 { 674 struct cifs_ntsd *pntsd = NULL; 675 u32 acllen = 0; 676 int rc = 0; 677 678 cFYI(DBG2, ("converting ACL to mode for %s", path)); 679 - pntsd = get_cifs_acl(&acllen, inode, path); 680 681 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 682 if (pntsd) ··· 699 cFYI(DBG2, ("set ACL from mode for %s", path)); 700 701 /* Get the security descriptor */ 702 - pntsd = get_cifs_acl(&acllen, inode, path); 703 704 /* Add three ACEs for owner, group, everyone getting rid of 705 other ACEs as chmod disables ACEs and set the security descriptor */
··· 1 /* 2 * fs/cifs/cifsacl.c 3 * 4 + * Copyright (C) International Business Machines Corp., 2007,2008 5 * Author(s): Steve French (sfrench@us.ibm.com) 6 * 7 * Contains the routines for mapping CIFS/NTFS ACLs ··· 556 557 /* Retrieve an ACL from the server */ 558 static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode, 559 + const char *path, const __u16 *pfid) 560 { 561 + struct cifsFileInfo *open_file = NULL; 562 int unlock_file = FALSE; 563 int xid; 564 int rc = -EIO; ··· 573 return NULL; 574 575 xid = GetXid(); 576 + if (pfid == NULL) 577 + open_file = find_readable_file(CIFS_I(inode)); 578 + else 579 + fid = *pfid; 580 + 581 sb = inode->i_sb; 582 if (sb == NULL) { 583 FreeXid(xid); ··· 584 if (open_file) { 585 unlock_file = TRUE; 586 fid = open_file->netfid; 587 + } else if (pfid == NULL) { 588 int oplock = FALSE; 589 /* open file */ 590 rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN, ··· 600 601 rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); 602 cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); 603 + if (unlock_file == TRUE) /* find_readable_file increments ref count */ 604 atomic_dec(&open_file->wrtPending); 605 + else if (pfid == NULL) /* if opened above we have to close the handle */ 606 CIFSSMBClose(xid, cifs_sb->tcon, fid); 607 + /* else handle was passed in by caller */ 608 609 FreeXid(xid); 610 return pntsd; ··· 664 } 665 666 /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ 667 + void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid) 668 { 669 struct cifs_ntsd *pntsd = NULL; 670 u32 acllen = 0; 671 int rc = 0; 672 673 cFYI(DBG2, ("converting ACL to mode for %s", path)); 674 + pntsd = get_cifs_acl(&acllen, inode, path, pfid); 675 676 /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ 677 if (pntsd) ··· 694 cFYI(DBG2, ("set ACL from mode for %s", path)); 695 696 /* Get the security descriptor */ 697 + pntsd = get_cifs_acl(&acllen, inode, path, NULL); 698 699 /* Add three ACEs for owner, group, everyone getting rid of 700 other ACEs as chmod disables ACEs and set the security descriptor */
+5 -4
fs/cifs/cifsproto.h
··· 39 unsigned int /* length */ , struct sockaddr *); 40 extern unsigned int _GetXid(void); 41 extern void _FreeXid(unsigned int); 42 - #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid)); 43 - #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));} 44 extern char *build_path_from_dentry(struct dentry *); 45 extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46 /* extern void renew_parental_timestamps(struct dentry *direntry);*/ ··· 92 extern int cifs_get_inode_info(struct inode **pinode, 93 const unsigned char *search_path, 94 FILE_ALL_INFO * pfile_info, 95 - struct super_block *sb, int xid); 96 extern int cifs_get_inode_info_unix(struct inode **pinode, 97 const unsigned char *search_path, 98 struct super_block *sb, int xid); 99 - extern void acl_to_uid_mode(struct inode *inode, const char *search_path); 100 extern int mode_to_acl(struct inode *inode, const char *path, __u64); 101 102 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
··· 39 unsigned int /* length */ , struct sockaddr *); 40 extern unsigned int _GetXid(void); 41 extern void _FreeXid(unsigned int); 42 + #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); 43 + #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} 44 extern char *build_path_from_dentry(struct dentry *); 45 extern char *build_wildcard_path_from_dentry(struct dentry *direntry); 46 /* extern void renew_parental_timestamps(struct dentry *direntry);*/ ··· 92 extern int cifs_get_inode_info(struct inode **pinode, 93 const unsigned char *search_path, 94 FILE_ALL_INFO * pfile_info, 95 + struct super_block *sb, int xid, const __u16 *pfid); 96 extern int cifs_get_inode_info_unix(struct inode **pinode, 97 const unsigned char *search_path, 98 struct super_block *sb, int xid); 99 + extern void acl_to_uid_mode(struct inode *inode, const char *path, 100 + const __u16 *pfid); 101 extern int mode_to_acl(struct inode *inode, const char *path, __u64); 102 103 extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
+3 -2
fs/cifs/dir.c
··· 229 inode->i_sb, xid); 230 else { 231 rc = cifs_get_inode_info(&newinode, full_path, 232 - buf, inode->i_sb, xid); 233 if (newinode) { 234 newinode->i_mode = mode; 235 if ((oplock & CIFS_CREATE_ACTION) && ··· 484 parent_dir_inode->i_sb, xid); 485 else 486 rc = cifs_get_inode_info(&newInode, full_path, NULL, 487 - parent_dir_inode->i_sb, xid); 488 489 if ((rc == 0) && (newInode != NULL)) { 490 if (pTcon->nocase)
··· 229 inode->i_sb, xid); 230 else { 231 rc = cifs_get_inode_info(&newinode, full_path, 232 + buf, inode->i_sb, xid, 233 + &fileHandle); 234 if (newinode) { 235 newinode->i_mode = mode; 236 if ((oplock & CIFS_CREATE_ACTION) && ··· 483 parent_dir_inode->i_sb, xid); 484 else 485 rc = cifs_get_inode_info(&newInode, full_path, NULL, 486 + parent_dir_inode->i_sb, xid, NULL); 487 488 if ((rc == 0) && (newInode != NULL)) { 489 if (pTcon->nocase)
+4 -4
fs/cifs/dns_resolve.c
··· 77 /* search for server name delimiter */ 78 len = strlen(unc); 79 if (len < 3) { 80 - cFYI(1, ("%s: unc is too short: %s", __FUNCTION__, unc)); 81 return -EINVAL; 82 } 83 len -= 2; 84 name = memchr(unc+2, '\\', len); 85 if (!name) { 86 cFYI(1, ("%s: probably server name is whole unc: %s", 87 - __FUNCTION__, unc)); 88 } else { 89 len = (name - unc) - 2/* leading // */; 90 } ··· 104 if (*ip_addr) { 105 memcpy(*ip_addr, rkey->payload.data, len); 106 (*ip_addr)[len] = '\0'; 107 - cFYI(1, ("%s: resolved: %s to %s", __FUNCTION__, 108 rkey->description, 109 *ip_addr 110 )); ··· 114 } 115 key_put(rkey); 116 } else { 117 - cERROR(1, ("%s: unable to resolve: %s", __FUNCTION__, name)); 118 } 119 120 kfree(name);
··· 77 /* search for server name delimiter */ 78 len = strlen(unc); 79 if (len < 3) { 80 + cFYI(1, ("%s: unc is too short: %s", __func__, unc)); 81 return -EINVAL; 82 } 83 len -= 2; 84 name = memchr(unc+2, '\\', len); 85 if (!name) { 86 cFYI(1, ("%s: probably server name is whole unc: %s", 87 + __func__, unc)); 88 } else { 89 len = (name - unc) - 2/* leading // */; 90 } ··· 104 if (*ip_addr) { 105 memcpy(*ip_addr, rkey->payload.data, len); 106 (*ip_addr)[len] = '\0'; 107 + cFYI(1, ("%s: resolved: %s to %s", __func__, 108 rkey->description, 109 *ip_addr 110 )); ··· 114 } 115 key_put(rkey); 116 } else { 117 + cERROR(1, ("%s: unable to resolve: %s", __func__, name)); 118 } 119 120 kfree(name);
+2 -2
fs/cifs/file.c
··· 145 full_path, inode->i_sb, xid); 146 else 147 rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, 148 - full_path, buf, inode->i_sb, xid); 149 150 if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { 151 pCifsInode->clientCanCacheAll = TRUE; ··· 440 else 441 rc = cifs_get_inode_info(&inode, 442 full_path, NULL, inode->i_sb, 443 - xid); 444 } /* else we are writing out data to server already 445 and could deadlock if we tried to flush data, and 446 since we do not know if we have data that would
··· 145 full_path, inode->i_sb, xid); 146 else 147 rc = cifs_get_inode_info(&file->f_path.dentry->d_inode, 148 + full_path, buf, inode->i_sb, xid, NULL); 149 150 if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { 151 pCifsInode->clientCanCacheAll = TRUE; ··· 440 else 441 rc = cifs_get_inode_info(&inode, 442 full_path, NULL, inode->i_sb, 443 + xid, NULL); 444 } /* else we are writing out data to server already 445 and could deadlock if we tried to flush data, and 446 since we do not know if we have data that would
+91 -70
fs/cifs/inode.c
··· 30 #include "cifs_fs_sb.h" 31 32 33 - static void cifs_set_ops(struct inode *inode) 34 { 35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 36 ··· 57 inode->i_data.a_ops = &cifs_addr_ops; 58 break; 59 case S_IFDIR: 60 - inode->i_op = &cifs_dir_inode_ops; 61 - inode->i_fop = &cifs_dir_ops; 62 break; 63 case S_IFLNK: 64 inode->i_op = &cifs_symlink_inode_ops; ··· 161 spin_unlock(&inode->i_lock); 162 } 163 164 int cifs_get_inode_info_unix(struct inode **pinode, 165 const unsigned char *search_path, struct super_block *sb, int xid) 166 { ··· 193 struct cifsTconInfo *pTcon; 194 struct inode *inode; 195 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 196 - char *tmp_path; 197 198 pTcon = cifs_sb->tcon; 199 cFYI(1, ("Getting info on %s", search_path)); 200 /* could have done a find first instead but this returns more info */ 201 - rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, 202 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 203 CIFS_MOUNT_MAP_SPECIAL_CHR); 204 /* dump_mem("\nUnixQPathInfo return data", &findData, 205 sizeof(findData)); */ 206 if (rc) { 207 - if (rc == -EREMOTE) { 208 - tmp_path = 209 - kmalloc(strnlen(pTcon->treeName, 210 - MAX_TREE_SIZE + 1) + 211 - strnlen(search_path, MAX_PATHCONF) + 1, 212 - GFP_KERNEL); 213 - if (tmp_path == NULL) 214 - return -ENOMEM; 215 - 216 - /* have to skip first of the double backslash of 217 - UNC name */ 218 - strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); 219 - strncat(tmp_path, search_path, MAX_PATHCONF); 220 - rc = connect_to_dfs_path(xid, pTcon->ses, 221 - /* treename + */ tmp_path, 222 - cifs_sb->local_nls, 223 - cifs_sb->mnt_cifs_flags & 224 - CIFS_MOUNT_MAP_SPECIAL_CHR); 225 - kfree(tmp_path); 226 - 227 - /* BB fix up inode etc. */ 228 - } else if (rc) { 229 - return rc; 230 } 231 } else { 232 struct cifsInodeInfo *cifsInfo; 233 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); ··· 226 /* get new inode */ 227 if (*pinode == NULL) { 228 *pinode = new_inode(sb); 229 - if (*pinode == NULL) 230 - return -ENOMEM; 231 /* Is an i_ino of zero legal? */ 232 /* Are there sanity checks we can use to ensure that 233 the server is really filling in that field? */ ··· 261 (unsigned long) inode->i_size, 262 (unsigned long long)inode->i_blocks)); 263 264 - cifs_set_ops(inode); 265 } 266 return rc; 267 } 268 ··· 374 375 int cifs_get_inode_info(struct inode **pinode, 376 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 377 - struct super_block *sb, int xid) 378 { 379 int rc = 0; 380 struct cifsTconInfo *pTcon; 381 struct inode *inode; 382 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 383 - char *tmp_path; 384 char *buf = NULL; 385 int adjustTZ = FALSE; 386 387 pTcon = cifs_sb->tcon; 388 cFYI(1, ("Getting info on %s", search_path)); ··· 401 if (buf == NULL) 402 return -ENOMEM; 403 pfindData = (FILE_ALL_INFO *)buf; 404 /* could do find first instead but this returns more info */ 405 - rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, 406 0 /* not legacy */, 407 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 408 CIFS_MOUNT_MAP_SPECIAL_CHR); ··· 414 when server claims no NT SMB support and the above call 415 failed at least once - set flag in tcon or mount */ 416 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { 417 - rc = SMBQueryInformation(xid, pTcon, search_path, 418 pfindData, cifs_sb->local_nls, 419 cifs_sb->mnt_cifs_flags & 420 CIFS_MOUNT_MAP_SPECIAL_CHR); ··· 423 } 424 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 425 if (rc) { 426 - if (rc == -EREMOTE) { 427 - tmp_path = 428 - kmalloc(strnlen 429 - (pTcon->treeName, 430 - MAX_TREE_SIZE + 1) + 431 - strnlen(search_path, MAX_PATHCONF) + 1, 432 - GFP_KERNEL); 433 - if (tmp_path == NULL) { 434 - kfree(buf); 435 - return -ENOMEM; 436 } 437 - 438 - strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); 439 - strncat(tmp_path, search_path, MAX_PATHCONF); 440 - rc = connect_to_dfs_path(xid, pTcon->ses, 441 - /* treename + */ tmp_path, 442 - cifs_sb->local_nls, 443 - cifs_sb->mnt_cifs_flags & 444 - CIFS_MOUNT_MAP_SPECIAL_CHR); 445 - kfree(tmp_path); 446 - /* BB fix up inode etc. */ 447 - } else if (rc) { 448 - kfree(buf); 449 - return rc; 450 } 451 } else { 452 struct cifsInodeInfo *cifsInfo; 453 __u32 attr = le32_to_cpu(pfindData->Attributes); ··· 440 if (*pinode == NULL) { 441 *pinode = new_inode(sb); 442 if (*pinode == NULL) { 443 - kfree(buf); 444 - return -ENOMEM; 445 } 446 /* Is an i_ino of zero legal? Can we use that to check 447 if the server supports returning inode numbers? Are ··· 575 /* fill in 0777 bits from ACL */ 576 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 577 cFYI(1, ("Getting mode bits from ACL")); 578 - acl_to_uid_mode(inode, search_path); 579 } 580 #endif 581 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { ··· 589 atomic_set(&cifsInfo->inUse, 1); 590 } 591 592 - cifs_set_ops(inode); 593 } 594 kfree(buf); 595 return rc; 596 } ··· 622 if (cifs_sb->tcon->unix_ext) 623 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); 624 else 625 - rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid); 626 if (rc && cifs_sb->tcon->ipc) { 627 cFYI(1, ("ipc connection - fake read inode")); 628 inode->i_mode |= S_IFDIR; ··· 824 local_size = tmp_inode->i_size; 825 826 cifs_unix_info_to_inode(tmp_inode, pData, 1); 827 - cifs_set_ops(tmp_inode); 828 829 if (!S_ISREG(tmp_inode->i_mode)) 830 return; ··· 956 inode->i_sb, xid); 957 else 958 rc = cifs_get_inode_info(&newinode, full_path, NULL, 959 - inode->i_sb, xid); 960 961 if (pTcon->nocase) 962 direntry->d_op = &cifs_ci_dentry_ops; ··· 1238 } 1239 } else { 1240 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, 1241 - direntry->d_sb, xid); 1242 if (rc) { 1243 cFYI(1, ("error on getting revalidate info %d", rc)); 1244 /* if (rc != -ENOENT) ··· 1427 } 1428 cifsInode = CIFS_I(direntry->d_inode); 1429 1430 - /* BB check if we need to refresh inode from server now ? BB */ 1431 - 1432 - if (attrs->ia_valid & ATTR_SIZE) { 1433 /* 1434 - Flush data before changing file size on server. If the 1435 flush returns error, store it to report later and continue. 1436 BB: This should be smarter. Why bother flushing pages that 1437 will be truncated anyway? Also, should we error out here if ··· 1441 CIFS_I(direntry->d_inode)->write_behind_rc = rc; 1442 rc = 0; 1443 } 1444 1445 /* To avoid spurious oplock breaks from server, in the case of 1446 inodes that we already have open, avoid doing path based 1447 setting of file size if we can do it by handle.
··· 30 #include "cifs_fs_sb.h" 31 32 33 + static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) 34 { 35 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 36 ··· 57 inode->i_data.a_ops = &cifs_addr_ops; 58 break; 59 case S_IFDIR: 60 + #ifdef CONFIG_CIFS_DFS_UPCALL 61 + if (is_dfs_referral) { 62 + inode->i_op = &cifs_dfs_referral_inode_operations; 63 + } else { 64 + #else /* NO DFS support, treat as a directory */ 65 + { 66 + #endif 67 + inode->i_op = &cifs_dir_inode_ops; 68 + inode->i_fop = &cifs_dir_ops; 69 + } 70 break; 71 case S_IFLNK: 72 inode->i_op = &cifs_symlink_inode_ops; ··· 153 spin_unlock(&inode->i_lock); 154 } 155 156 + static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon, 157 + const char *search_path) 158 + { 159 + int tree_len; 160 + int path_len; 161 + char *tmp_path; 162 + 163 + if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS)) 164 + return search_path; 165 + 166 + /* use full path name for working with DFS */ 167 + tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1); 168 + path_len = strnlen(search_path, MAX_PATHCONF); 169 + 170 + tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL); 171 + if (tmp_path == NULL) 172 + return search_path; 173 + 174 + strncpy(tmp_path, pTcon->treeName, tree_len); 175 + strncpy(tmp_path+tree_len, search_path, path_len); 176 + tmp_path[tree_len+path_len] = 0; 177 + return tmp_path; 178 + } 179 + 180 int cifs_get_inode_info_unix(struct inode **pinode, 181 const unsigned char *search_path, struct super_block *sb, int xid) 182 { ··· 161 struct cifsTconInfo *pTcon; 162 struct inode *inode; 163 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 164 + const unsigned char *full_path; 165 + bool is_dfs_referral = false; 166 167 pTcon = cifs_sb->tcon; 168 cFYI(1, ("Getting info on %s", search_path)); 169 + 170 + full_path = cifs_get_search_path(pTcon, search_path); 171 + 172 + try_again_CIFSSMBUnixQPathInfo: 173 /* could have done a find first instead but this returns more info */ 174 + rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData, 175 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 176 CIFS_MOUNT_MAP_SPECIAL_CHR); 177 /* dump_mem("\nUnixQPathInfo return data", &findData, 178 sizeof(findData)); */ 179 if (rc) { 180 + if (rc == -EREMOTE && !is_dfs_referral) { 181 + is_dfs_referral = true; 182 + if (full_path != search_path) { 183 + kfree(full_path); 184 + full_path = search_path; 185 + } 186 + goto try_again_CIFSSMBUnixQPathInfo; 187 } 188 + goto cgiiu_exit; 189 } else { 190 struct cifsInodeInfo *cifsInfo; 191 __u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes); ··· 204 /* get new inode */ 205 if (*pinode == NULL) { 206 *pinode = new_inode(sb); 207 + if (*pinode == NULL) { 208 + rc = -ENOMEM; 209 + goto cgiiu_exit; 210 + } 211 /* Is an i_ino of zero legal? */ 212 /* Are there sanity checks we can use to ensure that 213 the server is really filling in that field? */ ··· 237 (unsigned long) inode->i_size, 238 (unsigned long long)inode->i_blocks)); 239 240 + cifs_set_ops(inode, is_dfs_referral); 241 } 242 + cgiiu_exit: 243 + if (full_path != search_path) 244 + kfree(full_path); 245 return rc; 246 } 247 ··· 347 348 int cifs_get_inode_info(struct inode **pinode, 349 const unsigned char *search_path, FILE_ALL_INFO *pfindData, 350 + struct super_block *sb, int xid, const __u16 *pfid) 351 { 352 int rc = 0; 353 struct cifsTconInfo *pTcon; 354 struct inode *inode; 355 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 356 + const unsigned char *full_path = NULL; 357 char *buf = NULL; 358 int adjustTZ = FALSE; 359 + bool is_dfs_referral = false; 360 361 pTcon = cifs_sb->tcon; 362 cFYI(1, ("Getting info on %s", search_path)); ··· 373 if (buf == NULL) 374 return -ENOMEM; 375 pfindData = (FILE_ALL_INFO *)buf; 376 + 377 + full_path = cifs_get_search_path(pTcon, search_path); 378 + 379 + try_again_CIFSSMBQPathInfo: 380 /* could do find first instead but this returns more info */ 381 + rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData, 382 0 /* not legacy */, 383 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 384 CIFS_MOUNT_MAP_SPECIAL_CHR); ··· 382 when server claims no NT SMB support and the above call 383 failed at least once - set flag in tcon or mount */ 384 if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { 385 + rc = SMBQueryInformation(xid, pTcon, full_path, 386 pfindData, cifs_sb->local_nls, 387 cifs_sb->mnt_cifs_flags & 388 CIFS_MOUNT_MAP_SPECIAL_CHR); ··· 391 } 392 /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ 393 if (rc) { 394 + if (rc == -EREMOTE && !is_dfs_referral) { 395 + is_dfs_referral = true; 396 + if (full_path != search_path) { 397 + kfree(full_path); 398 + full_path = search_path; 399 } 400 + goto try_again_CIFSSMBQPathInfo; 401 } 402 + goto cgii_exit; 403 } else { 404 struct cifsInodeInfo *cifsInfo; 405 __u32 attr = le32_to_cpu(pfindData->Attributes); ··· 424 if (*pinode == NULL) { 425 *pinode = new_inode(sb); 426 if (*pinode == NULL) { 427 + rc = -ENOMEM; 428 + goto cgii_exit; 429 } 430 /* Is an i_ino of zero legal? Can we use that to check 431 if the server supports returning inode numbers? Are ··· 559 /* fill in 0777 bits from ACL */ 560 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { 561 cFYI(1, ("Getting mode bits from ACL")); 562 + acl_to_uid_mode(inode, search_path, pfid); 563 } 564 #endif 565 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { ··· 573 atomic_set(&cifsInfo->inUse, 1); 574 } 575 576 + cifs_set_ops(inode, is_dfs_referral); 577 } 578 + cgii_exit: 579 + if (full_path != search_path) 580 + kfree(full_path); 581 kfree(buf); 582 return rc; 583 } ··· 603 if (cifs_sb->tcon->unix_ext) 604 rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid); 605 else 606 + rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid, 607 + NULL); 608 if (rc && cifs_sb->tcon->ipc) { 609 cFYI(1, ("ipc connection - fake read inode")); 610 inode->i_mode |= S_IFDIR; ··· 804 local_size = tmp_inode->i_size; 805 806 cifs_unix_info_to_inode(tmp_inode, pData, 1); 807 + cifs_set_ops(tmp_inode, false); 808 809 if (!S_ISREG(tmp_inode->i_mode)) 810 return; ··· 936 inode->i_sb, xid); 937 else 938 rc = cifs_get_inode_info(&newinode, full_path, NULL, 939 + inode->i_sb, xid, NULL); 940 941 if (pTcon->nocase) 942 direntry->d_op = &cifs_ci_dentry_ops; ··· 1218 } 1219 } else { 1220 rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL, 1221 + direntry->d_sb, xid, NULL); 1222 if (rc) { 1223 cFYI(1, ("error on getting revalidate info %d", rc)); 1224 /* if (rc != -ENOENT) ··· 1407 } 1408 cifsInode = CIFS_I(direntry->d_inode); 1409 1410 + if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1411 /* 1412 + Flush data before changing file size or changing the last 1413 + write time of the file on the server. If the 1414 flush returns error, store it to report later and continue. 1415 BB: This should be smarter. Why bother flushing pages that 1416 will be truncated anyway? Also, should we error out here if ··· 1422 CIFS_I(direntry->d_inode)->write_behind_rc = rc; 1423 rc = 0; 1424 } 1425 + } 1426 1427 + if (attrs->ia_valid & ATTR_SIZE) { 1428 /* To avoid spurious oplock breaks from server, in the case of 1429 inodes that we already have open, avoid doing path based 1430 setting of file size if we can do it by handle.
+1 -1
fs/cifs/link.c
··· 205 inode->i_sb, xid); 206 else 207 rc = cifs_get_inode_info(&newinode, full_path, NULL, 208 - inode->i_sb, xid); 209 210 if (rc != 0) { 211 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
··· 205 inode->i_sb, xid); 206 else 207 rc = cifs_get_inode_info(&newinode, full_path, NULL, 208 + inode->i_sb, xid, NULL); 209 210 if (rc != 0) { 211 cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",