Blame view
fs/cifs/misc.c
30.6 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * fs/cifs/misc.c * |
ad7a2926b [CIFS] reduce che... |
4 |
* Copyright (C) International Business Machines Corp., 2002,2008 |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
* Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software |
fb8c4b14d [CIFS] whitespace... |
19 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 24 |
*/ #include <linux/slab.h> #include <linux/ctype.h> #include <linux/mempool.h> |
ccf7f4088 CIFS: Add asynchr... |
25 |
#include <linux/vmalloc.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 29 30 31 |
#include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" #include "cifs_debug.h" #include "smberr.h" #include "nterr.h" |
6c91d362f [PATCH] cifs: fin... |
32 |
#include "cifs_unicode.h" |
3792c1732 CIFS: Respect SMB... |
33 |
#include "smb2pdu.h" |
bacd704a9 cifs: handle pref... |
34 |
#include "cifsfs.h" |
e4af35fa5 cifs: handle host... |
35 36 37 |
#ifdef CONFIG_CIFS_DFS_UPCALL #include "dns_resolve.h" #endif |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 |
extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; |
1da177e4c Linux-2.6.12-rc2 |
41 |
|
fb8c4b14d [CIFS] whitespace... |
42 43 44 45 |
/* The xid serves as a useful identifier for each incoming vfs request, in a similar way to the mid which is useful to track each sent smb, and CurrentXid can also provide a running counter (although it will eventually wrap past zero) of the total vfs operations handled |
1da177e4c Linux-2.6.12-rc2 |
46 47 48 |
since the cifs fs was mounted */ unsigned int |
6d5786a34 CIFS: Rename Get/... |
49 |
_get_xid(void) |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 53 54 |
{ unsigned int xid; spin_lock(&GlobalMid_Lock); GlobalTotalActiveXid++; |
50c2f7538 [CIFS] whitespace... |
55 56 |
/* keep high water mark for number of simultaneous ops in filesystem */ |
1da177e4c Linux-2.6.12-rc2 |
57 |
if (GlobalTotalActiveXid > GlobalMaxActiveXid) |
50c2f7538 [CIFS] whitespace... |
58 |
GlobalMaxActiveXid = GlobalTotalActiveXid; |
790fe579f [CIFS] more white... |
59 |
if (GlobalTotalActiveXid > 65000) |
f96637be0 [CIFS] cifs: Rena... |
60 61 |
cifs_dbg(FYI, "warning: more than 65000 requests active "); |
1da177e4c Linux-2.6.12-rc2 |
62 63 64 65 66 67 |
xid = GlobalCurrentXid++; spin_unlock(&GlobalMid_Lock); return xid; } void |
6d5786a34 CIFS: Rename Get/... |
68 |
_free_xid(unsigned int xid) |
1da177e4c Linux-2.6.12-rc2 |
69 70 |
{ spin_lock(&GlobalMid_Lock); |
790fe579f [CIFS] more white... |
71 |
/* if (GlobalTotalActiveXid == 0) |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 |
BUG(); */ GlobalTotalActiveXid--; spin_unlock(&GlobalMid_Lock); } |
96daf2b09 [CIFS] Rename thr... |
76 |
struct cifs_ses * |
1da177e4c Linux-2.6.12-rc2 |
77 78 |
sesInfoAlloc(void) { |
96daf2b09 [CIFS] Rename thr... |
79 |
struct cifs_ses *ret_buf; |
1da177e4c Linux-2.6.12-rc2 |
80 |
|
96daf2b09 [CIFS] Rename thr... |
81 |
ret_buf = kzalloc(sizeof(struct cifs_ses), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
82 |
if (ret_buf) { |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
atomic_inc(&sesInfoAllocCount); ret_buf->status = CifsNew; |
14fbf50d6 cifs: reinstate s... |
85 86 |
++ret_buf->ses_count; INIT_LIST_HEAD(&ret_buf->smb_ses_list); |
f1987b44f cifs: reinstate s... |
87 |
INIT_LIST_HEAD(&ret_buf->tcon_list); |
d7b619cf5 [CIFS] pSesInfo->... |
88 |
mutex_init(&ret_buf->session_mutex); |
b6f0dd5d7 CIFS: add iface i... |
89 |
spin_lock_init(&ret_buf->iface_lock); |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 93 94 |
} return ret_buf; } void |
96daf2b09 [CIFS] Rename thr... |
95 |
sesInfoFree(struct cifs_ses *buf_to_free) |
1da177e4c Linux-2.6.12-rc2 |
96 97 |
{ if (buf_to_free == NULL) { |
f96637be0 [CIFS] cifs: Rena... |
98 99 |
cifs_dbg(FYI, "Null buffer passed to sesInfoFree "); |
1da177e4c Linux-2.6.12-rc2 |
100 101 |
return; } |
1da177e4c Linux-2.6.12-rc2 |
102 |
atomic_dec(&sesInfoAllocCount); |
f99d49adf [PATCH] kfree cle... |
103 104 105 |
kfree(buf_to_free->serverOS); kfree(buf_to_free->serverDomain); kfree(buf_to_free->serverNOS); |
453431a54 mm, treewide: ren... |
106 |
kfree_sensitive(buf_to_free->password); |
8727c8a85 Allow user names ... |
107 |
kfree(buf_to_free->user_name); |
3979877e5 [CIFS] Support fo... |
108 |
kfree(buf_to_free->domainName); |
453431a54 mm, treewide: ren... |
109 |
kfree_sensitive(buf_to_free->auth_key.response); |
b6f0dd5d7 CIFS: add iface i... |
110 |
kfree(buf_to_free->iface_list); |
453431a54 mm, treewide: ren... |
111 |
kfree_sensitive(buf_to_free); |
1da177e4c Linux-2.6.12-rc2 |
112 |
} |
96daf2b09 [CIFS] Rename thr... |
113 |
struct cifs_tcon * |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
tconInfoAlloc(void) { |
96daf2b09 [CIFS] Rename thr... |
116 |
struct cifs_tcon *ret_buf; |
0544b324e cifs: check kzall... |
117 118 119 120 121 122 123 124 |
ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); if (!ret_buf) return NULL; ret_buf->crfid.fid = kzalloc(sizeof(*ret_buf->crfid.fid), GFP_KERNEL); if (!ret_buf->crfid.fid) { kfree(ret_buf); return NULL; |
1da177e4c Linux-2.6.12-rc2 |
125 |
} |
0544b324e cifs: check kzall... |
126 127 128 129 130 131 132 133 134 135 136 |
atomic_inc(&tconInfoAllocCount); ret_buf->tidStatus = CifsNew; ++ret_buf->tc_count; INIT_LIST_HEAD(&ret_buf->openFileList); INIT_LIST_HEAD(&ret_buf->tcon_list); spin_lock_init(&ret_buf->open_file_lock); mutex_init(&ret_buf->crfid.fid_mutex); spin_lock_init(&ret_buf->stat_lock); atomic_set(&ret_buf->num_local_opens, 0); atomic_set(&ret_buf->num_remote_opens, 0); |
1da177e4c Linux-2.6.12-rc2 |
137 138 139 140 |
return ret_buf; } void |
96daf2b09 [CIFS] Rename thr... |
141 |
tconInfoFree(struct cifs_tcon *buf_to_free) |
1da177e4c Linux-2.6.12-rc2 |
142 143 |
{ if (buf_to_free == NULL) { |
f96637be0 [CIFS] cifs: Rena... |
144 145 |
cifs_dbg(FYI, "Null buffer passed to tconInfoFree "); |
1da177e4c Linux-2.6.12-rc2 |
146 147 |
return; } |
1da177e4c Linux-2.6.12-rc2 |
148 |
atomic_dec(&tconInfoAllocCount); |
f99d49adf [PATCH] kfree cle... |
149 |
kfree(buf_to_free->nativeFileSystem); |
453431a54 mm, treewide: ren... |
150 |
kfree_sensitive(buf_to_free->password); |
a93864d93 cifs: add lease t... |
151 |
kfree(buf_to_free->crfid.fid); |
4a367dc04 cifs: Add support... |
152 153 154 |
#ifdef CONFIG_CIFS_DFS_UPCALL kfree(buf_to_free->dfs_path); #endif |
1da177e4c Linux-2.6.12-rc2 |
155 156 157 158 159 160 161 |
kfree(buf_to_free); } struct smb_hdr * cifs_buf_get(void) { struct smb_hdr *ret_buf = NULL; |
3792c1732 CIFS: Respect SMB... |
162 163 164 165 |
/* * SMB2 header is bigger than CIFS one - no problems to clean some * more bytes for CIFS. */ |
49f466bdb cifs: remove stru... |
166 |
size_t buf_size = sizeof(struct smb2_sync_hdr); |
2a38e1205 [SMB3] Remove ifd... |
167 |
|
3792c1732 CIFS: Respect SMB... |
168 169 170 171 172 173 |
/* * 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. */ |
232087cb7 cifs: don't use G... |
174 |
ret_buf = mempool_alloc(cifs_req_poolp, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
175 176 177 |
/* clear the first few header bytes */ /* for most paths, more is cleared in header_assemble */ |
a6f74e80f cifs: don't check... |
178 179 |
memset(ret_buf, 0, buf_size + 3); atomic_inc(&bufAllocCount); |
4498eed50 [CIFS] Add extend... |
180 |
#ifdef CONFIG_CIFS_STATS2 |
a6f74e80f cifs: don't check... |
181 |
atomic_inc(&totBufAllocCount); |
4498eed50 [CIFS] Add extend... |
182 |
#endif /* CONFIG_CIFS_STATS2 */ |
1da177e4c Linux-2.6.12-rc2 |
183 184 185 186 187 188 189 |
return ret_buf; } void cifs_buf_release(void *buf_to_free) { |
1da177e4c Linux-2.6.12-rc2 |
190 |
if (buf_to_free == NULL) { |
f96637be0 [CIFS] cifs: Rena... |
191 192 |
/* cifs_dbg(FYI, "Null buffer passed to cifs_buf_release ");*/ |
1da177e4c Linux-2.6.12-rc2 |
193 194 |
return; } |
fb8c4b14d [CIFS] whitespace... |
195 |
mempool_free(buf_to_free, cifs_req_poolp); |
1da177e4c Linux-2.6.12-rc2 |
196 197 198 199 200 201 202 203 204 |
atomic_dec(&bufAllocCount); return; } struct smb_hdr * cifs_small_buf_get(void) { struct smb_hdr *ret_buf = NULL; |
fb8c4b14d [CIFS] whitespace... |
205 206 207 |
/* 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 |
1da177e4c Linux-2.6.12-rc2 |
208 |
defaults to this and can not be bigger */ |
232087cb7 cifs: don't use G... |
209 |
ret_buf = mempool_alloc(cifs_sm_req_poolp, GFP_NOFS); |
1da177e4c Linux-2.6.12-rc2 |
210 211 |
/* No need to clear memory here, cleared in header assemble */ /* memset(ret_buf, 0, sizeof(struct smb_hdr) + 27);*/ |
a6f74e80f cifs: don't check... |
212 |
atomic_inc(&smBufAllocCount); |
4498eed50 [CIFS] Add extend... |
213 |
#ifdef CONFIG_CIFS_STATS2 |
a6f74e80f cifs: don't check... |
214 |
atomic_inc(&totSmBufAllocCount); |
4498eed50 [CIFS] Add extend... |
215 |
#endif /* CONFIG_CIFS_STATS2 */ |
1da177e4c Linux-2.6.12-rc2 |
216 217 218 219 220 221 222 223 |
return ret_buf; } void cifs_small_buf_release(void *buf_to_free) { if (buf_to_free == NULL) { |
f96637be0 [CIFS] cifs: Rena... |
224 225 |
cifs_dbg(FYI, "Null buffer passed to cifs_small_buf_release "); |
1da177e4c Linux-2.6.12-rc2 |
226 227 |
return; } |
fb8c4b14d [CIFS] whitespace... |
228 |
mempool_free(buf_to_free, cifs_sm_req_poolp); |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 232 |
atomic_dec(&smBufAllocCount); return; } |
6d81ed1ec cifs: replace cod... |
233 234 235 236 237 238 239 240 |
void free_rsp_buf(int resp_buftype, void *rsp) { if (resp_buftype == CIFS_SMALL_BUFFER) cifs_small_buf_release(rsp); else if (resp_buftype == CIFS_LARGE_BUFFER) cifs_buf_release(rsp); } |
1982c344f [CIFS] Ensure tha... |
241 242 |
/* NB: MID can not be set if treeCon not passed in, in that case it is responsbility of caller to set the mid */ |
1da177e4c Linux-2.6.12-rc2 |
243 244 |
void header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , |
96daf2b09 [CIFS] Rename thr... |
245 |
const struct cifs_tcon *treeCon, int word_count |
1da177e4c Linux-2.6.12-rc2 |
246 247 |
/* length of fixed section (word count) in two byte units */) { |
1da177e4c Linux-2.6.12-rc2 |
248 |
char *temp = (char *) buffer; |
fb8c4b14d [CIFS] whitespace... |
249 |
memset(temp, 0, 256); /* bigger than MAX_CIFS_HDR_SIZE */ |
1da177e4c Linux-2.6.12-rc2 |
250 |
|
be8e3b004 consistently use ... |
251 |
buffer->smb_buf_length = cpu_to_be32( |
630f3f0c4 [CIFS] acl suppor... |
252 |
(2 * word_count) + sizeof(struct smb_hdr) - |
1da177e4c Linux-2.6.12-rc2 |
253 |
4 /* RFC 1001 length field does not count */ + |
be8e3b004 consistently use ... |
254 |
2 /* for bcc field itself */) ; |
1da177e4c Linux-2.6.12-rc2 |
255 256 257 258 259 260 261 262 263 264 |
buffer->Protocol[0] = 0xFF; buffer->Protocol[1] = 'S'; buffer->Protocol[2] = 'M'; buffer->Protocol[3] = 'B'; buffer->Command = smb_command; buffer->Flags = 0x00; /* case sensitive */ buffer->Flags2 = SMBFLG2_KNOWS_LONG_NAMES; buffer->Pid = cpu_to_le16((__u16)current->tgid); buffer->PidHigh = cpu_to_le16((__u16)(current->tgid >> 16)); |
1da177e4c Linux-2.6.12-rc2 |
265 266 267 268 269 |
if (treeCon) { buffer->Tid = treeCon->tid; if (treeCon->ses) { if (treeCon->ses->capabilities & CAP_UNICODE) buffer->Flags2 |= SMBFLG2_UNICODE; |
ad7a2926b [CIFS] reduce che... |
270 |
if (treeCon->ses->capabilities & CAP_STATUS32) |
1da177e4c Linux-2.6.12-rc2 |
271 |
buffer->Flags2 |= SMBFLG2_ERR_STATUS; |
ad7a2926b [CIFS] reduce che... |
272 |
|
1982c344f [CIFS] Ensure tha... |
273 274 |
/* Uid is not converted */ buffer->Uid = treeCon->ses->Suid; |
882573606 CIFS: Move get_ne... |
275 |
buffer->Mid = get_next_mid(treeCon->ses->server); |
1da177e4c Linux-2.6.12-rc2 |
276 277 278 |
} if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) buffer->Flags2 |= SMBFLG2_DFS; |
d3485d37c [CIFS] Finish cif... |
279 280 |
if (treeCon->nocase) buffer->Flags |= SMBFLG_CASELESS; |
790fe579f [CIFS] more white... |
281 |
if ((treeCon->ses) && (treeCon->ses->server)) |
38d77c50b cifs: track the e... |
282 |
if (treeCon->ses->server->sign) |
1da177e4c Linux-2.6.12-rc2 |
283 284 285 286 287 288 289 |
buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; } /* endian conversion of flags is now done just before sending */ buffer->WordCount = (char) word_count; return; } |
2cd646a2d [CIFS] Remove sta... |
290 |
static int |
944d6f1a5 cifs: Remove redu... |
291 |
check_smb_hdr(struct smb_hdr *smb) |
1da177e4c Linux-2.6.12-rc2 |
292 |
{ |
68abaffa6 cifs: simplify SM... |
293 294 |
/* does it have the right SMB "signature" ? */ if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) { |
f96637be0 [CIFS] cifs: Rena... |
295 296 297 |
cifs_dbg(VFS, "Bad protocol string signature header 0x%x ", *(unsigned int *)smb->Protocol); |
68abaffa6 cifs: simplify SM... |
298 299 |
return 1; } |
68abaffa6 cifs: simplify SM... |
300 301 302 303 304 305 306 |
/* if it's a response then accept */ if (smb->Flags & SMBFLG_RESPONSE) return 0; /* only one valid case where server sends us request */ if (smb->Command == SMB_COM_LOCKING_ANDX) return 0; |
3d378d3fd cifs: Make big en... |
307 308 309 |
cifs_dbg(VFS, "Server sent request, not response. mid=%u ", get_mid(smb)); |
1da177e4c Linux-2.6.12-rc2 |
310 311 312 313 |
return 1; } int |
373512ec5 Prepare for encry... |
314 |
checkSMB(char *buf, unsigned int total_read, struct TCP_Server_Info *server) |
1da177e4c Linux-2.6.12-rc2 |
315 |
{ |
d4e4854fd CIFS: Separate pr... |
316 |
struct smb_hdr *smb = (struct smb_hdr *)buf; |
376b43f41 cifs: clean up ch... |
317 |
__u32 rfclen = be32_to_cpu(smb->smb_buf_length); |
190fdeb84 [CIFS] Fix byte r... |
318 |
__u32 clc_len; /* calculated length */ |
f96637be0 [CIFS] cifs: Rena... |
319 320 321 |
cifs_dbg(FYI, "checkSMB Length: 0x%x, smb_buf_length: 0x%x ", total_read, rfclen); |
d103e164b [CIFS] Workaround... |
322 |
|
376b43f41 cifs: clean up ch... |
323 324 325 |
/* is this frame too small to even get to a BCC? */ if (total_read < 2 + sizeof(struct smb_hdr)) { if ((total_read >= sizeof(struct smb_hdr) - 1) |
1da177e4c Linux-2.6.12-rc2 |
326 |
&& (smb->Status.CifsError != 0)) { |
376b43f41 cifs: clean up ch... |
327 |
/* it's an error return */ |
d103e164b [CIFS] Workaround... |
328 329 330 |
smb->WordCount = 0; /* some error cases do not return wct and bcc */ return 0; |
376b43f41 cifs: clean up ch... |
331 |
} else if ((total_read == sizeof(struct smb_hdr) + 1) && |
d103e164b [CIFS] Workaround... |
332 |
(smb->WordCount == 0)) { |
fb8c4b14d [CIFS] whitespace... |
333 |
char *tmp = (char *)smb; |
d103e164b [CIFS] Workaround... |
334 335 336 337 338 339 340 341 342 343 344 |
/* Need to work around a bug in two servers here */ /* First, check if the part of bcc they sent was zero */ if (tmp[sizeof(struct smb_hdr)] == 0) { /* some servers return only half of bcc * on simple responses (wct, bcc both zero) * in particular have seen this on * ulogoffX and FindClose. This leaves * one byte of bcc potentially unitialized */ /* zero rest of bcc */ tmp[sizeof(struct smb_hdr)+1] = 0; |
46c79a645 [CIFS] Move noisy... |
345 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
346 |
} |
f96637be0 [CIFS] cifs: Rena... |
347 348 |
cifs_dbg(VFS, "rcvd invalid byte count (bcc) "); |
d103e164b [CIFS] Workaround... |
349 |
} else { |
f96637be0 [CIFS] cifs: Rena... |
350 351 |
cifs_dbg(VFS, "Length less than smb header size "); |
1da177e4c Linux-2.6.12-rc2 |
352 |
} |
376b43f41 cifs: clean up ch... |
353 |
return -EIO; |
1da177e4c Linux-2.6.12-rc2 |
354 |
} |
376b43f41 cifs: clean up ch... |
355 |
/* otherwise, there is enough to get to the BCC */ |
944d6f1a5 cifs: Remove redu... |
356 |
if (check_smb_hdr(smb)) |
376b43f41 cifs: clean up ch... |
357 |
return -EIO; |
9ec672bd1 cifs: update calc... |
358 |
clc_len = smbCalcSize(smb, server); |
184ed2110 [CIFS] Fix large ... |
359 |
|
376b43f41 cifs: clean up ch... |
360 |
if (4 + rfclen != total_read) { |
f96637be0 [CIFS] cifs: Rena... |
361 362 363 |
cifs_dbg(VFS, "Length read does not match RFC1001 length %d ", rfclen); |
376b43f41 cifs: clean up ch... |
364 |
return -EIO; |
184ed2110 [CIFS] Fix large ... |
365 |
} |
376b43f41 cifs: clean up ch... |
366 |
if (4 + rfclen != clc_len) { |
3d378d3fd cifs: Make big en... |
367 |
__u16 mid = get_mid(smb); |
184ed2110 [CIFS] Fix large ... |
368 |
/* check if bcc wrapped around for large read responses */ |
376b43f41 cifs: clean up ch... |
369 |
if ((rfclen > 64 * 1024) && (rfclen > clc_len)) { |
184ed2110 [CIFS] Fix large ... |
370 |
/* check if lengths match mod 64K */ |
376b43f41 cifs: clean up ch... |
371 |
if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF)) |
fb8c4b14d [CIFS] whitespace... |
372 |
return 0; /* bcc wrapped */ |
184ed2110 [CIFS] Fix large ... |
373 |
} |
f96637be0 [CIFS] cifs: Rena... |
374 375 |
cifs_dbg(FYI, "Calculated size %u vs length %u mismatch for mid=%u ", |
3d378d3fd cifs: Make big en... |
376 |
clc_len, 4 + rfclen, mid); |
6284644e8 cifs: fix length ... |
377 |
|
376b43f41 cifs: clean up ch... |
378 |
if (4 + rfclen < clc_len) { |
f96637be0 [CIFS] cifs: Rena... |
379 380 |
cifs_dbg(VFS, "RFC1001 size %u smaller than SMB for mid=%u ", |
3d378d3fd cifs: Make big en... |
381 |
rfclen, mid); |
376b43f41 cifs: clean up ch... |
382 383 |
return -EIO; } else if (rfclen > clc_len + 512) { |
6284644e8 cifs: fix length ... |
384 385 386 387 388 389 390 391 392 |
/* * Some servers (Windows XP in particular) send more * data than the lengths in the SMB packet would * indicate on certain calls (byte range locks and * trans2 find first calls in particular). While the * client can handle such a frame by ignoring the * trailing data, we choose limit the amount of extra * data to 512 bytes. */ |
f96637be0 [CIFS] cifs: Rena... |
393 394 |
cifs_dbg(VFS, "RFC1001 size %u more than 512 bytes larger than SMB for mid=%u ", |
3d378d3fd cifs: Make big en... |
395 |
rfclen, mid); |
376b43f41 cifs: clean up ch... |
396 |
return -EIO; |
46c79a645 [CIFS] Move noisy... |
397 |
} |
1da177e4c Linux-2.6.12-rc2 |
398 |
} |
209624388 [CIFS] Add suppor... |
399 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
400 |
} |
4b18f2a9c [CIFS] convert us... |
401 402 |
bool |
d4e4854fd CIFS: Separate pr... |
403 |
is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) |
fb8c4b14d [CIFS] whitespace... |
404 |
{ |
d4e4854fd CIFS: Separate pr... |
405 |
struct smb_hdr *buf = (struct smb_hdr *)buffer; |
fb8c4b14d [CIFS] whitespace... |
406 |
struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; |
f1987b44f cifs: reinstate s... |
407 |
struct list_head *tmp, *tmp1, *tmp2; |
96daf2b09 [CIFS] Rename thr... |
408 409 |
struct cifs_ses *ses; struct cifs_tcon *tcon; |
f1987b44f cifs: reinstate s... |
410 |
struct cifsInodeInfo *pCifsInode; |
1da177e4c Linux-2.6.12-rc2 |
411 |
struct cifsFileInfo *netfile; |
f96637be0 [CIFS] cifs: Rena... |
412 413 |
cifs_dbg(FYI, "Checking for oplock break or dnotify response "); |
790fe579f [CIFS] more white... |
414 |
if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && |
1da177e4c Linux-2.6.12-rc2 |
415 |
(pSMB->hdr.Flags & SMBFLG_RESPONSE)) { |
fb8c4b14d [CIFS] whitespace... |
416 |
struct smb_com_transaction_change_notify_rsp *pSMBr = |
1da177e4c Linux-2.6.12-rc2 |
417 |
(struct smb_com_transaction_change_notify_rsp *)buf; |
fb8c4b14d [CIFS] whitespace... |
418 |
struct file_notify_information *pnotify; |
1da177e4c Linux-2.6.12-rc2 |
419 |
__u32 data_offset = 0; |
097f5863b cifs: read overfl... |
420 |
size_t len = srv->total_read - sizeof(pSMBr->hdr.smb_buf_length); |
820a803ff cifs: keep BCC in... |
421 |
if (get_bcc(buf) > sizeof(struct file_notify_information)) { |
1da177e4c Linux-2.6.12-rc2 |
422 |
data_offset = le32_to_cpu(pSMBr->DataOffset); |
097f5863b cifs: read overfl... |
423 424 |
if (data_offset > len - sizeof(struct file_notify_information)) { |
a0a3036b8 cifs: Standardize... |
425 426 |
cifs_dbg(FYI, "Invalid data_offset %u ", |
097f5863b cifs: read overfl... |
427 428 429 |
data_offset); return true; } |
3979877e5 [CIFS] Support fo... |
430 431 |
pnotify = (struct file_notify_information *) ((char *)&pSMBr->hdr.Protocol + data_offset); |
f96637be0 [CIFS] cifs: Rena... |
432 433 |
cifs_dbg(FYI, "dnotify on %s Action: 0x%x ", |
b6b38f704 [CIFS] Neaten cER... |
434 |
pnotify->FileName, pnotify->Action); |
fb8c4b14d [CIFS] whitespace... |
435 |
/* cifs_dump_mem("Rcvd notify Data: ",buf, |
3979877e5 [CIFS] Support fo... |
436 |
sizeof(struct smb_hdr)+60); */ |
4b18f2a9c [CIFS] convert us... |
437 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
438 |
} |
790fe579f [CIFS] more white... |
439 |
if (pSMBr->hdr.Status.CifsError) { |
59b04c5df [CIFS] Fix incorr... |
440 441 |
cifs_dbg(FYI, "notify err 0x%x ", |
f96637be0 [CIFS] cifs: Rena... |
442 |
pSMBr->hdr.Status.CifsError); |
4b18f2a9c [CIFS] convert us... |
443 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
444 |
} |
4b18f2a9c [CIFS] convert us... |
445 |
return false; |
fb8c4b14d [CIFS] whitespace... |
446 |
} |
790fe579f [CIFS] more white... |
447 |
if (pSMB->hdr.Command != SMB_COM_LOCKING_ANDX) |
4b18f2a9c [CIFS] convert us... |
448 |
return false; |
790fe579f [CIFS] more white... |
449 |
if (pSMB->hdr.Flags & SMBFLG_RESPONSE) { |
1da177e4c Linux-2.6.12-rc2 |
450 451 452 453 |
/* no sense logging error on invalid handle on oplock break - harmless race between close request and oplock break response is expected from time to time writing out large dirty files cached on the client */ |
fb8c4b14d [CIFS] whitespace... |
454 455 |
if ((NT_STATUS_INVALID_HANDLE) == le32_to_cpu(pSMB->hdr.Status.CifsError)) { |
a0a3036b8 cifs: Standardize... |
456 457 |
cifs_dbg(FYI, "Invalid handle on oplock break "); |
4b18f2a9c [CIFS] convert us... |
458 |
return true; |
fb8c4b14d [CIFS] whitespace... |
459 |
} else if (ERRbadfid == |
1da177e4c Linux-2.6.12-rc2 |
460 |
le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { |
4b18f2a9c [CIFS] convert us... |
461 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
462 |
} else { |
4b18f2a9c [CIFS] convert us... |
463 |
return false; /* on valid oplock brk we get "request" */ |
1da177e4c Linux-2.6.12-rc2 |
464 465 |
} } |
790fe579f [CIFS] more white... |
466 |
if (pSMB->hdr.WordCount != 8) |
4b18f2a9c [CIFS] convert us... |
467 |
return false; |
1da177e4c Linux-2.6.12-rc2 |
468 |
|
59b04c5df [CIFS] Fix incorr... |
469 470 |
cifs_dbg(FYI, "oplock type 0x%x level 0x%x ", |
b6b38f704 [CIFS] Neaten cER... |
471 |
pSMB->LockType, pSMB->OplockLevel); |
790fe579f [CIFS] more white... |
472 |
if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) |
4b18f2a9c [CIFS] convert us... |
473 |
return false; |
1da177e4c Linux-2.6.12-rc2 |
474 475 |
/* look up tcon based on tid & uid */ |
3f9bcca78 cifs: convert cif... |
476 |
spin_lock(&cifs_tcp_ses_lock); |
f1987b44f cifs: reinstate s... |
477 |
list_for_each(tmp, &srv->smb_ses_list) { |
96daf2b09 [CIFS] Rename thr... |
478 |
ses = list_entry(tmp, struct cifs_ses, smb_ses_list); |
f1987b44f cifs: reinstate s... |
479 |
list_for_each(tmp1, &ses->tcon_list) { |
96daf2b09 [CIFS] Rename thr... |
480 |
tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); |
f1987b44f cifs: reinstate s... |
481 482 |
if (tcon->tid != buf->Tid) continue; |
44c581866 CIFS: Move clear/... |
483 |
cifs_stats_inc(&tcon->stats.cifs_stats.num_oplock_brks); |
3afca265b Clarify locking o... |
484 |
spin_lock(&tcon->open_file_lock); |
f1987b44f cifs: reinstate s... |
485 486 |
list_for_each(tmp2, &tcon->openFileList) { netfile = list_entry(tmp2, struct cifsFileInfo, |
57337e42f [PATCH] cifs: han... |
487 |
tlist); |
4b4de76e3 CIFS: Replace net... |
488 |
if (pSMB->Fid != netfile->fid.netfid) |
f1987b44f cifs: reinstate s... |
489 |
continue; |
f96637be0 [CIFS] cifs: Rena... |
490 491 |
cifs_dbg(FYI, "file id match, oplock break "); |
2b0143b5c VFS: normal files... |
492 |
pCifsInode = CIFS_I(d_inode(netfile->dentry)); |
9b6469724 cifs: use workque... |
493 |
|
c11f1df50 cifs: Wait for wr... |
494 495 |
set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &pCifsInode->flags); |
9bd454083 CIFS: Properly pr... |
496 497 |
netfile->oplock_epoch = 0; netfile->oplock_level = pSMB->OplockLevel; |
9b6469724 cifs: use workque... |
498 |
netfile->oplock_break_cancelled = false; |
9bd454083 CIFS: Properly pr... |
499 |
cifs_queue_oplock_break(netfile); |
9b6469724 cifs: use workque... |
500 |
|
3afca265b Clarify locking o... |
501 |
spin_unlock(&tcon->open_file_lock); |
3f9bcca78 cifs: convert cif... |
502 |
spin_unlock(&cifs_tcp_ses_lock); |
f1987b44f cifs: reinstate s... |
503 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
504 |
} |
3afca265b Clarify locking o... |
505 |
spin_unlock(&tcon->open_file_lock); |
3f9bcca78 cifs: convert cif... |
506 |
spin_unlock(&cifs_tcp_ses_lock); |
f96637be0 [CIFS] cifs: Rena... |
507 508 |
cifs_dbg(FYI, "No matching file for oplock break "); |
4b18f2a9c [CIFS] convert us... |
509 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
510 511 |
} } |
3f9bcca78 cifs: convert cif... |
512 |
spin_unlock(&cifs_tcp_ses_lock); |
f96637be0 [CIFS] cifs: Rena... |
513 514 |
cifs_dbg(FYI, "Can not process oplock break for non-existent connection "); |
4b18f2a9c [CIFS] convert us... |
515 |
return true; |
1da177e4c Linux-2.6.12-rc2 |
516 517 518 |
} void |
792af7b05 CIFS: Separate pr... |
519 |
dump_smb(void *buf, int smb_buf_length) |
1da177e4c Linux-2.6.12-rc2 |
520 |
{ |
1da177e4c Linux-2.6.12-rc2 |
521 522 |
if (traceSMB == 0) return; |
55d83e0db cifs: convert to ... |
523 524 |
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 8, 2, buf, smb_buf_length, true); |
1da177e4c Linux-2.6.12-rc2 |
525 |
} |
6a0b48245 [PATCH] cifs: Add... |
526 |
|
ec06aedd4 cifs: clean up ha... |
527 528 529 530 |
void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { |
5fc7fcd05 cifs: auto disabl... |
531 532 533 534 |
struct cifs_tcon *tcon = NULL; if (cifs_sb->master_tlink) tcon = cifs_sb_master_tcon(cifs_sb); |
f534dc994 cifs: clear serve... |
535 |
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; |
29fbeb7a9 cifs: Properly ha... |
536 |
cifs_sb->mnt_cifs_serverino_autodisabled = true; |
a0a3036b8 cifs: Standardize... |
537 538 |
cifs_dbg(VFS, "Autodisabling the use of server inode numbers on %s ", |
5fc7fcd05 cifs: auto disabl... |
539 |
tcon ? tcon->treeName : "new server"); |
a0a3036b8 cifs: Standardize... |
540 541 |
cifs_dbg(VFS, "The server doesn't seem to support them properly or the files might be on different servers (DFS) "); |
5fc7fcd05 cifs: auto disabl... |
542 543 |
cifs_dbg(VFS, "Hardlinks will not be recognized on this mount. Consider mounting with the \"noserverino\" option to silence this message. "); |
ec06aedd4 cifs: clean up ha... |
544 545 |
} } |
e66673e39 CIFS: Add cifs_se... |
546 |
|
c67236281 cifs: make cifs_s... |
547 |
void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) |
e66673e39 CIFS: Add cifs_se... |
548 |
{ |
c67236281 cifs: make cifs_s... |
549 |
oplock &= 0xF; |
e66673e39 CIFS: Add cifs_se... |
550 |
|
c67236281 cifs: make cifs_s... |
551 |
if (oplock == OPLOCK_EXCLUSIVE) { |
18cceb6a7 CIFS: Replace cli... |
552 |
cinode->oplock = CIFS_CACHE_WRITE_FLG | CIFS_CACHE_READ_FLG; |
f96637be0 [CIFS] cifs: Rena... |
553 554 555 |
cifs_dbg(FYI, "Exclusive Oplock granted on inode %p ", &cinode->vfs_inode); |
c67236281 cifs: make cifs_s... |
556 |
} else if (oplock == OPLOCK_READ) { |
18cceb6a7 CIFS: Replace cli... |
557 |
cinode->oplock = CIFS_CACHE_READ_FLG; |
f96637be0 [CIFS] cifs: Rena... |
558 559 560 |
cifs_dbg(FYI, "Level II Oplock granted on inode %p ", &cinode->vfs_inode); |
18cceb6a7 CIFS: Replace cli... |
561 562 |
} else cinode->oplock = 0; |
e66673e39 CIFS: Add cifs_se... |
563 |
} |
3d3ea8e64 cifs: Add mount o... |
564 |
|
c11f1df50 cifs: Wait for wr... |
565 566 567 568 569 570 571 572 573 574 |
/* * We wait for oplock breaks to be processed before we attempt to perform * writes. */ int cifs_get_writer(struct cifsInodeInfo *cinode) { int rc; start: rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK, |
743162013 sched: Remove pro... |
575 |
TASK_KILLABLE); |
c11f1df50 cifs: Wait for wr... |
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
if (rc) return rc; spin_lock(&cinode->writers_lock); if (!cinode->writers) set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); cinode->writers++; /* Check to see if we have started servicing an oplock break */ if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) { cinode->writers--; if (cinode->writers == 0) { clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS); } spin_unlock(&cinode->writers_lock); goto start; } spin_unlock(&cinode->writers_lock); return 0; } void cifs_put_writer(struct cifsInodeInfo *cinode) { spin_lock(&cinode->writers_lock); cinode->writers--; if (cinode->writers == 0) { clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS); } spin_unlock(&cinode->writers_lock); } |
b98749cac CIFS: keep FileIn... |
607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 |
/** * cifs_queue_oplock_break - queue the oplock break handler for cfile * * This function is called from the demultiplex thread when it * receives an oplock break for @cfile. * * Assumes the tcon->open_file_lock is held. * Assumes cfile->file_info_lock is NOT held. */ void cifs_queue_oplock_break(struct cifsFileInfo *cfile) { /* * Bump the handle refcount now while we hold the * open_file_lock to enforce the validity of it for the oplock * break handler. The matching put is done at the end of the * handler. */ cifsFileInfo_get(cfile); queue_work(cifsoplockd_wq, &cfile->oplock_break); } |
c11f1df50 cifs: Wait for wr... |
628 629 630 631 632 |
void cifs_done_oplock_break(struct cifsInodeInfo *cinode) { clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags); wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK); } |
3d3ea8e64 cifs: Add mount o... |
633 634 635 636 |
bool backup_cred(struct cifs_sb_info *cifs_sb) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) { |
1f68233c5 cifs: Convert str... |
637 |
if (uid_eq(cifs_sb->mnt_backupuid, current_fsuid())) |
3d3ea8e64 cifs: Add mount o... |
638 639 640 641 642 643 644 645 646 |
return true; } if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) { if (in_group_p(cifs_sb->mnt_backupgid)) return true; } return false; } |
233839b1d CIFS: Fix fast le... |
647 648 649 650 |
void cifs_del_pending_open(struct cifs_pending_open *open) { |
3afca265b Clarify locking o... |
651 |
spin_lock(&tlink_tcon(open->tlink)->open_file_lock); |
233839b1d CIFS: Fix fast le... |
652 |
list_del(&open->olist); |
3afca265b Clarify locking o... |
653 |
spin_unlock(&tlink_tcon(open->tlink)->open_file_lock); |
233839b1d CIFS: Fix fast le... |
654 655 656 657 658 659 |
} void cifs_add_pending_open_locked(struct cifs_fid *fid, struct tcon_link *tlink, struct cifs_pending_open *open) { |
233839b1d CIFS: Fix fast le... |
660 |
memcpy(open->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE); |
233839b1d CIFS: Fix fast le... |
661 662 663 664 665 666 667 668 669 670 |
open->oplock = CIFS_OPLOCK_NO_CHANGE; open->tlink = tlink; fid->pending_open = open; list_add_tail(&open->olist, &tlink_tcon(tlink)->pending_opens); } void cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink, struct cifs_pending_open *open) { |
3afca265b Clarify locking o... |
671 |
spin_lock(&tlink_tcon(tlink)->open_file_lock); |
233839b1d CIFS: Fix fast le... |
672 |
cifs_add_pending_open_locked(fid, tlink, open); |
3afca265b Clarify locking o... |
673 |
spin_unlock(&tlink_tcon(open->tlink)->open_file_lock); |
233839b1d CIFS: Fix fast le... |
674 |
} |
4ecce920e CIFS: move DFS re... |
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 |
/* parses DFS refferal V3 structure * caller is responsible for freeing target_nodes * returns: * - on success - 0 * - on failure - errno */ int parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, unsigned int *num_of_nodes, struct dfs_info3_param **target_nodes, const struct nls_table *nls_codepage, int remap, const char *searchName, bool is_unicode) { int i, rc = 0; char *data_end; struct dfs_referral_level_3 *ref; *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals); if (*num_of_nodes < 1) { cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d ", *num_of_nodes); rc = -EINVAL; goto parse_DFS_referrals_exit; } ref = (struct dfs_referral_level_3 *) &(rsp->referrals); if (ref->VersionNumber != cpu_to_le16(3)) { cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3 ", le16_to_cpu(ref->VersionNumber)); rc = -EINVAL; goto parse_DFS_referrals_exit; } /* get the upper boundary of the resp buffer */ data_end = (char *)rsp + rsp_size; cifs_dbg(FYI, "num_referrals: %d dfs flags: 0x%x ... ", *num_of_nodes, le32_to_cpu(rsp->DFSFlags)); *target_nodes = kcalloc(*num_of_nodes, sizeof(struct dfs_info3_param), GFP_KERNEL); if (*target_nodes == NULL) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } /* collect necessary data from referrals */ for (i = 0; i < *num_of_nodes; i++) { char *temp; int max_len; struct dfs_info3_param *node = (*target_nodes)+i; node->flags = le32_to_cpu(rsp->DFSFlags); if (is_unicode) { __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, GFP_KERNEL); if (tmp == NULL) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } cifsConvertToUTF16((__le16 *) tmp, searchName, PATH_MAX, nls_codepage, remap); node->path_consumed = cifs_utf16_bytes(tmp, le16_to_cpu(rsp->PathConsumed), nls_codepage); kfree(tmp); } else node->path_consumed = le16_to_cpu(rsp->PathConsumed); node->server_type = le16_to_cpu(ref->ServerType); node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); /* copy DfsPath */ temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); max_len = data_end - temp; node->path_name = cifs_strndup_from_utf16(temp, max_len, is_unicode, nls_codepage); if (!node->path_name) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } /* copy link target UNC */ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); max_len = data_end - temp; node->node_name = cifs_strndup_from_utf16(temp, max_len, is_unicode, nls_codepage); if (!node->node_name) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } |
e7b602f43 cifs: Save TTL va... |
771 |
node->ttl = le32_to_cpu(ref->TimeToLive); |
4ecce920e CIFS: move DFS re... |
772 773 774 775 776 777 778 779 780 781 782 |
ref++; } parse_DFS_referrals_exit: if (rc) { free_dfs_info_array(*target_nodes, *num_of_nodes); *target_nodes = NULL; *num_of_nodes = 0; } return rc; } |
ccf7f4088 CIFS: Add asynchr... |
783 784 785 786 787 |
struct cifs_aio_ctx * cifs_aio_ctx_alloc(void) { struct cifs_aio_ctx *ctx; |
13f5938d8 cifs: fix page re... |
788 789 790 791 792 |
/* * Must use kzalloc to initialize ctx->bv to NULL and ctx->direct_io * to false so that we know when we have to unreference pages within * cifs_aio_ctx_release() */ |
ccf7f4088 CIFS: Add asynchr... |
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 |
ctx = kzalloc(sizeof(struct cifs_aio_ctx), GFP_KERNEL); if (!ctx) return NULL; INIT_LIST_HEAD(&ctx->list); mutex_init(&ctx->aio_mutex); init_completion(&ctx->done); kref_init(&ctx->refcount); return ctx; } void cifs_aio_ctx_release(struct kref *refcount) { struct cifs_aio_ctx *ctx = container_of(refcount, struct cifs_aio_ctx, refcount); cifsFileInfo_put(ctx->cfile); |
13f5938d8 cifs: fix page re... |
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
/* * ctx->bv is only set if setup_aio_ctx_iter() was call successfuly * which means that iov_iter_get_pages() was a success and thus that * we have taken reference on pages. */ if (ctx->bv) { unsigned i; for (i = 0; i < ctx->npages; i++) { if (ctx->should_dirty) set_page_dirty(ctx->bv[i].bv_page); put_page(ctx->bv[i].bv_page); } kvfree(ctx->bv); } |
ccf7f4088 CIFS: Add asynchr... |
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 |
kfree(ctx); } #define CIFS_AIO_KMALLOC_LIMIT (1024 * 1024) int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw) { ssize_t rc; unsigned int cur_npages; unsigned int npages = 0; unsigned int i; size_t len; size_t count = iov_iter_count(iter); unsigned int saved_len; size_t start; unsigned int max_pages = iov_iter_npages(iter, INT_MAX); struct page **pages = NULL; struct bio_vec *bv = NULL; |
00e237074 iov_iter: Use acc... |
846 |
if (iov_iter_is_kvec(iter)) { |
bf1028a41 cifs: misc: Use a... |
847 |
memcpy(&ctx->iter, iter, sizeof(*iter)); |
ccf7f4088 CIFS: Add asynchr... |
848 849 850 851 |
ctx->len = count; iov_iter_advance(iter, count); return 0; } |
bf1028a41 cifs: misc: Use a... |
852 853 |
if (array_size(max_pages, sizeof(*bv)) <= CIFS_AIO_KMALLOC_LIMIT) bv = kmalloc_array(max_pages, sizeof(*bv), GFP_KERNEL); |
ccf7f4088 CIFS: Add asynchr... |
854 855 |
if (!bv) { |
bf1028a41 cifs: misc: Use a... |
856 |
bv = vmalloc(array_size(max_pages, sizeof(*bv))); |
ccf7f4088 CIFS: Add asynchr... |
857 858 859 |
if (!bv) return -ENOMEM; } |
bf1028a41 cifs: misc: Use a... |
860 861 |
if (array_size(max_pages, sizeof(*pages)) <= CIFS_AIO_KMALLOC_LIMIT) pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL); |
ccf7f4088 CIFS: Add asynchr... |
862 863 |
if (!pages) { |
bf1028a41 cifs: misc: Use a... |
864 |
pages = vmalloc(array_size(max_pages, sizeof(*pages))); |
ecf3411a1 CIFS: check if pa... |
865 |
if (!pages) { |
ccf7f4088 CIFS: Add asynchr... |
866 867 868 869 870 871 872 873 874 875 |
kvfree(bv); return -ENOMEM; } } saved_len = count; while (count && npages < max_pages) { rc = iov_iter_get_pages(iter, pages, count, max_pages, &start); if (rc < 0) { |
a0a3036b8 cifs: Standardize... |
876 877 |
cifs_dbg(VFS, "Couldn't get user pages (rc=%zd) ", rc); |
ccf7f4088 CIFS: Add asynchr... |
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 |
break; } if (rc > count) { cifs_dbg(VFS, "get pages rc=%zd more than %zu ", rc, count); break; } iov_iter_advance(iter, rc); count -= rc; rc += start; cur_npages = DIV_ROUND_UP(rc, PAGE_SIZE); if (npages + cur_npages > max_pages) { cifs_dbg(VFS, "out of vec array capacity (%u vs %u) ", npages + cur_npages, max_pages); break; } for (i = 0; i < cur_npages; i++) { len = rc > PAGE_SIZE ? PAGE_SIZE : rc; bv[npages + i].bv_page = pages[i]; bv[npages + i].bv_offset = start; bv[npages + i].bv_len = len - start; rc -= len; start = 0; } npages += cur_npages; } kvfree(pages); ctx->bv = bv; ctx->len = saved_len - count; ctx->npages = npages; |
aa563d7bc iov_iter: Separat... |
916 |
iov_iter_bvec(&ctx->iter, rw, ctx->bv, npages, ctx->len); |
ccf7f4088 CIFS: Add asynchr... |
917 918 |
return 0; } |
82fb82be0 CIFS: refactor cr... |
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 |
/** * cifs_alloc_hash - allocate hash and hash context together * * The caller has to make sure @sdesc is initialized to either NULL or * a valid context. Both can be freed via cifs_free_hash(). */ int cifs_alloc_hash(const char *name, struct crypto_shash **shash, struct sdesc **sdesc) { int rc = 0; size_t size; if (*sdesc != NULL) return 0; *shash = crypto_alloc_shash(name, 0, 0); if (IS_ERR(*shash)) { |
a0a3036b8 cifs: Standardize... |
938 939 |
cifs_dbg(VFS, "Could not allocate crypto %s ", name); |
82fb82be0 CIFS: refactor cr... |
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 |
rc = PTR_ERR(*shash); *shash = NULL; *sdesc = NULL; return rc; } size = sizeof(struct shash_desc) + crypto_shash_descsize(*shash); *sdesc = kmalloc(size, GFP_KERNEL); if (*sdesc == NULL) { cifs_dbg(VFS, "no memory left to allocate crypto %s ", name); crypto_free_shash(*shash); *shash = NULL; return -ENOMEM; } (*sdesc)->shash.tfm = *shash; |
82fb82be0 CIFS: refactor cr... |
957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 |
return 0; } /** * cifs_free_hash - free hash and hash context together * * Freeing a NULL hash or context is safe. */ void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc) { kfree(*sdesc); *sdesc = NULL; if (*shash) crypto_free_shash(*shash); *shash = NULL; } |
7b7f2bdf8 CIFS: Introduce h... |
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 |
/** * rqst_page_get_length - obtain the length and offset for a page in smb_rqst * 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) { *len = rqst->rq_pagesz; *offset = (page == 0) ? rqst->rq_offset : 0; if (rqst->rq_npages == 1 || page == rqst->rq_npages-1) *len = rqst->rq_tailsz; else if (page == 0) *len = rqst->rq_pagesz - rqst->rq_offset; } |
a3a53b760 cifs: Add support... |
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 |
void extract_unc_hostname(const char *unc, const char **h, size_t *len) { const char *end; /* skip initial slashes */ while (*unc && (*unc == '\\' || *unc == '/')) unc++; end = unc; while (*end && !(*end == '\\' || *end == '/')) end++; *h = unc; *len = end - unc; } |
340625e61 cifs: replace var... |
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 |
/** * copy_path_name - copy src path to dst, possibly truncating * * returns number of bytes written (including trailing nul) */ int copy_path_name(char *dst, const char *src) { int name_len; /* * PATH_MAX includes nul, so if strlen(src) >= PATH_MAX it * will truncate and strlen(dst) will be PATH_MAX-1 */ name_len = strscpy(dst, src, PATH_MAX); if (WARN_ON_ONCE(name_len < 0)) name_len = PATH_MAX-1; /* we count the trailing nul */ name_len++; return name_len; } |
bacd704a9 cifs: handle pref... |
1030 1031 |
struct super_cb_data { |
3786f4bdd cifs: ensure corr... |
1032 |
void *data; |
bacd704a9 cifs: handle pref... |
1033 1034 |
struct super_block *sb; }; |
3786f4bdd cifs: ensure corr... |
1035 |
static void tcp_super_cb(struct super_block *sb, void *arg) |
bacd704a9 cifs: handle pref... |
1036 |
{ |
3786f4bdd cifs: ensure corr... |
1037 1038 |
struct super_cb_data *sd = arg; struct TCP_Server_Info *server = sd->data; |
bacd704a9 cifs: handle pref... |
1039 1040 |
struct cifs_sb_info *cifs_sb; struct cifs_tcon *tcon; |
3786f4bdd cifs: ensure corr... |
1041 |
if (sd->sb) |
bacd704a9 cifs: handle pref... |
1042 1043 1044 1045 |
return; cifs_sb = CIFS_SB(sb); tcon = cifs_sb_master_tcon(cifs_sb); |
3786f4bdd cifs: ensure corr... |
1046 1047 |
if (tcon->ses->server == server) sd->sb = sb; |
bacd704a9 cifs: handle pref... |
1048 |
} |
3786f4bdd cifs: ensure corr... |
1049 1050 |
static struct super_block *__cifs_get_super(void (*f)(struct super_block *, void *), void *data) |
bacd704a9 cifs: handle pref... |
1051 |
{ |
3786f4bdd cifs: ensure corr... |
1052 1053 |
struct super_cb_data sd = { .data = data, |
bacd704a9 cifs: handle pref... |
1054 1055 |
.sb = NULL, }; |
3786f4bdd cifs: ensure corr... |
1056 |
iterate_supers_type(&cifs_fs_type, f, &sd); |
bacd704a9 cifs: handle pref... |
1057 |
|
3786f4bdd cifs: ensure corr... |
1058 1059 |
if (!sd.sb) return ERR_PTR(-EINVAL); |
bacd704a9 cifs: handle pref... |
1060 1061 1062 1063 1064 |
/* * Grab an active reference in order to prevent automounts (DFS links) * of expiring and then freeing up our cifs superblock pointer while * we're doing failover. */ |
3786f4bdd cifs: ensure corr... |
1065 1066 |
cifs_sb_active(sd.sb); return sd.sb; |
bacd704a9 cifs: handle pref... |
1067 |
} |
3786f4bdd cifs: ensure corr... |
1068 |
static void __cifs_put_super(struct super_block *sb) |
bacd704a9 cifs: handle pref... |
1069 1070 1071 1072 |
{ if (!IS_ERR_OR_NULL(sb)) cifs_sb_deactive(sb); } |
3786f4bdd cifs: ensure corr... |
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 |
struct super_block *cifs_get_tcp_super(struct TCP_Server_Info *server) { return __cifs_get_super(tcp_super_cb, server); } void cifs_put_tcp_super(struct super_block *sb) { __cifs_put_super(sb); } #ifdef CONFIG_CIFS_DFS_UPCALL |
e4af35fa5 cifs: handle host... |
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 |
int match_target_ip(struct TCP_Server_Info *server, const char *share, size_t share_len, bool *result) { int rc; char *target, *tip = NULL; struct sockaddr tipaddr; *result = false; target = kzalloc(share_len + 3, GFP_KERNEL); if (!target) { rc = -ENOMEM; goto out; } scnprintf(target, share_len + 3, "\\\\%.*s", (int)share_len, share); cifs_dbg(FYI, "%s: target name: %s ", __func__, target + 2); rc = dns_resolve_server_name_to_ip(target, &tip); if (rc < 0) goto out; cifs_dbg(FYI, "%s: target ip: %s ", __func__, tip); if (!cifs_convert_address(&tipaddr, tip, strlen(tip))) { cifs_dbg(VFS, "%s: failed to convert target ip address ", __func__); rc = -EINVAL; goto out; } *result = cifs_match_ipaddr((struct sockaddr *)&server->dstaddr, &tipaddr); cifs_dbg(FYI, "%s: ip addresses match: %u ", __func__, *result); rc = 0; out: kfree(target); kfree(tip); return rc; } |
3786f4bdd cifs: ensure corr... |
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 |
static void tcon_super_cb(struct super_block *sb, void *arg) { struct super_cb_data *sd = arg; struct cifs_tcon *tcon = sd->data; struct cifs_sb_info *cifs_sb; if (sd->sb) return; cifs_sb = CIFS_SB(sb); if (tcon->dfs_path && cifs_sb->origin_fullpath && !strcasecmp(tcon->dfs_path, cifs_sb->origin_fullpath)) sd->sb = sb; } static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) { return __cifs_get_super(tcon_super_cb, tcon); } static inline void cifs_put_tcon_super(struct super_block *sb) { __cifs_put_super(sb); } #else static inline struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon) { return ERR_PTR(-EOPNOTSUPP); } static inline void cifs_put_tcon_super(struct super_block *sb) { } #endif |
7548e1da8 cifs: handle RESP... |
1166 |
int update_super_prepath(struct cifs_tcon *tcon, char *prefix) |
bacd704a9 cifs: handle pref... |
1167 1168 1169 1170 |
{ struct super_block *sb; struct cifs_sb_info *cifs_sb; int rc = 0; |
3786f4bdd cifs: ensure corr... |
1171 |
sb = cifs_get_tcon_super(tcon); |
bacd704a9 cifs: handle pref... |
1172 1173 1174 1175 1176 1177 |
if (IS_ERR(sb)) return PTR_ERR(sb); cifs_sb = CIFS_SB(sb); kfree(cifs_sb->prepath); |
7548e1da8 cifs: handle RESP... |
1178 1179 |
if (prefix && *prefix) { cifs_sb->prepath = kstrndup(prefix, strlen(prefix), GFP_ATOMIC); |
bacd704a9 cifs: handle pref... |
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 |
if (!cifs_sb->prepath) { rc = -ENOMEM; goto out; } convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); } else cifs_sb->prepath = NULL; cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; out: |
3786f4bdd cifs: ensure corr... |
1192 |
cifs_put_tcon_super(sb); |
bacd704a9 cifs: handle pref... |
1193 1194 |
return rc; } |