diff options
-rw-r--r-- | fs/ksmbd/connection.c | 2 | ||||
-rw-r--r-- | fs/ksmbd/oplock.c | 3 | ||||
-rw-r--r-- | fs/ksmbd/smb2pdu.c | 93 | ||||
-rw-r--r-- | fs/ksmbd/transport_rdma.c | 14 | ||||
-rw-r--r-- | fs/ksmbd/transport_rdma.h | 2 | ||||
-rw-r--r-- | fs/ksmbd/vfs.c | 101 |
6 files changed, 106 insertions, 109 deletions
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c index 8430848bea45..d7ee0bfb5838 100644 --- a/fs/ksmbd/connection.c +++ b/fs/ksmbd/connection.c @@ -372,7 +372,7 @@ int ksmbd_conn_transport_init(void) ret = ksmbd_rdma_init(); if (ret) { - pr_err("Failed to init KSMBD subsystem: %d\n", ret); + pr_err("Failed to init RDMA subsystem: %d\n", ret); goto out; } out: diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index 8e53815eedc6..6ace6c2f22dc 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -1446,7 +1446,8 @@ struct lease_ctx_info *parse_lease_state(void *open_req) * @open_req: buffer containing smb2 file open(create) request * @tag: context name to search for * - * Return: pointer to requested context, NULL if @str context not found + * Return: pointer to requested context, NULL if @str context not found + * or error pointer if name length is invalid. */ struct create_context *smb2_find_context_vals(void *open_req, const char *tag) { diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 2e266a9d3935..c1a594599431 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -22,6 +22,7 @@ #include "asn1.h" #include "connection.h" #include "transport_ipc.h" +#include "transport_rdma.h" #include "vfs.h" #include "vfs_cache.h" #include "misc.h" @@ -2126,21 +2127,6 @@ next: return rc; } -static inline int check_context_err(void *ctx, char *str) -{ - int err; - - err = PTR_ERR(ctx); - ksmbd_debug(SMB, "find context %s err %d\n", str, err ? err : -ENOENT); - - if (err == -EINVAL) { - pr_err("bad name length\n"); - return err; - } - - return 0; -} - static noinline int smb2_set_stream_name_xattr(struct path *path, struct ksmbd_file *fp, char *stream_name, int s_type) @@ -2523,11 +2509,10 @@ int smb2_open(struct ksmbd_work *work) if (req->CreateContextsOffset) { /* Parse non-durable handle create contexts */ context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER); - if (IS_ERR_OR_NULL(context)) { - rc = check_context_err(context, SMB2_CREATE_EA_BUFFER); - if (rc < 0) - goto err_out1; - } else { + if (IS_ERR(context)) { + rc = PTR_ERR(context); + goto err_out1; + } else if (context) { ea_buf = (struct create_ea_buf_req *)context; if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { rsp->hdr.Status = STATUS_ACCESS_DENIED; @@ -2538,12 +2523,10 @@ int smb2_open(struct ksmbd_work *work) context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST); - if (IS_ERR_OR_NULL(context)) { - rc = check_context_err(context, - SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST); - if (rc < 0) - goto err_out1; - } else { + if (IS_ERR(context)) { + rc = PTR_ERR(context); + goto err_out1; + } else if (context) { ksmbd_debug(SMB, "get query maximal access context\n"); maximal_access_ctxt = 1; @@ -2551,12 +2534,10 @@ int smb2_open(struct ksmbd_work *work) context = smb2_find_context_vals(req, SMB2_CREATE_TIMEWARP_REQUEST); - if (IS_ERR_OR_NULL(context)) { - rc = check_context_err(context, - SMB2_CREATE_TIMEWARP_REQUEST); - if (rc < 0) - goto err_out1; - } else { + if (IS_ERR(context)) { + rc = PTR_ERR(context); + goto err_out1; + } else if (context) { ksmbd_debug(SMB, "get timewarp context\n"); rc = -EBADF; goto err_out1; @@ -2565,12 +2546,10 @@ int smb2_open(struct ksmbd_work *work) if (tcon->posix_extensions) { context = smb2_find_context_vals(req, SMB2_CREATE_TAG_POSIX); - if (IS_ERR_OR_NULL(context)) { - rc = check_context_err(context, - SMB2_CREATE_TAG_POSIX); - if (rc < 0) - goto err_out1; - } else { + if (IS_ERR(context)) { + rc = PTR_ERR(context); + goto err_out1; + } else if (context) { struct create_posix *posix = (struct create_posix *)context; ksmbd_debug(SMB, "get posix context\n"); @@ -2968,12 +2947,10 @@ int smb2_open(struct ksmbd_work *work) az_req = (struct create_alloc_size_req *)smb2_find_context_vals(req, SMB2_CREATE_ALLOCATION_SIZE); - if (IS_ERR_OR_NULL(az_req)) { - rc = check_context_err(az_req, - SMB2_CREATE_ALLOCATION_SIZE); - if (rc < 0) - goto err_out; - } else { + if (IS_ERR(az_req)) { + rc = PTR_ERR(az_req); + goto err_out; + } else if (az_req) { loff_t alloc_size = le64_to_cpu(az_req->AllocationSize); int err; @@ -2990,11 +2967,10 @@ int smb2_open(struct ksmbd_work *work) } context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID); - if (IS_ERR_OR_NULL(context)) { - rc = check_context_err(context, SMB2_CREATE_QUERY_ON_DISK_ID); - if (rc < 0) - goto err_out; - } else { + if (IS_ERR(context)) { + rc = PTR_ERR(context); + goto err_out; + } else if (context) { ksmbd_debug(SMB, "get query on disk id context\n"); query_disk_id = 1; } @@ -6860,7 +6836,7 @@ skip: rsp->Reserved = 0; inc_rfc1001_len(rsp, 4); ksmbd_fd_put(work, fp); - return err; + return 0; out: list_for_each_entry_safe(smb_lock, tmp, &lock_list, llist) { @@ -6871,15 +6847,16 @@ out: list_for_each_entry_safe(smb_lock, tmp, &rollback_list, llist) { struct file_lock *rlock = NULL; + int rc; rlock = smb_flock_init(filp); rlock->fl_type = F_UNLCK; rlock->fl_start = smb_lock->start; rlock->fl_end = smb_lock->end; - err = vfs_lock_file(filp, 0, rlock, NULL); - if (err) - pr_err("rollback unlock fail : %d\n", err); + rc = vfs_lock_file(filp, 0, rlock, NULL); + if (rc) + pr_err("rollback unlock fail : %d\n", rc); list_del(&smb_lock->llist); spin_lock(&work->conn->llist_lock); @@ -6896,7 +6873,7 @@ out2: ksmbd_debug(SMB, "failed in taking lock(flags : %x)\n", flags); smb2_set_err_rsp(work); ksmbd_fd_put(work, fp); - return 0; + return err; } static int fsctl_copychunk(struct ksmbd_work *work, struct smb2_ioctl_req *req, @@ -7052,11 +7029,11 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn, &rsp->Buffer[nbytes]; nii_rsp->IfIndex = cpu_to_le32(netdev->ifindex); - /* TODO: specify the RDMA capabilities */ + nii_rsp->Capability = 0; if (netdev->num_tx_queues > 1) - nii_rsp->Capability = cpu_to_le32(RSS_CAPABLE); - else - nii_rsp->Capability = 0; + nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE); + if (ksmbd_rdma_capable_netdev(netdev)) + nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE); nii_rsp->Next = cpu_to_le32(152); nii_rsp->Reserved = 0; diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c index d5728c84a15a..f818fe358f31 100644 --- a/fs/ksmbd/transport_rdma.c +++ b/fs/ksmbd/transport_rdma.c @@ -2033,6 +2033,20 @@ int ksmbd_rdma_destroy(void) return 0; } +bool ksmbd_rdma_capable_netdev(struct net_device *netdev) +{ + struct ib_device *ibdev; + bool rdma_capable = false; + + ibdev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_UNKNOWN); + if (ibdev) { + if (rdma_frwr_is_supported(&ibdev->attrs)) + rdma_capable = true; + ib_device_put(ibdev); + } + return rdma_capable; +} + static struct ksmbd_transport_ops ksmbd_smb_direct_transport_ops = { .prepare = smb_direct_prepare, .disconnect = smb_direct_disconnect, diff --git a/fs/ksmbd/transport_rdma.h b/fs/ksmbd/transport_rdma.h index da60fcec3ede..72e2574079f3 100644 --- a/fs/ksmbd/transport_rdma.h +++ b/fs/ksmbd/transport_rdma.h @@ -53,9 +53,11 @@ struct smb_direct_data_transfer { #ifdef CONFIG_SMB_SERVER_SMBDIRECT int ksmbd_rdma_init(void); int ksmbd_rdma_destroy(void); +bool ksmbd_rdma_capable_netdev(struct net_device *netdev); #else static inline int ksmbd_rdma_init(void) { return 0; } static inline int ksmbd_rdma_destroy(void) { return 0; } +static inline bool ksmbd_rdma_capable_netdev(struct net_device *netdev) { return false; } #endif #endif /* __KSMBD_TRANSPORT_RDMA_H__ */ diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c index 88e947f69f47..612c52d7a01b 100644 --- a/fs/ksmbd/vfs.c +++ b/fs/ksmbd/vfs.c @@ -1498,63 +1498,66 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, { int rc; struct ndr n; + struct inode *inode = d_inode(dentry); + struct ndr acl_ndr = {0}; + struct xattr_ntacl acl; + struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL; + __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0}; rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data); - if (rc > 0) { - struct inode *inode = d_inode(dentry); - struct ndr acl_ndr = {0}; - struct xattr_ntacl acl; - struct xattr_smb_acl *smb_acl = NULL, *def_smb_acl = NULL; - __u8 cmp_hash[XATTR_SD_HASH_SIZE] = {0}; - - n.length = rc; - rc = ndr_decode_v4_ntacl(&n, &acl); - if (rc) - return rc; - - smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, - ACL_TYPE_ACCESS); - if (S_ISDIR(inode->i_mode)) - def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, - inode, - ACL_TYPE_DEFAULT); - - rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, - smb_acl, def_smb_acl); - if (rc) { - pr_err("failed to encode ndr to posix acl\n"); - goto out; - } + if (rc <= 0) + return rc; - rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, - cmp_hash); - if (rc) { - pr_err("failed to generate hash for ndr acl\n"); - goto out; - } + n.length = rc; + rc = ndr_decode_v4_ntacl(&n, &acl); + if (rc) + goto free_n_data; - if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) { - pr_err("hash value diff\n"); - rc = -EINVAL; - goto out; - } + smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, + ACL_TYPE_ACCESS); + if (S_ISDIR(inode->i_mode)) + def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, + ACL_TYPE_DEFAULT); + + rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, smb_acl, + def_smb_acl); + if (rc) { + pr_err("failed to encode ndr to posix acl\n"); + goto out_free; + } - *pntsd = acl.sd_buf; - (*pntsd)->osidoffset = - cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) - NDR_NTSD_OFFSETOF); - (*pntsd)->gsidoffset = - cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) - NDR_NTSD_OFFSETOF); - (*pntsd)->dacloffset = - cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) - NDR_NTSD_OFFSETOF); + rc = ksmbd_gen_sd_hash(conn, acl_ndr.data, acl_ndr.offset, cmp_hash); + if (rc) { + pr_err("failed to generate hash for ndr acl\n"); + goto out_free; + } - rc = acl.sd_size; -out: - kfree(n.data); - kfree(acl_ndr.data); - kfree(smb_acl); - kfree(def_smb_acl); + if (memcmp(cmp_hash, acl.posix_acl_hash, XATTR_SD_HASH_SIZE)) { + pr_err("hash value diff\n"); + rc = -EINVAL; + goto out_free; } + *pntsd = acl.sd_buf; + (*pntsd)->osidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->osidoffset) - + NDR_NTSD_OFFSETOF); + (*pntsd)->gsidoffset = cpu_to_le32(le32_to_cpu((*pntsd)->gsidoffset) - + NDR_NTSD_OFFSETOF); + (*pntsd)->dacloffset = cpu_to_le32(le32_to_cpu((*pntsd)->dacloffset) - + NDR_NTSD_OFFSETOF); + + rc = acl.sd_size; +out_free: + kfree(acl_ndr.data); + kfree(smb_acl); + kfree(def_smb_acl); + if (rc < 0) { + kfree(acl.sd_buf); + *pntsd = NULL; + } + +free_n_data: + kfree(n.data); return rc; } |