Merge master.kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6
This commit is contained in:
commit
252ec9e28f
|
@ -3,6 +3,8 @@ Version 1.39
|
|||
Defer close of a file handle slightly if pending writes depend on that file handle
|
||||
(this reduces the EBADF bad file handle errors that can be logged under heavy
|
||||
stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2
|
||||
Fix SFU style symlinks and mknod needed for servers which do not support the CIFS
|
||||
Unix Extensions. Fix setfacl/getfacl on bigendian.
|
||||
|
||||
Version 1.38
|
||||
------------
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* fs/cifs/cifs_unicode.c
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2000,2002
|
||||
* Copyright (c) International Business Machines Corp., 2000,2005
|
||||
* Modified by Steve French (sfrench@us.ibm.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -31,7 +31,7 @@
|
|||
*
|
||||
*/
|
||||
int
|
||||
cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
|
||||
cifs_strfromUCS_le(char *to, const __le16 * from,
|
||||
int len, const struct nls_table *codepage)
|
||||
{
|
||||
int i;
|
||||
|
@ -60,25 +60,26 @@ cifs_strfromUCS_le(char *to, const wchar_t * from, /* LITTLE ENDIAN */
|
|||
*
|
||||
*/
|
||||
int
|
||||
cifs_strtoUCS(wchar_t * to, const char *from, int len,
|
||||
cifs_strtoUCS(__le16 * to, const char *from, int len,
|
||||
const struct nls_table *codepage)
|
||||
{
|
||||
int charlen;
|
||||
int i;
|
||||
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
|
||||
|
||||
for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
|
||||
|
||||
/* works for 2.4.0 kernel or later */
|
||||
charlen = codepage->char2uni(from, len, &to[i]);
|
||||
charlen = codepage->char2uni(from, len, &wchar_to[i]);
|
||||
if (charlen < 1) {
|
||||
cERROR(1,
|
||||
("cifs_strtoUCS: char2uni returned %d",
|
||||
charlen));
|
||||
/* A question mark */
|
||||
to[i] = (wchar_t)cpu_to_le16(0x003f);
|
||||
to[i] = cpu_to_le16(0x003f);
|
||||
charlen = 1;
|
||||
} else
|
||||
to[i] = (wchar_t)cpu_to_le16(to[i]);
|
||||
to[i] = cpu_to_le16(wchar_to[i]);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Convert a unicode character to upper or lower case using
|
||||
* compressed tables.
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2000,2002
|
||||
* Copyright (c) International Business Machines Corp., 2000,2005555555555555555555555555555555555555555555555555555555
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -59,8 +59,8 @@ extern struct UniCaseRange UniLowerRange[];
|
|||
#endif /* UNIUPR_NOLOWER */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
int cifs_strfromUCS_le(char *, const wchar_t *, int, const struct nls_table *);
|
||||
int cifs_strtoUCS(wchar_t *, const char *, int, const struct nls_table *);
|
||||
int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
|
||||
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -149,7 +149,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_
|
|||
char temp_hash[16];
|
||||
struct HMACMD5Context ctx;
|
||||
char * ucase_buf;
|
||||
wchar_t * unicode_buf;
|
||||
__le16 * unicode_buf;
|
||||
unsigned int i,user_name_len,dom_name_len;
|
||||
|
||||
if(ses == NULL)
|
||||
|
|
113
fs/cifs/cifsfs.c
113
fs/cifs/cifsfs.c
|
@ -483,56 +483,29 @@ cifs_get_sb(struct file_system_type *fs_type,
|
|||
return sb;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cifs_read_wrapper(struct file * file, char __user *read_data, size_t read_size,
|
||||
loff_t * poffset)
|
||||
{
|
||||
if(file->f_dentry == NULL)
|
||||
return -EIO;
|
||||
else if(file->f_dentry->d_inode == NULL)
|
||||
return -EIO;
|
||||
|
||||
cFYI(1,("In read_wrapper size %zd at %lld",read_size,*poffset));
|
||||
|
||||
if(CIFS_I(file->f_dentry->d_inode)->clientCanCacheRead) {
|
||||
return generic_file_read(file,read_data,read_size,poffset);
|
||||
} else {
|
||||
/* BB do we need to lock inode from here until after invalidate? */
|
||||
/* if(file->f_dentry->d_inode->i_mapping) {
|
||||
filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
|
||||
filemap_fdatawait(file->f_dentry->d_inode->i_mapping);
|
||||
}*/
|
||||
/* cifs_revalidate(file->f_dentry);*/ /* BB fixme */
|
||||
|
||||
/* BB we should make timer configurable - perhaps
|
||||
by simply calling cifs_revalidate here */
|
||||
/* invalidate_remote_inode(file->f_dentry->d_inode);*/
|
||||
return generic_file_read(file,read_data,read_size,poffset);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
cifs_write_wrapper(struct file * file, const char __user *write_data,
|
||||
size_t write_size, loff_t * poffset)
|
||||
static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t *ppos)
|
||||
{
|
||||
struct inode *inode = file->f_dentry->d_inode;
|
||||
ssize_t written;
|
||||
|
||||
if(file->f_dentry == NULL)
|
||||
return -EIO;
|
||||
else if(file->f_dentry->d_inode == NULL)
|
||||
return -EIO;
|
||||
|
||||
cFYI(1,("In write_wrapper size %zd at %lld",write_size,*poffset));
|
||||
|
||||
written = generic_file_write(file,write_data,write_size,poffset);
|
||||
if(!CIFS_I(file->f_dentry->d_inode)->clientCanCacheAll) {
|
||||
if(file->f_dentry->d_inode->i_mapping) {
|
||||
filemap_fdatawrite(file->f_dentry->d_inode->i_mapping);
|
||||
}
|
||||
}
|
||||
written = generic_file_writev(file, iov, nr_segs, ppos);
|
||||
if (!CIFS_I(inode)->clientCanCacheAll)
|
||||
filemap_fdatawrite(inode->i_mapping);
|
||||
return written;
|
||||
}
|
||||
|
||||
static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
|
||||
ssize_t written;
|
||||
|
||||
written = generic_file_aio_write(iocb, buf, count, pos);
|
||||
if (!CIFS_I(inode)->clientCanCacheAll)
|
||||
filemap_fdatawrite(inode->i_mapping);
|
||||
return written;
|
||||
}
|
||||
|
||||
static struct file_system_type cifs_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -594,8 +567,12 @@ struct inode_operations cifs_symlink_inode_ops = {
|
|||
};
|
||||
|
||||
struct file_operations cifs_file_ops = {
|
||||
.read = cifs_read_wrapper,
|
||||
.write = cifs_write_wrapper,
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.readv = generic_file_readv,
|
||||
.writev = cifs_file_writev,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = cifs_file_aio_write,
|
||||
.open = cifs_open,
|
||||
.release = cifs_close,
|
||||
.lock = cifs_lock,
|
||||
|
@ -608,10 +585,6 @@ struct file_operations cifs_file_ops = {
|
|||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.readv = generic_file_readv,
|
||||
.writev = generic_file_writev,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = generic_file_aio_write,
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
};
|
||||
|
@ -631,6 +604,46 @@ struct file_operations cifs_file_direct_ops = {
|
|||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
};
|
||||
struct file_operations cifs_file_nobrl_ops = {
|
||||
.read = do_sync_read,
|
||||
.write = do_sync_write,
|
||||
.readv = generic_file_readv,
|
||||
.writev = cifs_file_writev,
|
||||
.aio_read = generic_file_aio_read,
|
||||
.aio_write = cifs_file_aio_write,
|
||||
.open = cifs_open,
|
||||
.release = cifs_close,
|
||||
.fsync = cifs_fsync,
|
||||
.flush = cifs_flush,
|
||||
.mmap = cifs_file_mmap,
|
||||
.sendfile = generic_file_sendfile,
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
};
|
||||
|
||||
struct file_operations cifs_file_direct_nobrl_ops = {
|
||||
/* no mmap, no aio, no readv -
|
||||
BB reevaluate whether they can be done with directio, no cache */
|
||||
.read = cifs_user_read,
|
||||
.write = cifs_user_write,
|
||||
.open = cifs_open,
|
||||
.release = cifs_close,
|
||||
.fsync = cifs_fsync,
|
||||
.flush = cifs_flush,
|
||||
.sendfile = generic_file_sendfile, /* BB removeme BB */
|
||||
#ifdef CONFIG_CIFS_POSIX
|
||||
.ioctl = cifs_ioctl,
|
||||
#endif /* CONFIG_CIFS_POSIX */
|
||||
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
.dir_notify = cifs_dir_notify,
|
||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||
|
|
|
@ -63,6 +63,8 @@ extern struct inode_operations cifs_symlink_inode_ops;
|
|||
/* Functions related to files and directories */
|
||||
extern struct file_operations cifs_file_ops;
|
||||
extern struct file_operations cifs_file_direct_ops; /* if directio mount */
|
||||
extern struct file_operations cifs_file_nobrl_ops;
|
||||
extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */
|
||||
extern int cifs_open(struct inode *inode, struct file *file);
|
||||
extern int cifs_close(struct inode *inode, struct file *file);
|
||||
extern int cifs_closedir(struct inode *inode, struct file *file);
|
||||
|
|
|
@ -603,7 +603,9 @@ typedef struct smb_com_logoff_andx_rsp {
|
|||
__u16 ByteCount;
|
||||
} __attribute__((packed)) LOGOFF_ANDX_RSP;
|
||||
|
||||
typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on tree_connect PDU to effect disconnect *//* probably the simplest SMB PDU */
|
||||
typedef union smb_com_tree_disconnect { /* as an altetnative can use flag on
|
||||
tree_connect PDU to effect disconnect */
|
||||
/* tdis is probably simplest SMB PDU */
|
||||
struct {
|
||||
struct smb_hdr hdr; /* wct = 0 */
|
||||
__u16 ByteCount; /* bcc = 0 */
|
||||
|
@ -2025,6 +2027,12 @@ typedef struct {
|
|||
} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FF response data area */
|
||||
|
||||
|
||||
struct win_dev {
|
||||
unsigned char type[8]; /* IntxCHR or IntxBLK */
|
||||
__le64 major;
|
||||
__le64 minor;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gea {
|
||||
unsigned char name_len;
|
||||
char name[1];
|
||||
|
|
|
@ -1142,7 +1142,9 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
|
|||
int bytes_returned, wct;
|
||||
int smb_hdr_len;
|
||||
|
||||
cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
|
||||
/* BB removeme BB */
|
||||
cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
|
||||
|
||||
if(tcon->ses->capabilities & CAP_LARGE_FILES)
|
||||
wct = 14;
|
||||
else
|
||||
|
@ -1553,7 +1555,7 @@ createSymLinkRetry:
|
|||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
|
||||
cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
|
@ -1577,7 +1579,7 @@ createSymLinkRetry:
|
|||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len_target =
|
||||
cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
|
||||
cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
name_len_target++; /* trailing null */
|
||||
|
@ -1803,7 +1805,7 @@ querySymLinkRetry:
|
|||
|
||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
name_len =
|
||||
cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
|
||||
cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
|
||||
/* find define for this maxpathcomponent */
|
||||
, nls_codepage);
|
||||
name_len++; /* trailing null */
|
||||
|
@ -1860,7 +1862,7 @@ querySymLinkRetry:
|
|||
min_t(const int, buflen,count) / 2);
|
||||
/* BB FIXME investigate remapping reserved chars here */
|
||||
cifs_strfromUCS_le(symlinkinfo,
|
||||
(wchar_t *) ((char *)&pSMBr->hdr.Protocol +
|
||||
(__le16 *) ((char *)&pSMBr->hdr.Protocol +
|
||||
data_offset),
|
||||
name_len, nls_codepage);
|
||||
} else {
|
||||
|
@ -1951,7 +1953,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
|
|||
reparse_buf->TargetNameOffset),
|
||||
min(buflen/2, reparse_buf->TargetNameLen / 2));
|
||||
cifs_strfromUCS_le(symlinkinfo,
|
||||
(wchar_t *) (reparse_buf->LinkNamesBuf +
|
||||
(__le16 *) (reparse_buf->LinkNamesBuf +
|
||||
reparse_buf->TargetNameOffset),
|
||||
name_len, nls_codepage);
|
||||
} else { /* ASCII names */
|
||||
|
@ -1983,9 +1985,9 @@ qreparse_out:
|
|||
static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
|
||||
{
|
||||
/* u8 cifs fields do not need le conversion */
|
||||
ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
|
||||
ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
|
||||
ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
|
||||
ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
|
||||
ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag);
|
||||
ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
|
||||
/* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
|
||||
|
||||
return;
|
||||
|
@ -2037,7 +2039,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
|
|||
} else if(size > buflen) {
|
||||
return -ERANGE;
|
||||
} else /* buffer big enough */ {
|
||||
local_acl->a_version = POSIX_ACL_XATTR_VERSION;
|
||||
local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
|
||||
for(i = 0;i < count ;i++) {
|
||||
cifs_convert_ace(&local_acl->a_entries[i],pACE);
|
||||
pACE ++;
|
||||
|
@ -2051,14 +2053,14 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
|
|||
{
|
||||
__u16 rc = 0; /* 0 = ACL converted ok */
|
||||
|
||||
cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
|
||||
cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
|
||||
cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
|
||||
cifs_ace->cifs_e_tag = le16_to_cpu(local_ace->e_tag);
|
||||
/* BB is there a better way to handle the large uid? */
|
||||
if(local_ace->e_id == -1) {
|
||||
if(local_ace->e_id == cpu_to_le32(-1)) {
|
||||
/* Probably no need to le convert -1 on any arch but can not hurt */
|
||||
cifs_ace->cifs_uid = cpu_to_le64(-1);
|
||||
} else
|
||||
cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
|
||||
cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
|
||||
/*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
|
||||
return rc;
|
||||
}
|
||||
|
@ -2078,16 +2080,17 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl
|
|||
|
||||
count = posix_acl_xattr_count((size_t)buflen);
|
||||
cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
|
||||
count,buflen,local_acl->a_version));
|
||||
if(local_acl->a_version != 2) {
|
||||
cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
|
||||
count, buflen, le32_to_cpu(local_acl->a_version)));
|
||||
if(le32_to_cpu(local_acl->a_version) != 2) {
|
||||
cFYI(1,("unknown POSIX ACL version %d",
|
||||
le32_to_cpu(local_acl->a_version)));
|
||||
return 0;
|
||||
}
|
||||
cifs_acl->version = cpu_to_le16(1);
|
||||
if(acl_type == ACL_TYPE_ACCESS)
|
||||
cifs_acl->access_entry_count = count;
|
||||
cifs_acl->access_entry_count = cpu_to_le16(count);
|
||||
else if(acl_type == ACL_TYPE_DEFAULT)
|
||||
cifs_acl->default_entry_count = count;
|
||||
cifs_acl->default_entry_count = cpu_to_le16(count);
|
||||
else {
|
||||
cFYI(1,("unknown ACL type %d",acl_type));
|
||||
return 0;
|
||||
|
@ -3203,7 +3206,7 @@ getDFSRetry:
|
|||
temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
|
||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||
cifs_strfromUCS_le(*targetUNCs,
|
||||
(wchar_t *) temp, name_len, nls_codepage);
|
||||
(__le16 *) temp, name_len, nls_codepage);
|
||||
} else {
|
||||
strncpy(*targetUNCs,temp,name_len);
|
||||
}
|
||||
|
|
|
@ -1986,32 +1986,32 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
bytes_returned = 0; /* skill null user */
|
||||
else
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
|
||||
nls_codepage);
|
||||
/* convert number of 16 bit words to bytes */
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
if (domain == NULL)
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr,
|
||||
"CIFS_LINUX_DOM", 32, nls_codepage);
|
||||
else
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
|
||||
32, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
|
||||
32, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
64, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
|
@ -2081,7 +2081,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
if(ses->serverOS == NULL)
|
||||
goto sesssetup_nomem;
|
||||
cifs_strfromUCS_le(ses->serverOS,
|
||||
(wchar_t *)bcc_ptr, len,nls_codepage);
|
||||
(__le16 *)bcc_ptr, len,nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
remaining_words -= len + 1;
|
||||
ses->serverOS[2 * len] = 0;
|
||||
|
@ -2093,7 +2093,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
if(ses->serverNOS == NULL)
|
||||
goto sesssetup_nomem;
|
||||
cifs_strfromUCS_le(ses->serverNOS,
|
||||
(wchar_t *)bcc_ptr,len,nls_codepage);
|
||||
(__le16 *)bcc_ptr,len,nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
ses->serverNOS[2 * len] = 0;
|
||||
ses->serverNOS[1 + (2 * len)] = 0;
|
||||
|
@ -2111,7 +2111,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
if(ses->serverDomain == NULL)
|
||||
goto sesssetup_nomem;
|
||||
cifs_strfromUCS_le(ses->serverDomain,
|
||||
(wchar_t *)bcc_ptr,len,nls_codepage);
|
||||
(__le16 *)bcc_ptr,len,nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
ses->serverDomain[2*len] = 0;
|
||||
ses->serverDomain[1+(2*len)] = 0;
|
||||
|
@ -2255,30 +2255,30 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
bcc_ptr++;
|
||||
}
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned; /* convert num of 16 bit words to bytes */
|
||||
bcc_ptr += 2; /* trailing null */
|
||||
if (domain == NULL)
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr,
|
||||
"CIFS_LINUX_DOM", 32, nls_codepage);
|
||||
else
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
|
||||
32, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
64, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2;
|
||||
|
@ -2357,7 +2357,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
ses->serverOS =
|
||||
kzalloc(2 * (len + 1), GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->serverOS,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr, len,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
|
@ -2372,7 +2372,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
kzalloc(2 * (len + 1),
|
||||
GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->serverNOS,
|
||||
(wchar_t *)bcc_ptr,
|
||||
(__le16 *)bcc_ptr,
|
||||
len,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
|
@ -2384,9 +2384,8 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
/* last string is not always null terminated (for e.g. for Windows XP & 2000) */
|
||||
ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->serverDomain,
|
||||
(wchar_t *)bcc_ptr,
|
||||
len,
|
||||
nls_codepage);
|
||||
(__le16 *)bcc_ptr,
|
||||
len, nls_codepage);
|
||||
bcc_ptr += 2*(len+1);
|
||||
ses->serverDomain[2*len] = 0;
|
||||
ses->serverDomain[1+(2*len)] = 0;
|
||||
|
@ -2560,16 +2559,16 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||
}
|
||||
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
|
||||
32, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2; /* null terminate Linux version */
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
64, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
*(bcc_ptr + 1) = 0;
|
||||
|
@ -2673,7 +2672,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||
ses->serverOS =
|
||||
kzalloc(2 * (len + 1), GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->serverOS,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr, len,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
|
@ -2690,7 +2689,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||
GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->
|
||||
serverNOS,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr,
|
||||
len,
|
||||
nls_codepage);
|
||||
|
@ -2708,23 +2707,15 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
|
|||
1),
|
||||
GFP_KERNEL);
|
||||
cifs_strfromUCS_le
|
||||
(ses->
|
||||
serverDomain,
|
||||
(wchar_t *)
|
||||
bcc_ptr, len,
|
||||
nls_codepage);
|
||||
(ses->serverDomain,
|
||||
(__le16 *)bcc_ptr,
|
||||
len, nls_codepage);
|
||||
bcc_ptr +=
|
||||
2 * (len + 1);
|
||||
ses->
|
||||
serverDomain[2
|
||||
* len]
|
||||
ses->serverDomain[2*len]
|
||||
= 0;
|
||||
ses->
|
||||
serverDomain[1
|
||||
+
|
||||
(2
|
||||
*
|
||||
len)]
|
||||
ses->serverDomain
|
||||
[1 + (2 * len)]
|
||||
= 0;
|
||||
} /* else no more room so create dummy domain string */
|
||||
else
|
||||
|
@ -2903,7 +2894,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
SecurityBlob->DomainName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, domain, 64,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
|
||||
nls_codepage);
|
||||
len *= 2;
|
||||
SecurityBlob->DomainName.MaximumLength =
|
||||
|
@ -2921,7 +2912,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
SecurityBlob->UserName.MaximumLength = 0;
|
||||
} else {
|
||||
__u16 len =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 64,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
|
||||
nls_codepage);
|
||||
len *= 2;
|
||||
SecurityBlob->UserName.MaximumLength =
|
||||
|
@ -2934,7 +2925,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
cpu_to_le16(len);
|
||||
}
|
||||
|
||||
/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((wchar_t *) bcc_ptr, "AMACHINE",64, nls_codepage);
|
||||
/* SecurityBlob->WorkstationName.Length = cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
|
||||
SecurityBlob->WorkstationName.Length *= 2;
|
||||
SecurityBlob->WorkstationName.MaximumLength = cpu_to_le16(SecurityBlob->WorkstationName.Length);
|
||||
SecurityBlob->WorkstationName.Buffer = cpu_to_le32(SecurityBlobLength);
|
||||
|
@ -2947,16 +2938,16 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
bcc_ptr++;
|
||||
}
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, "Linux version ",
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
|
||||
32, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, system_utsname.release, 32,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
bcc_ptr += 2; /* null term version string */
|
||||
bytes_returned =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
|
||||
64, nls_codepage);
|
||||
bcc_ptr += 2 * bytes_returned;
|
||||
*(bcc_ptr + 1) = 0;
|
||||
|
@ -3069,7 +3060,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
ses->serverOS =
|
||||
kzalloc(2 * (len + 1), GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->serverOS,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr, len,
|
||||
nls_codepage);
|
||||
bcc_ptr += 2 * (len + 1);
|
||||
|
@ -3086,7 +3077,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
GFP_KERNEL);
|
||||
cifs_strfromUCS_le(ses->
|
||||
serverNOS,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr,
|
||||
len,
|
||||
nls_codepage);
|
||||
|
@ -3105,7 +3096,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
|
|||
cifs_strfromUCS_le
|
||||
(ses->
|
||||
serverDomain,
|
||||
(wchar_t *)
|
||||
(__le16 *)
|
||||
bcc_ptr, len,
|
||||
nls_codepage);
|
||||
bcc_ptr +=
|
||||
|
@ -3227,7 +3218,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||
if (ses->capabilities & CAP_UNICODE) {
|
||||
smb_buffer->Flags2 |= SMBFLG2_UNICODE;
|
||||
length =
|
||||
cifs_strtoUCS((wchar_t *) bcc_ptr, tree, 100, nls_codepage);
|
||||
cifs_strtoUCS((__le16 *) bcc_ptr, tree, 100, nls_codepage);
|
||||
bcc_ptr += 2 * length; /* convert num of 16 bit words to bytes */
|
||||
bcc_ptr += 2; /* skip trailing null */
|
||||
} else { /* ASCII */
|
||||
|
@ -3263,7 +3254,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
|
|||
tcon->nativeFileSystem =
|
||||
kzalloc(length + 2, GFP_KERNEL);
|
||||
cifs_strfromUCS_le(tcon->nativeFileSystem,
|
||||
(wchar_t *) bcc_ptr,
|
||||
(__le16 *) bcc_ptr,
|
||||
length, nls_codepage);
|
||||
bcc_ptr += 2 * length;
|
||||
bcc_ptr[0] = 0; /* null terminate the string */
|
||||
|
|
|
@ -292,7 +292,8 @@ cifs_create_out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t device_number)
|
||||
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
|
||||
dev_t device_number)
|
||||
{
|
||||
int rc = -EPERM;
|
||||
int xid;
|
||||
|
@ -368,7 +369,34 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
|
|||
|
||||
if(!rc) {
|
||||
/* BB Do not bother to decode buf since no
|
||||
local inode yet to put timestamps in */
|
||||
local inode yet to put timestamps in,
|
||||
but we can reuse it safely */
|
||||
int bytes_written;
|
||||
struct win_dev *pdev;
|
||||
pdev = (struct win_dev *)buf;
|
||||
if(S_ISCHR(mode)) {
|
||||
memcpy(pdev->type, "IntxCHR", 8);
|
||||
pdev->major =
|
||||
cpu_to_le64(MAJOR(device_number));
|
||||
pdev->minor =
|
||||
cpu_to_le64(MINOR(device_number));
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
fileHandle,
|
||||
sizeof(struct win_dev),
|
||||
0, &bytes_written, (char *)pdev,
|
||||
NULL, 0);
|
||||
} else if(S_ISBLK(mode)) {
|
||||
memcpy(pdev->type, "IntxBLK", 8);
|
||||
pdev->major =
|
||||
cpu_to_le64(MAJOR(device_number));
|
||||
pdev->minor =
|
||||
cpu_to_le64(MINOR(device_number));
|
||||
rc = CIFSSMBWrite(xid, pTcon,
|
||||
fileHandle,
|
||||
sizeof(struct win_dev),
|
||||
0, &bytes_written, (char *)pdev,
|
||||
NULL, 0);
|
||||
} /* else if(S_ISFIFO */
|
||||
CIFSSMBClose(xid, pTcon, fileHandle);
|
||||
d_drop(direntry);
|
||||
}
|
||||
|
|
|
@ -489,8 +489,10 @@ int cifs_close(struct inode *inode, struct file *file)
|
|||
the struct would be in each open file,
|
||||
but this should give enough time to
|
||||
clear the socket */
|
||||
write_unlock(&file->f_owner.lock);
|
||||
cERROR(1,("close with pending writes"));
|
||||
msleep(timeout);
|
||||
write_lock(&file->f_owner.lock);
|
||||
timeout *= 4;
|
||||
}
|
||||
write_unlock(&file->f_owner.lock);
|
||||
|
|
202
fs/cifs/inode.c
202
fs/cifs/inode.c
|
@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
char *tmp_path;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, (" Getting info on %s ", search_path));
|
||||
cFYI(1, ("Getting info on %s ", search_path));
|
||||
/* could have done a find first instead but this returns more info */
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
|
@ -97,9 +97,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
cFYI(1, (" Old time %ld ", cifsInfo->time));
|
||||
cFYI(1, ("Old time %ld ", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, (" New time %ld ", cifsInfo->time));
|
||||
cFYI(1, ("New time %ld ", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse,1);
|
||||
|
||||
|
@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
|
||||
inode->i_mode = le64_to_cpu(findData.Permissions);
|
||||
/* since we set the inode type below we need to mask off
|
||||
to avoid strange results if bits set above */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
inode->i_mode |= S_IFREG;
|
||||
} else if (type == UNIX_SYMLINK) {
|
||||
|
@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
inode->i_mode |= S_IFIFO;
|
||||
} else if (type == UNIX_SOCKET) {
|
||||
inode->i_mode |= S_IFSOCK;
|
||||
} else {
|
||||
/* safest to call it a file if we do not know */
|
||||
inode->i_mode |= S_IFREG;
|
||||
cFYI(1,("unknown type %d",type));
|
||||
}
|
||||
inode->i_uid = le64_to_cpu(findData.Uid);
|
||||
inode->i_gid = le64_to_cpu(findData.Gid);
|
||||
|
@ -155,34 +162,39 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
}
|
||||
|
||||
if (num_of_bytes < end_of_file)
|
||||
cFYI(1, ("allocation size less than end of file "));
|
||||
cFYI(1, ("allocation size less than end of file"));
|
||||
cFYI(1,
|
||||
("Size %ld and blocks %ld",
|
||||
(unsigned long) inode->i_size, inode->i_blocks));
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
cFYI(1, (" File inode "));
|
||||
cFYI(1, ("File inode"));
|
||||
inode->i_op = &cifs_file_inode_ops;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
else
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop =
|
||||
&cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop->lock = NULL;
|
||||
|
||||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
/* check if server can support readpages */
|
||||
if(pTcon->ses->server->maxBuf <
|
||||
4096 + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops->readpages = NULL;
|
||||
} else if (S_ISDIR(inode->i_mode)) {
|
||||
cFYI(1, (" Directory inode"));
|
||||
cFYI(1, ("Directory inode"));
|
||||
inode->i_op = &cifs_dir_inode_ops;
|
||||
inode->i_fop = &cifs_dir_ops;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
cFYI(1, (" Symbolic Link inode "));
|
||||
cFYI(1, ("Symbolic Link inode"));
|
||||
inode->i_op = &cifs_symlink_inode_ops;
|
||||
/* tmp_inode->i_fop = */ /* do not need to set to anything */
|
||||
} else {
|
||||
cFYI(1, (" Init special inode "));
|
||||
cFYI(1, ("Init special inode"));
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
inode->i_rdev);
|
||||
}
|
||||
|
@ -190,6 +202,111 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int decode_sfu_inode(struct inode * inode, __u64 size,
|
||||
const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
{
|
||||
int rc;
|
||||
int oplock = FALSE;
|
||||
__u16 netfid;
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
char buf[24];
|
||||
unsigned int bytes_read;
|
||||
char * pbuf;
|
||||
|
||||
pbuf = buf;
|
||||
|
||||
if(size == 0) {
|
||||
inode->i_mode |= S_IFIFO;
|
||||
return 0;
|
||||
} else if (size < 8) {
|
||||
return -EINVAL; /* EOPNOTSUPP? */
|
||||
}
|
||||
|
||||
rc = CIFSSMBOpen(xid, pTcon, path, FILE_OPEN, GENERIC_READ,
|
||||
CREATE_NOT_DIR, &netfid, &oplock, NULL,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc==0) {
|
||||
/* Read header */
|
||||
rc = CIFSSMBRead(xid, pTcon,
|
||||
netfid,
|
||||
24 /* length */, 0 /* offset */,
|
||||
&bytes_read, &pbuf);
|
||||
if((rc == 0) && (bytes_read >= 8)) {
|
||||
if(memcmp("IntxBLK", pbuf, 8) == 0) {
|
||||
cFYI(1,("Block device"));
|
||||
inode->i_mode |= S_IFBLK;
|
||||
if(bytes_read == 24) {
|
||||
/* we have enough to decode dev num */
|
||||
__u64 mjr; /* major */
|
||||
__u64 mnr; /* minor */
|
||||
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||
inode->i_rdev = MKDEV(mjr, mnr);
|
||||
}
|
||||
} else if(memcmp("IntxCHR", pbuf, 8) == 0) {
|
||||
cFYI(1,("Char device"));
|
||||
inode->i_mode |= S_IFCHR;
|
||||
if(bytes_read == 24) {
|
||||
/* we have enough to decode dev num */
|
||||
__u64 mjr; /* major */
|
||||
__u64 mnr; /* minor */
|
||||
mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
|
||||
mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
|
||||
inode->i_rdev = MKDEV(mjr, mnr);
|
||||
}
|
||||
} else if(memcmp("IntxLNK", pbuf, 7) == 0) {
|
||||
cFYI(1,("Symlink"));
|
||||
inode->i_mode |= S_IFLNK;
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG; /* file? */
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG; /* then it is a file */
|
||||
rc = -EOPNOTSUPP; /* or some unknown SFU type */
|
||||
}
|
||||
CIFSSMBClose(xid, pTcon, netfid);
|
||||
}
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
#define SFBITS_MASK (S_ISVTX | S_ISGID | S_ISUID) /* SETFILEBITS valid bits */
|
||||
|
||||
static int get_sfu_uid_mode(struct inode * inode,
|
||||
const unsigned char *path,
|
||||
struct cifs_sb_info *cifs_sb, int xid)
|
||||
{
|
||||
#ifdef CONFIG_CIFS_XATTR
|
||||
ssize_t rc;
|
||||
char ea_value[4];
|
||||
__u32 mode;
|
||||
|
||||
rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS",
|
||||
ea_value, 4 /* size of buf */, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if(rc < 0)
|
||||
return (int)rc;
|
||||
else if (rc > 3) {
|
||||
mode = le32_to_cpu(*((__le32 *)ea_value));
|
||||
inode->i_mode &= ~SFBITS_MASK;
|
||||
cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
|
||||
inode->i_mode = (mode & SFBITS_MASK) | inode->i_mode;
|
||||
cFYI(1,("special mode bits 0%o", mode));
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
return -EOPNOTSUPP;
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *search_path, FILE_ALL_INFO *pfindData,
|
||||
struct super_block *sb, int xid)
|
||||
|
@ -202,7 +319,7 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
char *buf = NULL;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1,("Getting info on %s ", search_path));
|
||||
cFYI(1,("Getting info on %s", search_path));
|
||||
|
||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||
|
@ -303,9 +420,9 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
cifsInfo->cifsAttrs = attr;
|
||||
cFYI(1, (" Old time %ld ", cifsInfo->time));
|
||||
cFYI(1, ("Old time %ld ", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, (" New time %ld ", cifsInfo->time));
|
||||
cFYI(1, ("New time %ld ", cifsInfo->time));
|
||||
|
||||
/* blksize needs to be multiple of two. So safer to default to
|
||||
blksize and blkbits set in superblock so 2**blkbits and blksize
|
||||
|
@ -319,13 +436,15 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
|
||||
inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
|
||||
cFYI(0, (" Attributes came in as 0x%x ", attr));
|
||||
cFYI(0, ("Attributes came in as 0x%x ", attr));
|
||||
|
||||
/* set default mode. will override for dirs below */
|
||||
if (atomic_read(&cifsInfo->inUse) == 0)
|
||||
/* new inode, can safely set these fields */
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
|
||||
else /* since we set the inode type below we need to mask off
|
||||
to avoid strange results if type changes and both get orred in */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
/* if (attr & ATTR_REPARSE) */
|
||||
/* We no longer handle these as symlinks because we could not
|
||||
follow them due to the absolute path with drive letter */
|
||||
|
@ -340,10 +459,16 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
(pfindData->EndOfFile == 0)) {
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
inode->i_mode |= S_IFIFO;
|
||||
/* BB Finish for SFU style symlinks and devies */
|
||||
/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM) && ) */
|
||||
|
||||
/* BB Finish for SFU style symlinks and devices */
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
|
||||
if (decode_sfu_inode(inode,
|
||||
le64_to_cpu(pfindData->EndOfFile),
|
||||
search_path,
|
||||
cifs_sb, xid)) {
|
||||
cFYI(1,("Unrecognized sfu inode type"));
|
||||
}
|
||||
cFYI(1,("sfu mode 0%o",inode->i_mode));
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG;
|
||||
/* treat the dos attribute of read-only as read-only
|
||||
|
@ -368,7 +493,10 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/* fill in uid, gid, mode from server ACL */
|
||||
get_sfu_uid_mode(inode, search_path, cifs_sb, xid);
|
||||
} else if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
/* set so we do not keep refreshing these fields with
|
||||
|
@ -377,24 +505,29 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
}
|
||||
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
cFYI(1, (" File inode "));
|
||||
cFYI(1, ("File inode"));
|
||||
inode->i_op = &cifs_file_inode_ops;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
else
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop =
|
||||
&cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
inode->i_fop = &cifs_file_direct_ops;
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else /* not direct, send byte range locks */
|
||||
inode->i_fop = &cifs_file_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
inode->i_fop->lock = NULL;
|
||||
|
||||
inode->i_data.a_ops = &cifs_addr_ops;
|
||||
if(pTcon->ses->server->maxBuf <
|
||||
4096 + MAX_CIFS_HDR_SIZE)
|
||||
inode->i_data.a_ops->readpages = NULL;
|
||||
} else if (S_ISDIR(inode->i_mode)) {
|
||||
cFYI(1, (" Directory inode "));
|
||||
cFYI(1, ("Directory inode"));
|
||||
inode->i_op = &cifs_dir_inode_ops;
|
||||
inode->i_fop = &cifs_dir_ops;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
cFYI(1, (" Symbolic Link inode "));
|
||||
cFYI(1, ("Symbolic Link inode"));
|
||||
inode->i_op = &cifs_symlink_inode_ops;
|
||||
} else {
|
||||
init_special_inode(inode, inode->i_mode,
|
||||
|
@ -431,7 +564,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
|||
struct cifsInodeInfo *cifsInode;
|
||||
FILE_BASIC_INFO *pinfo_buf;
|
||||
|
||||
cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
|
||||
cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
|
@ -651,7 +784,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
|||
char *full_path = NULL;
|
||||
struct cifsInodeInfo *cifsInode;
|
||||
|
||||
cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
|
||||
cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
|
||||
|
||||
xid = GetXid();
|
||||
|
||||
|
@ -970,7 +1103,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
|
||||
xid = GetXid();
|
||||
|
||||
cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
|
||||
cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
|
||||
direntry->d_name.name, attrs->ia_valid));
|
||||
cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
|
||||
pTcon = cifs_sb->tcon;
|
||||
|
@ -1086,6 +1219,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
else if (attrs->ia_valid & ATTR_MODE) {
|
||||
rc = 0;
|
||||
if ((mode & S_IWUGO) == 0) /* not writeable */ {
|
||||
if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
|
||||
time_buf.Attributes =
|
||||
|
|
|
@ -678,7 +678,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
|||
__u16 temp;
|
||||
|
||||
if(!mapChars)
|
||||
return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp);
|
||||
return cifs_strtoUCS(target, source, PATH_MAX, cp);
|
||||
|
||||
for(i = 0, j = 0; i < maxlen; j++) {
|
||||
src_char = source[i];
|
||||
|
|
|
@ -142,6 +142,11 @@ static void fill_in_inode(struct inode *tmp_inode,
|
|||
tmp_inode->i_gid = cifs_sb->mnt_gid;
|
||||
/* set default mode. will override for dirs below */
|
||||
tmp_inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
} else {
|
||||
/* mask off the type bits since it gets set
|
||||
below and we do not want to get two type
|
||||
bits set */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
}
|
||||
|
||||
if (attr & ATTR_DIRECTORY) {
|
||||
|
@ -152,12 +157,18 @@ static void fill_in_inode(struct inode *tmp_inode,
|
|||
}
|
||||
tmp_inode->i_mode |= S_IFDIR;
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(attr & ATTR_SYSTEM) && (end_of_file == 0)) {
|
||||
*pobject_type = DT_FIFO;
|
||||
tmp_inode->i_mode |= S_IFIFO;
|
||||
/* BB Finish for SFU style symlinks and devies */
|
||||
/* } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(attr & ATTR_SYSTEM) && ) { */
|
||||
(attr & ATTR_SYSTEM)) {
|
||||
if (end_of_file == 0) {
|
||||
*pobject_type = DT_FIFO;
|
||||
tmp_inode->i_mode |= S_IFIFO;
|
||||
} else {
|
||||
/* rather than get the type here, we mark the
|
||||
inode as needing revalidate and get the real type
|
||||
(blk vs chr vs. symlink) later ie in lookup */
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cifsInfo->time = 0;
|
||||
}
|
||||
/* we no longer mark these because we could not follow them */
|
||||
/* } else if (attr & ATTR_REPARSE) {
|
||||
*pobject_type = DT_LNK;
|
||||
|
@ -193,8 +204,14 @@ static void fill_in_inode(struct inode *tmp_inode,
|
|||
if (S_ISREG(tmp_inode->i_mode)) {
|
||||
cFYI(1, ("File inode"));
|
||||
tmp_inode->i_op = &cifs_file_inode_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) {
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_direct_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_direct_ops;
|
||||
|
||||
} else if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
tmp_inode->i_fop = &cifs_file_nobrl_ops;
|
||||
else
|
||||
tmp_inode->i_fop = &cifs_file_ops;
|
||||
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
|
||||
|
@ -258,6 +275,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
|
||||
|
||||
tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
|
||||
/* since we set the inode type below we need to mask off type
|
||||
to avoid strange results if bits above were corrupt */
|
||||
tmp_inode->i_mode &= ~S_IFMT;
|
||||
if (type == UNIX_FILE) {
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
|
@ -283,6 +303,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
|
|||
} else if (type == UNIX_SOCKET) {
|
||||
*pobject_type = DT_SOCK;
|
||||
tmp_inode->i_mode |= S_IFSOCK;
|
||||
} else {
|
||||
/* safest to just call it a file */
|
||||
*pobject_type = DT_REG;
|
||||
tmp_inode->i_mode |= S_IFREG;
|
||||
cFYI(1,("unknown inode type %d",type));
|
||||
}
|
||||
|
||||
tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);
|
||||
|
@ -699,7 +724,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
|
|||
(__le16 *)filename, len/2, nlt);
|
||||
else
|
||||
pqst->len = cifs_strfromUCS_le((char *)pqst->name,
|
||||
(wchar_t *)filename,len/2,nlt);
|
||||
(__le16 *)filename,len/2,nlt);
|
||||
} else {
|
||||
pqst->name = filename;
|
||||
pqst->len = len;
|
||||
|
|
|
@ -522,7 +522,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
(2 * in_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(in_buf) = le16_to_cpu(BCC(in_buf));
|
||||
BCC(in_buf) = le16_to_cpu(BCC_LE(in_buf));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cFYI(1,("Bad MID state?"));
|
||||
|
@ -786,7 +786,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
|
|||
sizeof (struct smb_hdr) -
|
||||
4 /* do not count RFC1001 header */ +
|
||||
(2 * out_buf->WordCount) + 2 /* bcc */ )
|
||||
BCC(out_buf) = le16_to_cpu(BCC(out_buf));
|
||||
BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
|
||||
} else {
|
||||
rc = -EIO;
|
||||
cERROR(1,("Bad MID state? "));
|
||||
|
|
Loading…
Reference in New Issue