~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/cifs/smb2ops.c

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  SMB2 version specific operations
  3  *
  4  *  Copyright (c) 2012, Jeff Layton <jlayton@redhat.com>
  5  *
  6  *  This library is free software; you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License v2 as published
  8  *  by the Free Software Foundation.
  9  *
 10  *  This library is distributed in the hope that it will be useful,
 11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 13  *  the GNU Lesser General Public License for more details.
 14  *
 15  *  You should have received a copy of the GNU Lesser General Public License
 16  *  along with this library; if not, write to the Free Software
 17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 18  */
 19 
 20 #include <linux/pagemap.h>
 21 #include <linux/vfs.h>
 22 #include "cifsglob.h"
 23 #include "smb2pdu.h"
 24 #include "smb2proto.h"
 25 #include "cifsproto.h"
 26 #include "cifs_debug.h"
 27 #include "smb2status.h"
 28 #include "smb2glob.h"
 29 
 30 static int
 31 change_conf(struct TCP_Server_Info *server)
 32 {
 33         server->credits += server->echo_credits + server->oplock_credits;
 34         server->oplock_credits = server->echo_credits = 0;
 35         switch (server->credits) {
 36         case 0:
 37                 return -1;
 38         case 1:
 39                 server->echoes = false;
 40                 server->oplocks = false;
 41                 cifs_dbg(VFS, "disabling echoes and oplocks\n");
 42                 break;
 43         case 2:
 44                 server->echoes = true;
 45                 server->oplocks = false;
 46                 server->echo_credits = 1;
 47                 cifs_dbg(FYI, "disabling oplocks\n");
 48                 break;
 49         default:
 50                 server->echoes = true;
 51                 server->oplocks = true;
 52                 server->echo_credits = 1;
 53                 server->oplock_credits = 1;
 54         }
 55         server->credits -= server->echo_credits + server->oplock_credits;
 56         return 0;
 57 }
 58 
 59 static void
 60 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
 61                  const int optype)
 62 {
 63         int *val, rc = 0;
 64         spin_lock(&server->req_lock);
 65         val = server->ops->get_credits_field(server, optype);
 66         *val += add;
 67         server->in_flight--;
 68         if (server->in_flight == 0 && (optype & CIFS_OP_MASK) != CIFS_NEG_OP)
 69                 rc = change_conf(server);
 70         /*
 71          * Sometimes server returns 0 credits on oplock break ack - we need to
 72          * rebalance credits in this case.
 73          */
 74         else if (server->in_flight > 0 && server->oplock_credits == 0 &&
 75                  server->oplocks) {
 76                 if (server->credits > 1) {
 77                         server->credits--;
 78                         server->oplock_credits++;
 79                 }
 80         }
 81         spin_unlock(&server->req_lock);
 82         wake_up(&server->request_q);
 83         if (rc)
 84                 cifs_reconnect(server);
 85 }
 86 
 87 static void
 88 smb2_set_credits(struct TCP_Server_Info *server, const int val)
 89 {
 90         spin_lock(&server->req_lock);
 91         server->credits = val;
 92         spin_unlock(&server->req_lock);
 93 }
 94 
 95 static int *
 96 smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
 97 {
 98         switch (optype) {
 99         case CIFS_ECHO_OP:
100                 return &server->echo_credits;
101         case CIFS_OBREAK_OP:
102                 return &server->oplock_credits;
103         default:
104                 return &server->credits;
105         }
106 }
107 
108 static unsigned int
109 smb2_get_credits(struct mid_q_entry *mid)
110 {
111         return le16_to_cpu(((struct smb2_hdr *)mid->resp_buf)->CreditRequest);
112 }
113 
114 static __u64
115 smb2_get_next_mid(struct TCP_Server_Info *server)
116 {
117         __u64 mid;
118         /* for SMB2 we need the current value */
119         spin_lock(&GlobalMid_Lock);
120         mid = server->CurrentMid++;
121         spin_unlock(&GlobalMid_Lock);
122         return mid;
123 }
124 
125 static struct mid_q_entry *
126 smb2_find_mid(struct TCP_Server_Info *server, char *buf)
127 {
128         struct mid_q_entry *mid;
129         struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
130 
131         spin_lock(&GlobalMid_Lock);
132         list_for_each_entry(mid, &server->pending_mid_q, qhead) {
133                 if ((mid->mid == hdr->MessageId) &&
134                     (mid->mid_state == MID_REQUEST_SUBMITTED) &&
135                     (mid->command == hdr->Command)) {
136                         spin_unlock(&GlobalMid_Lock);
137                         return mid;
138                 }
139         }
140         spin_unlock(&GlobalMid_Lock);
141         return NULL;
142 }
143 
144 static void
145 smb2_dump_detail(void *buf)
146 {
147 #ifdef CONFIG_CIFS_DEBUG2
148         struct smb2_hdr *smb = (struct smb2_hdr *)buf;
149 
150         cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
151                  smb->Command, smb->Status, smb->Flags, smb->MessageId,
152                  smb->ProcessId);
153         cifs_dbg(VFS, "smb buf %p len %u\n", smb, smb2_calc_size(smb));
154 #endif
155 }
156 
157 static bool
158 smb2_need_neg(struct TCP_Server_Info *server)
159 {
160         return server->max_read == 0;
161 }
162 
163 static int
164 smb2_negotiate(const unsigned int xid, struct cifs_ses *ses)
165 {
166         int rc;
167         ses->server->CurrentMid = 0;
168         rc = SMB2_negotiate(xid, ses);
169         /* BB we probably don't need to retry with modern servers */
170         if (rc == -EAGAIN)
171                 rc = -EHOSTDOWN;
172         return rc;
173 }
174 
175 static unsigned int
176 smb2_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
177 {
178         struct TCP_Server_Info *server = tcon->ses->server;
179         unsigned int wsize;
180 
181         /* start with specified wsize, or default */
182         wsize = volume_info->wsize ? volume_info->wsize : CIFS_DEFAULT_IOSIZE;
183         wsize = min_t(unsigned int, wsize, server->max_write);
184         /*
185          * limit write size to 2 ** 16, because we don't support multicredit
186          * requests now.
187          */
188         wsize = min_t(unsigned int, wsize, 2 << 15);
189 
190         return wsize;
191 }
192 
193 static unsigned int
194 smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
195 {
196         struct TCP_Server_Info *server = tcon->ses->server;
197         unsigned int rsize;
198 
199         /* start with specified rsize, or default */
200         rsize = volume_info->rsize ? volume_info->rsize : CIFS_DEFAULT_IOSIZE;
201         rsize = min_t(unsigned int, rsize, server->max_read);
202         /*
203          * limit write size to 2 ** 16, because we don't support multicredit
204          * requests now.
205          */
206         rsize = min_t(unsigned int, rsize, 2 << 15);
207 
208         return rsize;
209 }
210 
211 static int
212 smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
213                         struct cifs_sb_info *cifs_sb, const char *full_path)
214 {
215         int rc;
216         __le16 *utf16_path;
217         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
218         struct cifs_open_parms oparms;
219         struct cifs_fid fid;
220 
221         utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
222         if (!utf16_path)
223                 return -ENOMEM;
224 
225         oparms.tcon = tcon;
226         oparms.desired_access = FILE_READ_ATTRIBUTES;
227         oparms.disposition = FILE_OPEN;
228         oparms.create_options = 0;
229         oparms.fid = &fid;
230         oparms.reconnect = false;
231 
232         rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
233         if (rc) {
234                 kfree(utf16_path);
235                 return rc;
236         }
237 
238         rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
239         kfree(utf16_path);
240         return rc;
241 }
242 
243 static int
244 smb2_get_srv_inum(const unsigned int xid, struct cifs_tcon *tcon,
245                   struct cifs_sb_info *cifs_sb, const char *full_path,
246                   u64 *uniqueid, FILE_ALL_INFO *data)
247 {
248         *uniqueid = le64_to_cpu(data->IndexNumber);
249         return 0;
250 }
251 
252 static int
253 smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
254                      struct cifs_fid *fid, FILE_ALL_INFO *data)
255 {
256         int rc;
257         struct smb2_file_all_info *smb2_data;
258 
259         smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
260                             GFP_KERNEL);
261         if (smb2_data == NULL)
262                 return -ENOMEM;
263 
264         rc = SMB2_query_info(xid, tcon, fid->persistent_fid, fid->volatile_fid,
265                              smb2_data);
266         if (!rc)
267                 move_smb2_info_to_cifs(data, smb2_data);
268         kfree(smb2_data);
269         return rc;
270 }
271 
272 static bool
273 smb2_can_echo(struct TCP_Server_Info *server)
274 {
275         return server->echoes;
276 }
277 
278 static void
279 smb2_clear_stats(struct cifs_tcon *tcon)
280 {
281 #ifdef CONFIG_CIFS_STATS
282         int i;
283         for (i = 0; i < NUMBER_OF_SMB2_COMMANDS; i++) {
284                 atomic_set(&tcon->stats.smb2_stats.smb2_com_sent[i], 0);
285                 atomic_set(&tcon->stats.smb2_stats.smb2_com_failed[i], 0);
286         }
287 #endif
288 }
289 
290 static void
291 smb2_dump_share_caps(struct seq_file *m, struct cifs_tcon *tcon)
292 {
293         seq_puts(m, "\n\tShare Capabilities:");
294         if (tcon->capabilities & SMB2_SHARE_CAP_DFS)
295                 seq_puts(m, " DFS,");
296         if (tcon->capabilities & SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY)
297                 seq_puts(m, " CONTINUOUS AVAILABILITY,");
298         if (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT)
299                 seq_puts(m, " SCALEOUT,");
300         if (tcon->capabilities & SMB2_SHARE_CAP_CLUSTER)
301                 seq_puts(m, " CLUSTER,");
302         if (tcon->capabilities & SMB2_SHARE_CAP_ASYMMETRIC)
303                 seq_puts(m, " ASYMMETRIC,");
304         if (tcon->capabilities == 0)
305                 seq_puts(m, " None");
306         seq_printf(m, "\tShare Flags: 0x%x", tcon->share_flags);
307 }
308 
309 static void
310 smb2_print_stats(struct seq_file *m, struct cifs_tcon *tcon)
311 {
312 #ifdef CONFIG_CIFS_STATS
313         atomic_t *sent = tcon->stats.smb2_stats.smb2_com_sent;
314         atomic_t *failed = tcon->stats.smb2_stats.smb2_com_failed;
315         seq_printf(m, "\nNegotiates: %d sent %d failed",
316                    atomic_read(&sent[SMB2_NEGOTIATE_HE]),
317                    atomic_read(&failed[SMB2_NEGOTIATE_HE]));
318         seq_printf(m, "\nSessionSetups: %d sent %d failed",
319                    atomic_read(&sent[SMB2_SESSION_SETUP_HE]),
320                    atomic_read(&failed[SMB2_SESSION_SETUP_HE]));
321         seq_printf(m, "\nLogoffs: %d sent %d failed",
322                    atomic_read(&sent[SMB2_LOGOFF_HE]),
323                    atomic_read(&failed[SMB2_LOGOFF_HE]));
324         seq_printf(m, "\nTreeConnects: %d sent %d failed",
325                    atomic_read(&sent[SMB2_TREE_CONNECT_HE]),
326                    atomic_read(&failed[SMB2_TREE_CONNECT_HE]));
327         seq_printf(m, "\nTreeDisconnects: %d sent %d failed",
328                    atomic_read(&sent[SMB2_TREE_DISCONNECT_HE]),
329                    atomic_read(&failed[SMB2_TREE_DISCONNECT_HE]));
330         seq_printf(m, "\nCreates: %d sent %d failed",
331                    atomic_read(&sent[SMB2_CREATE_HE]),
332                    atomic_read(&failed[SMB2_CREATE_HE]));
333         seq_printf(m, "\nCloses: %d sent %d failed",
334                    atomic_read(&sent[SMB2_CLOSE_HE]),
335                    atomic_read(&failed[SMB2_CLOSE_HE]));
336         seq_printf(m, "\nFlushes: %d sent %d failed",
337                    atomic_read(&sent[SMB2_FLUSH_HE]),
338                    atomic_read(&failed[SMB2_FLUSH_HE]));
339         seq_printf(m, "\nReads: %d sent %d failed",
340                    atomic_read(&sent[SMB2_READ_HE]),
341                    atomic_read(&failed[SMB2_READ_HE]));
342         seq_printf(m, "\nWrites: %d sent %d failed",
343                    atomic_read(&sent[SMB2_WRITE_HE]),
344                    atomic_read(&failed[SMB2_WRITE_HE]));
345         seq_printf(m, "\nLocks: %d sent %d failed",
346                    atomic_read(&sent[SMB2_LOCK_HE]),
347                    atomic_read(&failed[SMB2_LOCK_HE]));
348         seq_printf(m, "\nIOCTLs: %d sent %d failed",
349                    atomic_read(&sent[SMB2_IOCTL_HE]),
350                    atomic_read(&failed[SMB2_IOCTL_HE]));
351         seq_printf(m, "\nCancels: %d sent %d failed",
352                    atomic_read(&sent[SMB2_CANCEL_HE]),
353                    atomic_read(&failed[SMB2_CANCEL_HE]));
354         seq_printf(m, "\nEchos: %d sent %d failed",
355                    atomic_read(&sent[SMB2_ECHO_HE]),
356                    atomic_read(&failed[SMB2_ECHO_HE]));
357         seq_printf(m, "\nQueryDirectories: %d sent %d failed",
358                    atomic_read(&sent[SMB2_QUERY_DIRECTORY_HE]),
359                    atomic_read(&failed[SMB2_QUERY_DIRECTORY_HE]));
360         seq_printf(m, "\nChangeNotifies: %d sent %d failed",
361                    atomic_read(&sent[SMB2_CHANGE_NOTIFY_HE]),
362                    atomic_read(&failed[SMB2_CHANGE_NOTIFY_HE]));
363         seq_printf(m, "\nQueryInfos: %d sent %d failed",
364                    atomic_read(&sent[SMB2_QUERY_INFO_HE]),
365                    atomic_read(&failed[SMB2_QUERY_INFO_HE]));
366         seq_printf(m, "\nSetInfos: %d sent %d failed",
367                    atomic_read(&sent[SMB2_SET_INFO_HE]),
368                    atomic_read(&failed[SMB2_SET_INFO_HE]));
369         seq_printf(m, "\nOplockBreaks: %d sent %d failed",
370                    atomic_read(&sent[SMB2_OPLOCK_BREAK_HE]),
371                    atomic_read(&failed[SMB2_OPLOCK_BREAK_HE]));
372 #endif
373 }
374 
375 static void
376 smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
377 {
378         struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode);
379         cfile->fid.persistent_fid = fid->persistent_fid;
380         cfile->fid.volatile_fid = fid->volatile_fid;
381         smb2_set_oplock_level(cinode, oplock);
382         cinode->can_cache_brlcks = cinode->clientCanCacheAll;
383 }
384 
385 static void
386 smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
387                 struct cifs_fid *fid)
388 {
389         SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
390 }
391 
392 static int
393 smb2_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
394                 struct cifs_fid *fid)
395 {
396         return SMB2_flush(xid, tcon, fid->persistent_fid, fid->volatile_fid);
397 }
398 
399 static unsigned int
400 smb2_read_data_offset(char *buf)
401 {
402         struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
403         return rsp->DataOffset;
404 }
405 
406 static unsigned int
407 smb2_read_data_length(char *buf)
408 {
409         struct smb2_read_rsp *rsp = (struct smb2_read_rsp *)buf;
410         return le32_to_cpu(rsp->DataLength);
411 }
412 
413 
414 static int
415 smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile,
416                struct cifs_io_parms *parms, unsigned int *bytes_read,
417                char **buf, int *buf_type)
418 {
419         parms->persistent_fid = cfile->fid.persistent_fid;
420         parms->volatile_fid = cfile->fid.volatile_fid;
421         return SMB2_read(xid, parms, bytes_read, buf, buf_type);
422 }
423 
424 static int
425 smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile,
426                 struct cifs_io_parms *parms, unsigned int *written,
427                 struct kvec *iov, unsigned long nr_segs)
428 {
429 
430         parms->persistent_fid = cfile->fid.persistent_fid;
431         parms->volatile_fid = cfile->fid.volatile_fid;
432         return SMB2_write(xid, parms, written, iov, nr_segs);
433 }
434 
435 static int
436 smb2_set_file_size(const unsigned int xid, struct cifs_tcon *tcon,
437                    struct cifsFileInfo *cfile, __u64 size, bool set_alloc)
438 {
439         __le64 eof = cpu_to_le64(size);
440         return SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid,
441                             cfile->fid.volatile_fid, cfile->pid, &eof);
442 }
443 
444 static int
445 smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
446                      const char *path, struct cifs_sb_info *cifs_sb,
447                      struct cifs_fid *fid, __u16 search_flags,
448                      struct cifs_search_info *srch_inf)
449 {
450         __le16 *utf16_path;
451         int rc;
452         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
453         struct cifs_open_parms oparms;
454 
455         utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
456         if (!utf16_path)
457                 return -ENOMEM;
458 
459         oparms.tcon = tcon;
460         oparms.desired_access = FILE_READ_ATTRIBUTES | FILE_READ_DATA;
461         oparms.disposition = FILE_OPEN;
462         oparms.create_options = 0;
463         oparms.fid = fid;
464         oparms.reconnect = false;
465 
466         rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL);
467         kfree(utf16_path);
468         if (rc) {
469                 cifs_dbg(VFS, "open dir failed\n");
470                 return rc;
471         }
472 
473         srch_inf->entries_in_buffer = 0;
474         srch_inf->index_of_last_entry = 0;
475 
476         rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
477                                   fid->volatile_fid, 0, srch_inf);
478         if (rc) {
479                 cifs_dbg(VFS, "query directory failed\n");
480                 SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
481         }
482         return rc;
483 }
484 
485 static int
486 smb2_query_dir_next(const unsigned int xid, struct cifs_tcon *tcon,
487                     struct cifs_fid *fid, __u16 search_flags,
488                     struct cifs_search_info *srch_inf)
489 {
490         return SMB2_query_directory(xid, tcon, fid->persistent_fid,
491                                     fid->volatile_fid, 0, srch_inf);
492 }
493 
494 static int
495 smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
496                struct cifs_fid *fid)
497 {
498         return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
499 }
500 
501 /*
502 * If we negotiate SMB2 protocol and get STATUS_PENDING - update
503 * the number of credits and return true. Otherwise - return false.
504 */
505 static bool
506 smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
507 {
508         struct smb2_hdr *hdr = (struct smb2_hdr *)buf;
509 
510         if (hdr->Status != STATUS_PENDING)
511                 return false;
512 
513         if (!length) {
514                 spin_lock(&server->req_lock);
515                 server->credits += le16_to_cpu(hdr->CreditRequest);
516                 spin_unlock(&server->req_lock);
517                 wake_up(&server->request_q);
518         }
519 
520         return true;
521 }
522 
523 static int
524 smb2_oplock_response(struct cifs_tcon *tcon, struct cifs_fid *fid,
525                      struct cifsInodeInfo *cinode)
526 {
527         if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
528                 return SMB2_lease_break(0, tcon, cinode->lease_key,
529                                         smb2_get_lease_state(cinode));
530 
531         return SMB2_oplock_break(0, tcon, fid->persistent_fid,
532                                  fid->volatile_fid,
533                                  cinode->clientCanCacheRead ? 1 : 0);
534 }
535 
536 static int
537 smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
538              struct kstatfs *buf)
539 {
540         int rc;
541         __le16 srch_path = 0; /* Null - open root of share */
542         u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
543         struct cifs_open_parms oparms;
544         struct cifs_fid fid;
545 
546         oparms.tcon = tcon;
547         oparms.desired_access = FILE_READ_ATTRIBUTES;
548         oparms.disposition = FILE_OPEN;
549         oparms.create_options = 0;
550         oparms.fid = &fid;
551         oparms.reconnect = false;
552 
553         rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL);
554         if (rc)
555                 return rc;
556         buf->f_type = SMB2_MAGIC_NUMBER;
557         rc = SMB2_QFS_info(xid, tcon, fid.persistent_fid, fid.volatile_fid,
558                            buf);
559         SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
560         return rc;
561 }
562 
563 static bool
564 smb2_compare_fids(struct cifsFileInfo *ob1, struct cifsFileInfo *ob2)
565 {
566         return ob1->fid.persistent_fid == ob2->fid.persistent_fid &&
567                ob1->fid.volatile_fid == ob2->fid.volatile_fid;
568 }
569 
570 static int
571 smb2_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
572                __u64 length, __u32 type, int lock, int unlock, bool wait)
573 {
574         if (unlock && !lock)
575                 type = SMB2_LOCKFLAG_UNLOCK;
576         return SMB2_lock(xid, tlink_tcon(cfile->tlink),
577                          cfile->fid.persistent_fid, cfile->fid.volatile_fid,
578                          current->tgid, length, offset, type, wait);
579 }
580 
581 static void
582 smb2_get_lease_key(struct inode *inode, struct cifs_fid *fid)
583 {
584         memcpy(fid->lease_key, CIFS_I(inode)->lease_key, SMB2_LEASE_KEY_SIZE);
585 }
586 
587 static void
588 smb2_set_lease_key(struct inode *inode, struct cifs_fid *fid)
589 {
590         memcpy(CIFS_I(inode)->lease_key, fid->lease_key, SMB2_LEASE_KEY_SIZE);
591 }
592 
593 static void
594 smb2_new_lease_key(struct cifs_fid *fid)
595 {
596         get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
597 }
598 
599 struct smb_version_operations smb21_operations = {
600         .compare_fids = smb2_compare_fids,
601         .setup_request = smb2_setup_request,
602         .setup_async_request = smb2_setup_async_request,
603         .check_receive = smb2_check_receive,
604         .add_credits = smb2_add_credits,
605         .set_credits = smb2_set_credits,
606         .get_credits_field = smb2_get_credits_field,
607         .get_credits = smb2_get_credits,
608         .get_next_mid = smb2_get_next_mid,
609         .read_data_offset = smb2_read_data_offset,
610         .read_data_length = smb2_read_data_length,
611         .map_error = map_smb2_to_linux_error,
612         .find_mid = smb2_find_mid,
613         .check_message = smb2_check_message,
614         .dump_detail = smb2_dump_detail,
615         .clear_stats = smb2_clear_stats,
616         .print_stats = smb2_print_stats,
617         .is_oplock_break = smb2_is_valid_oplock_break,
618         .need_neg = smb2_need_neg,
619         .negotiate = smb2_negotiate,
620         .negotiate_wsize = smb2_negotiate_wsize,
621         .negotiate_rsize = smb2_negotiate_rsize,
622         .sess_setup = SMB2_sess_setup,
623         .logoff = SMB2_logoff,
624         .tree_connect = SMB2_tcon,
625         .tree_disconnect = SMB2_tdis,
626         .is_path_accessible = smb2_is_path_accessible,
627         .can_echo = smb2_can_echo,
628         .echo = SMB2_echo,
629         .query_path_info = smb2_query_path_info,
630         .get_srv_inum = smb2_get_srv_inum,
631         .query_file_info = smb2_query_file_info,
632         .set_path_size = smb2_set_path_size,
633         .set_file_size = smb2_set_file_size,
634         .set_file_info = smb2_set_file_info,
635         .mkdir = smb2_mkdir,
636         .mkdir_setinfo = smb2_mkdir_setinfo,
637         .rmdir = smb2_rmdir,
638         .unlink = smb2_unlink,
639         .rename = smb2_rename_path,
640         .create_hardlink = smb2_create_hardlink,
641         .open = smb2_open_file,
642         .set_fid = smb2_set_fid,
643         .close = smb2_close_file,
644         .flush = smb2_flush_file,
645         .async_readv = smb2_async_readv,
646         .async_writev = smb2_async_writev,
647         .sync_read = smb2_sync_read,
648         .sync_write = smb2_sync_write,
649         .query_dir_first = smb2_query_dir_first,
650         .query_dir_next = smb2_query_dir_next,
651         .close_dir = smb2_close_dir,
652         .calc_smb_size = smb2_calc_size,
653         .is_status_pending = smb2_is_status_pending,
654         .oplock_response = smb2_oplock_response,
655         .queryfs = smb2_queryfs,
656         .mand_lock = smb2_mand_lock,
657         .mand_unlock_range = smb2_unlock_range,
658         .push_mand_locks = smb2_push_mandatory_locks,
659         .get_lease_key = smb2_get_lease_key,
660         .set_lease_key = smb2_set_lease_key,
661         .new_lease_key = smb2_new_lease_key,
662         .calc_signature = smb2_calc_signature,
663 };
664 
665 
666 struct smb_version_operations smb30_operations = {
667         .compare_fids = smb2_compare_fids,
668         .setup_request = smb2_setup_request,
669         .setup_async_request = smb2_setup_async_request,
670         .check_receive = smb2_check_receive,
671         .add_credits = smb2_add_credits,
672         .set_credits = smb2_set_credits,
673         .get_credits_field = smb2_get_credits_field,
674         .get_credits = smb2_get_credits,
675         .get_next_mid = smb2_get_next_mid,
676         .read_data_offset = smb2_read_data_offset,
677         .read_data_length = smb2_read_data_length,
678         .map_error = map_smb2_to_linux_error,
679         .find_mid = smb2_find_mid,
680         .check_message = smb2_check_message,
681         .dump_detail = smb2_dump_detail,
682         .clear_stats = smb2_clear_stats,
683         .print_stats = smb2_print_stats,
684         .dump_share_caps = smb2_dump_share_caps,
685         .is_oplock_break = smb2_is_valid_oplock_break,
686         .need_neg = smb2_need_neg,
687         .negotiate = smb2_negotiate,
688         .negotiate_wsize = smb2_negotiate_wsize,
689         .negotiate_rsize = smb2_negotiate_rsize,
690         .sess_setup = SMB2_sess_setup,
691         .logoff = SMB2_logoff,
692         .tree_connect = SMB2_tcon,
693         .tree_disconnect = SMB2_tdis,
694         .is_path_accessible = smb2_is_path_accessible,
695         .can_echo = smb2_can_echo,
696         .echo = SMB2_echo,
697         .query_path_info = smb2_query_path_info,
698         .get_srv_inum = smb2_get_srv_inum,
699         .query_file_info = smb2_query_file_info,
700         .set_path_size = smb2_set_path_size,
701         .set_file_size = smb2_set_file_size,
702         .set_file_info = smb2_set_file_info,
703         .mkdir = smb2_mkdir,
704         .mkdir_setinfo = smb2_mkdir_setinfo,
705         .rmdir = smb2_rmdir,
706         .unlink = smb2_unlink,
707         .rename = smb2_rename_path,
708         .create_hardlink = smb2_create_hardlink,
709         .open = smb2_open_file,
710         .set_fid = smb2_set_fid,
711         .close = smb2_close_file,
712         .flush = smb2_flush_file,
713         .async_readv = smb2_async_readv,
714         .async_writev = smb2_async_writev,
715         .sync_read = smb2_sync_read,
716         .sync_write = smb2_sync_write,
717         .query_dir_first = smb2_query_dir_first,
718         .query_dir_next = smb2_query_dir_next,
719         .close_dir = smb2_close_dir,
720         .calc_smb_size = smb2_calc_size,
721         .is_status_pending = smb2_is_status_pending,
722         .oplock_response = smb2_oplock_response,
723         .queryfs = smb2_queryfs,
724         .mand_lock = smb2_mand_lock,
725         .mand_unlock_range = smb2_unlock_range,
726         .push_mand_locks = smb2_push_mandatory_locks,
727         .get_lease_key = smb2_get_lease_key,
728         .set_lease_key = smb2_set_lease_key,
729         .new_lease_key = smb2_new_lease_key,
730         .generate_signingkey = generate_smb3signingkey,
731         .calc_signature = smb3_calc_signature,
732 };
733 
734 struct smb_version_values smb20_values = {
735         .version_string = SMB20_VERSION_STRING,
736         .protocol_id = SMB20_PROT_ID,
737         .req_capabilities = 0, /* MBZ */
738         .large_lock_type = 0,
739         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
740         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
741         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
742         .header_size = sizeof(struct smb2_hdr),
743         .max_header_size = MAX_SMB2_HDR_SIZE,
744         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
745         .lock_cmd = SMB2_LOCK,
746         .cap_unix = 0,
747         .cap_nt_find = SMB2_NT_FIND,
748         .cap_large_files = SMB2_LARGE_FILES,
749         .oplock_read = SMB2_OPLOCK_LEVEL_II,
750         .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
751         .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
752 };
753 
754 struct smb_version_values smb21_values = {
755         .version_string = SMB21_VERSION_STRING,
756         .protocol_id = SMB21_PROT_ID,
757         .req_capabilities = 0, /* MBZ on negotiate req until SMB3 dialect */
758         .large_lock_type = 0,
759         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
760         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
761         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
762         .header_size = sizeof(struct smb2_hdr),
763         .max_header_size = MAX_SMB2_HDR_SIZE,
764         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
765         .lock_cmd = SMB2_LOCK,
766         .cap_unix = 0,
767         .cap_nt_find = SMB2_NT_FIND,
768         .cap_large_files = SMB2_LARGE_FILES,
769         .oplock_read = SMB2_OPLOCK_LEVEL_II,
770         .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
771         .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
772 };
773 
774 struct smb_version_values smb30_values = {
775         .version_string = SMB30_VERSION_STRING,
776         .protocol_id = SMB30_PROT_ID,
777         .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
778         .large_lock_type = 0,
779         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
780         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
781         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
782         .header_size = sizeof(struct smb2_hdr),
783         .max_header_size = MAX_SMB2_HDR_SIZE,
784         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
785         .lock_cmd = SMB2_LOCK,
786         .cap_unix = 0,
787         .cap_nt_find = SMB2_NT_FIND,
788         .cap_large_files = SMB2_LARGE_FILES,
789         .oplock_read = SMB2_OPLOCK_LEVEL_II,
790         .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
791         .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
792 };
793 
794 struct smb_version_values smb302_values = {
795         .version_string = SMB302_VERSION_STRING,
796         .protocol_id = SMB302_PROT_ID,
797         .req_capabilities = SMB2_GLOBAL_CAP_DFS | SMB2_GLOBAL_CAP_LEASING | SMB2_GLOBAL_CAP_LARGE_MTU,
798         .large_lock_type = 0,
799         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
800         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
801         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
802         .header_size = sizeof(struct smb2_hdr),
803         .max_header_size = MAX_SMB2_HDR_SIZE,
804         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
805         .lock_cmd = SMB2_LOCK,
806         .cap_unix = 0,
807         .cap_nt_find = SMB2_NT_FIND,
808         .cap_large_files = SMB2_LARGE_FILES,
809         .oplock_read = SMB2_OPLOCK_LEVEL_II,
810         .signing_enabled = SMB2_NEGOTIATE_SIGNING_ENABLED | SMB2_NEGOTIATE_SIGNING_REQUIRED,
811         .signing_required = SMB2_NEGOTIATE_SIGNING_REQUIRED,
812 };
813 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp