Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: LGPL-2.1
0002 /*
0003  *
0004  *   Copyright (C) International Business Machines  Corp., 2002, 2011
0005  *   Author(s): Steve French (sfrench@us.ibm.com),
0006  *              Pavel Shilovsky ((pshilovsky@samba.org) 2012
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         /* default timeout is 0, servers pick default (120 seconds) */
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 /* no return info */);
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         /* if open response does not have IndexNumber field - get it */
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                  * let get_inode_info disable server inode
0086                  * numbers
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      * Accessing maxBuf is racy with cifs_reconnect - need to store value
0119      * and check it before using.
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              * flock and OFD lock are associated with an open
0143              * file description, not the process.
0144              */
0145             if (!(flock->fl_flags & (FL_FLOCK | FL_OFDLCK)))
0146                 continue;
0147         if (cinode->can_cache_brlcks) {
0148             /*
0149              * We can cache brlock requests - simply remove a lock
0150              * from the file's list.
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          * We need to save a lock here to let us add it again to the
0162          * file's list if the unlock range request fails on the server.
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                  * We failed on the unlock range request - add
0173                  * all locks from the tmp list to the head of
0174                  * the file's list.
0175                  */
0176                 cifs_move_llist(&tmp_llist,
0177                         &cfile->llist->locks);
0178                 rc = stored_rc;
0179             } else
0180                 /*
0181                  * The unlock range request succeed - free the
0182                  * tmp list.
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      * Accessing maxBuf is racy with cifs_reconnect - need to store value
0260      * and check it for zero before using.
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 }