Commit 4b1fefac authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6:
  When verifying the decoded header before decoding the object identifier
  [CIFS] Fix warnings from checkpatch
  [CIFS] Fix improper endian conversion of ACL subauth field
  [CIFS] Fix possible double free if search immediately after search rewind fails
  [CIFS] remove checkpatch warning
Signed-off-by: default avatarAlexey Dobriyan <adobriyan@gmail.com>
  cifs: assorted endian annotations
  [CIFS] break ATTR_SIZE changes out into their own function
  lockdep: annotate cifs in-kernel sockets
  [CIFS] Fix compiler warning on 64-bit
parents 6ca813c4 e2d2867f
...@@ -400,7 +400,7 @@ asn1_oid_decode(struct asn1_ctx *ctx, ...@@ -400,7 +400,7 @@ asn1_oid_decode(struct asn1_ctx *ctx,
size = eoc - ctx->pointer + 1; size = eoc - ctx->pointer + 1;
/* first subid actually encodes first two subids */ /* first subid actually encodes first two subids */
if (size < 2 || size > ULONG_MAX/sizeof(unsigned long)) if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
return 0; return 0;
*oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC); *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
...@@ -494,7 +494,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, ...@@ -494,7 +494,7 @@ decode_negTokenInit(unsigned char *security_blob, int length,
/* remember to free obj->oid */ /* remember to free obj->oid */
rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag);
if (rc) { if (rc) {
if ((tag == ASN1_OJI) && (cls == ASN1_PRI)) { if ((tag == ASN1_OJI) && (con == ASN1_PRI)) {
rc = asn1_oid_decode(&ctx, end, &oid, &oidlen); rc = asn1_oid_decode(&ctx, end, &oid, &oidlen);
if (rc) { if (rc) {
rc = compare_oid(oid, oidlen, rc = compare_oid(oid, oidlen,
......
This diff is collapsed.
...@@ -56,7 +56,7 @@ int match_sid(struct cifs_sid *ctsid) ...@@ -56,7 +56,7 @@ int match_sid(struct cifs_sid *ctsid)
struct cifs_sid *cwsid; struct cifs_sid *cwsid;
if (!ctsid) if (!ctsid)
return (-1); return -1;
for (i = 0; i < NUM_WK_SIDS; ++i) { for (i = 0; i < NUM_WK_SIDS; ++i) {
cwsid = &(wksidarr[i].cifssid); cwsid = &(wksidarr[i].cifssid);
...@@ -87,11 +87,11 @@ int match_sid(struct cifs_sid *ctsid) ...@@ -87,11 +87,11 @@ int match_sid(struct cifs_sid *ctsid)
} }
cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname)); cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
return (0); /* sids compare/match */ return 0; /* sids compare/match */
} }
cFYI(1, ("No matching sid")); cFYI(1, ("No matching sid"));
return (-1); return -1;
} }
/* if the two SIDs (roughly equivalent to a UUID for a user or group) are /* if the two SIDs (roughly equivalent to a UUID for a user or group) are
...@@ -102,16 +102,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) ...@@ -102,16 +102,16 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
int num_subauth, num_sat, num_saw; int num_subauth, num_sat, num_saw;
if ((!ctsid) || (!cwsid)) if ((!ctsid) || (!cwsid))
return (0); return 0;
/* compare the revision */ /* compare the revision */
if (ctsid->revision != cwsid->revision) if (ctsid->revision != cwsid->revision)
return (0); return 0;
/* compare all of the six auth values */ /* compare all of the six auth values */
for (i = 0; i < 6; ++i) { for (i = 0; i < 6; ++i) {
if (ctsid->authority[i] != cwsid->authority[i]) if (ctsid->authority[i] != cwsid->authority[i])
return (0); return 0;
} }
/* compare all of the subauth values if any */ /* compare all of the subauth values if any */
...@@ -121,11 +121,11 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) ...@@ -121,11 +121,11 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
if (num_subauth) { if (num_subauth) {
for (i = 0; i < num_subauth; ++i) { for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
return (0); return 0;
} }
} }
return (1); /* sids compare/match */ return 1; /* sids compare/match */
} }
...@@ -169,8 +169,7 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, ...@@ -169,8 +169,7 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
ngroup_sid_ptr->sub_auth[i] = ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
cpu_to_le32(group_sid_ptr->sub_auth[i]);
return; return;
} }
...@@ -285,7 +284,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace, ...@@ -285,7 +284,7 @@ static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4); size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
pntace->size = cpu_to_le16(size); pntace->size = cpu_to_le16(size);
return (size); return size;
} }
...@@ -426,7 +425,7 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid, ...@@ -426,7 +425,7 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl)); pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
pndacl->num_aces = cpu_to_le32(3); pndacl->num_aces = cpu_to_le32(3);
return (0); return 0;
} }
...@@ -510,7 +509,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, ...@@ -510,7 +509,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
sizeof(struct cifs_sid)); */ sizeof(struct cifs_sid)); */
return (0); return 0;
} }
...@@ -527,7 +526,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, ...@@ -527,7 +526,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL)) if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL))
return (-EIO); return -EIO;
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
le32_to_cpu(pntsd->osidoffset)); le32_to_cpu(pntsd->osidoffset));
...@@ -550,7 +549,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, ...@@ -550,7 +549,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
/* copy security descriptor control portion and owner and group sid */ /* copy security descriptor control portion and owner and group sid */
copy_sec_desc(pntsd, pnntsd, sidsoffset); copy_sec_desc(pntsd, pnntsd, sidsoffset);
return (rc); return rc;
} }
...@@ -629,11 +628,11 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ...@@ -629,11 +628,11 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode));
if (!inode) if (!inode)
return (rc); return rc;
sb = inode->i_sb; sb = inode->i_sb;
if (sb == NULL) if (sb == NULL)
return (rc); return rc;
cifs_sb = CIFS_SB(sb); cifs_sb = CIFS_SB(sb);
xid = GetXid(); xid = GetXid();
...@@ -652,7 +651,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ...@@ -652,7 +651,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
if (rc != 0) { if (rc != 0) {
cERROR(1, ("Unable to open file to set ACL")); cERROR(1, ("Unable to open file to set ACL"));
FreeXid(xid); FreeXid(xid);
return (rc); return rc;
} }
} }
...@@ -665,7 +664,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, ...@@ -665,7 +664,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
FreeXid(xid); FreeXid(xid);
return (rc); return rc;
} }
/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
...@@ -715,7 +714,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) ...@@ -715,7 +714,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
if (!pnntsd) { if (!pnntsd) {
cERROR(1, ("Unable to allocate security descriptor")); cERROR(1, ("Unable to allocate security descriptor"));
kfree(pntsd); kfree(pntsd);
return (-ENOMEM); return -ENOMEM;
} }
rc = build_sec_desc(pntsd, pnntsd, inode, nmode); rc = build_sec_desc(pntsd, pnntsd, inode, nmode);
...@@ -732,6 +731,6 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) ...@@ -732,6 +731,6 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode)
kfree(pntsd); kfree(pntsd);
} }
return (rc); return rc;
} }
#endif /* CONFIG_CIFS_EXPERIMENTAL */ #endif /* CONFIG_CIFS_EXPERIMENTAL */
...@@ -310,9 +310,8 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key) ...@@ -310,9 +310,8 @@ void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key)
utf8 and other multibyte codepages each need their own strupper utf8 and other multibyte codepages each need their own strupper
function since a byte at a time will ont work. */ function since a byte at a time will ont work. */
for (i = 0; i < CIFS_ENCPWD_SIZE; i++) { for (i = 0; i < CIFS_ENCPWD_SIZE; i++)
password_with_pad[i] = toupper(password_with_pad[i]); password_with_pad[i] = toupper(password_with_pad[i]);
}
SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key); SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
/* clear password before we return/free memory */ /* clear password before we return/free memory */
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#define MAX_SES_INFO 2 #define MAX_SES_INFO 2
#define MAX_TCON_INFO 4 #define MAX_TCON_INFO 4
#define MAX_TREE_SIZE 2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1 #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
#define MAX_SERVER_SIZE 15 #define MAX_SERVER_SIZE 15
#define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */ #define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */
#define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null #define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null
...@@ -537,8 +537,8 @@ require use of the stronger protocol */ ...@@ -537,8 +537,8 @@ require use of the stronger protocol */
#endif /* WEAK_PW_HASH */ #endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */ #define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
#define CIFSSEC_DEF CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 #define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2)
#define CIFSSEC_MAX CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2 #define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5) #define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
/* /*
***************************************************************** *****************************************************************
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#else #else
#define CIFS_PROT 0 #define CIFS_PROT 0
#endif #endif
#define POSIX_PROT CIFS_PROT+1 #define POSIX_PROT (CIFS_PROT+1)
#define BAD_PROT 0xFFFF #define BAD_PROT 0xFFFF
/* SMB command codes */ /* SMB command codes */
...@@ -341,7 +341,7 @@ ...@@ -341,7 +341,7 @@
#define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */ #define CREATE_COMPLETE_IF_OPLK 0x00000100 /* should be zero */
#define CREATE_NO_EA_KNOWLEDGE 0x00000200 #define CREATE_NO_EA_KNOWLEDGE 0x00000200
#define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete #define CREATE_EIGHT_DOT_THREE 0x00000400 /* doc says this is obsolete
"open for recovery" flag - should "open for recovery" flag should
be zero in any case */ be zero in any case */
#define CREATE_OPEN_FOR_RECOVERY 0x00000400 #define CREATE_OPEN_FOR_RECOVERY 0x00000400
#define CREATE_RANDOM_ACCESS 0x00000800 #define CREATE_RANDOM_ACCESS 0x00000800
...@@ -414,8 +414,8 @@ struct smb_hdr { ...@@ -414,8 +414,8 @@ struct smb_hdr {
__u8 WordCount; __u8 WordCount;
} __attribute__((packed)); } __attribute__((packed));
/* given a pointer to an smb_hdr retrieve the value of byte count */ /* given a pointer to an smb_hdr retrieve the value of byte count */
#define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) #define BCC(smb_var) (*(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) #define BCC_LE(smb_var) (*(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount)))
/* given a pointer to an smb_hdr retrieve the pointer to the byte area */ /* given a pointer to an smb_hdr retrieve the pointer to the byte area */
#define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2) #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2)
......
...@@ -686,11 +686,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -686,11 +686,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
SecurityBlob, SecurityBlob,
count - 16, count - 16,
&server->secType); &server->secType);
if (rc == 1) { if (rc == 1)
rc = 0; rc = 0;
} else { else
rc = -EINVAL; rc = -EINVAL;
}
} }
} else } else
server->capabilities &= ~CAP_EXTENDED_SECURITY; server->capabilities &= ~CAP_EXTENDED_SECURITY;
...@@ -3914,7 +3913,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, ...@@ -3914,7 +3913,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
bool is_unicode; bool is_unicode;
struct dfs_referral_level_3 *ref; struct dfs_referral_level_3 *ref;
is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE; if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
is_unicode = true;
else
is_unicode = false;
*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
if (*num_of_nodes < 1) { if (*num_of_nodes < 1) {
......
...@@ -455,7 +455,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) ...@@ -455,7 +455,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
/* Note that FC 1001 length is big endian on the wire, /* Note that FC 1001 length is big endian on the wire,
but we convert it here so it is always manipulated but we convert it here so it is always manipulated
as host byte order */ as host byte order */
pdu_length = ntohl(smb_buffer->smb_buf_length); pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length);
smb_buffer->smb_buf_length = pdu_length; smb_buffer->smb_buf_length = pdu_length;
cFYI(1, ("rfc1002 length 0x%x", pdu_length+4)); cFYI(1, ("rfc1002 length 0x%x", pdu_length+4));
...@@ -1461,6 +1461,39 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, ...@@ -1461,6 +1461,39 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
return rc; return rc;
} }
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key cifs_key[2];
static struct lock_class_key cifs_slock_key[2];
static inline void
cifs_reclassify_socket4(struct socket *sock)
{
struct sock *sk = sock->sk;
BUG_ON(sock_owned_by_user(sk));
sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
}
static inline void
cifs_reclassify_socket6(struct socket *sock)
{
struct sock *sk = sock->sk;
BUG_ON(sock_owned_by_user(sk));
sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
}
#else
static inline void
cifs_reclassify_socket4(struct socket *sock)
{
}
static inline void
cifs_reclassify_socket6(struct socket *sock)
{
}
#endif
/* See RFC1001 section 14 on representation of Netbios names */ /* See RFC1001 section 14 on representation of Netbios names */
static void rfc1002mangle(char *target, char *source, unsigned int length) static void rfc1002mangle(char *target, char *source, unsigned int length)
{ {
...@@ -1495,6 +1528,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, ...@@ -1495,6 +1528,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket,
/* BB other socket options to set KEEPALIVE, NODELAY? */ /* BB other socket options to set KEEPALIVE, NODELAY? */
cFYI(1, ("Socket created")); cFYI(1, ("Socket created"));
(*csocket)->sk->sk_allocation = GFP_NOFS; (*csocket)->sk->sk_allocation = GFP_NOFS;
cifs_reclassify_socket4(*csocket);
} }
} }
...@@ -1627,6 +1661,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) ...@@ -1627,6 +1661,7 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket)
/* BB other socket options to set KEEPALIVE, NODELAY? */ /* BB other socket options to set KEEPALIVE, NODELAY? */
cFYI(1, ("ipv6 Socket created")); cFYI(1, ("ipv6 Socket created"));
(*csocket)->sk->sk_allocation = GFP_NOFS; (*csocket)->sk->sk_allocation = GFP_NOFS;
cifs_reclassify_socket6(*csocket);
} }
} }
......
...@@ -1413,6 +1413,82 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset) ...@@ -1413,6 +1413,82 @@ static int cifs_vmtruncate(struct inode *inode, loff_t offset)
return -ETXTBSY; return -ETXTBSY;
} }
static int
cifs_set_file_size(struct inode *inode, struct iattr *attrs,
int xid, char *full_path)
{
int rc;
struct cifsFileInfo *open_file;
struct cifsInodeInfo *cifsInode = CIFS_I(inode);
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct cifsTconInfo *pTcon = cifs_sb->tcon;
/*
* 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.
* This keeps our caching token (oplock) and avoids timeouts
* when the local oplock break takes longer to flush
* writebehind data than the SMB timeout for the SetPathInfo
* request would allow
*/
open_file = find_writable_file(cifsInode);
if (open_file) {
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
npid, false);
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL, 1);
cFYI(1, ("Wrt seteof rc %d", rc));
}
} else
rc = -EINVAL;
if (rc != 0) {
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size,
false, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = 0;
rc = SMBLegacyOpen(xid, pTcon, full_path,
FILE_OPEN, GENERIC_WRITE,
CREATE_NOT_DIR, &netfid, &oplock, NULL,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
attrs->ia_size,
&bytes_written, NULL,
NULL, 1);
cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid);
}
}
}
if (rc == 0) {
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
}
return rc;
}
int cifs_setattr(struct dentry *direntry, struct iattr *attrs) int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
{ {
int xid; int xid;
...@@ -1420,7 +1496,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1420,7 +1496,6 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
char *full_path = NULL; char *full_path = NULL;
int rc = -EACCES; int rc = -EACCES;
struct cifsFileInfo *open_file = NULL;
FILE_BASIC_INFO time_buf; FILE_BASIC_INFO time_buf;
bool set_time = false; bool set_time = false;
bool set_dosattr = false; bool set_dosattr = false;
...@@ -1472,78 +1547,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) ...@@ -1472,78 +1547,8 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
} }
if (attrs->ia_valid & ATTR_SIZE) { if (attrs->ia_valid & ATTR_SIZE) {
/* To avoid spurious oplock breaks from server, in the case of rc = cifs_set_file_size(inode, attrs, xid, full_path);
inodes that we already have open, avoid doing path based if (rc != 0)
setting of file size if we can do it by handle.
This keeps our caching token (oplock) and avoids timeouts
when the local oplock break takes longer to flush
writebehind data than the SMB timeout for the SetPathInfo
request would allow */
open_file = find_writable_file(cifsInode);
if (open_file) {
__u16 nfid = open_file->netfid;
__u32 npid = open_file->pid;
rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size,
nfid, npid, false);
atomic_dec(&open_file->wrtPending);
cFYI(1, ("SetFSize for attrs rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
nfid, 0, attrs->ia_size,
&bytes_written, NULL, NULL,
1 /* 45 seconds */);
cFYI(1, ("Wrt seteof rc %d", rc));
}
} else
rc = -EINVAL;
if (rc != 0) {
/* Set file size by pathname rather than by handle
either because no valid, writeable file handle for
it was found or because there was an error setting
it by handle */
rc = CIFSSMBSetEOF(xid, pTcon, full_path,
attrs->ia_size, false,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
__u16 netfid;
int oplock = 0;
rc = SMBLegacyOpen(xid, pTcon, full_path,
FILE_OPEN, GENERIC_WRITE,
CREATE_NOT_DIR, &netfid, &oplock,
NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == 0) {
unsigned int bytes_written;
rc = CIFSSMBWrite(xid, pTcon,
netfid, 0,
attrs->ia_size,
&bytes_written, NULL,
NULL, 1 /* 45 sec */);
cFYI(1, ("wrt seteof rc %d", rc));
CIFSSMBClose(xid, pTcon, netfid);
}
}
}
/* Server is ok setting allocation size implicitly - no need
to call:
CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, true,
cifs_sb->local_nls);
*/
if (rc == 0) {
rc = cifs_vmtruncate(inode, attrs->ia_size);
cifs_truncate_page(inode->i_mapping, inode->i_size);
} else
goto cifs_setattr_exit; goto cifs_setattr_exit;
} }
......
...@@ -690,6 +690,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, ...@@ -690,6 +690,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
else else
cifs_buf_release(cifsFile->srch_inf. cifs_buf_release(cifsFile->srch_inf.
ntwrk_buf_start); ntwrk_buf_start);
cifsFile->srch_inf.ntwrk_buf_start = NULL;
} }
rc = initiate_cifs_search(xid, file); rc = initiate_cifs_search(xid, file);
if (rc) { if (rc) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment