1*38c8a9a5SSteve French // SPDX-License-Identifier: GPL-2.0-only 2*38c8a9a5SSteve French /* 3*38c8a9a5SSteve French * SMB1 (CIFS) version specific operations 4*38c8a9a5SSteve French * 5*38c8a9a5SSteve French * Copyright (c) 2012, Jeff Layton <jlayton@redhat.com> 6*38c8a9a5SSteve French */ 7*38c8a9a5SSteve French 8*38c8a9a5SSteve French #include <linux/pagemap.h> 9*38c8a9a5SSteve French #include <linux/vfs.h> 10*38c8a9a5SSteve French #include <uapi/linux/magic.h> 11*38c8a9a5SSteve French #include "cifsglob.h" 12*38c8a9a5SSteve French #include "cifsproto.h" 13*38c8a9a5SSteve French #include "cifs_debug.h" 14*38c8a9a5SSteve French #include "cifspdu.h" 15*38c8a9a5SSteve French #include "cifs_unicode.h" 16*38c8a9a5SSteve French #include "fs_context.h" 17*38c8a9a5SSteve French 18*38c8a9a5SSteve French /* 19*38c8a9a5SSteve French * An NT cancel request header looks just like the original request except: 20*38c8a9a5SSteve French * 21*38c8a9a5SSteve French * The Command is SMB_COM_NT_CANCEL 22*38c8a9a5SSteve French * The WordCount is zeroed out 23*38c8a9a5SSteve French * The ByteCount is zeroed out 24*38c8a9a5SSteve French * 25*38c8a9a5SSteve French * This function mangles an existing request buffer into a 26*38c8a9a5SSteve French * SMB_COM_NT_CANCEL request and then sends it. 27*38c8a9a5SSteve French */ 28*38c8a9a5SSteve French static int 29*38c8a9a5SSteve French send_nt_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst, 30*38c8a9a5SSteve French struct mid_q_entry *mid) 31*38c8a9a5SSteve French { 32*38c8a9a5SSteve French int rc = 0; 33*38c8a9a5SSteve French struct smb_hdr *in_buf = (struct smb_hdr *)rqst->rq_iov[0].iov_base; 34*38c8a9a5SSteve French 35*38c8a9a5SSteve French /* -4 for RFC1001 length and +2 for BCC field */ 36*38c8a9a5SSteve French in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2); 37*38c8a9a5SSteve French in_buf->Command = SMB_COM_NT_CANCEL; 38*38c8a9a5SSteve French in_buf->WordCount = 0; 39*38c8a9a5SSteve French put_bcc(0, in_buf); 40*38c8a9a5SSteve French 41*38c8a9a5SSteve French cifs_server_lock(server); 42*38c8a9a5SSteve French rc = cifs_sign_smb(in_buf, server, &mid->sequence_number); 43*38c8a9a5SSteve French if (rc) { 44*38c8a9a5SSteve French cifs_server_unlock(server); 45*38c8a9a5SSteve French return rc; 46*38c8a9a5SSteve French } 47*38c8a9a5SSteve French 48*38c8a9a5SSteve French /* 49*38c8a9a5SSteve French * The response to this call was already factored into the sequence 50*38c8a9a5SSteve French * number when the call went out, so we must adjust it back downward 51*38c8a9a5SSteve French * after signing here. 52*38c8a9a5SSteve French */ 53*38c8a9a5SSteve French --server->sequence_number; 54*38c8a9a5SSteve French rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); 55*38c8a9a5SSteve French if (rc < 0) 56*38c8a9a5SSteve French server->sequence_number--; 57*38c8a9a5SSteve French 58*38c8a9a5SSteve French cifs_server_unlock(server); 59*38c8a9a5SSteve French 60*38c8a9a5SSteve French cifs_dbg(FYI, "issued NT_CANCEL for mid %u, rc = %d\n", 61*38c8a9a5SSteve French get_mid(in_buf), rc); 62*38c8a9a5SSteve French 63*38c8a9a5SSteve French return rc; 64*38c8a9a5SSteve French } 65*38c8a9a5SSteve French 66*38c8a9a5SSteve French static bool 67*38c8a9a5SSteve French cifs_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2) 68*38c8a9a5SSteve French { 69*38c8a9a5SSteve French return ob1->fid.netfid == ob2->fid.netfid; 70*38c8a9a5SSteve French } 71*38c8a9a5SSteve French 72*38c8a9a5SSteve French static unsigned int 73*38c8a9a5SSteve French cifs_read_data_offset(char *buf) 74*38c8a9a5SSteve French { 75*38c8a9a5SSteve French READ_RSP *rsp = (READ_RSP *)buf; 76*38c8a9a5SSteve French return le16_to_cpu(rsp->DataOffset); 77*38c8a9a5SSteve French } 78*38c8a9a5SSteve French 79*38c8a9a5SSteve French static unsigned int 80*38c8a9a5SSteve French cifs_read_data_length(char *buf, bool in_remaining) 81*38c8a9a5SSteve French { 82*38c8a9a5SSteve French READ_RSP *rsp = (READ_RSP *)buf; 83*38c8a9a5SSteve French /* It's a bug reading remaining data for SMB1 packets */ 84*38c8a9a5SSteve French WARN_ON(in_remaining); 85*38c8a9a5SSteve French return (le16_to_cpu(rsp->DataLengthHigh) << 16) + 86*38c8a9a5SSteve French le16_to_cpu(rsp->DataLength); 87*38c8a9a5SSteve French } 88*38c8a9a5SSteve French 89*38c8a9a5SSteve French static struct mid_q_entry * 90*38c8a9a5SSteve French cifs_find_mid(struct TCP_Server_Info *server, char *buffer) 91*38c8a9a5SSteve French { 92*38c8a9a5SSteve French struct smb_hdr *buf = (struct smb_hdr *)buffer; 93*38c8a9a5SSteve French struct mid_q_entry *mid; 94*38c8a9a5SSteve French 95*38c8a9a5SSteve French spin_lock(&server->mid_lock); 96*38c8a9a5SSteve French list_for_each_entry(mid, &server->pending_mid_q, qhead) { 97*38c8a9a5SSteve French if (compare_mid(mid->mid, buf) && 98*38c8a9a5SSteve French mid->mid_state == MID_REQUEST_SUBMITTED && 99*38c8a9a5SSteve French le16_to_cpu(mid->command) == buf->Command) { 100*38c8a9a5SSteve French kref_get(&mid->refcount); 101*38c8a9a5SSteve French spin_unlock(&server->mid_lock); 102*38c8a9a5SSteve French return mid; 103*38c8a9a5SSteve French } 104*38c8a9a5SSteve French } 105*38c8a9a5SSteve French spin_unlock(&server->mid_lock); 106*38c8a9a5SSteve French return NULL; 107*38c8a9a5SSteve French } 108*38c8a9a5SSteve French 109*38c8a9a5SSteve French static void 110*38c8a9a5SSteve French cifs_add_credits(struct TCP_Server_Info *server, 111*38c8a9a5SSteve French const struct cifs_credits *credits, const int optype) 112*38c8a9a5SSteve French { 113*38c8a9a5SSteve French spin_lock(&server->req_lock); 114*38c8a9a5SSteve French server->credits += credits->value; 115*38c8a9a5SSteve French server->in_flight--; 116*38c8a9a5SSteve French spin_unlock(&server->req_lock); 117*38c8a9a5SSteve French wake_up(&server->request_q); 118*38c8a9a5SSteve French } 119*38c8a9a5SSteve French 120*38c8a9a5SSteve French static void 121*38c8a9a5SSteve French cifs_set_credits(struct TCP_Server_Info *server, const int val) 122*38c8a9a5SSteve French { 123*38c8a9a5SSteve French spin_lock(&server->req_lock); 124*38c8a9a5SSteve French server->credits = val; 125*38c8a9a5SSteve French server->oplocks = val > 1 ? enable_oplocks : false; 126*38c8a9a5SSteve French spin_unlock(&server->req_lock); 127*38c8a9a5SSteve French } 128*38c8a9a5SSteve French 129*38c8a9a5SSteve French static int * 130*38c8a9a5SSteve French cifs_get_credits_field(struct TCP_Server_Info *server, const int optype) 131*38c8a9a5SSteve French { 132*38c8a9a5SSteve French return &server->credits; 133*38c8a9a5SSteve French } 134*38c8a9a5SSteve French 135*38c8a9a5SSteve French static unsigned int 136*38c8a9a5SSteve French cifs_get_credits(struct mid_q_entry *mid) 137*38c8a9a5SSteve French { 138*38c8a9a5SSteve French return 1; 139*38c8a9a5SSteve French } 140*38c8a9a5SSteve French 141*38c8a9a5SSteve French /* 142*38c8a9a5SSteve French * Find a free multiplex id (SMB mid). Otherwise there could be 143*38c8a9a5SSteve French * mid collisions which might cause problems, demultiplexing the 144*38c8a9a5SSteve French * wrong response to this request. Multiplex ids could collide if 145*38c8a9a5SSteve French * one of a series requests takes much longer than the others, or 146*38c8a9a5SSteve French * if a very large number of long lived requests (byte range 147*38c8a9a5SSteve French * locks or FindNotify requests) are pending. No more than 148*38c8a9a5SSteve French * 64K-1 requests can be outstanding at one time. If no 149*38c8a9a5SSteve French * mids are available, return zero. A future optimization 150*38c8a9a5SSteve French * could make the combination of mids and uid the key we use 151*38c8a9a5SSteve French * to demultiplex on (rather than mid alone). 152*38c8a9a5SSteve French * In addition to the above check, the cifs demultiplex 153*38c8a9a5SSteve French * code already used the command code as a secondary 154*38c8a9a5SSteve French * check of the frame and if signing is negotiated the 155*38c8a9a5SSteve French * response would be discarded if the mid were the same 156*38c8a9a5SSteve French * but the signature was wrong. Since the mid is not put in the 157*38c8a9a5SSteve French * pending queue until later (when it is about to be dispatched) 158*38c8a9a5SSteve French * we do have to limit the number of outstanding requests 159*38c8a9a5SSteve French * to somewhat less than 64K-1 although it is hard to imagine 160*38c8a9a5SSteve French * so many threads being in the vfs at one time. 161*38c8a9a5SSteve French */ 162*38c8a9a5SSteve French static __u64 163*38c8a9a5SSteve French cifs_get_next_mid(struct TCP_Server_Info *server) 164*38c8a9a5SSteve French { 165*38c8a9a5SSteve French __u64 mid = 0; 166*38c8a9a5SSteve French __u16 last_mid, cur_mid; 167*38c8a9a5SSteve French bool collision, reconnect = false; 168*38c8a9a5SSteve French 169*38c8a9a5SSteve French spin_lock(&server->mid_lock); 170*38c8a9a5SSteve French 171*38c8a9a5SSteve French /* mid is 16 bit only for CIFS/SMB */ 172*38c8a9a5SSteve French cur_mid = (__u16)((server->CurrentMid) & 0xffff); 173*38c8a9a5SSteve French /* we do not want to loop forever */ 174*38c8a9a5SSteve French last_mid = cur_mid; 175*38c8a9a5SSteve French cur_mid++; 176*38c8a9a5SSteve French /* avoid 0xFFFF MID */ 177*38c8a9a5SSteve French if (cur_mid == 0xffff) 178*38c8a9a5SSteve French cur_mid++; 179*38c8a9a5SSteve French 180*38c8a9a5SSteve French /* 181*38c8a9a5SSteve French * This nested loop looks more expensive than it is. 182*38c8a9a5SSteve French * In practice the list of pending requests is short, 183*38c8a9a5SSteve French * fewer than 50, and the mids are likely to be unique 184*38c8a9a5SSteve French * on the first pass through the loop unless some request 185*38c8a9a5SSteve French * takes longer than the 64 thousand requests before it 186*38c8a9a5SSteve French * (and it would also have to have been a request that 187*38c8a9a5SSteve French * did not time out). 188*38c8a9a5SSteve French */ 189*38c8a9a5SSteve French while (cur_mid != last_mid) { 190*38c8a9a5SSteve French struct mid_q_entry *mid_entry; 191*38c8a9a5SSteve French unsigned int num_mids; 192*38c8a9a5SSteve French 193*38c8a9a5SSteve French collision = false; 194*38c8a9a5SSteve French if (cur_mid == 0) 195*38c8a9a5SSteve French cur_mid++; 196*38c8a9a5SSteve French 197*38c8a9a5SSteve French num_mids = 0; 198*38c8a9a5SSteve French list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { 199*38c8a9a5SSteve French ++num_mids; 200*38c8a9a5SSteve French if (mid_entry->mid == cur_mid && 201*38c8a9a5SSteve French mid_entry->mid_state == MID_REQUEST_SUBMITTED) { 202*38c8a9a5SSteve French /* This mid is in use, try a different one */ 203*38c8a9a5SSteve French collision = true; 204*38c8a9a5SSteve French break; 205*38c8a9a5SSteve French } 206*38c8a9a5SSteve French } 207*38c8a9a5SSteve French 208*38c8a9a5SSteve French /* 209*38c8a9a5SSteve French * if we have more than 32k mids in the list, then something 210*38c8a9a5SSteve French * is very wrong. Possibly a local user is trying to DoS the 211*38c8a9a5SSteve French * box by issuing long-running calls and SIGKILL'ing them. If 212*38c8a9a5SSteve French * we get to 2^16 mids then we're in big trouble as this 213*38c8a9a5SSteve French * function could loop forever. 214*38c8a9a5SSteve French * 215*38c8a9a5SSteve French * Go ahead and assign out the mid in this situation, but force 216*38c8a9a5SSteve French * an eventual reconnect to clean out the pending_mid_q. 217*38c8a9a5SSteve French */ 218*38c8a9a5SSteve French if (num_mids > 32768) 219*38c8a9a5SSteve French reconnect = true; 220*38c8a9a5SSteve French 221*38c8a9a5SSteve French if (!collision) { 222*38c8a9a5SSteve French mid = (__u64)cur_mid; 223*38c8a9a5SSteve French server->CurrentMid = mid; 224*38c8a9a5SSteve French break; 225*38c8a9a5SSteve French } 226*38c8a9a5SSteve French cur_mid++; 227*38c8a9a5SSteve French } 228*38c8a9a5SSteve French spin_unlock(&server->mid_lock); 229*38c8a9a5SSteve French 230*38c8a9a5SSteve French if (reconnect) { 231*38c8a9a5SSteve French cifs_signal_cifsd_for_reconnect(server, false); 232*38c8a9a5SSteve French } 233*38c8a9a5SSteve French 234*38c8a9a5SSteve French return mid; 235*38c8a9a5SSteve French } 236*38c8a9a5SSteve French 237*38c8a9a5SSteve French /* 238*38c8a9a5SSteve French return codes: 239*38c8a9a5SSteve French 0 not a transact2, or all data present 240*38c8a9a5SSteve French >0 transact2 with that much data missing 241*38c8a9a5SSteve French -EINVAL invalid transact2 242*38c8a9a5SSteve French */ 243*38c8a9a5SSteve French static int 244*38c8a9a5SSteve French check2ndT2(char *buf) 245*38c8a9a5SSteve French { 246*38c8a9a5SSteve French struct smb_hdr *pSMB = (struct smb_hdr *)buf; 247*38c8a9a5SSteve French struct smb_t2_rsp *pSMBt; 248*38c8a9a5SSteve French int remaining; 249*38c8a9a5SSteve French __u16 total_data_size, data_in_this_rsp; 250*38c8a9a5SSteve French 251*38c8a9a5SSteve French if (pSMB->Command != SMB_COM_TRANSACTION2) 252*38c8a9a5SSteve French return 0; 253*38c8a9a5SSteve French 254*38c8a9a5SSteve French /* check for plausible wct, bcc and t2 data and parm sizes */ 255*38c8a9a5SSteve French /* check for parm and data offset going beyond end of smb */ 256*38c8a9a5SSteve French if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ 257*38c8a9a5SSteve French cifs_dbg(FYI, "Invalid transact2 word count\n"); 258*38c8a9a5SSteve French return -EINVAL; 259*38c8a9a5SSteve French } 260*38c8a9a5SSteve French 261*38c8a9a5SSteve French pSMBt = (struct smb_t2_rsp *)pSMB; 262*38c8a9a5SSteve French 263*38c8a9a5SSteve French total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); 264*38c8a9a5SSteve French data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); 265*38c8a9a5SSteve French 266*38c8a9a5SSteve French if (total_data_size == data_in_this_rsp) 267*38c8a9a5SSteve French return 0; 268*38c8a9a5SSteve French else if (total_data_size < data_in_this_rsp) { 269*38c8a9a5SSteve French cifs_dbg(FYI, "total data %d smaller than data in frame %d\n", 270*38c8a9a5SSteve French total_data_size, data_in_this_rsp); 271*38c8a9a5SSteve French return -EINVAL; 272*38c8a9a5SSteve French } 273*38c8a9a5SSteve French 274*38c8a9a5SSteve French remaining = total_data_size - data_in_this_rsp; 275*38c8a9a5SSteve French 276*38c8a9a5SSteve French cifs_dbg(FYI, "missing %d bytes from transact2, check next response\n", 277*38c8a9a5SSteve French remaining); 278*38c8a9a5SSteve French if (total_data_size > CIFSMaxBufSize) { 279*38c8a9a5SSteve French cifs_dbg(VFS, "TotalDataSize %d is over maximum buffer %d\n", 280*38c8a9a5SSteve French total_data_size, CIFSMaxBufSize); 281*38c8a9a5SSteve French return -EINVAL; 282*38c8a9a5SSteve French } 283*38c8a9a5SSteve French return remaining; 284*38c8a9a5SSteve French } 285*38c8a9a5SSteve French 286*38c8a9a5SSteve French static int 287*38c8a9a5SSteve French coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) 288*38c8a9a5SSteve French { 289*38c8a9a5SSteve French struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf; 290*38c8a9a5SSteve French struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr; 291*38c8a9a5SSteve French char *data_area_of_tgt; 292*38c8a9a5SSteve French char *data_area_of_src; 293*38c8a9a5SSteve French int remaining; 294*38c8a9a5SSteve French unsigned int byte_count, total_in_tgt; 295*38c8a9a5SSteve French __u16 tgt_total_cnt, src_total_cnt, total_in_src; 296*38c8a9a5SSteve French 297*38c8a9a5SSteve French src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount); 298*38c8a9a5SSteve French tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); 299*38c8a9a5SSteve French 300*38c8a9a5SSteve French if (tgt_total_cnt != src_total_cnt) 301*38c8a9a5SSteve French cifs_dbg(FYI, "total data count of primary and secondary t2 differ source=%hu target=%hu\n", 302*38c8a9a5SSteve French src_total_cnt, tgt_total_cnt); 303*38c8a9a5SSteve French 304*38c8a9a5SSteve French total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); 305*38c8a9a5SSteve French 306*38c8a9a5SSteve French remaining = tgt_total_cnt - total_in_tgt; 307*38c8a9a5SSteve French 308*38c8a9a5SSteve French if (remaining < 0) { 309*38c8a9a5SSteve French cifs_dbg(FYI, "Server sent too much data. tgt_total_cnt=%hu total_in_tgt=%u\n", 310*38c8a9a5SSteve French tgt_total_cnt, total_in_tgt); 311*38c8a9a5SSteve French return -EPROTO; 312*38c8a9a5SSteve French } 313*38c8a9a5SSteve French 314*38c8a9a5SSteve French if (remaining == 0) { 315*38c8a9a5SSteve French /* nothing to do, ignore */ 316*38c8a9a5SSteve French cifs_dbg(FYI, "no more data remains\n"); 317*38c8a9a5SSteve French return 0; 318*38c8a9a5SSteve French } 319*38c8a9a5SSteve French 320*38c8a9a5SSteve French total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount); 321*38c8a9a5SSteve French if (remaining < total_in_src) 322*38c8a9a5SSteve French cifs_dbg(FYI, "transact2 2nd response contains too much data\n"); 323*38c8a9a5SSteve French 324*38c8a9a5SSteve French /* find end of first SMB data area */ 325*38c8a9a5SSteve French data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + 326*38c8a9a5SSteve French get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); 327*38c8a9a5SSteve French 328*38c8a9a5SSteve French /* validate target area */ 329*38c8a9a5SSteve French data_area_of_src = (char *)&pSMBs->hdr.Protocol + 330*38c8a9a5SSteve French get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); 331*38c8a9a5SSteve French 332*38c8a9a5SSteve French data_area_of_tgt += total_in_tgt; 333*38c8a9a5SSteve French 334*38c8a9a5SSteve French total_in_tgt += total_in_src; 335*38c8a9a5SSteve French /* is the result too big for the field? */ 336*38c8a9a5SSteve French if (total_in_tgt > USHRT_MAX) { 337*38c8a9a5SSteve French cifs_dbg(FYI, "coalesced DataCount too large (%u)\n", 338*38c8a9a5SSteve French total_in_tgt); 339*38c8a9a5SSteve French return -EPROTO; 340*38c8a9a5SSteve French } 341*38c8a9a5SSteve French put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); 342*38c8a9a5SSteve French 343*38c8a9a5SSteve French /* fix up the BCC */ 344*38c8a9a5SSteve French byte_count = get_bcc(target_hdr); 345*38c8a9a5SSteve French byte_count += total_in_src; 346*38c8a9a5SSteve French /* is the result too big for the field? */ 347*38c8a9a5SSteve French if (byte_count > USHRT_MAX) { 348*38c8a9a5SSteve French cifs_dbg(FYI, "coalesced BCC too large (%u)\n", byte_count); 349*38c8a9a5SSteve French return -EPROTO; 350*38c8a9a5SSteve French } 351*38c8a9a5SSteve French put_bcc(byte_count, target_hdr); 352*38c8a9a5SSteve French 353*38c8a9a5SSteve French byte_count = be32_to_cpu(target_hdr->smb_buf_length); 354*38c8a9a5SSteve French byte_count += total_in_src; 355*38c8a9a5SSteve French /* don't allow buffer to overflow */ 356*38c8a9a5SSteve French if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { 357*38c8a9a5SSteve French cifs_dbg(FYI, "coalesced BCC exceeds buffer size (%u)\n", 358*38c8a9a5SSteve French byte_count); 359*38c8a9a5SSteve French return -ENOBUFS; 360*38c8a9a5SSteve French } 361*38c8a9a5SSteve French target_hdr->smb_buf_length = cpu_to_be32(byte_count); 362*38c8a9a5SSteve French 363*38c8a9a5SSteve French /* copy second buffer into end of first buffer */ 364*38c8a9a5SSteve French memcpy(data_area_of_tgt, data_area_of_src, total_in_src); 365*38c8a9a5SSteve French 366*38c8a9a5SSteve French if (remaining != total_in_src) { 367*38c8a9a5SSteve French /* more responses to go */ 368*38c8a9a5SSteve French cifs_dbg(FYI, "waiting for more secondary responses\n"); 369*38c8a9a5SSteve French return 1; 370*38c8a9a5SSteve French } 371*38c8a9a5SSteve French 372*38c8a9a5SSteve French /* we are done */ 373*38c8a9a5SSteve French cifs_dbg(FYI, "found the last secondary response\n"); 374*38c8a9a5SSteve French return 0; 375*38c8a9a5SSteve French } 376*38c8a9a5SSteve French 377*38c8a9a5SSteve French static void 378*38c8a9a5SSteve French cifs_downgrade_oplock(struct TCP_Server_Info *server, 379*38c8a9a5SSteve French struct cifsInodeInfo *cinode, __u32 oplock, 380*38c8a9a5SSteve French unsigned int epoch, bool *purge_cache) 381*38c8a9a5SSteve French { 382*38c8a9a5SSteve French cifs_set_oplock_level(cinode, oplock); 383*38c8a9a5SSteve French } 384*38c8a9a5SSteve French 385*38c8a9a5SSteve French static bool 386*38c8a9a5SSteve French cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server, 387*38c8a9a5SSteve French char *buf, int malformed) 388*38c8a9a5SSteve French { 389*38c8a9a5SSteve French if (malformed) 390*38c8a9a5SSteve French return false; 391*38c8a9a5SSteve French if (check2ndT2(buf) <= 0) 392*38c8a9a5SSteve French return false; 393*38c8a9a5SSteve French mid->multiRsp = true; 394*38c8a9a5SSteve French if (mid->resp_buf) { 395*38c8a9a5SSteve French /* merge response - fix up 1st*/ 396*38c8a9a5SSteve French malformed = coalesce_t2(buf, mid->resp_buf); 397*38c8a9a5SSteve French if (malformed > 0) 398*38c8a9a5SSteve French return true; 399*38c8a9a5SSteve French /* All parts received or packet is malformed. */ 400*38c8a9a5SSteve French mid->multiEnd = true; 401*38c8a9a5SSteve French dequeue_mid(mid, malformed); 402*38c8a9a5SSteve French return true; 403*38c8a9a5SSteve French } 404*38c8a9a5SSteve French if (!server->large_buf) { 405*38c8a9a5SSteve French /*FIXME: switch to already allocated largebuf?*/ 406*38c8a9a5SSteve French cifs_dbg(VFS, "1st trans2 resp needs bigbuf\n"); 407*38c8a9a5SSteve French } else { 408*38c8a9a5SSteve French /* Have first buffer */ 409*38c8a9a5SSteve French mid->resp_buf = buf; 410*38c8a9a5SSteve French mid->large_buf = true; 411*38c8a9a5SSteve French server->bigbuf = NULL; 412*38c8a9a5SSteve French } 413*38c8a9a5SSteve French return true; 414*38c8a9a5SSteve French } 415*38c8a9a5SSteve French 416*38c8a9a5SSteve French static bool 417*38c8a9a5SSteve French cifs_need_neg(struct TCP_Server_Info *server) 418*38c8a9a5SSteve French { 419*38c8a9a5SSteve French return server->maxBuf == 0; 420*38c8a9a5SSteve French } 421*38c8a9a5SSteve French 422*38c8a9a5SSteve French static int 423*38c8a9a5SSteve French cifs_negotiate(const unsigned int xid, 424*38c8a9a5SSteve French struct cifs_ses *ses, 425*38c8a9a5SSteve French struct TCP_Server_Info *server) 426*38c8a9a5SSteve French { 427*38c8a9a5SSteve French int rc; 428*38c8a9a5SSteve French rc = CIFSSMBNegotiate(xid, ses, server); 429*38c8a9a5SSteve French if (rc == -EAGAIN) { 430*38c8a9a5SSteve French /* retry only once on 1st time connection */ 431*38c8a9a5SSteve French set_credits(server, 1); 432*38c8a9a5SSteve French rc = CIFSSMBNegotiate(xid, ses, server); 433*38c8a9a5SSteve French if (rc == -EAGAIN) 434*38c8a9a5SSteve French rc = -EHOSTDOWN; 435*38c8a9a5SSteve French } 436*38c8a9a5SSteve French return rc; 437*38c8a9a5SSteve French } 438*38c8a9a5SSteve French 439*38c8a9a5SSteve French static unsigned int 440*38c8a9a5SSteve French cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) 441*38c8a9a5SSteve French { 442*38c8a9a5SSteve French __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); 443*38c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 444*38c8a9a5SSteve French unsigned int wsize; 445*38c8a9a5SSteve French 446*38c8a9a5SSteve French /* start with specified wsize, or default */ 447*38c8a9a5SSteve French if (ctx->wsize) 448*38c8a9a5SSteve French wsize = ctx->wsize; 449*38c8a9a5SSteve French else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) 450*38c8a9a5SSteve French wsize = CIFS_DEFAULT_IOSIZE; 451*38c8a9a5SSteve French else 452*38c8a9a5SSteve French wsize = CIFS_DEFAULT_NON_POSIX_WSIZE; 453*38c8a9a5SSteve French 454*38c8a9a5SSteve French /* can server support 24-bit write sizes? (via UNIX extensions) */ 455*38c8a9a5SSteve French if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) 456*38c8a9a5SSteve French wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE); 457*38c8a9a5SSteve French 458*38c8a9a5SSteve French /* 459*38c8a9a5SSteve French * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set? 460*38c8a9a5SSteve French * Limit it to max buffer offered by the server, minus the size of the 461*38c8a9a5SSteve French * WRITEX header, not including the 4 byte RFC1001 length. 462*38c8a9a5SSteve French */ 463*38c8a9a5SSteve French if (!(server->capabilities & CAP_LARGE_WRITE_X) || 464*38c8a9a5SSteve French (!(server->capabilities & CAP_UNIX) && server->sign)) 465*38c8a9a5SSteve French wsize = min_t(unsigned int, wsize, 466*38c8a9a5SSteve French server->maxBuf - sizeof(WRITE_REQ) + 4); 467*38c8a9a5SSteve French 468*38c8a9a5SSteve French /* hard limit of CIFS_MAX_WSIZE */ 469*38c8a9a5SSteve French wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); 470*38c8a9a5SSteve French 471*38c8a9a5SSteve French return wsize; 472*38c8a9a5SSteve French } 473*38c8a9a5SSteve French 474*38c8a9a5SSteve French static unsigned int 475*38c8a9a5SSteve French cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb3_fs_context *ctx) 476*38c8a9a5SSteve French { 477*38c8a9a5SSteve French __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); 478*38c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 479*38c8a9a5SSteve French unsigned int rsize, defsize; 480*38c8a9a5SSteve French 481*38c8a9a5SSteve French /* 482*38c8a9a5SSteve French * Set default value... 483*38c8a9a5SSteve French * 484*38c8a9a5SSteve French * HACK alert! Ancient servers have very small buffers. Even though 485*38c8a9a5SSteve French * MS-CIFS indicates that servers are only limited by the client's 486*38c8a9a5SSteve French * bufsize for reads, testing against win98se shows that it throws 487*38c8a9a5SSteve French * INVALID_PARAMETER errors if you try to request too large a read. 488*38c8a9a5SSteve French * OS/2 just sends back short reads. 489*38c8a9a5SSteve French * 490*38c8a9a5SSteve French * If the server doesn't advertise CAP_LARGE_READ_X, then assume that 491*38c8a9a5SSteve French * it can't handle a read request larger than its MaxBufferSize either. 492*38c8a9a5SSteve French */ 493*38c8a9a5SSteve French if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) 494*38c8a9a5SSteve French defsize = CIFS_DEFAULT_IOSIZE; 495*38c8a9a5SSteve French else if (server->capabilities & CAP_LARGE_READ_X) 496*38c8a9a5SSteve French defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; 497*38c8a9a5SSteve French else 498*38c8a9a5SSteve French defsize = server->maxBuf - sizeof(READ_RSP); 499*38c8a9a5SSteve French 500*38c8a9a5SSteve French rsize = ctx->rsize ? ctx->rsize : defsize; 501*38c8a9a5SSteve French 502*38c8a9a5SSteve French /* 503*38c8a9a5SSteve French * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to 504*38c8a9a5SSteve French * the client's MaxBufferSize. 505*38c8a9a5SSteve French */ 506*38c8a9a5SSteve French if (!(server->capabilities & CAP_LARGE_READ_X)) 507*38c8a9a5SSteve French rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); 508*38c8a9a5SSteve French 509*38c8a9a5SSteve French /* hard limit of CIFS_MAX_RSIZE */ 510*38c8a9a5SSteve French rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); 511*38c8a9a5SSteve French 512*38c8a9a5SSteve French return rsize; 513*38c8a9a5SSteve French } 514*38c8a9a5SSteve French 515*38c8a9a5SSteve French static void 516*38c8a9a5SSteve French cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon, 517*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb) 518*38c8a9a5SSteve French { 519*38c8a9a5SSteve French CIFSSMBQFSDeviceInfo(xid, tcon); 520*38c8a9a5SSteve French CIFSSMBQFSAttributeInfo(xid, tcon); 521*38c8a9a5SSteve French } 522*38c8a9a5SSteve French 523*38c8a9a5SSteve French static int 524*38c8a9a5SSteve French cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon, 525*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, const char *full_path) 526*38c8a9a5SSteve French { 527*38c8a9a5SSteve French int rc; 528*38c8a9a5SSteve French FILE_ALL_INFO *file_info; 529*38c8a9a5SSteve French 530*38c8a9a5SSteve French file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 531*38c8a9a5SSteve French if (file_info == NULL) 532*38c8a9a5SSteve French return -ENOMEM; 533*38c8a9a5SSteve French 534*38c8a9a5SSteve French rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info, 535*38c8a9a5SSteve French 0 /* not legacy */, cifs_sb->local_nls, 536*38c8a9a5SSteve French cifs_remap(cifs_sb)); 537*38c8a9a5SSteve French 538*38c8a9a5SSteve French if (rc == -EOPNOTSUPP || rc == -EINVAL) 539*38c8a9a5SSteve French rc = SMBQueryInformation(xid, tcon, full_path, file_info, 540*38c8a9a5SSteve French cifs_sb->local_nls, cifs_remap(cifs_sb)); 541*38c8a9a5SSteve French kfree(file_info); 542*38c8a9a5SSteve French return rc; 543*38c8a9a5SSteve French } 544*38c8a9a5SSteve French 545*38c8a9a5SSteve French static int cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon, 546*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, const char *full_path, 547*38c8a9a5SSteve French struct cifs_open_info_data *data, bool *adjustTZ, bool *symlink) 548*38c8a9a5SSteve French { 549*38c8a9a5SSteve French int rc; 550*38c8a9a5SSteve French FILE_ALL_INFO fi = {}; 551*38c8a9a5SSteve French 552*38c8a9a5SSteve French *symlink = false; 553*38c8a9a5SSteve French 554*38c8a9a5SSteve French /* could do find first instead but this returns more info */ 555*38c8a9a5SSteve French rc = CIFSSMBQPathInfo(xid, tcon, full_path, &fi, 0 /* not legacy */, cifs_sb->local_nls, 556*38c8a9a5SSteve French cifs_remap(cifs_sb)); 557*38c8a9a5SSteve French /* 558*38c8a9a5SSteve French * BB optimize code so we do not make the above call when server claims 559*38c8a9a5SSteve French * no NT SMB support and the above call failed at least once - set flag 560*38c8a9a5SSteve French * in tcon or mount. 561*38c8a9a5SSteve French */ 562*38c8a9a5SSteve French if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) { 563*38c8a9a5SSteve French rc = SMBQueryInformation(xid, tcon, full_path, &fi, cifs_sb->local_nls, 564*38c8a9a5SSteve French cifs_remap(cifs_sb)); 565*38c8a9a5SSteve French *adjustTZ = true; 566*38c8a9a5SSteve French } 567*38c8a9a5SSteve French 568*38c8a9a5SSteve French if (!rc) { 569*38c8a9a5SSteve French int tmprc; 570*38c8a9a5SSteve French int oplock = 0; 571*38c8a9a5SSteve French struct cifs_fid fid; 572*38c8a9a5SSteve French struct cifs_open_parms oparms; 573*38c8a9a5SSteve French 574*38c8a9a5SSteve French move_cifs_info_to_smb2(&data->fi, &fi); 575*38c8a9a5SSteve French 576*38c8a9a5SSteve French if (!(le32_to_cpu(fi.Attributes) & ATTR_REPARSE)) 577*38c8a9a5SSteve French return 0; 578*38c8a9a5SSteve French 579*38c8a9a5SSteve French oparms = (struct cifs_open_parms) { 580*38c8a9a5SSteve French .tcon = tcon, 581*38c8a9a5SSteve French .cifs_sb = cifs_sb, 582*38c8a9a5SSteve French .desired_access = FILE_READ_ATTRIBUTES, 583*38c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, 0), 584*38c8a9a5SSteve French .disposition = FILE_OPEN, 585*38c8a9a5SSteve French .path = full_path, 586*38c8a9a5SSteve French .fid = &fid, 587*38c8a9a5SSteve French }; 588*38c8a9a5SSteve French 589*38c8a9a5SSteve French /* Need to check if this is a symbolic link or not */ 590*38c8a9a5SSteve French tmprc = CIFS_open(xid, &oparms, &oplock, NULL); 591*38c8a9a5SSteve French if (tmprc == -EOPNOTSUPP) 592*38c8a9a5SSteve French *symlink = true; 593*38c8a9a5SSteve French else if (tmprc == 0) 594*38c8a9a5SSteve French CIFSSMBClose(xid, tcon, fid.netfid); 595*38c8a9a5SSteve French } 596*38c8a9a5SSteve French 597*38c8a9a5SSteve French return rc; 598*38c8a9a5SSteve French } 599*38c8a9a5SSteve French 600*38c8a9a5SSteve French static int cifs_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon, 601*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, const char *full_path, 602*38c8a9a5SSteve French u64 *uniqueid, struct cifs_open_info_data *unused) 603*38c8a9a5SSteve French { 604*38c8a9a5SSteve French /* 605*38c8a9a5SSteve French * We can not use the IndexNumber field by default from Windows or 606*38c8a9a5SSteve French * Samba (in ALL_INFO buf) but we can request it explicitly. The SNIA 607*38c8a9a5SSteve French * CIFS spec claims that this value is unique within the scope of a 608*38c8a9a5SSteve French * share, and the windows docs hint that it's actually unique 609*38c8a9a5SSteve French * per-machine. 610*38c8a9a5SSteve French * 611*38c8a9a5SSteve French * There may be higher info levels that work but are there Windows 612*38c8a9a5SSteve French * server or network appliances for which IndexNumber field is not 613*38c8a9a5SSteve French * guaranteed unique? 614*38c8a9a5SSteve French */ 615*38c8a9a5SSteve French return CIFSGetSrvInodeNumber(xid, tcon, full_path, uniqueid, 616*38c8a9a5SSteve French cifs_sb->local_nls, 617*38c8a9a5SSteve French cifs_remap(cifs_sb)); 618*38c8a9a5SSteve French } 619*38c8a9a5SSteve French 620*38c8a9a5SSteve French static int cifs_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, 621*38c8a9a5SSteve French struct cifsFileInfo *cfile, struct cifs_open_info_data *data) 622*38c8a9a5SSteve French { 623*38c8a9a5SSteve French int rc; 624*38c8a9a5SSteve French FILE_ALL_INFO fi = {}; 625*38c8a9a5SSteve French 626*38c8a9a5SSteve French if (cfile->symlink_target) { 627*38c8a9a5SSteve French data->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL); 628*38c8a9a5SSteve French if (!data->symlink_target) 629*38c8a9a5SSteve French return -ENOMEM; 630*38c8a9a5SSteve French } 631*38c8a9a5SSteve French 632*38c8a9a5SSteve French rc = CIFSSMBQFileInfo(xid, tcon, cfile->fid.netfid, &fi); 633*38c8a9a5SSteve French if (!rc) 634*38c8a9a5SSteve French move_cifs_info_to_smb2(&data->fi, &fi); 635*38c8a9a5SSteve French return rc; 636*38c8a9a5SSteve French } 637*38c8a9a5SSteve French 638*38c8a9a5SSteve French static void 639*38c8a9a5SSteve French cifs_clear_stats(struct cifs_tcon *tcon) 640*38c8a9a5SSteve French { 641*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_writes, 0); 642*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_reads, 0); 643*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_flushes, 0); 644*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_oplock_brks, 0); 645*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_opens, 0); 646*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_posixopens, 0); 647*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_posixmkdirs, 0); 648*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_closes, 0); 649*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_deletes, 0); 650*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_mkdirs, 0); 651*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_rmdirs, 0); 652*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_renames, 0); 653*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_t2renames, 0); 654*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_ffirst, 0); 655*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_fnext, 0); 656*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_fclose, 0); 657*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_hardlinks, 0); 658*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_symlinks, 0); 659*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_locks, 0); 660*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_acl_get, 0); 661*38c8a9a5SSteve French atomic_set(&tcon->stats.cifs_stats.num_acl_set, 0); 662*38c8a9a5SSteve French } 663*38c8a9a5SSteve French 664*38c8a9a5SSteve French static void 665*38c8a9a5SSteve French cifs_print_stats(struct seq_file *m, struct cifs_tcon *tcon) 666*38c8a9a5SSteve French { 667*38c8a9a5SSteve French seq_printf(m, " Oplocks breaks: %d", 668*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_oplock_brks)); 669*38c8a9a5SSteve French seq_printf(m, "\nReads: %d Bytes: %llu", 670*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_reads), 671*38c8a9a5SSteve French (long long)(tcon->bytes_read)); 672*38c8a9a5SSteve French seq_printf(m, "\nWrites: %d Bytes: %llu", 673*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_writes), 674*38c8a9a5SSteve French (long long)(tcon->bytes_written)); 675*38c8a9a5SSteve French seq_printf(m, "\nFlushes: %d", 676*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_flushes)); 677*38c8a9a5SSteve French seq_printf(m, "\nLocks: %d HardLinks: %d Symlinks: %d", 678*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_locks), 679*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_hardlinks), 680*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_symlinks)); 681*38c8a9a5SSteve French seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d", 682*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_opens), 683*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_closes), 684*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_deletes)); 685*38c8a9a5SSteve French seq_printf(m, "\nPosix Opens: %d Posix Mkdirs: %d", 686*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_posixopens), 687*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_posixmkdirs)); 688*38c8a9a5SSteve French seq_printf(m, "\nMkdirs: %d Rmdirs: %d", 689*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_mkdirs), 690*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_rmdirs)); 691*38c8a9a5SSteve French seq_printf(m, "\nRenames: %d T2 Renames %d", 692*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_renames), 693*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_t2renames)); 694*38c8a9a5SSteve French seq_printf(m, "\nFindFirst: %d FNext %d FClose %d", 695*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_ffirst), 696*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_fnext), 697*38c8a9a5SSteve French atomic_read(&tcon->stats.cifs_stats.num_fclose)); 698*38c8a9a5SSteve French } 699*38c8a9a5SSteve French 700*38c8a9a5SSteve French static void 701*38c8a9a5SSteve French cifs_mkdir_setinfo(struct inode *inode, const char *full_path, 702*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, struct cifs_tcon *tcon, 703*38c8a9a5SSteve French const unsigned int xid) 704*38c8a9a5SSteve French { 705*38c8a9a5SSteve French FILE_BASIC_INFO info; 706*38c8a9a5SSteve French struct cifsInodeInfo *cifsInode; 707*38c8a9a5SSteve French u32 dosattrs; 708*38c8a9a5SSteve French int rc; 709*38c8a9a5SSteve French 710*38c8a9a5SSteve French memset(&info, 0, sizeof(info)); 711*38c8a9a5SSteve French cifsInode = CIFS_I(inode); 712*38c8a9a5SSteve French dosattrs = cifsInode->cifsAttrs|ATTR_READONLY; 713*38c8a9a5SSteve French info.Attributes = cpu_to_le32(dosattrs); 714*38c8a9a5SSteve French rc = CIFSSMBSetPathInfo(xid, tcon, full_path, &info, cifs_sb->local_nls, 715*38c8a9a5SSteve French cifs_sb); 716*38c8a9a5SSteve French if (rc == 0) 717*38c8a9a5SSteve French cifsInode->cifsAttrs = dosattrs; 718*38c8a9a5SSteve French } 719*38c8a9a5SSteve French 720*38c8a9a5SSteve French static int cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, 721*38c8a9a5SSteve French void *buf) 722*38c8a9a5SSteve French { 723*38c8a9a5SSteve French struct cifs_open_info_data *data = buf; 724*38c8a9a5SSteve French FILE_ALL_INFO fi = {}; 725*38c8a9a5SSteve French int rc; 726*38c8a9a5SSteve French 727*38c8a9a5SSteve French if (!(oparms->tcon->ses->capabilities & CAP_NT_SMBS)) 728*38c8a9a5SSteve French rc = SMBLegacyOpen(xid, oparms->tcon, oparms->path, 729*38c8a9a5SSteve French oparms->disposition, 730*38c8a9a5SSteve French oparms->desired_access, 731*38c8a9a5SSteve French oparms->create_options, 732*38c8a9a5SSteve French &oparms->fid->netfid, oplock, &fi, 733*38c8a9a5SSteve French oparms->cifs_sb->local_nls, 734*38c8a9a5SSteve French cifs_remap(oparms->cifs_sb)); 735*38c8a9a5SSteve French else 736*38c8a9a5SSteve French rc = CIFS_open(xid, oparms, oplock, &fi); 737*38c8a9a5SSteve French 738*38c8a9a5SSteve French if (!rc && data) 739*38c8a9a5SSteve French move_cifs_info_to_smb2(&data->fi, &fi); 740*38c8a9a5SSteve French 741*38c8a9a5SSteve French return rc; 742*38c8a9a5SSteve French } 743*38c8a9a5SSteve French 744*38c8a9a5SSteve French static void 745*38c8a9a5SSteve French cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) 746*38c8a9a5SSteve French { 747*38c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 748*38c8a9a5SSteve French cfile->fid.netfid = fid->netfid; 749*38c8a9a5SSteve French cifs_set_oplock_level(cinode, oplock); 750*38c8a9a5SSteve French cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); 751*38c8a9a5SSteve French } 752*38c8a9a5SSteve French 753*38c8a9a5SSteve French static void 754*38c8a9a5SSteve French cifs_close_file(const unsigned int xid, struct cifs_tcon *tcon, 755*38c8a9a5SSteve French struct cifs_fid *fid) 756*38c8a9a5SSteve French { 757*38c8a9a5SSteve French CIFSSMBClose(xid, tcon, fid->netfid); 758*38c8a9a5SSteve French } 759*38c8a9a5SSteve French 760*38c8a9a5SSteve French static int 761*38c8a9a5SSteve French cifs_flush_file(const unsigned int xid, struct cifs_tcon *tcon, 762*38c8a9a5SSteve French struct cifs_fid *fid) 763*38c8a9a5SSteve French { 764*38c8a9a5SSteve French return CIFSSMBFlush(xid, tcon, fid->netfid); 765*38c8a9a5SSteve French } 766*38c8a9a5SSteve French 767*38c8a9a5SSteve French static int 768*38c8a9a5SSteve French cifs_sync_read(const unsigned int xid, struct cifs_fid *pfid, 769*38c8a9a5SSteve French struct cifs_io_parms *parms, unsigned int *bytes_read, 770*38c8a9a5SSteve French char **buf, int *buf_type) 771*38c8a9a5SSteve French { 772*38c8a9a5SSteve French parms->netfid = pfid->netfid; 773*38c8a9a5SSteve French return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type); 774*38c8a9a5SSteve French } 775*38c8a9a5SSteve French 776*38c8a9a5SSteve French static int 777*38c8a9a5SSteve French cifs_sync_write(const unsigned int xid, struct cifs_fid *pfid, 778*38c8a9a5SSteve French struct cifs_io_parms *parms, unsigned int *written, 779*38c8a9a5SSteve French struct kvec *iov, unsigned long nr_segs) 780*38c8a9a5SSteve French { 781*38c8a9a5SSteve French 782*38c8a9a5SSteve French parms->netfid = pfid->netfid; 783*38c8a9a5SSteve French return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); 784*38c8a9a5SSteve French } 785*38c8a9a5SSteve French 786*38c8a9a5SSteve French static int 787*38c8a9a5SSteve French smb_set_file_info(struct inode *inode, const char *full_path, 788*38c8a9a5SSteve French FILE_BASIC_INFO *buf, const unsigned int xid) 789*38c8a9a5SSteve French { 790*38c8a9a5SSteve French int oplock = 0; 791*38c8a9a5SSteve French int rc; 792*38c8a9a5SSteve French __u32 netpid; 793*38c8a9a5SSteve French struct cifs_fid fid; 794*38c8a9a5SSteve French struct cifs_open_parms oparms; 795*38c8a9a5SSteve French struct cifsFileInfo *open_file; 796*38c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 797*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 798*38c8a9a5SSteve French struct tcon_link *tlink = NULL; 799*38c8a9a5SSteve French struct cifs_tcon *tcon; 800*38c8a9a5SSteve French 801*38c8a9a5SSteve French /* if the file is already open for write, just use that fileid */ 802*38c8a9a5SSteve French open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); 803*38c8a9a5SSteve French if (open_file) { 804*38c8a9a5SSteve French fid.netfid = open_file->fid.netfid; 805*38c8a9a5SSteve French netpid = open_file->pid; 806*38c8a9a5SSteve French tcon = tlink_tcon(open_file->tlink); 807*38c8a9a5SSteve French goto set_via_filehandle; 808*38c8a9a5SSteve French } 809*38c8a9a5SSteve French 810*38c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 811*38c8a9a5SSteve French if (IS_ERR(tlink)) { 812*38c8a9a5SSteve French rc = PTR_ERR(tlink); 813*38c8a9a5SSteve French tlink = NULL; 814*38c8a9a5SSteve French goto out; 815*38c8a9a5SSteve French } 816*38c8a9a5SSteve French tcon = tlink_tcon(tlink); 817*38c8a9a5SSteve French 818*38c8a9a5SSteve French rc = CIFSSMBSetPathInfo(xid, tcon, full_path, buf, cifs_sb->local_nls, 819*38c8a9a5SSteve French cifs_sb); 820*38c8a9a5SSteve French if (rc == 0) { 821*38c8a9a5SSteve French cinode->cifsAttrs = le32_to_cpu(buf->Attributes); 822*38c8a9a5SSteve French goto out; 823*38c8a9a5SSteve French } else if (rc != -EOPNOTSUPP && rc != -EINVAL) { 824*38c8a9a5SSteve French goto out; 825*38c8a9a5SSteve French } 826*38c8a9a5SSteve French 827*38c8a9a5SSteve French oparms = (struct cifs_open_parms) { 828*38c8a9a5SSteve French .tcon = tcon, 829*38c8a9a5SSteve French .cifs_sb = cifs_sb, 830*38c8a9a5SSteve French .desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 831*38c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR), 832*38c8a9a5SSteve French .disposition = FILE_OPEN, 833*38c8a9a5SSteve French .path = full_path, 834*38c8a9a5SSteve French .fid = &fid, 835*38c8a9a5SSteve French }; 836*38c8a9a5SSteve French 837*38c8a9a5SSteve French cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); 838*38c8a9a5SSteve French rc = CIFS_open(xid, &oparms, &oplock, NULL); 839*38c8a9a5SSteve French if (rc != 0) { 840*38c8a9a5SSteve French if (rc == -EIO) 841*38c8a9a5SSteve French rc = -EINVAL; 842*38c8a9a5SSteve French goto out; 843*38c8a9a5SSteve French } 844*38c8a9a5SSteve French 845*38c8a9a5SSteve French netpid = current->tgid; 846*38c8a9a5SSteve French 847*38c8a9a5SSteve French set_via_filehandle: 848*38c8a9a5SSteve French rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid); 849*38c8a9a5SSteve French if (!rc) 850*38c8a9a5SSteve French cinode->cifsAttrs = le32_to_cpu(buf->Attributes); 851*38c8a9a5SSteve French 852*38c8a9a5SSteve French if (open_file == NULL) 853*38c8a9a5SSteve French CIFSSMBClose(xid, tcon, fid.netfid); 854*38c8a9a5SSteve French else 855*38c8a9a5SSteve French cifsFileInfo_put(open_file); 856*38c8a9a5SSteve French out: 857*38c8a9a5SSteve French if (tlink != NULL) 858*38c8a9a5SSteve French cifs_put_tlink(tlink); 859*38c8a9a5SSteve French return rc; 860*38c8a9a5SSteve French } 861*38c8a9a5SSteve French 862*38c8a9a5SSteve French static int 863*38c8a9a5SSteve French cifs_set_compression(const unsigned int xid, struct cifs_tcon *tcon, 864*38c8a9a5SSteve French struct cifsFileInfo *cfile) 865*38c8a9a5SSteve French { 866*38c8a9a5SSteve French return CIFSSMB_set_compression(xid, tcon, cfile->fid.netfid); 867*38c8a9a5SSteve French } 868*38c8a9a5SSteve French 869*38c8a9a5SSteve French static int 870*38c8a9a5SSteve French cifs_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon, 871*38c8a9a5SSteve French const char *path, struct cifs_sb_info *cifs_sb, 872*38c8a9a5SSteve French struct cifs_fid *fid, __u16 search_flags, 873*38c8a9a5SSteve French struct cifs_search_info *srch_inf) 874*38c8a9a5SSteve French { 875*38c8a9a5SSteve French int rc; 876*38c8a9a5SSteve French 877*38c8a9a5SSteve French rc = CIFSFindFirst(xid, tcon, path, cifs_sb, 878*38c8a9a5SSteve French &fid->netfid, search_flags, srch_inf, true); 879*38c8a9a5SSteve French if (rc) 880*38c8a9a5SSteve French cifs_dbg(FYI, "find first failed=%d\n", rc); 881*38c8a9a5SSteve French return rc; 882*38c8a9a5SSteve French } 883*38c8a9a5SSteve French 884*38c8a9a5SSteve French static int 885*38c8a9a5SSteve French cifs_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon, 886*38c8a9a5SSteve French struct cifs_fid *fid, __u16 search_flags, 887*38c8a9a5SSteve French struct cifs_search_info *srch_inf) 888*38c8a9a5SSteve French { 889*38c8a9a5SSteve French return CIFSFindNext(xid, tcon, fid->netfid, search_flags, srch_inf); 890*38c8a9a5SSteve French } 891*38c8a9a5SSteve French 892*38c8a9a5SSteve French static int 893*38c8a9a5SSteve French cifs_close_dir(const unsigned int xid, struct cifs_tcon *tcon, 894*38c8a9a5SSteve French struct cifs_fid *fid) 895*38c8a9a5SSteve French { 896*38c8a9a5SSteve French return CIFSFindClose(xid, tcon, fid->netfid); 897*38c8a9a5SSteve French } 898*38c8a9a5SSteve French 899*38c8a9a5SSteve French static int 900*38c8a9a5SSteve French cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, 901*38c8a9a5SSteve French __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode) 902*38c8a9a5SSteve French { 903*38c8a9a5SSteve French return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0, 904*38c8a9a5SSteve French LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0); 905*38c8a9a5SSteve French } 906*38c8a9a5SSteve French 907*38c8a9a5SSteve French static int 908*38c8a9a5SSteve French cifs_queryfs(const unsigned int xid, struct cifs_tcon *tcon, 909*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, struct kstatfs *buf) 910*38c8a9a5SSteve French { 911*38c8a9a5SSteve French int rc = -EOPNOTSUPP; 912*38c8a9a5SSteve French 913*38c8a9a5SSteve French buf->f_type = CIFS_SUPER_MAGIC; 914*38c8a9a5SSteve French 915*38c8a9a5SSteve French /* 916*38c8a9a5SSteve French * We could add a second check for a QFS Unix capability bit 917*38c8a9a5SSteve French */ 918*38c8a9a5SSteve French if ((tcon->ses->capabilities & CAP_UNIX) && 919*38c8a9a5SSteve French (CIFS_POSIX_EXTENSIONS & le64_to_cpu(tcon->fsUnixInfo.Capability))) 920*38c8a9a5SSteve French rc = CIFSSMBQFSPosixInfo(xid, tcon, buf); 921*38c8a9a5SSteve French 922*38c8a9a5SSteve French /* 923*38c8a9a5SSteve French * Only need to call the old QFSInfo if failed on newer one, 924*38c8a9a5SSteve French * e.g. by OS/2. 925*38c8a9a5SSteve French **/ 926*38c8a9a5SSteve French if (rc && (tcon->ses->capabilities & CAP_NT_SMBS)) 927*38c8a9a5SSteve French rc = CIFSSMBQFSInfo(xid, tcon, buf); 928*38c8a9a5SSteve French 929*38c8a9a5SSteve French /* 930*38c8a9a5SSteve French * Some old Windows servers also do not support level 103, retry with 931*38c8a9a5SSteve French * older level one if old server failed the previous call or we 932*38c8a9a5SSteve French * bypassed it because we detected that this was an older LANMAN sess 933*38c8a9a5SSteve French */ 934*38c8a9a5SSteve French if (rc) 935*38c8a9a5SSteve French rc = SMBOldQFSInfo(xid, tcon, buf); 936*38c8a9a5SSteve French return rc; 937*38c8a9a5SSteve French } 938*38c8a9a5SSteve French 939*38c8a9a5SSteve French static int 940*38c8a9a5SSteve French cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset, 941*38c8a9a5SSteve French __u64 length, __u32 type, int lock, int unlock, bool wait) 942*38c8a9a5SSteve French { 943*38c8a9a5SSteve French return CIFSSMBLock(xid, tlink_tcon(cfile->tlink), cfile->fid.netfid, 944*38c8a9a5SSteve French current->tgid, length, offset, unlock, lock, 945*38c8a9a5SSteve French (__u8)type, wait, 0); 946*38c8a9a5SSteve French } 947*38c8a9a5SSteve French 948*38c8a9a5SSteve French static int 949*38c8a9a5SSteve French cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon, 950*38c8a9a5SSteve French const unsigned char *searchName, char **symlinkinfo, 951*38c8a9a5SSteve French const struct nls_table *nls_codepage) 952*38c8a9a5SSteve French { 953*38c8a9a5SSteve French #ifdef CONFIG_CIFS_DFS_UPCALL 954*38c8a9a5SSteve French int rc; 955*38c8a9a5SSteve French struct dfs_info3_param referral = {0}; 956*38c8a9a5SSteve French 957*38c8a9a5SSteve French rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage, &referral, 958*38c8a9a5SSteve French 0); 959*38c8a9a5SSteve French 960*38c8a9a5SSteve French if (!rc) { 961*38c8a9a5SSteve French *symlinkinfo = kstrdup(referral.node_name, GFP_KERNEL); 962*38c8a9a5SSteve French free_dfs_info_param(&referral); 963*38c8a9a5SSteve French if (!*symlinkinfo) 964*38c8a9a5SSteve French rc = -ENOMEM; 965*38c8a9a5SSteve French } 966*38c8a9a5SSteve French return rc; 967*38c8a9a5SSteve French #else /* No DFS support */ 968*38c8a9a5SSteve French return -EREMOTE; 969*38c8a9a5SSteve French #endif 970*38c8a9a5SSteve French } 971*38c8a9a5SSteve French 972*38c8a9a5SSteve French static int 973*38c8a9a5SSteve French cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, 974*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb, const char *full_path, 975*38c8a9a5SSteve French char **target_path, bool is_reparse_point) 976*38c8a9a5SSteve French { 977*38c8a9a5SSteve French int rc; 978*38c8a9a5SSteve French int oplock = 0; 979*38c8a9a5SSteve French struct cifs_fid fid; 980*38c8a9a5SSteve French struct cifs_open_parms oparms; 981*38c8a9a5SSteve French 982*38c8a9a5SSteve French cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); 983*38c8a9a5SSteve French 984*38c8a9a5SSteve French if (is_reparse_point) { 985*38c8a9a5SSteve French cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n"); 986*38c8a9a5SSteve French return -EOPNOTSUPP; 987*38c8a9a5SSteve French } 988*38c8a9a5SSteve French 989*38c8a9a5SSteve French /* Check for unix extensions */ 990*38c8a9a5SSteve French if (cap_unix(tcon->ses)) { 991*38c8a9a5SSteve French rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, 992*38c8a9a5SSteve French cifs_sb->local_nls, 993*38c8a9a5SSteve French cifs_remap(cifs_sb)); 994*38c8a9a5SSteve French if (rc == -EREMOTE) 995*38c8a9a5SSteve French rc = cifs_unix_dfs_readlink(xid, tcon, full_path, 996*38c8a9a5SSteve French target_path, 997*38c8a9a5SSteve French cifs_sb->local_nls); 998*38c8a9a5SSteve French 999*38c8a9a5SSteve French goto out; 1000*38c8a9a5SSteve French } 1001*38c8a9a5SSteve French 1002*38c8a9a5SSteve French oparms = (struct cifs_open_parms) { 1003*38c8a9a5SSteve French .tcon = tcon, 1004*38c8a9a5SSteve French .cifs_sb = cifs_sb, 1005*38c8a9a5SSteve French .desired_access = FILE_READ_ATTRIBUTES, 1006*38c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, 1007*38c8a9a5SSteve French OPEN_REPARSE_POINT), 1008*38c8a9a5SSteve French .disposition = FILE_OPEN, 1009*38c8a9a5SSteve French .path = full_path, 1010*38c8a9a5SSteve French .fid = &fid, 1011*38c8a9a5SSteve French }; 1012*38c8a9a5SSteve French 1013*38c8a9a5SSteve French rc = CIFS_open(xid, &oparms, &oplock, NULL); 1014*38c8a9a5SSteve French if (rc) 1015*38c8a9a5SSteve French goto out; 1016*38c8a9a5SSteve French 1017*38c8a9a5SSteve French rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path, 1018*38c8a9a5SSteve French cifs_sb->local_nls); 1019*38c8a9a5SSteve French if (rc) 1020*38c8a9a5SSteve French goto out_close; 1021*38c8a9a5SSteve French 1022*38c8a9a5SSteve French convert_delimiter(*target_path, '/'); 1023*38c8a9a5SSteve French out_close: 1024*38c8a9a5SSteve French CIFSSMBClose(xid, tcon, fid.netfid); 1025*38c8a9a5SSteve French out: 1026*38c8a9a5SSteve French if (!rc) 1027*38c8a9a5SSteve French cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); 1028*38c8a9a5SSteve French return rc; 1029*38c8a9a5SSteve French } 1030*38c8a9a5SSteve French 1031*38c8a9a5SSteve French static bool 1032*38c8a9a5SSteve French cifs_is_read_op(__u32 oplock) 1033*38c8a9a5SSteve French { 1034*38c8a9a5SSteve French return oplock == OPLOCK_READ; 1035*38c8a9a5SSteve French } 1036*38c8a9a5SSteve French 1037*38c8a9a5SSteve French static unsigned int 1038*38c8a9a5SSteve French cifs_wp_retry_size(struct inode *inode) 1039*38c8a9a5SSteve French { 1040*38c8a9a5SSteve French return CIFS_SB(inode->i_sb)->ctx->wsize; 1041*38c8a9a5SSteve French } 1042*38c8a9a5SSteve French 1043*38c8a9a5SSteve French static bool 1044*38c8a9a5SSteve French cifs_dir_needs_close(struct cifsFileInfo *cfile) 1045*38c8a9a5SSteve French { 1046*38c8a9a5SSteve French return !cfile->srch_inf.endOfSearch && !cfile->invalidHandle; 1047*38c8a9a5SSteve French } 1048*38c8a9a5SSteve French 1049*38c8a9a5SSteve French static bool 1050*38c8a9a5SSteve French cifs_can_echo(struct TCP_Server_Info *server) 1051*38c8a9a5SSteve French { 1052*38c8a9a5SSteve French if (server->tcpStatus == CifsGood) 1053*38c8a9a5SSteve French return true; 1054*38c8a9a5SSteve French 1055*38c8a9a5SSteve French return false; 1056*38c8a9a5SSteve French } 1057*38c8a9a5SSteve French 1058*38c8a9a5SSteve French static int 1059*38c8a9a5SSteve French cifs_make_node(unsigned int xid, struct inode *inode, 1060*38c8a9a5SSteve French struct dentry *dentry, struct cifs_tcon *tcon, 1061*38c8a9a5SSteve French const char *full_path, umode_t mode, dev_t dev) 1062*38c8a9a5SSteve French { 1063*38c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1064*38c8a9a5SSteve French struct inode *newinode = NULL; 1065*38c8a9a5SSteve French int rc = -EPERM; 1066*38c8a9a5SSteve French struct cifs_open_info_data buf = {}; 1067*38c8a9a5SSteve French struct cifs_io_parms io_parms; 1068*38c8a9a5SSteve French __u32 oplock = 0; 1069*38c8a9a5SSteve French struct cifs_fid fid; 1070*38c8a9a5SSteve French struct cifs_open_parms oparms; 1071*38c8a9a5SSteve French unsigned int bytes_written; 1072*38c8a9a5SSteve French struct win_dev *pdev; 1073*38c8a9a5SSteve French struct kvec iov[2]; 1074*38c8a9a5SSteve French 1075*38c8a9a5SSteve French if (tcon->unix_ext) { 1076*38c8a9a5SSteve French /* 1077*38c8a9a5SSteve French * SMB1 Unix Extensions: requires server support but 1078*38c8a9a5SSteve French * works with all special files 1079*38c8a9a5SSteve French */ 1080*38c8a9a5SSteve French struct cifs_unix_set_info_args args = { 1081*38c8a9a5SSteve French .mode = mode & ~current_umask(), 1082*38c8a9a5SSteve French .ctime = NO_CHANGE_64, 1083*38c8a9a5SSteve French .atime = NO_CHANGE_64, 1084*38c8a9a5SSteve French .mtime = NO_CHANGE_64, 1085*38c8a9a5SSteve French .device = dev, 1086*38c8a9a5SSteve French }; 1087*38c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 1088*38c8a9a5SSteve French args.uid = current_fsuid(); 1089*38c8a9a5SSteve French args.gid = current_fsgid(); 1090*38c8a9a5SSteve French } else { 1091*38c8a9a5SSteve French args.uid = INVALID_UID; /* no change */ 1092*38c8a9a5SSteve French args.gid = INVALID_GID; /* no change */ 1093*38c8a9a5SSteve French } 1094*38c8a9a5SSteve French rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 1095*38c8a9a5SSteve French cifs_sb->local_nls, 1096*38c8a9a5SSteve French cifs_remap(cifs_sb)); 1097*38c8a9a5SSteve French if (rc) 1098*38c8a9a5SSteve French return rc; 1099*38c8a9a5SSteve French 1100*38c8a9a5SSteve French rc = cifs_get_inode_info_unix(&newinode, full_path, 1101*38c8a9a5SSteve French inode->i_sb, xid); 1102*38c8a9a5SSteve French 1103*38c8a9a5SSteve French if (rc == 0) 1104*38c8a9a5SSteve French d_instantiate(dentry, newinode); 1105*38c8a9a5SSteve French return rc; 1106*38c8a9a5SSteve French } 1107*38c8a9a5SSteve French 1108*38c8a9a5SSteve French /* 1109*38c8a9a5SSteve French * SMB1 SFU emulation: should work with all servers, but only 1110*38c8a9a5SSteve French * support block and char device (no socket & fifo) 1111*38c8a9a5SSteve French */ 1112*38c8a9a5SSteve French if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) 1113*38c8a9a5SSteve French return rc; 1114*38c8a9a5SSteve French 1115*38c8a9a5SSteve French if (!S_ISCHR(mode) && !S_ISBLK(mode)) 1116*38c8a9a5SSteve French return rc; 1117*38c8a9a5SSteve French 1118*38c8a9a5SSteve French cifs_dbg(FYI, "sfu compat create special file\n"); 1119*38c8a9a5SSteve French 1120*38c8a9a5SSteve French oparms = (struct cifs_open_parms) { 1121*38c8a9a5SSteve French .tcon = tcon, 1122*38c8a9a5SSteve French .cifs_sb = cifs_sb, 1123*38c8a9a5SSteve French .desired_access = GENERIC_WRITE, 1124*38c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | 1125*38c8a9a5SSteve French CREATE_OPTION_SPECIAL), 1126*38c8a9a5SSteve French .disposition = FILE_CREATE, 1127*38c8a9a5SSteve French .path = full_path, 1128*38c8a9a5SSteve French .fid = &fid, 1129*38c8a9a5SSteve French }; 1130*38c8a9a5SSteve French 1131*38c8a9a5SSteve French if (tcon->ses->server->oplocks) 1132*38c8a9a5SSteve French oplock = REQ_OPLOCK; 1133*38c8a9a5SSteve French else 1134*38c8a9a5SSteve French oplock = 0; 1135*38c8a9a5SSteve French rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); 1136*38c8a9a5SSteve French if (rc) 1137*38c8a9a5SSteve French return rc; 1138*38c8a9a5SSteve French 1139*38c8a9a5SSteve French /* 1140*38c8a9a5SSteve French * BB Do not bother to decode buf since no local inode yet to put 1141*38c8a9a5SSteve French * timestamps in, but we can reuse it safely. 1142*38c8a9a5SSteve French */ 1143*38c8a9a5SSteve French 1144*38c8a9a5SSteve French pdev = (struct win_dev *)&buf.fi; 1145*38c8a9a5SSteve French io_parms.pid = current->tgid; 1146*38c8a9a5SSteve French io_parms.tcon = tcon; 1147*38c8a9a5SSteve French io_parms.offset = 0; 1148*38c8a9a5SSteve French io_parms.length = sizeof(struct win_dev); 1149*38c8a9a5SSteve French iov[1].iov_base = &buf.fi; 1150*38c8a9a5SSteve French iov[1].iov_len = sizeof(struct win_dev); 1151*38c8a9a5SSteve French if (S_ISCHR(mode)) { 1152*38c8a9a5SSteve French memcpy(pdev->type, "IntxCHR", 8); 1153*38c8a9a5SSteve French pdev->major = cpu_to_le64(MAJOR(dev)); 1154*38c8a9a5SSteve French pdev->minor = cpu_to_le64(MINOR(dev)); 1155*38c8a9a5SSteve French rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 1156*38c8a9a5SSteve French &bytes_written, iov, 1); 1157*38c8a9a5SSteve French } else if (S_ISBLK(mode)) { 1158*38c8a9a5SSteve French memcpy(pdev->type, "IntxBLK", 8); 1159*38c8a9a5SSteve French pdev->major = cpu_to_le64(MAJOR(dev)); 1160*38c8a9a5SSteve French pdev->minor = cpu_to_le64(MINOR(dev)); 1161*38c8a9a5SSteve French rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 1162*38c8a9a5SSteve French &bytes_written, iov, 1); 1163*38c8a9a5SSteve French } 1164*38c8a9a5SSteve French tcon->ses->server->ops->close(xid, tcon, &fid); 1165*38c8a9a5SSteve French d_drop(dentry); 1166*38c8a9a5SSteve French 1167*38c8a9a5SSteve French /* FIXME: add code here to set EAs */ 1168*38c8a9a5SSteve French 1169*38c8a9a5SSteve French cifs_free_open_info(&buf); 1170*38c8a9a5SSteve French return rc; 1171*38c8a9a5SSteve French } 1172*38c8a9a5SSteve French 1173*38c8a9a5SSteve French 1174*38c8a9a5SSteve French 1175*38c8a9a5SSteve French struct smb_version_operations smb1_operations = { 1176*38c8a9a5SSteve French .send_cancel = send_nt_cancel, 1177*38c8a9a5SSteve French .compare_fids = cifs_compare_fids, 1178*38c8a9a5SSteve French .setup_request = cifs_setup_request, 1179*38c8a9a5SSteve French .setup_async_request = cifs_setup_async_request, 1180*38c8a9a5SSteve French .check_receive = cifs_check_receive, 1181*38c8a9a5SSteve French .add_credits = cifs_add_credits, 1182*38c8a9a5SSteve French .set_credits = cifs_set_credits, 1183*38c8a9a5SSteve French .get_credits_field = cifs_get_credits_field, 1184*38c8a9a5SSteve French .get_credits = cifs_get_credits, 1185*38c8a9a5SSteve French .wait_mtu_credits = cifs_wait_mtu_credits, 1186*38c8a9a5SSteve French .get_next_mid = cifs_get_next_mid, 1187*38c8a9a5SSteve French .read_data_offset = cifs_read_data_offset, 1188*38c8a9a5SSteve French .read_data_length = cifs_read_data_length, 1189*38c8a9a5SSteve French .map_error = map_smb_to_linux_error, 1190*38c8a9a5SSteve French .find_mid = cifs_find_mid, 1191*38c8a9a5SSteve French .check_message = checkSMB, 1192*38c8a9a5SSteve French .dump_detail = cifs_dump_detail, 1193*38c8a9a5SSteve French .clear_stats = cifs_clear_stats, 1194*38c8a9a5SSteve French .print_stats = cifs_print_stats, 1195*38c8a9a5SSteve French .is_oplock_break = is_valid_oplock_break, 1196*38c8a9a5SSteve French .downgrade_oplock = cifs_downgrade_oplock, 1197*38c8a9a5SSteve French .check_trans2 = cifs_check_trans2, 1198*38c8a9a5SSteve French .need_neg = cifs_need_neg, 1199*38c8a9a5SSteve French .negotiate = cifs_negotiate, 1200*38c8a9a5SSteve French .negotiate_wsize = cifs_negotiate_wsize, 1201*38c8a9a5SSteve French .negotiate_rsize = cifs_negotiate_rsize, 1202*38c8a9a5SSteve French .sess_setup = CIFS_SessSetup, 1203*38c8a9a5SSteve French .logoff = CIFSSMBLogoff, 1204*38c8a9a5SSteve French .tree_connect = CIFSTCon, 1205*38c8a9a5SSteve French .tree_disconnect = CIFSSMBTDis, 1206*38c8a9a5SSteve French .get_dfs_refer = CIFSGetDFSRefer, 1207*38c8a9a5SSteve French .qfs_tcon = cifs_qfs_tcon, 1208*38c8a9a5SSteve French .is_path_accessible = cifs_is_path_accessible, 1209*38c8a9a5SSteve French .can_echo = cifs_can_echo, 1210*38c8a9a5SSteve French .query_path_info = cifs_query_path_info, 1211*38c8a9a5SSteve French .query_file_info = cifs_query_file_info, 1212*38c8a9a5SSteve French .get_srv_inum = cifs_get_srv_inum, 1213*38c8a9a5SSteve French .set_path_size = CIFSSMBSetEOF, 1214*38c8a9a5SSteve French .set_file_size = CIFSSMBSetFileSize, 1215*38c8a9a5SSteve French .set_file_info = smb_set_file_info, 1216*38c8a9a5SSteve French .set_compression = cifs_set_compression, 1217*38c8a9a5SSteve French .echo = CIFSSMBEcho, 1218*38c8a9a5SSteve French .mkdir = CIFSSMBMkDir, 1219*38c8a9a5SSteve French .mkdir_setinfo = cifs_mkdir_setinfo, 1220*38c8a9a5SSteve French .rmdir = CIFSSMBRmDir, 1221*38c8a9a5SSteve French .unlink = CIFSSMBDelFile, 1222*38c8a9a5SSteve French .rename_pending_delete = cifs_rename_pending_delete, 1223*38c8a9a5SSteve French .rename = CIFSSMBRename, 1224*38c8a9a5SSteve French .create_hardlink = CIFSCreateHardLink, 1225*38c8a9a5SSteve French .query_symlink = cifs_query_symlink, 1226*38c8a9a5SSteve French .open = cifs_open_file, 1227*38c8a9a5SSteve French .set_fid = cifs_set_fid, 1228*38c8a9a5SSteve French .close = cifs_close_file, 1229*38c8a9a5SSteve French .flush = cifs_flush_file, 1230*38c8a9a5SSteve French .async_readv = cifs_async_readv, 1231*38c8a9a5SSteve French .async_writev = cifs_async_writev, 1232*38c8a9a5SSteve French .sync_read = cifs_sync_read, 1233*38c8a9a5SSteve French .sync_write = cifs_sync_write, 1234*38c8a9a5SSteve French .query_dir_first = cifs_query_dir_first, 1235*38c8a9a5SSteve French .query_dir_next = cifs_query_dir_next, 1236*38c8a9a5SSteve French .close_dir = cifs_close_dir, 1237*38c8a9a5SSteve French .calc_smb_size = smbCalcSize, 1238*38c8a9a5SSteve French .oplock_response = cifs_oplock_response, 1239*38c8a9a5SSteve French .queryfs = cifs_queryfs, 1240*38c8a9a5SSteve French .mand_lock = cifs_mand_lock, 1241*38c8a9a5SSteve French .mand_unlock_range = cifs_unlock_range, 1242*38c8a9a5SSteve French .push_mand_locks = cifs_push_mandatory_locks, 1243*38c8a9a5SSteve French .query_mf_symlink = cifs_query_mf_symlink, 1244*38c8a9a5SSteve French .create_mf_symlink = cifs_create_mf_symlink, 1245*38c8a9a5SSteve French .is_read_op = cifs_is_read_op, 1246*38c8a9a5SSteve French .wp_retry_size = cifs_wp_retry_size, 1247*38c8a9a5SSteve French .dir_needs_close = cifs_dir_needs_close, 1248*38c8a9a5SSteve French .select_sectype = cifs_select_sectype, 1249*38c8a9a5SSteve French #ifdef CONFIG_CIFS_XATTR 1250*38c8a9a5SSteve French .query_all_EAs = CIFSSMBQAllEAs, 1251*38c8a9a5SSteve French .set_EA = CIFSSMBSetEA, 1252*38c8a9a5SSteve French #endif /* CIFS_XATTR */ 1253*38c8a9a5SSteve French .get_acl = get_cifs_acl, 1254*38c8a9a5SSteve French .get_acl_by_fid = get_cifs_acl_by_fid, 1255*38c8a9a5SSteve French .set_acl = set_cifs_acl, 1256*38c8a9a5SSteve French .make_node = cifs_make_node, 1257*38c8a9a5SSteve French }; 1258*38c8a9a5SSteve French 1259*38c8a9a5SSteve French struct smb_version_values smb1_values = { 1260*38c8a9a5SSteve French .version_string = SMB1_VERSION_STRING, 1261*38c8a9a5SSteve French .protocol_id = SMB10_PROT_ID, 1262*38c8a9a5SSteve French .large_lock_type = LOCKING_ANDX_LARGE_FILES, 1263*38c8a9a5SSteve French .exclusive_lock_type = 0, 1264*38c8a9a5SSteve French .shared_lock_type = LOCKING_ANDX_SHARED_LOCK, 1265*38c8a9a5SSteve French .unlock_lock_type = 0, 1266*38c8a9a5SSteve French .header_preamble_size = 4, 1267*38c8a9a5SSteve French .header_size = sizeof(struct smb_hdr), 1268*38c8a9a5SSteve French .max_header_size = MAX_CIFS_HDR_SIZE, 1269*38c8a9a5SSteve French .read_rsp_size = sizeof(READ_RSP), 1270*38c8a9a5SSteve French .lock_cmd = cpu_to_le16(SMB_COM_LOCKING_ANDX), 1271*38c8a9a5SSteve French .cap_unix = CAP_UNIX, 1272*38c8a9a5SSteve French .cap_nt_find = CAP_NT_SMBS | CAP_NT_FIND, 1273*38c8a9a5SSteve French .cap_large_files = CAP_LARGE_FILES, 1274*38c8a9a5SSteve French .signing_enabled = SECMODE_SIGN_ENABLED, 1275*38c8a9a5SSteve French .signing_required = SECMODE_SIGN_REQUIRED, 1276*38c8a9a5SSteve French }; 1277