.. | .. |
---|
22 | 22 | #include <linux/in.h> |
---|
23 | 23 | #include <linux/in6.h> |
---|
24 | 24 | #include <linux/slab.h> |
---|
| 25 | +#include <linux/scatterlist.h> |
---|
| 26 | +#include <linux/mm.h> |
---|
25 | 27 | #include <linux/mempool.h> |
---|
26 | 28 | #include <linux/workqueue.h> |
---|
27 | 29 | #include "cifs_fs_sb.h" |
---|
.. | .. |
---|
30 | 32 | #include <linux/scatterlist.h> |
---|
31 | 33 | #include <uapi/linux/cifs/cifs_mount.h> |
---|
32 | 34 | #include "smb2pdu.h" |
---|
| 35 | +#include "smb2glob.h" |
---|
33 | 36 | |
---|
34 | 37 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ |
---|
35 | 38 | |
---|
.. | .. |
---|
2046 | 2049 | tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT); |
---|
2047 | 2050 | } |
---|
2048 | 2051 | |
---|
| 2052 | +static inline unsigned int cifs_get_num_sgs(const struct smb_rqst *rqst, |
---|
| 2053 | + int num_rqst, |
---|
| 2054 | + const u8 *sig) |
---|
| 2055 | +{ |
---|
| 2056 | + unsigned int len, skip; |
---|
| 2057 | + unsigned int nents = 0; |
---|
| 2058 | + unsigned long addr; |
---|
| 2059 | + int i, j; |
---|
| 2060 | + |
---|
| 2061 | + /* Assumes the first rqst has a transform header as the first iov. |
---|
| 2062 | + * I.e. |
---|
| 2063 | + * rqst[0].rq_iov[0] is transform header |
---|
| 2064 | + * rqst[0].rq_iov[1+] data to be encrypted/decrypted |
---|
| 2065 | + * rqst[1+].rq_iov[0+] data to be encrypted/decrypted |
---|
| 2066 | + */ |
---|
| 2067 | + for (i = 0; i < num_rqst; i++) { |
---|
| 2068 | + /* |
---|
| 2069 | + * The first rqst has a transform header where the |
---|
| 2070 | + * first 20 bytes are not part of the encrypted blob. |
---|
| 2071 | + */ |
---|
| 2072 | + for (j = 0; j < rqst[i].rq_nvec; j++) { |
---|
| 2073 | + struct kvec *iov = &rqst[i].rq_iov[j]; |
---|
| 2074 | + |
---|
| 2075 | + skip = (i == 0) && (j == 0) ? 20 : 0; |
---|
| 2076 | + addr = (unsigned long)iov->iov_base + skip; |
---|
| 2077 | + if (unlikely(is_vmalloc_addr((void *)addr))) { |
---|
| 2078 | + len = iov->iov_len - skip; |
---|
| 2079 | + nents += DIV_ROUND_UP(offset_in_page(addr) + len, |
---|
| 2080 | + PAGE_SIZE); |
---|
| 2081 | + } else { |
---|
| 2082 | + nents++; |
---|
| 2083 | + } |
---|
| 2084 | + } |
---|
| 2085 | + nents += rqst[i].rq_npages; |
---|
| 2086 | + } |
---|
| 2087 | + nents += DIV_ROUND_UP(offset_in_page(sig) + SMB2_SIGNATURE_SIZE, PAGE_SIZE); |
---|
| 2088 | + return nents; |
---|
| 2089 | +} |
---|
| 2090 | + |
---|
| 2091 | +/* We can not use the normal sg_set_buf() as we will sometimes pass a |
---|
| 2092 | + * stack object as buf. |
---|
| 2093 | + */ |
---|
| 2094 | +static inline struct scatterlist *cifs_sg_set_buf(struct scatterlist *sg, |
---|
| 2095 | + const void *buf, |
---|
| 2096 | + unsigned int buflen) |
---|
| 2097 | +{ |
---|
| 2098 | + unsigned long addr = (unsigned long)buf; |
---|
| 2099 | + unsigned int off = offset_in_page(addr); |
---|
| 2100 | + |
---|
| 2101 | + addr &= PAGE_MASK; |
---|
| 2102 | + if (unlikely(is_vmalloc_addr((void *)addr))) { |
---|
| 2103 | + do { |
---|
| 2104 | + unsigned int len = min_t(unsigned int, buflen, PAGE_SIZE - off); |
---|
| 2105 | + |
---|
| 2106 | + sg_set_page(sg++, vmalloc_to_page((void *)addr), len, off); |
---|
| 2107 | + |
---|
| 2108 | + off = 0; |
---|
| 2109 | + addr += PAGE_SIZE; |
---|
| 2110 | + buflen -= len; |
---|
| 2111 | + } while (buflen); |
---|
| 2112 | + } else { |
---|
| 2113 | + sg_set_page(sg++, virt_to_page(addr), buflen, off); |
---|
| 2114 | + } |
---|
| 2115 | + return sg; |
---|
| 2116 | +} |
---|
| 2117 | + |
---|
2049 | 2118 | #endif /* _CIFS_GLOB_H */ |
---|