Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion drivers/gpu/drm/drm_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
if (!state->planes)
goto fail;

/*
* Because drm_atomic_state can be committed asynchronously we need our
* own reference and cannot rely on the on implied by drm_file in the
* ioctl call.
*/
drm_dev_get(dev);
state->dev = dev;

DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
Expand Down Expand Up @@ -297,7 +303,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
void __drm_atomic_state_free(struct kref *ref)
{
struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
struct drm_mode_config *config = &state->dev->mode_config;
struct drm_device *dev = state->dev;
struct drm_mode_config *config = &dev->mode_config;

drm_atomic_state_clear(state);

Expand All @@ -309,6 +316,8 @@ void __drm_atomic_state_free(struct kref *ref)
drm_atomic_state_default_release(state);
kfree(state);
}

drm_dev_put(dev);
}
EXPORT_SYMBOL(__drm_atomic_state_free);

Expand Down
70 changes: 69 additions & 1 deletion fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
#include <linux/mm.h>
#include <linux/mempool.h>
#include <linux/workqueue.h>
#include "cifs_fs_sb.h"
#include "cifsacl.h"
#include <crypto/internal/hash.h>
#include <linux/scatterlist.h>
#include <uapi/linux/cifs/cifs_mount.h>
#include "smb2pdu.h"
#include "smb2glob.h"

#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */

Expand Down Expand Up @@ -1959,4 +1961,70 @@ static inline bool is_tcon_dfs(struct cifs_tcon *tcon)
tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT);
}

static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst,
int num_rqst,
const u8 *sig)
{
unsigned int len, skip;
unsigned int nents = 0;
unsigned long addr;
int i, j;

/* Assumes the first rqst has a transform header as the first iov.
* I.e.
* rqst[0].rq_iov[0] is transform header
* rqst[0].rq_iov[1+] data to be encrypted/decrypted
* rqst[1+].rq_iov[0+] data to be encrypted/decrypted
*/
for (i = 0; i < num_rqst; i++) {
/*
* The first rqst has a transform header where the
* first 20 bytes are not part of the encrypted blob.
*/
for (j = 0; j < rqst[i].rq_nvec; j++) {
struct kvec *iov = &rqst[i].rq_iov[j];

skip = (i == 0) && (j == 0) ? 20 : 0;
addr = (unsigned long)iov->iov_base + skip;
if (unlikely(is_vmalloc_addr((void *)addr))) {
len = iov->iov_len - skip;
nents += DIV_ROUND_UP(offset_in_page(addr) + len,
PAGE_SIZE);
} else {
nents++;
}
}
nents += rqst[i].rq_npages;
}
nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE);
return nents;
}

/* We can not use the normal sg_set_buf() as we will sometimes pass a
* stack object as buf.
*/
static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg,
const void *buf,
unsigned int buflen)
{
unsigned long addr = (unsigned long)buf;
unsigned int off = offset_in_page(addr);

addr &= PAGE_MASK;
if (unlikely(is_vmalloc_addr((void *)addr))) {
do {
unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off);

sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off);

off = 0;
addr += PAGE_SIZE;
buflen -= len;
} while (buflen);
} else {
sg_set_page(sg++, virt_to_page(addr), buflen, off);
}
return sg;
}

#endif /* _CIFS_GLOB_H */
4 changes: 2 additions & 2 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -595,8 +595,8 @@ int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
struct sdesc **sdesc);
void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);

extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset);
void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset);
struct cifs_chan *
cifs_ses_find_chan(struct cifs_ses *ses, struct TCP_Server_Info *server);
int cifs_try_adding_channels(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
Expand Down
8 changes: 6 additions & 2 deletions fs/cifs/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server)
cifs_dbg(VFS, "Length less than smb header size\n");
}
return -EIO;
} else if (total_read < sizeof(*smb) + 2 * smb->WordCount) {
cifs_dbg(VFS, "%s: can't read BCC due to invalid WordCount(%u)\n",
__func__, smb->WordCount);
return -EIO;
}

/* otherwise, there is enough to get to the BCC */
Expand Down Expand Up @@ -976,8 +980,8 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
* Input: rqst - a smb_rqst, page - a page index for rqst
* Output: *len - the length for this page, *offset - the offset for this page
*/
void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset)
void rqst_page_get_length(const struct smb_rqst *rqst, unsigned int page,
unsigned int *len, unsigned int *offset)
{
*len = rqst->rq_pagesz;
*offset = (page == 0) ? rqst->rq_offset : 0;
Expand Down
30 changes: 15 additions & 15 deletions fs/cifs/smb2misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,21 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
}

mid = le64_to_cpu(shdr->MessageId);
if (check_smb2_hdr(shdr, mid))
return 1;

if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
cifs_dbg(VFS, "Invalid structure size %u\n",
le16_to_cpu(shdr->StructureSize));
return 1;
}

command = le16_to_cpu(shdr->Command);
if (command >= NUMBER_OF_SMB2_COMMANDS) {
cifs_dbg(VFS, "Invalid SMB2 command %d\n", command);
return 1;
}

if (len < pdu_size) {
if ((len >= hdr_size)
&& (shdr->Status != 0)) {
Expand All @@ -186,21 +201,6 @@ smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
return 1;
}

if (check_smb2_hdr(shdr, mid))
return 1;

if (shdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
cifs_dbg(VFS, "Invalid structure size %u\n",
le16_to_cpu(shdr->StructureSize));
return 1;
}

command = le16_to_cpu(shdr->Command);
if (command >= NUMBER_OF_SMB2_COMMANDS) {
cifs_dbg(VFS, "Invalid SMB2 command %d\n", command);
return 1;
}

if (smb2_rsp_struct_sizes[command] != pdu->StructureSize2) {
if (command != SMB2_OPLOCK_BREAK_HE && (shdr->Status == 0 ||
pdu->StructureSize2 != SMB2_ERROR_STRUCTURE_SIZE2)) {
Expand Down
Loading
Loading