0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/fs.h>
0010 #include <linux/stat.h>
0011 #include <linux/slab.h>
0012 #include <linux/pagemap.h>
0013 #include <asm/div64.h>
0014 #include "cifsfs.h"
0015 #include "cifspdu.h"
0016 #include "cifsglob.h"
0017 #include "cifsproto.h"
0018 #include "cifs_debug.h"
0019 #include "cifs_fs_sb.h"
0020 #include "cifs_unicode.h"
0021 #include "fscache.h"
0022 #include "smb2proto.h"
0023
0024 int
0025 smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
0026 __u32 *oplock, FILE_ALL_INFO *buf)
0027 {
0028 int rc;
0029 __le16 *smb2_path;
0030 struct smb2_file_all_info *smb2_data = NULL;
0031 __u8 smb2_oplock;
0032 struct cifs_fid *fid = oparms->fid;
0033 struct network_resiliency_req nr_ioctl_req;
0034
0035 smb2_path = cifs_convert_path_to_utf16(oparms->path, oparms->cifs_sb);
0036 if (smb2_path == NULL) {
0037 rc = -ENOMEM;
0038 goto out;
0039 }
0040
0041 smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
0042 GFP_KERNEL);
0043 if (smb2_data == NULL) {
0044 rc = -ENOMEM;
0045 goto out;
0046 }
0047
0048 oparms->desired_access |= FILE_READ_ATTRIBUTES;
0049 smb2_oplock = SMB2_OPLOCK_LEVEL_BATCH;
0050
0051 rc = SMB2_open(xid, oparms, smb2_path, &smb2_oplock, smb2_data, NULL,
0052 NULL, NULL);
0053 if (rc)
0054 goto out;
0055
0056
0057 if (oparms->tcon->use_resilient) {
0058
0059 nr_ioctl_req.Timeout =
0060 cpu_to_le32(oparms->tcon->handle_timeout);
0061 nr_ioctl_req.Reserved = 0;
0062 rc = SMB2_ioctl(xid, oparms->tcon, fid->persistent_fid,
0063 fid->volatile_fid, FSCTL_LMR_REQUEST_RESILIENCY,
0064 (char *)&nr_ioctl_req, sizeof(nr_ioctl_req),
0065 CIFSMaxBufSize, NULL, NULL );
0066 if (rc == -EOPNOTSUPP) {
0067 cifs_dbg(VFS,
0068 "resiliency not supported by server, disabling\n");
0069 oparms->tcon->use_resilient = false;
0070 } else if (rc)
0071 cifs_dbg(FYI, "error %d setting resiliency\n", rc);
0072
0073 rc = 0;
0074 }
0075
0076 if (buf) {
0077
0078 if (smb2_data->IndexNumber == 0) {
0079 rc = SMB2_get_srv_num(xid, oparms->tcon,
0080 fid->persistent_fid,
0081 fid->volatile_fid,
0082 &smb2_data->IndexNumber);
0083 if (rc) {
0084
0085
0086
0087
0088 smb2_data->IndexNumber = 0;
0089 rc = 0;
0090 }
0091 }
0092 move_smb2_info_to_cifs(buf, smb2_data);
0093 }
0094
0095 *oplock = smb2_oplock;
0096 out:
0097 kfree(smb2_data);
0098 kfree(smb2_path);
0099 return rc;
0100 }
0101
0102 int
0103 smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
0104 const unsigned int xid)
0105 {
0106 int rc = 0, stored_rc;
0107 unsigned int max_num, num = 0, max_buf;
0108 struct smb2_lock_element *buf, *cur;
0109 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
0110 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
0111 struct cifsLockInfo *li, *tmp;
0112 __u64 length = 1 + flock->fl_end - flock->fl_start;
0113 struct list_head tmp_llist;
0114
0115 INIT_LIST_HEAD(&tmp_llist);
0116
0117
0118
0119
0120
0121 max_buf = tcon->ses->server->maxBuf;
0122 if (max_buf < sizeof(struct smb2_lock_element))
0123 return -EINVAL;
0124
0125 BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
0126 max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
0127 max_num = max_buf / sizeof(struct smb2_lock_element);
0128 buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
0129 if (!buf)
0130 return -ENOMEM;
0131
0132 cur = buf;
0133
0134 cifs_down_write(&cinode->lock_sem);
0135 list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) {
0136 if (flock->fl_start > li->offset ||
0137 (flock->fl_start + length) <
0138 (li->offset + li->length))
0139 continue;
0140 if (current->tgid != li->pid)
0141
0142
0143
0144
0145 if (!(flock->fl_flags & (FL_FLOCK | FL_OFDLCK)))
0146 continue;
0147 if (cinode->can_cache_brlcks) {
0148
0149
0150
0151
0152 list_del(&li->llist);
0153 cifs_del_lock_waiters(li);
0154 kfree(li);
0155 continue;
0156 }
0157 cur->Length = cpu_to_le64(li->length);
0158 cur->Offset = cpu_to_le64(li->offset);
0159 cur->Flags = cpu_to_le32(SMB2_LOCKFLAG_UNLOCK);
0160
0161
0162
0163
0164 list_move(&li->llist, &tmp_llist);
0165 if (++num == max_num) {
0166 stored_rc = smb2_lockv(xid, tcon,
0167 cfile->fid.persistent_fid,
0168 cfile->fid.volatile_fid,
0169 current->tgid, num, buf);
0170 if (stored_rc) {
0171
0172
0173
0174
0175
0176 cifs_move_llist(&tmp_llist,
0177 &cfile->llist->locks);
0178 rc = stored_rc;
0179 } else
0180
0181
0182
0183
0184 cifs_free_llist(&tmp_llist);
0185 cur = buf;
0186 num = 0;
0187 } else
0188 cur++;
0189 }
0190 if (num) {
0191 stored_rc = smb2_lockv(xid, tcon, cfile->fid.persistent_fid,
0192 cfile->fid.volatile_fid, current->tgid,
0193 num, buf);
0194 if (stored_rc) {
0195 cifs_move_llist(&tmp_llist, &cfile->llist->locks);
0196 rc = stored_rc;
0197 } else
0198 cifs_free_llist(&tmp_llist);
0199 }
0200 up_write(&cinode->lock_sem);
0201
0202 kfree(buf);
0203 return rc;
0204 }
0205
0206 static int
0207 smb2_push_mand_fdlocks(struct cifs_fid_locks *fdlocks, const unsigned int xid,
0208 struct smb2_lock_element *buf, unsigned int max_num)
0209 {
0210 int rc = 0, stored_rc;
0211 struct cifsFileInfo *cfile = fdlocks->cfile;
0212 struct cifsLockInfo *li;
0213 unsigned int num = 0;
0214 struct smb2_lock_element *cur = buf;
0215 struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
0216
0217 list_for_each_entry(li, &fdlocks->locks, llist) {
0218 cur->Length = cpu_to_le64(li->length);
0219 cur->Offset = cpu_to_le64(li->offset);
0220 cur->Flags = cpu_to_le32(li->type |
0221 SMB2_LOCKFLAG_FAIL_IMMEDIATELY);
0222 if (++num == max_num) {
0223 stored_rc = smb2_lockv(xid, tcon,
0224 cfile->fid.persistent_fid,
0225 cfile->fid.volatile_fid,
0226 current->tgid, num, buf);
0227 if (stored_rc)
0228 rc = stored_rc;
0229 cur = buf;
0230 num = 0;
0231 } else
0232 cur++;
0233 }
0234 if (num) {
0235 stored_rc = smb2_lockv(xid, tcon,
0236 cfile->fid.persistent_fid,
0237 cfile->fid.volatile_fid,
0238 current->tgid, num, buf);
0239 if (stored_rc)
0240 rc = stored_rc;
0241 }
0242
0243 return rc;
0244 }
0245
0246 int
0247 smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
0248 {
0249 int rc = 0, stored_rc;
0250 unsigned int xid;
0251 unsigned int max_num, max_buf;
0252 struct smb2_lock_element *buf;
0253 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry));
0254 struct cifs_fid_locks *fdlocks;
0255
0256 xid = get_xid();
0257
0258
0259
0260
0261
0262 max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
0263 if (max_buf < sizeof(struct smb2_lock_element)) {
0264 free_xid(xid);
0265 return -EINVAL;
0266 }
0267
0268 BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
0269 max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
0270 max_num = max_buf / sizeof(struct smb2_lock_element);
0271 buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
0272 if (!buf) {
0273 free_xid(xid);
0274 return -ENOMEM;
0275 }
0276
0277 list_for_each_entry(fdlocks, &cinode->llist, llist) {
0278 stored_rc = smb2_push_mand_fdlocks(fdlocks, xid, buf, max_num);
0279 if (stored_rc)
0280 rc = stored_rc;
0281 }
0282
0283 kfree(buf);
0284 free_xid(xid);
0285 return rc;
0286 }