smb2file.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * fs/cifs/smb2file.c
  3. *
  4. * Copyright (C) International Business Machines Corp., 2002, 2011
  5. * Author(s): Steve French (sfrench@us.ibm.com),
  6. * Pavel Shilovsky ((pshilovsky@samba.org) 2012
  7. *
  8. * This library is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as published
  10. * by the Free Software Foundation; either version 2.1 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  16. * the GNU Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include <linux/fs.h>
  23. #include <linux/stat.h>
  24. #include <linux/slab.h>
  25. #include <linux/pagemap.h>
  26. #include <asm/div64.h>
  27. #include "cifsfs.h"
  28. #include "cifspdu.h"
  29. #include "cifsglob.h"
  30. #include "cifsproto.h"
  31. #include "cifs_debug.h"
  32. #include "cifs_fs_sb.h"
  33. #include "cifs_unicode.h"
  34. #include "fscache.h"
  35. #include "smb2proto.h"
  36. int
  37. smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
  38. __u32 *oplock, FILE_ALL_INFO *buf)
  39. {
  40. int rc;
  41. __le16 *smb2_path;
  42. struct smb2_file_all_info *smb2_data = NULL;
  43. __u8 smb2_oplock[17];
  44. struct cifs_fid *fid = oparms->fid;
  45. smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
  46. if (smb2_path == NULL) {
  47. rc = -ENOMEM;
  48. goto out;
  49. }
  50. smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
  51. GFP_KERNEL);
  52. if (smb2_data == NULL) {
  53. rc = -ENOMEM;
  54. goto out;
  55. }
  56. oparms->desired_access |= FILE_READ_ATTRIBUTES;
  57. *smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
  58. if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
  59. memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
  60. rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
  61. if (rc)
  62. goto out;
  63. if (buf) {
  64. /* open response does not have IndexNumber field - get it */
  65. rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
  66. fid->volatile_fid,
  67. &smb2_data->IndexNumber);
  68. if (rc) {
  69. /* let get_inode_info disable server inode numbers */
  70. smb2_data->IndexNumber = 0;
  71. rc = 0;
  72. }
  73. move_smb2_info_to_cifs(buf, smb2_data);
  74. }
  75. *oplock = *smb2_oplock;
  76. out:
  77. kfree(smb2_data);
  78. kfree(smb2_path);
  79. return rc;
  80. }
  81. int
  82. smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
  83. const unsigned int xid)
  84. {
  85. int rc = 0, stored_rc;
  86. unsigned int max_num, num = 0, max_buf;
  87. struct smb2_lock_element *buf, *cur;
  88. struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
  89. struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
  90. struct cifsLockInfo *li, *tmp;
  91. __u64 length = 1 + flock->fl_end - flock->fl_start;
  92. struct list_head tmp_llist;
  93. INIT_LIST_HEAD(&tmp_llist);
  94. /*
  95. * Accessing maxBuf is racy with cifs_reconnect - need to store value
  96. * and check it for zero before using.
  97. */
  98. max_buf = tcon->ses->server->maxBuf;
  99. if (!max_buf)
  100. return -EINVAL;
  101. max_num = max_buf / sizeof(struct smb2_lock_element);
  102. buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
  103. if (!buf)
  104. return -ENOMEM;
  105. cur = buf;
  106. down_write(&cinode->lock_sem);
  107. list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
  108. if (flock->fl_start > li->offset ||
  109. (flock->fl_start + length) <
  110. (li->offset + li->length))
  111. continue;
  112. if (current->tgid != li->pid)
  113. continue;
  114. if (cinode->can_cache_brlcks) {
  115. /*
  116. * We can cache brlock requests - simply remove a lock
  117. * from the file's list.
  118. */
  119. list_del(&li->llist);
  120. cifs_del_lock_waiters(li);
  121. kfree(li);
  122. continue;
  123. }
  124. cur->Length = cpu_to_le64(li->length);
  125. cur->Offset = cpu_to_le64(li->offset);
  126. cur->Flags = cpu_to_le32(SMB2_LOCKFLAG_UNLOCK);
  127. /*
  128. * We need to save a lock here to let us add it again to the
  129. * file's list if the unlock range request fails on the server.
  130. */
  131. list_move(&li->llist, &tmp_llist);
  132. if (++num == max_num) {
  133. stored_rc = smb2_lockv(xid, tcon,
  134. cfile->fid.persistent_fid,
  135. cfile->fid.volatile_fid,
  136. current->tgid, num, buf);
  137. if (stored_rc) {
  138. /*
  139. * We failed on the unlock range request - add
  140. * all locks from the tmp list to the head of
  141. * the file's list.
  142. */
  143. cifs_move_llist(&tmp_llist,
  144. &cfile->llist->locks);
  145. rc = stored_rc;
  146. } else
  147. /*
  148. * The unlock range request succeed - free the
  149. * tmp list.
  150. */
  151. cifs_free_llist(&tmp_llist);
  152. cur = buf;
  153. num = 0;
  154. } else
  155. cur++;
  156. }
  157. if (num) {
  158. stored_rc = smb2_lockv(xid, tcon, cfile->fid.persistent_fid,
  159. cfile->fid.volatile_fid, current->tgid,
  160. num, buf);
  161. if (stored_rc) {
  162. cifs_move_llist(&tmp_llist, &cfile->llist->locks);
  163. rc = stored_rc;
  164. } else
  165. cifs_free_llist(&tmp_llist);
  166. }
  167. up_write(&cinode->lock_sem);
  168. kfree(buf);
  169. return rc;
  170. }
  171. static int
  172. smb2_push_mand_fdlocks(struct cifs_fid_locks *fdlocks, const unsigned int xid,
  173. struct smb2_lock_element *buf, unsigned int max_num)
  174. {
  175. int rc = 0, stored_rc;
  176. struct cifsFileInfo *cfile = fdlocks->cfile;
  177. struct cifsLockInfo *li;
  178. unsigned int num = 0;
  179. struct smb2_lock_element *cur = buf;
  180. struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
  181. list_for_each_entry(li, &fdlocks->locks, llist) {
  182. cur->Length = cpu_to_le64(li->length);
  183. cur->Offset = cpu_to_le64(li->offset);
  184. cur->Flags = cpu_to_le32(li->type |
  185. SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
  186. if (++num == max_num) {
  187. stored_rc = smb2_lockv(xid, tcon,
  188. cfile->fid.persistent_fid,
  189. cfile->fid.volatile_fid,
  190. current->tgid, num, buf);
  191. if (stored_rc)
  192. rc = stored_rc;
  193. cur = buf;
  194. num = 0;
  195. } else
  196. cur++;
  197. }
  198. if (num) {
  199. stored_rc = smb2_lockv(xid, tcon,
  200. cfile->fid.persistent_fid,
  201. cfile->fid.volatile_fid,
  202. current->tgid, num, buf);
  203. if (stored_rc)
  204. rc = stored_rc;
  205. }
  206. return rc;
  207. }
  208. int
  209. smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
  210. {
  211. int rc = 0, stored_rc;
  212. unsigned int xid;
  213. unsigned int max_num, max_buf;
  214. struct smb2_lock_element *buf;
  215. struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
  216. struct cifs_fid_locks *fdlocks;
  217. xid = get_xid();
  218. /*
  219. * Accessing maxBuf is racy with cifs_reconnect - need to store value
  220. * and check it for zero before using.
  221. */
  222. max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
  223. if (!max_buf) {
  224. free_xid(xid);
  225. return -EINVAL;
  226. }
  227. max_num = max_buf / sizeof(struct smb2_lock_element);
  228. buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
  229. if (!buf) {
  230. free_xid(xid);
  231. return -ENOMEM;
  232. }
  233. list_for_each_entry(fdlocks, &cinode->llist, llist) {
  234. stored_rc = smb2_push_mand_fdlocks(fdlocks, xid, buf, max_num);
  235. if (stored_rc)
  236. rc = stored_rc;
  237. }
  238. kfree(buf);
  239. free_xid(xid);
  240. return rc;
  241. }