forked from luck/tmp_suning_uos_patched
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
This commit is contained in:
commit
0d995b2b44
@ -74,7 +74,7 @@ static char *cifs_get_share_name(const char *node_name)
|
||||
pSep = memchr(UNC+2, '\\', len-2);
|
||||
if (!pSep) {
|
||||
cERROR(1, ("%s: no server name end in node name: %s",
|
||||
__FUNCTION__, node_name));
|
||||
__func__, node_name));
|
||||
kfree(UNC);
|
||||
return NULL;
|
||||
}
|
||||
@ -84,7 +84,7 @@ static char *cifs_get_share_name(const char *node_name)
|
||||
pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC));
|
||||
if (!pSep) {
|
||||
cERROR(1, ("%s:2 cant find share name in node name: %s",
|
||||
__FUNCTION__, node_name));
|
||||
__func__, node_name));
|
||||
kfree(UNC);
|
||||
return NULL;
|
||||
}
|
||||
@ -127,7 +127,7 @@ static char *compose_mount_options(const char *sb_mountdata,
|
||||
rc = dns_resolve_server_name_to_ip(*devname, &srvIP);
|
||||
if (rc != 0) {
|
||||
cERROR(1, ("%s: Failed to resolve server part of %s to IP",
|
||||
__FUNCTION__, *devname));
|
||||
__func__, *devname));
|
||||
mountdata = ERR_PTR(rc);
|
||||
goto compose_mount_options_out;
|
||||
}
|
||||
@ -181,8 +181,8 @@ static char *compose_mount_options(const char *sb_mountdata,
|
||||
}
|
||||
}
|
||||
|
||||
/*cFYI(1,("%s: parent mountdata: %s", __FUNCTION__,sb_mountdata));*/
|
||||
/*cFYI(1, ("%s: submount mountdata: %s", __FUNCTION__, mountdata ));*/
|
||||
/*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/
|
||||
/*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/
|
||||
|
||||
compose_mount_options_out:
|
||||
kfree(srvIP);
|
||||
@ -302,7 +302,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
||||
int rc = 0;
|
||||
struct vfsmount *mnt = ERR_PTR(-ENOENT);
|
||||
|
||||
cFYI(1, ("in %s", __FUNCTION__));
|
||||
cFYI(1, ("in %s", __func__));
|
||||
BUG_ON(IS_ROOT(dentry));
|
||||
|
||||
xid = GetXid();
|
||||
@ -336,7 +336,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
||||
len = strlen(referrals[i].node_name);
|
||||
if (len < 2) {
|
||||
cERROR(1, ("%s: Net Address path too short: %s",
|
||||
__FUNCTION__, referrals[i].node_name));
|
||||
__func__, referrals[i].node_name));
|
||||
rc = -EINVAL;
|
||||
goto out_err;
|
||||
}
|
||||
@ -344,7 +344,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
||||
nd->path.dentry,
|
||||
referrals[i].node_name);
|
||||
cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
|
||||
__FUNCTION__,
|
||||
__func__,
|
||||
referrals[i].node_name, mnt));
|
||||
|
||||
/* complete mount procedure if we accured submount */
|
||||
@ -365,7 +365,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
|
||||
FreeXid(xid);
|
||||
free_dfs_info_array(referrals, num_referrals);
|
||||
kfree(full_path);
|
||||
cFYI(1, ("leaving %s" , __FUNCTION__));
|
||||
cFYI(1, ("leaving %s" , __func__));
|
||||
return ERR_PTR(rc);
|
||||
out_err:
|
||||
path_put(&nd->path);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fs/cifs/cifsacl.c
|
||||
*
|
||||
* Copyright (C) International Business Machines Corp., 2007
|
||||
* Copyright (C) International Business Machines Corp., 2007,2008
|
||||
* Author(s): Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* Contains the routines for mapping CIFS/NTFS ACLs
|
||||
@ -556,9 +556,9 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
|
||||
/* Retrieve an ACL from the server */
|
||||
static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
||||
const char *path)
|
||||
const char *path, const __u16 *pfid)
|
||||
{
|
||||
struct cifsFileInfo *open_file;
|
||||
struct cifsFileInfo *open_file = NULL;
|
||||
int unlock_file = FALSE;
|
||||
int xid;
|
||||
int rc = -EIO;
|
||||
@ -573,7 +573,11 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
||||
return NULL;
|
||||
|
||||
xid = GetXid();
|
||||
open_file = find_readable_file(CIFS_I(inode));
|
||||
if (pfid == NULL)
|
||||
open_file = find_readable_file(CIFS_I(inode));
|
||||
else
|
||||
fid = *pfid;
|
||||
|
||||
sb = inode->i_sb;
|
||||
if (sb == NULL) {
|
||||
FreeXid(xid);
|
||||
@ -584,7 +588,7 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
||||
if (open_file) {
|
||||
unlock_file = TRUE;
|
||||
fid = open_file->netfid;
|
||||
} else {
|
||||
} else if (pfid == NULL) {
|
||||
int oplock = FALSE;
|
||||
/* open file */
|
||||
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
|
||||
@ -600,10 +604,11 @@ static struct cifs_ntsd *get_cifs_acl(u32 *pacllen, struct inode *inode,
|
||||
|
||||
rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen);
|
||||
cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen));
|
||||
if (unlock_file == TRUE)
|
||||
if (unlock_file == TRUE) /* find_readable_file increments ref count */
|
||||
atomic_dec(&open_file->wrtPending);
|
||||
else
|
||||
else if (pfid == NULL) /* if opened above we have to close the handle */
|
||||
CIFSSMBClose(xid, cifs_sb->tcon, fid);
|
||||
/* else handle was passed in by caller */
|
||||
|
||||
FreeXid(xid);
|
||||
return pntsd;
|
||||
@ -664,14 +669,14 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
|
||||
}
|
||||
|
||||
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
|
||||
void acl_to_uid_mode(struct inode *inode, const char *path)
|
||||
void acl_to_uid_mode(struct inode *inode, const char *path, const __u16 *pfid)
|
||||
{
|
||||
struct cifs_ntsd *pntsd = NULL;
|
||||
u32 acllen = 0;
|
||||
int rc = 0;
|
||||
|
||||
cFYI(DBG2, ("converting ACL to mode for %s", path));
|
||||
pntsd = get_cifs_acl(&acllen, inode, path);
|
||||
pntsd = get_cifs_acl(&acllen, inode, path, pfid);
|
||||
|
||||
/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
|
||||
if (pntsd)
|
||||
@ -694,7 +699,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
|
||||
cFYI(DBG2, ("set ACL from mode for %s", path));
|
||||
|
||||
/* Get the security descriptor */
|
||||
pntsd = get_cifs_acl(&acllen, inode, path);
|
||||
pntsd = get_cifs_acl(&acllen, inode, path, NULL);
|
||||
|
||||
/* Add three ACEs for owner, group, everyone getting rid of
|
||||
other ACEs as chmod disables ACEs and set the security descriptor */
|
||||
|
@ -39,8 +39,8 @@ extern int smb_send(struct socket *, struct smb_hdr *,
|
||||
unsigned int /* length */ , struct sockaddr *);
|
||||
extern unsigned int _GetXid(void);
|
||||
extern void _FreeXid(unsigned int);
|
||||
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
|
||||
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
|
||||
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid));
|
||||
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
|
||||
extern char *build_path_from_dentry(struct dentry *);
|
||||
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
|
||||
/* extern void renew_parental_timestamps(struct dentry *direntry);*/
|
||||
@ -92,11 +92,12 @@ extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
|
||||
extern int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
FILE_ALL_INFO * pfile_info,
|
||||
struct super_block *sb, int xid);
|
||||
struct super_block *sb, int xid, const __u16 *pfid);
|
||||
extern int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path,
|
||||
struct super_block *sb, int xid);
|
||||
extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
|
||||
extern void acl_to_uid_mode(struct inode *inode, const char *path,
|
||||
const __u16 *pfid);
|
||||
extern int mode_to_acl(struct inode *inode, const char *path, __u64);
|
||||
|
||||
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
|
||||
|
@ -229,7 +229,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
|
||||
inode->i_sb, xid);
|
||||
else {
|
||||
rc = cifs_get_inode_info(&newinode, full_path,
|
||||
buf, inode->i_sb, xid);
|
||||
buf, inode->i_sb, xid,
|
||||
&fileHandle);
|
||||
if (newinode) {
|
||||
newinode->i_mode = mode;
|
||||
if ((oplock & CIFS_CREATE_ACTION) &&
|
||||
@ -483,7 +484,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
|
||||
parent_dir_inode->i_sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&newInode, full_path, NULL,
|
||||
parent_dir_inode->i_sb, xid);
|
||||
parent_dir_inode->i_sb, xid, NULL);
|
||||
|
||||
if ((rc == 0) && (newInode != NULL)) {
|
||||
if (pTcon->nocase)
|
||||
|
@ -77,14 +77,14 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
|
||||
/* search for server name delimiter */
|
||||
len = strlen(unc);
|
||||
if (len < 3) {
|
||||
cFYI(1, ("%s: unc is too short: %s", __FUNCTION__, unc));
|
||||
cFYI(1, ("%s: unc is too short: %s", __func__, unc));
|
||||
return -EINVAL;
|
||||
}
|
||||
len -= 2;
|
||||
name = memchr(unc+2, '\\', len);
|
||||
if (!name) {
|
||||
cFYI(1, ("%s: probably server name is whole unc: %s",
|
||||
__FUNCTION__, unc));
|
||||
__func__, unc));
|
||||
} else {
|
||||
len = (name - unc) - 2/* leading // */;
|
||||
}
|
||||
@ -104,7 +104,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
|
||||
if (*ip_addr) {
|
||||
memcpy(*ip_addr, rkey->payload.data, len);
|
||||
(*ip_addr)[len] = '\0';
|
||||
cFYI(1, ("%s: resolved: %s to %s", __FUNCTION__,
|
||||
cFYI(1, ("%s: resolved: %s to %s", __func__,
|
||||
rkey->description,
|
||||
*ip_addr
|
||||
));
|
||||
@ -114,7 +114,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
|
||||
}
|
||||
key_put(rkey);
|
||||
} else {
|
||||
cERROR(1, ("%s: unable to resolve: %s", __FUNCTION__, name));
|
||||
cERROR(1, ("%s: unable to resolve: %s", __func__, name));
|
||||
}
|
||||
|
||||
kfree(name);
|
||||
|
@ -145,7 +145,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
|
||||
full_path, inode->i_sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&file->f_path.dentry->d_inode,
|
||||
full_path, buf, inode->i_sb, xid);
|
||||
full_path, buf, inode->i_sb, xid, NULL);
|
||||
|
||||
if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) {
|
||||
pCifsInode->clientCanCacheAll = TRUE;
|
||||
@ -440,7 +440,7 @@ static int cifs_reopen_file(struct file *file, int can_flush)
|
||||
else
|
||||
rc = cifs_get_inode_info(&inode,
|
||||
full_path, NULL, inode->i_sb,
|
||||
xid);
|
||||
xid, NULL);
|
||||
} /* else we are writing out data to server already
|
||||
and could deadlock if we tried to flush data, and
|
||||
since we do not know if we have data that would
|
||||
|
161
fs/cifs/inode.c
161
fs/cifs/inode.c
@ -30,7 +30,7 @@
|
||||
#include "cifs_fs_sb.h"
|
||||
|
||||
|
||||
static void cifs_set_ops(struct inode *inode)
|
||||
static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
|
||||
{
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
|
||||
|
||||
@ -57,8 +57,16 @@ static void cifs_set_ops(struct inode *inode)
|
||||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
break;
|
||||
case S_IFDIR:
|
||||
inode->i_op = &cifs_dir_inode_ops;
|
||||
inode->i_fop = &cifs_dir_ops;
|
||||
#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;
|
||||
}
|
||||
break;
|
||||
case S_IFLNK:
|
||||
inode->i_op = &cifs_symlink_inode_ops;
|
||||
@ -153,6 +161,30 @@ static void cifs_unix_info_to_inode(struct inode *inode,
|
||||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
|
||||
const char *search_path)
|
||||
{
|
||||
int tree_len;
|
||||
int path_len;
|
||||
char *tmp_path;
|
||||
|
||||
if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
|
||||
return search_path;
|
||||
|
||||
/* use full path name for working with DFS */
|
||||
tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1);
|
||||
path_len = strnlen(search_path, MAX_PATHCONF);
|
||||
|
||||
tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL);
|
||||
if (tmp_path == NULL)
|
||||
return search_path;
|
||||
|
||||
strncpy(tmp_path, pTcon->treeName, tree_len);
|
||||
strncpy(tmp_path+tree_len, search_path, path_len);
|
||||
tmp_path[tree_len+path_len] = 0;
|
||||
return tmp_path;
|
||||
}
|
||||
|
||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path, struct super_block *sb, int xid)
|
||||
{
|
||||
@ -161,41 +193,31 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
char *tmp_path;
|
||||
const unsigned char *full_path;
|
||||
bool is_dfs_referral = false;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, ("Getting info on %s", search_path));
|
||||
|
||||
full_path = cifs_get_search_path(pTcon, search_path);
|
||||
|
||||
try_again_CIFSSMBUnixQPathInfo:
|
||||
/* could have done a find first instead but this returns more info */
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* dump_mem("\nUnixQPathInfo return data", &findData,
|
||||
sizeof(findData)); */
|
||||
if (rc) {
|
||||
if (rc == -EREMOTE) {
|
||||
tmp_path =
|
||||
kmalloc(strnlen(pTcon->treeName,
|
||||
MAX_TREE_SIZE + 1) +
|
||||
strnlen(search_path, MAX_PATHCONF) + 1,
|
||||
GFP_KERNEL);
|
||||
if (tmp_path == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/* have to skip first of the double backslash of
|
||||
UNC name */
|
||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
||||
strncat(tmp_path, search_path, MAX_PATHCONF);
|
||||
rc = connect_to_dfs_path(xid, pTcon->ses,
|
||||
/* treename + */ tmp_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(tmp_path);
|
||||
|
||||
/* BB fix up inode etc. */
|
||||
} else if (rc) {
|
||||
return rc;
|
||||
if (rc == -EREMOTE && !is_dfs_referral) {
|
||||
is_dfs_referral = true;
|
||||
if (full_path != search_path) {
|
||||
kfree(full_path);
|
||||
full_path = search_path;
|
||||
}
|
||||
goto try_again_CIFSSMBUnixQPathInfo;
|
||||
}
|
||||
goto cgiiu_exit;
|
||||
} else {
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
|
||||
@ -204,8 +226,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL)
|
||||
return -ENOMEM;
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
@ -237,8 +261,11 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
(unsigned long) inode->i_size,
|
||||
(unsigned long long)inode->i_blocks));
|
||||
|
||||
cifs_set_ops(inode);
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
}
|
||||
cgiiu_exit:
|
||||
if (full_path != search_path)
|
||||
kfree(full_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -347,15 +374,16 @@ static int get_sfu_mode(struct inode *inode,
|
||||
|
||||
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;
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
char *tmp_path;
|
||||
const unsigned char *full_path = NULL;
|
||||
char *buf = NULL;
|
||||
int adjustTZ = FALSE;
|
||||
bool is_dfs_referral = false;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, ("Getting info on %s", search_path));
|
||||
@ -373,8 +401,12 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
if (buf == NULL)
|
||||
return -ENOMEM;
|
||||
pfindData = (FILE_ALL_INFO *)buf;
|
||||
|
||||
full_path = cifs_get_search_path(pTcon, search_path);
|
||||
|
||||
try_again_CIFSSMBQPathInfo:
|
||||
/* could do find first instead but this returns more info */
|
||||
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
|
||||
rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
|
||||
0 /* not legacy */,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -382,7 +414,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
when server claims no NT SMB support and the above call
|
||||
failed at least once - set flag in tcon or mount */
|
||||
if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
|
||||
rc = SMBQueryInformation(xid, pTcon, search_path,
|
||||
rc = SMBQueryInformation(xid, pTcon, full_path,
|
||||
pfindData, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
@ -391,31 +423,15 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
}
|
||||
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
||||
if (rc) {
|
||||
if (rc == -EREMOTE) {
|
||||
tmp_path =
|
||||
kmalloc(strnlen
|
||||
(pTcon->treeName,
|
||||
MAX_TREE_SIZE + 1) +
|
||||
strnlen(search_path, MAX_PATHCONF) + 1,
|
||||
GFP_KERNEL);
|
||||
if (tmp_path == NULL) {
|
||||
kfree(buf);
|
||||
return -ENOMEM;
|
||||
if (rc == -EREMOTE && !is_dfs_referral) {
|
||||
is_dfs_referral = true;
|
||||
if (full_path != search_path) {
|
||||
kfree(full_path);
|
||||
full_path = search_path;
|
||||
}
|
||||
|
||||
strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
|
||||
strncat(tmp_path, search_path, MAX_PATHCONF);
|
||||
rc = connect_to_dfs_path(xid, pTcon->ses,
|
||||
/* treename + */ tmp_path,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
kfree(tmp_path);
|
||||
/* BB fix up inode etc. */
|
||||
} else if (rc) {
|
||||
kfree(buf);
|
||||
return rc;
|
||||
goto try_again_CIFSSMBQPathInfo;
|
||||
}
|
||||
goto cgii_exit;
|
||||
} else {
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u32 attr = le32_to_cpu(pfindData->Attributes);
|
||||
@ -424,8 +440,8 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
kfree(buf);
|
||||
return -ENOMEM;
|
||||
rc = -ENOMEM;
|
||||
goto cgii_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? Can we use that to check
|
||||
if the server supports returning inode numbers? Are
|
||||
@ -559,7 +575,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
/* 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) {
|
||||
@ -573,8 +589,11 @@ int cifs_get_inode_info(struct inode **pinode,
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
}
|
||||
|
||||
cifs_set_ops(inode);
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
}
|
||||
cgii_exit:
|
||||
if (full_path != search_path)
|
||||
kfree(full_path);
|
||||
kfree(buf);
|
||||
return rc;
|
||||
}
|
||||
@ -603,7 +622,8 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
|
||||
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;
|
||||
@ -804,7 +824,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
|
||||
local_size = tmp_inode->i_size;
|
||||
|
||||
cifs_unix_info_to_inode(tmp_inode, pData, 1);
|
||||
cifs_set_ops(tmp_inode);
|
||||
cifs_set_ops(tmp_inode, false);
|
||||
|
||||
if (!S_ISREG(tmp_inode->i_mode))
|
||||
return;
|
||||
@ -936,7 +956,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
|
||||
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;
|
||||
@ -1218,7 +1238,7 @@ int cifs_revalidate(struct dentry *direntry)
|
||||
}
|
||||
} 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)
|
||||
@ -1407,11 +1427,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
}
|
||||
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
|
||||
@ -1422,7 +1441,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
||||
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.
|
||||
|
@ -205,7 +205,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
|
||||
inode->i_sb, xid);
|
||||
else
|
||||
rc = cifs_get_inode_info(&newinode, full_path, NULL,
|
||||
inode->i_sb, xid);
|
||||
inode->i_sb, xid, NULL);
|
||||
|
||||
if (rc != 0) {
|
||||
cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
|
||||
|
Loading…
Reference in New Issue
Block a user