OSDN Git Service

cifs: use a compound for setting an xattr
authorRonnie Sahlberg <lsahlber@redhat.com>
Tue, 6 Nov 2018 12:52:43 +0000 (22:52 +1000)
committerSteve French <stfrench@microsoft.com>
Mon, 24 Dec 2018 04:36:24 +0000 (22:36 -0600)
Improve performance by reducing number of network round trips
for set xattr.

Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/cifs/smb2ops.c

index e25c7aa..6ecf137 100644 (file)
@@ -907,14 +907,28 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
            const __u16 ea_value_len, const struct nls_table *nls_codepage,
            struct cifs_sb_info *cifs_sb)
 {
-       int rc;
-       __le16 *utf16_path;
-       __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
-       struct cifs_open_parms oparms;
-       struct cifs_fid fid;
-       struct smb2_file_full_ea_info *ea;
+       struct cifs_ses *ses = tcon->ses;
+       struct TCP_Server_Info *server = ses->server;
+       __le16 *utf16_path = NULL;
        int ea_name_len = strlen(ea_name);
+       int flags = 0;
        int len;
+       struct smb_rqst rqst[3];
+       int resp_buftype[3];
+       struct kvec rsp_iov[3];
+       struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
+       struct cifs_open_parms oparms;
+       __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+       struct cifs_fid fid;
+       struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
+       unsigned int size[1];
+       void *data[1];
+       struct smb2_file_full_ea_info *ea = NULL;
+       struct kvec close_iov[1];
+       int rc;
+
+       if (smb3_encryption_required(tcon))
+               flags |= CIFS_TRANSFORM_REQ;
 
        if (ea_name_len > 255)
                return -EINVAL;
@@ -923,6 +937,16 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
        if (!utf16_path)
                return -ENOMEM;
 
+       memset(rqst, 0, sizeof(rqst));
+       resp_buftype[0] = resp_buftype[1] = resp_buftype[2] = CIFS_NO_BUFFER;
+       memset(rsp_iov, 0, sizeof(rsp_iov));
+
+       /* Open */
+       memset(&open_iov, 0, sizeof(open_iov));
+       rqst[0].rq_iov = open_iov;
+       rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE;
+
+       memset(&oparms, 0, sizeof(oparms));
        oparms.tcon = tcon;
        oparms.desired_access = FILE_WRITE_EA;
        oparms.disposition = FILE_OPEN;
@@ -933,18 +957,22 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
        oparms.fid = &fid;
        oparms.reconnect = false;
 
-       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
-       kfree(utf16_path);
-       if (rc) {
-               cifs_dbg(FYI, "open failed rc=%d\n", rc);
-               return rc;
-       }
+       rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, utf16_path);
+       if (rc)
+               goto sea_exit;
+       smb2_set_next_command(ses->server, &rqst[0]);
+
+
+       /* Set Info */
+       memset(&si_iov, 0, sizeof(si_iov));
+       rqst[1].rq_iov = si_iov;
+       rqst[1].rq_nvec = 1;
 
        len = sizeof(ea) + ea_name_len + ea_value_len + 1;
        ea = kzalloc(len, GFP_KERNEL);
        if (ea == NULL) {
-               SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto sea_exit;
        }
 
        ea->ea_name_length = ea_name_len;
@@ -952,12 +980,36 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
        memcpy(ea->ea_data, ea_name, ea_name_len + 1);
        memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
 
-       rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
-                        len);
-       kfree(ea);
+       size[0] = len;
+       data[0] = ea;
 
-       SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+       rc = SMB2_set_info_init(tcon, &rqst[1], COMPOUND_FID,
+                               COMPOUND_FID, current->tgid,
+                               FILE_FULL_EA_INFORMATION,
+                               SMB2_O_INFO_FILE, 0, data, size);
+       smb2_set_next_command(server, &rqst[1]);
+       smb2_set_related(&rqst[1]);
+
+
+       /* Close */
+       memset(&close_iov, 0, sizeof(close_iov));
+       rqst[2].rq_iov = close_iov;
+       rqst[2].rq_nvec = 1;
+       rc = SMB2_close_init(tcon, &rqst[2], COMPOUND_FID, COMPOUND_FID);
+       smb2_set_related(&rqst[2]);
+
+       rc = compound_send_recv(xid, ses, flags, 3, rqst,
+                               resp_buftype, rsp_iov);
 
+ sea_exit:
+       kfree(ea);
+       kfree(utf16_path);
+       SMB2_open_free(&rqst[0]);
+       SMB2_set_info_free(&rqst[1]);
+       SMB2_close_free(&rqst[2]);
+       free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+       free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base);
+       free_rsp_buf(resp_buftype[2], rsp_iov[2].iov_base);
        return rc;
 }
 #endif