aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/ksmbd/connection.c2
-rw-r--r--fs/ksmbd/oplock.c3
-rw-r--r--fs/ksmbd/smb2pdu.c93
-rw-r--r--fs/ksmbd/transport_rdma.c14
-rw-r--r--fs/ksmbd/transport_rdma.h2
-rw-r--r--fs/ksmbd/vfs.c101
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;
}