X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fcifs%2Fmisc.c;h=c79d8f707771cb87331e7ad0bfadb95d83b4e9e6;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=ca96ffe2c80e67f7c70d66dd8443eb27c5a90d4b;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index ca96ffe2c..c79d8f707 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -1,7 +1,7 @@ /* * fs/cifs/misc.c * - * Copyright (C) International Business Machines Corp., 2002,2003 + * Copyright (C) International Business Machines Corp., 2002,2004 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include #include +#include #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" @@ -28,7 +29,8 @@ #include "smberr.h" #include "nterr.h" -extern kmem_cache_t *cifs_req_cachep; +extern mempool_t *cifs_sm_req_poolp; +extern mempool_t *cifs_req_poolp; extern struct task_struct * oplockThread; __u16 GlobalMid; /* multiplex id - rotating counter */ @@ -122,6 +124,9 @@ tconInfoAlloc(void) ret_buf->tidStatus = CifsNew; INIT_LIST_HEAD(&ret_buf->openFileList); init_MUTEX(&ret_buf->tconSem); +#ifdef CONFIG_CIFS_STATS + spin_lock_init(&ret_buf->stat_lock); +#endif write_unlock(&GlobalSMBSeslock); } return ret_buf; @@ -146,18 +151,19 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) struct smb_hdr * cifs_buf_get(void) { - struct smb_hdr *ret_buf = 0; + struct smb_hdr *ret_buf = NULL; /* We could use negotiated size instead of max_msgsize - but it may be more efficient to always alloc same size albeit slightly larger than necessary and maxbuffersize defaults to this and can not be bigger */ ret_buf = - (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL | SLAB_NOFS); + (struct smb_hdr *) mempool_alloc(cifs_req_poolp, SLAB_KERNEL | SLAB_NOFS); /* clear the first few header bytes */ + /* for most paths, more is cleared in header_assemble */ if (ret_buf) { - memset(ret_buf, 0, sizeof (struct smb_hdr)); + memset(ret_buf, 0, sizeof(struct smb_hdr) + 3); atomic_inc(&bufAllocCount); } @@ -169,30 +175,58 @@ cifs_buf_release(void *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("Null buffer passed to cifs_buf_release")); + /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ return; } - kmem_cache_free(cifs_req_cachep, buf_to_free); + mempool_free(buf_to_free,cifs_req_poolp); atomic_dec(&bufAllocCount); return; } +struct smb_hdr * +cifs_small_buf_get(void) +{ + struct smb_hdr *ret_buf = NULL; + +/* We could use negotiated size instead of max_msgsize - + but it may be more efficient to always alloc same size + albeit slightly larger than necessary and maxbuffersize + defaults to this and can not be bigger */ + ret_buf = + (struct smb_hdr *) mempool_alloc(cifs_sm_req_poolp, SLAB_KERNEL | SLAB_NOFS); + if (ret_buf) { + /* No need to clear memory here, cleared in header assemble */ + /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ + atomic_inc(&smBufAllocCount); + } + return ret_buf; +} + +void +cifs_small_buf_release(void *buf_to_free) +{ + + if (buf_to_free == NULL) { + cFYI(1, ("Null buffer passed to cifs_small_buf_release")); + return; + } + mempool_free(buf_to_free,cifs_sm_req_poolp); + + atomic_dec(&smBufAllocCount); + return; +} + void header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , const struct cifsTconInfo *treeCon, int word_count - /* length of fixed section (word count) in two byte units */ - ) + /* length of fixed section (word count) in two byte units */) { - int i; - __u32 tmp; struct list_head* temp_item; struct cifsSesInfo * ses; char *temp = (char *) buffer; - for (i = 0; i < MAX_CIFS_HDR_SIZE; i++) { - temp[i] = 0; /* BB is this needed ?? */ - } + memset(temp,0,MAX_CIFS_HDR_SIZE); buffer->smb_buf_length = (2 * word_count) + sizeof (struct smb_hdr) - @@ -207,10 +241,8 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , buffer->Command = smb_command; buffer->Flags = 0x00; /* case sensitive */ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; - tmp = cpu_to_le32(current->tgid); - buffer->Pid = tmp & 0xFFFF; - tmp >>= 16; - buffer->PidHigh = tmp & 0xFFFF; + buffer->Pid = cpu_to_le16((__u16)current->tgid); + buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); spin_lock(&GlobalMid_Lock); GlobalMid++; buffer->Mid = GlobalMid; @@ -272,7 +304,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , } if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) buffer->Flags2 |= SMBFLG2_DFS; - if(treeCon->ses->server) + if((treeCon->ses) && (treeCon->ses->server)) if(treeCon->ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; @@ -288,7 +320,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) { /* Make sure that this really is an SMB, that it is a response, and that the message ids match */ - if ((*(unsigned int *) smb->Protocol == cpu_to_le32(0x424d53ff)) && + if ((*(__le32 *) smb->Protocol == cpu_to_le32(0x424d53ff)) && (mid == smb->Mid)) { if(smb->Flags & SMBFLG_RESPONSE) return 0; @@ -300,7 +332,7 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) cERROR(1, ("Rcvd Request not response ")); } } else { /* bad signature or mid */ - if (*(unsigned int *) smb->Protocol != cpu_to_le32(0x424d53ff)) + if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) cERROR(1, ("Bad protocol string signature header %x ", *(unsigned int *) smb->Protocol)); @@ -314,12 +346,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) int checkSMB(struct smb_hdr *smb, __u16 mid, int length) { + __u32 len = be32_to_cpu(smb->smb_buf_length); cFYI(0, ("Entering checkSMB with Length: %x, smb_buf_length: %x ", - length, ntohl(smb->smb_buf_length))); - if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) - || (ntohl(smb->smb_buf_length) > - CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4)) { + length, len)); + if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || + (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { if ((unsigned int)length < 2 + sizeof (struct smb_hdr)) { cERROR(1, ("Length less than 2 + sizeof smb_hdr ")); if (((unsigned int)length >= sizeof (struct smb_hdr) - 1) @@ -327,10 +359,9 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) return 0; /* some error cases do not return wct and bcc */ } - if (ntohl(smb->smb_buf_length) > - CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) cERROR(1, - ("smb_buf_length greater than CIFS_MAX_MSGSIZE ... ")); + ("smb_buf_length greater than MaxBufSize")); cERROR(1, ("bad smb detected. Illegal length. The mid=%d", smb->Mid)); @@ -340,8 +371,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) if (checkSMBhdr(smb, mid)) return 1; - if ((4 + ntohl(smb->smb_buf_length) != smbCalcSize(smb)) - || (4 + ntohl(smb->smb_buf_length) != (unsigned int)length)) { + if ((4 + len != smbCalcSize(smb)) + || (4 + len != (unsigned int)length)) { return 0; } else { cERROR(1, ("smbCalcSize %x ", smbCalcSize(smb))); @@ -359,8 +390,29 @@ is_valid_oplock_break(struct smb_hdr *buf) struct cifsTconInfo *tcon; struct cifsFileInfo *netfile; - /* could add check for smb response flag 0x80 */ - cFYI(1,("Checking for oplock break")); + cFYI(1,("Checking for oplock break or dnotify response")); + if((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && + (pSMB->hdr.Flags & SMBFLG_RESPONSE)) { + struct smb_com_transaction_change_notify_rsp * pSMBr = + (struct smb_com_transaction_change_notify_rsp *)buf; + struct file_notify_information * pnotify; + __u32 data_offset = 0; + if(pSMBr->ByteCount > sizeof(struct file_notify_information)) { + data_offset = le32_to_cpu(pSMBr->DataOffset); + + pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol + + data_offset); + cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName, + pnotify->Action)); /* BB removeme BB */ + /* cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */ + return TRUE; + } + if(pSMBr->hdr.Status.CifsError) { + cFYI(1,("notify err 0x%d",pSMBr->hdr.Status.CifsError)); + return TRUE; + } + return FALSE; + } if(pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) return FALSE; if(pSMB->hdr.Flags & SMBFLG_RESPONSE) { @@ -391,6 +443,9 @@ is_valid_oplock_break(struct smb_hdr *buf) list_for_each(tmp, &GlobalTreeConnectionList) { tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); if (tcon->tid == buf->Tid) { +#ifdef CONFIG_CIFS_STATS + atomic_inc(&tcon->num_oplock_brks); +#endif list_for_each(tmp1,&tcon->openFileList){ netfile = list_entry(tmp1,struct cifsFileInfo,tlist); if(pSMB->Fid == netfile->netfid) {