inode->i_data.a_ops = &cifs_addr_ops;
break;
case S_IFDIR:
+#ifdef CONFIG_CIFS_DFS_UPCALL
if (is_dfs_referral) {
inode->i_op = &cifs_dfs_referral_inode_operations;
} else {
+#else /* NO DFS support, treat as a directory */
+ {
+#endif
inode->i_op = &cifs_dir_inode_ops;
inode->i_fop = &cifs_dir_ops;
}
spin_unlock(&inode->i_lock);
}
-static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
- const char *search_path)
+static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
+ const char *search_path)
{
int tree_len;
int path_len;
+ int i;
char *tmp_path;
+ struct cifsTconInfo *pTcon = cifs_sb->tcon;
if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
return search_path;
return search_path;
strncpy(tmp_path, pTcon->treeName, tree_len);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
+ for (i = 0; i < tree_len; i++) {
+ if (tmp_path[i] == '\\')
+ tmp_path[i] = '/';
+ }
strncpy(tmp_path+tree_len, search_path, path_len);
tmp_path[tree_len+path_len] = 0;
return tmp_path;
pTcon = cifs_sb->tcon;
cFYI(1, ("Getting info on %s", search_path));
- full_path = cifs_get_search_path(pTcon, search_path);
+ full_path = cifs_get_search_path(cifs_sb, search_path);
try_again_CIFSSMBUnixQPathInfo:
/* could have done a find first instead but this returns more info */
if (rc) {
if (rc == -EREMOTE && !is_dfs_referral) {
is_dfs_referral = true;
- full_path = search_path;
+ if (full_path != search_path) {
+ kfree(full_path);
+ full_path = search_path;
+ }
goto try_again_CIFSSMBUnixQPathInfo;
}
goto cgiiu_exit;
int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path, FILE_ALL_INFO *pfindData,
- struct super_block *sb, int xid)
+ struct super_block *sb, int xid, const __u16 *pfid)
{
int rc = 0;
struct cifsTconInfo *pTcon;
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
- full_path = cifs_get_search_path(pTcon, search_path);
+ full_path = cifs_get_search_path(cifs_sb, search_path);
try_again_CIFSSMBQPathInfo:
/* could do find first instead but this returns more info */
if (rc) {
if (rc == -EREMOTE && !is_dfs_referral) {
is_dfs_referral = true;
- full_path = search_path;
+ if (full_path != search_path) {
+ kfree(full_path);
+ full_path = search_path;
+ }
goto try_again_CIFSSMBQPathInfo;
}
goto cgii_exit;
/* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
cFYI(1, ("Getting mode bits from ACL"));
- acl_to_uid_mode(inode, search_path);
+ acl_to_uid_mode(inode, search_path, pfid);
}
#endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
if (cifs_sb->tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
else
- rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+ rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
+ NULL);
if (rc && cifs_sb->tcon->ipc) {
cFYI(1, ("ipc connection - fake read inode"));
inode->i_mode |= S_IFDIR;
inode->i_sb, xid);
else
rc = cifs_get_inode_info(&newinode, full_path, NULL,
- inode->i_sb, xid);
+ inode->i_sb, xid, NULL);
if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops;
}
} else {
rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
- direntry->d_sb, xid);
+ direntry->d_sb, xid, NULL);
if (rc) {
cFYI(1, ("error on getting revalidate info %d", rc));
/* if (rc != -ENOENT)
}
cifsInode = CIFS_I(direntry->d_inode);
- /* BB check if we need to refresh inode from server now ? BB */
-
- if (attrs->ia_valid & ATTR_SIZE) {
+ if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
/*
- Flush data before changing file size on server. If the
+ Flush data before changing file size or changing the last
+ write time of the file on the server. If the
flush returns error, store it to report later and continue.
BB: This should be smarter. Why bother flushing pages that
will be truncated anyway? Also, should we error out here if
CIFS_I(direntry->d_inode)->write_behind_rc = rc;
rc = 0;
}
+ }
+ if (attrs->ia_valid & ATTR_SIZE) {
/* To avoid spurious oplock breaks from server, in the case of
inodes that we already have open, avoid doing path based
setting of file size if we can do it by handle.