Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French.

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
CIFS: Move get_next_mid to ops struct
CIFS: Make accessing is_valid_oplock/dump_detail ops struct field safe
CIFS: Improve identation in cifs_unlock_range
CIFS: Fix possible wrong memory allocation

+167 -143
+7
fs/cifs/cifsglob.h
··· 174 174 void (*add_credits)(struct TCP_Server_Info *, const unsigned int); 175 175 void (*set_credits)(struct TCP_Server_Info *, const int); 176 176 int * (*get_credits_field)(struct TCP_Server_Info *); 177 + __u64 (*get_next_mid)(struct TCP_Server_Info *); 177 178 /* data offset from read response message */ 178 179 unsigned int (*read_data_offset)(char *); 179 180 /* data length from read response message */ ··· 398 397 set_credits(struct TCP_Server_Info *server, const int val) 399 398 { 400 399 server->ops->set_credits(server, val); 400 + } 401 + 402 + static inline __u64 403 + get_next_mid(struct TCP_Server_Info *server) 404 + { 405 + return server->ops->get_next_mid(server); 401 406 } 402 407 403 408 /*
-1
fs/cifs/cifsproto.h
··· 114 114 void **request_buf); 115 115 extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, 116 116 const struct nls_table *nls_cp); 117 - extern __u64 GetNextMid(struct TCP_Server_Info *server); 118 117 extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); 119 118 extern u64 cifs_UnixTimeToNT(struct timespec); 120 119 extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time,
+4 -4
fs/cifs/cifssmb.c
··· 268 268 return rc; 269 269 270 270 buffer = (struct smb_hdr *)*request_buf; 271 - buffer->Mid = GetNextMid(ses->server); 271 + buffer->Mid = get_next_mid(ses->server); 272 272 if (ses->capabilities & CAP_UNICODE) 273 273 buffer->Flags2 |= SMBFLG2_UNICODE; 274 274 if (ses->capabilities & CAP_STATUS32) ··· 402 402 403 403 cFYI(1, "secFlags 0x%x", secFlags); 404 404 405 - pSMB->hdr.Mid = GetNextMid(server); 405 + pSMB->hdr.Mid = get_next_mid(server); 406 406 pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); 407 407 408 408 if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) ··· 782 782 return rc; 783 783 } 784 784 785 - pSMB->hdr.Mid = GetNextMid(ses->server); 785 + pSMB->hdr.Mid = get_next_mid(ses->server); 786 786 787 787 if (ses->server->sec_mode & 788 788 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) ··· 4762 4762 4763 4763 /* server pointer checked in called function, 4764 4764 but should never be null here anyway */ 4765 - pSMB->hdr.Mid = GetNextMid(ses->server); 4765 + pSMB->hdr.Mid = get_next_mid(ses->server); 4766 4766 pSMB->hdr.Tid = ses->ipc_tid; 4767 4767 pSMB->hdr.Uid = ses->Suid; 4768 4768 if (ses->capabilities & CAP_STATUS32)
+5 -3
fs/cifs/connect.c
··· 1058 1058 if (mid_entry != NULL) { 1059 1059 if (!mid_entry->multiRsp || mid_entry->multiEnd) 1060 1060 mid_entry->callback(mid_entry); 1061 - } else if (!server->ops->is_oplock_break(buf, server)) { 1061 + } else if (!server->ops->is_oplock_break || 1062 + !server->ops->is_oplock_break(buf, server)) { 1062 1063 cERROR(1, "No task to wake, unknown frame received! " 1063 1064 "NumMids %d", atomic_read(&midCount)); 1064 1065 cifs_dump_mem("Received Data is: ", buf, 1065 1066 HEADER_SIZE(server)); 1066 1067 #ifdef CONFIG_CIFS_DEBUG2 1067 - server->ops->dump_detail(buf); 1068 + if (server->ops->dump_detail) 1069 + server->ops->dump_detail(buf); 1068 1070 cifs_dump_mids(server); 1069 1071 #endif /* CIFS_DEBUG2 */ 1070 1072 ··· 3940 3938 header_assemble(smb_buffer, SMB_COM_TREE_CONNECT_ANDX, 3941 3939 NULL /*no tid */ , 4 /*wct */ ); 3942 3940 3943 - smb_buffer->Mid = GetNextMid(ses->server); 3941 + smb_buffer->Mid = get_next_mid(ses->server); 3944 3942 smb_buffer->Uid = ses->Suid; 3945 3943 pSMB = (TCONX_REQ *) smb_buffer; 3946 3944 pSMBr = (TCONX_RSP *) smb_buffer_response;
+60 -46
fs/cifs/file.c
··· 876 876 struct cifsLockInfo *li, *tmp; 877 877 struct cifs_tcon *tcon; 878 878 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); 879 - unsigned int num, max_num; 879 + unsigned int num, max_num, max_buf; 880 880 LOCKING_ANDX_RANGE *buf, *cur; 881 881 int types[] = {LOCKING_ANDX_LARGE_FILES, 882 882 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; ··· 892 892 return rc; 893 893 } 894 894 895 - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / 896 - sizeof(LOCKING_ANDX_RANGE); 895 + /* 896 + * Accessing maxBuf is racy with cifs_reconnect - need to store value 897 + * and check it for zero before using. 898 + */ 899 + max_buf = tcon->ses->server->maxBuf; 900 + if (!max_buf) { 901 + mutex_unlock(&cinode->lock_mutex); 902 + FreeXid(xid); 903 + return -EINVAL; 904 + } 905 + 906 + max_num = (max_buf - sizeof(struct smb_hdr)) / 907 + sizeof(LOCKING_ANDX_RANGE); 897 908 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); 898 909 if (!buf) { 899 910 mutex_unlock(&cinode->lock_mutex); ··· 1229 1218 int types[] = {LOCKING_ANDX_LARGE_FILES, 1230 1219 LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; 1231 1220 unsigned int i; 1232 - unsigned int max_num, num; 1221 + unsigned int max_num, num, max_buf; 1233 1222 LOCKING_ANDX_RANGE *buf, *cur; 1234 1223 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 1235 1224 struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); ··· 1239 1228 1240 1229 INIT_LIST_HEAD(&tmp_llist); 1241 1230 1242 - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / 1243 - sizeof(LOCKING_ANDX_RANGE); 1231 + /* 1232 + * Accessing maxBuf is racy with cifs_reconnect - need to store value 1233 + * and check it for zero before using. 1234 + */ 1235 + max_buf = tcon->ses->server->maxBuf; 1236 + if (!max_buf) 1237 + return -EINVAL; 1238 + 1239 + max_num = (max_buf - sizeof(struct smb_hdr)) / 1240 + sizeof(LOCKING_ANDX_RANGE); 1244 1241 buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); 1245 1242 if (!buf) 1246 1243 return -ENOMEM; ··· 1266 1247 continue; 1267 1248 if (types[i] != li->type) 1268 1249 continue; 1269 - if (!cinode->can_cache_brlcks) { 1270 - cur->Pid = cpu_to_le16(li->pid); 1271 - cur->LengthLow = cpu_to_le32((u32)li->length); 1272 - cur->LengthHigh = 1273 - cpu_to_le32((u32)(li->length>>32)); 1274 - cur->OffsetLow = cpu_to_le32((u32)li->offset); 1275 - cur->OffsetHigh = 1276 - cpu_to_le32((u32)(li->offset>>32)); 1277 - /* 1278 - * We need to save a lock here to let us add 1279 - * it again to the file's list if the unlock 1280 - * range request fails on the server. 1281 - */ 1282 - list_move(&li->llist, &tmp_llist); 1283 - if (++num == max_num) { 1284 - stored_rc = cifs_lockv(xid, tcon, 1285 - cfile->netfid, 1286 - li->type, num, 1287 - 0, buf); 1288 - if (stored_rc) { 1289 - /* 1290 - * We failed on the unlock range 1291 - * request - add all locks from 1292 - * the tmp list to the head of 1293 - * the file's list. 1294 - */ 1295 - cifs_move_llist(&tmp_llist, 1296 - &cfile->llist); 1297 - rc = stored_rc; 1298 - } else 1299 - /* 1300 - * The unlock range request 1301 - * succeed - free the tmp list. 1302 - */ 1303 - cifs_free_llist(&tmp_llist); 1304 - cur = buf; 1305 - num = 0; 1306 - } else 1307 - cur++; 1308 - } else { 1250 + if (cinode->can_cache_brlcks) { 1309 1251 /* 1310 1252 * We can cache brlock requests - simply remove 1311 1253 * a lock from the file's list. ··· 1274 1294 list_del(&li->llist); 1275 1295 cifs_del_lock_waiters(li); 1276 1296 kfree(li); 1297 + continue; 1277 1298 } 1299 + cur->Pid = cpu_to_le16(li->pid); 1300 + cur->LengthLow = cpu_to_le32((u32)li->length); 1301 + cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); 1302 + cur->OffsetLow = cpu_to_le32((u32)li->offset); 1303 + cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); 1304 + /* 1305 + * We need to save a lock here to let us add it again to 1306 + * the file's list if the unlock range request fails on 1307 + * the server. 1308 + */ 1309 + list_move(&li->llist, &tmp_llist); 1310 + if (++num == max_num) { 1311 + stored_rc = cifs_lockv(xid, tcon, cfile->netfid, 1312 + li->type, num, 0, buf); 1313 + if (stored_rc) { 1314 + /* 1315 + * We failed on the unlock range 1316 + * request - add all locks from the tmp 1317 + * list to the head of the file's list. 1318 + */ 1319 + cifs_move_llist(&tmp_llist, 1320 + &cfile->llist); 1321 + rc = stored_rc; 1322 + } else 1323 + /* 1324 + * The unlock range request succeed - 1325 + * free the tmp list. 1326 + */ 1327 + cifs_free_llist(&tmp_llist); 1328 + cur = buf; 1329 + num = 0; 1330 + } else 1331 + cur++; 1278 1332 } 1279 1333 if (num) { 1280 1334 stored_rc = cifs_lockv(xid, tcon, cfile->netfid,
+1 -88
fs/cifs/misc.c
··· 212 212 return; 213 213 } 214 214 215 - /* 216 - * Find a free multiplex id (SMB mid). Otherwise there could be 217 - * mid collisions which might cause problems, demultiplexing the 218 - * wrong response to this request. Multiplex ids could collide if 219 - * one of a series requests takes much longer than the others, or 220 - * if a very large number of long lived requests (byte range 221 - * locks or FindNotify requests) are pending. No more than 222 - * 64K-1 requests can be outstanding at one time. If no 223 - * mids are available, return zero. A future optimization 224 - * could make the combination of mids and uid the key we use 225 - * to demultiplex on (rather than mid alone). 226 - * In addition to the above check, the cifs demultiplex 227 - * code already used the command code as a secondary 228 - * check of the frame and if signing is negotiated the 229 - * response would be discarded if the mid were the same 230 - * but the signature was wrong. Since the mid is not put in the 231 - * pending queue until later (when it is about to be dispatched) 232 - * we do have to limit the number of outstanding requests 233 - * to somewhat less than 64K-1 although it is hard to imagine 234 - * so many threads being in the vfs at one time. 235 - */ 236 - __u64 GetNextMid(struct TCP_Server_Info *server) 237 - { 238 - __u64 mid = 0; 239 - __u16 last_mid, cur_mid; 240 - bool collision; 241 - 242 - spin_lock(&GlobalMid_Lock); 243 - 244 - /* mid is 16 bit only for CIFS/SMB */ 245 - cur_mid = (__u16)((server->CurrentMid) & 0xffff); 246 - /* we do not want to loop forever */ 247 - last_mid = cur_mid; 248 - cur_mid++; 249 - 250 - /* 251 - * This nested loop looks more expensive than it is. 252 - * In practice the list of pending requests is short, 253 - * fewer than 50, and the mids are likely to be unique 254 - * on the first pass through the loop unless some request 255 - * takes longer than the 64 thousand requests before it 256 - * (and it would also have to have been a request that 257 - * did not time out). 258 - */ 259 - while (cur_mid != last_mid) { 260 - struct mid_q_entry *mid_entry; 261 - unsigned int num_mids; 262 - 263 - collision = false; 264 - if (cur_mid == 0) 265 - cur_mid++; 266 - 267 - num_mids = 0; 268 - list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { 269 - ++num_mids; 270 - if (mid_entry->mid == cur_mid && 271 - mid_entry->mid_state == MID_REQUEST_SUBMITTED) { 272 - /* This mid is in use, try a different one */ 273 - collision = true; 274 - break; 275 - } 276 - } 277 - 278 - /* 279 - * if we have more than 32k mids in the list, then something 280 - * is very wrong. Possibly a local user is trying to DoS the 281 - * box by issuing long-running calls and SIGKILL'ing them. If 282 - * we get to 2^16 mids then we're in big trouble as this 283 - * function could loop forever. 284 - * 285 - * Go ahead and assign out the mid in this situation, but force 286 - * an eventual reconnect to clean out the pending_mid_q. 287 - */ 288 - if (num_mids > 32768) 289 - server->tcpStatus = CifsNeedReconnect; 290 - 291 - if (!collision) { 292 - mid = (__u64)cur_mid; 293 - server->CurrentMid = mid; 294 - break; 295 - } 296 - cur_mid++; 297 - } 298 - spin_unlock(&GlobalMid_Lock); 299 - return mid; 300 - } 301 - 302 215 /* NB: MID can not be set if treeCon not passed in, in that 303 216 case it is responsbility of caller to set the mid */ 304 217 void ··· 247 334 248 335 /* Uid is not converted */ 249 336 buffer->Uid = treeCon->ses->Suid; 250 - buffer->Mid = GetNextMid(treeCon->ses->server); 337 + buffer->Mid = get_next_mid(treeCon->ses->server); 251 338 } 252 339 if (treeCon->Flags & SMB_SHARE_IS_IN_DFS) 253 340 buffer->Flags2 |= SMBFLG2_DFS;
+89
fs/cifs/smb1ops.c
··· 125 125 return &server->credits; 126 126 } 127 127 128 + /* 129 + * Find a free multiplex id (SMB mid). Otherwise there could be 130 + * mid collisions which might cause problems, demultiplexing the 131 + * wrong response to this request. Multiplex ids could collide if 132 + * one of a series requests takes much longer than the others, or 133 + * if a very large number of long lived requests (byte range 134 + * locks or FindNotify requests) are pending. No more than 135 + * 64K-1 requests can be outstanding at one time. If no 136 + * mids are available, return zero. A future optimization 137 + * could make the combination of mids and uid the key we use 138 + * to demultiplex on (rather than mid alone). 139 + * In addition to the above check, the cifs demultiplex 140 + * code already used the command code as a secondary 141 + * check of the frame and if signing is negotiated the 142 + * response would be discarded if the mid were the same 143 + * but the signature was wrong. Since the mid is not put in the 144 + * pending queue until later (when it is about to be dispatched) 145 + * we do have to limit the number of outstanding requests 146 + * to somewhat less than 64K-1 although it is hard to imagine 147 + * so many threads being in the vfs at one time. 148 + */ 149 + static __u64 150 + cifs_get_next_mid(struct TCP_Server_Info *server) 151 + { 152 + __u64 mid = 0; 153 + __u16 last_mid, cur_mid; 154 + bool collision; 155 + 156 + spin_lock(&GlobalMid_Lock); 157 + 158 + /* mid is 16 bit only for CIFS/SMB */ 159 + cur_mid = (__u16)((server->CurrentMid) & 0xffff); 160 + /* we do not want to loop forever */ 161 + last_mid = cur_mid; 162 + cur_mid++; 163 + 164 + /* 165 + * This nested loop looks more expensive than it is. 166 + * In practice the list of pending requests is short, 167 + * fewer than 50, and the mids are likely to be unique 168 + * on the first pass through the loop unless some request 169 + * takes longer than the 64 thousand requests before it 170 + * (and it would also have to have been a request that 171 + * did not time out). 172 + */ 173 + while (cur_mid != last_mid) { 174 + struct mid_q_entry *mid_entry; 175 + unsigned int num_mids; 176 + 177 + collision = false; 178 + if (cur_mid == 0) 179 + cur_mid++; 180 + 181 + num_mids = 0; 182 + list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { 183 + ++num_mids; 184 + if (mid_entry->mid == cur_mid && 185 + mid_entry->mid_state == MID_REQUEST_SUBMITTED) { 186 + /* This mid is in use, try a different one */ 187 + collision = true; 188 + break; 189 + } 190 + } 191 + 192 + /* 193 + * if we have more than 32k mids in the list, then something 194 + * is very wrong. Possibly a local user is trying to DoS the 195 + * box by issuing long-running calls and SIGKILL'ing them. If 196 + * we get to 2^16 mids then we're in big trouble as this 197 + * function could loop forever. 198 + * 199 + * Go ahead and assign out the mid in this situation, but force 200 + * an eventual reconnect to clean out the pending_mid_q. 201 + */ 202 + if (num_mids > 32768) 203 + server->tcpStatus = CifsNeedReconnect; 204 + 205 + if (!collision) { 206 + mid = (__u64)cur_mid; 207 + server->CurrentMid = mid; 208 + break; 209 + } 210 + cur_mid++; 211 + } 212 + spin_unlock(&GlobalMid_Lock); 213 + return mid; 214 + } 215 + 128 216 struct smb_version_operations smb1_operations = { 129 217 .send_cancel = send_nt_cancel, 130 218 .compare_fids = cifs_compare_fids, ··· 221 133 .add_credits = cifs_add_credits, 222 134 .set_credits = cifs_set_credits, 223 135 .get_credits_field = cifs_get_credits_field, 136 + .get_next_mid = cifs_get_next_mid, 224 137 .read_data_offset = cifs_read_data_offset, 225 138 .read_data_length = cifs_read_data_length, 226 139 .map_error = map_smb_to_linux_error,
+1 -1
fs/cifs/transport.c
··· 779 779 780 780 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; 781 781 pSMB->Timeout = 0; 782 - pSMB->hdr.Mid = GetNextMid(ses->server); 782 + pSMB->hdr.Mid = get_next_mid(ses->server); 783 783 784 784 return SendReceive(xid, ses, in_buf, out_buf, 785 785 &bytes_returned, 0);