1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
6 #include <linux/list.h>
7 #include <linux/slab.h>
8 #include <linux/xarray.h>
10 #include "../transport_ipc.h"
11 #include "../connection.h"
13 #include "tree_connect.h"
14 #include "user_config.h"
15 #include "share_config.h"
16 #include "user_session.h"
18 struct ksmbd_tree_conn_status
19 ksmbd_tree_conn_connect(struct ksmbd_conn
*conn
, struct ksmbd_session
*sess
,
20 const char *share_name
)
22 struct ksmbd_tree_conn_status status
= {-ENOENT
, NULL
};
23 struct ksmbd_tree_connect_response
*resp
= NULL
;
24 struct ksmbd_share_config
*sc
;
25 struct ksmbd_tree_connect
*tree_conn
= NULL
;
26 struct sockaddr
*peer_addr
;
29 sc
= ksmbd_share_config_get(conn
->um
, share_name
);
33 tree_conn
= kzalloc(sizeof(struct ksmbd_tree_connect
), GFP_KERNEL
);
39 tree_conn
->id
= ksmbd_acquire_tree_conn_id(sess
);
40 if (tree_conn
->id
< 0) {
45 peer_addr
= KSMBD_TCP_PEER_SOCKADDR(conn
);
46 resp
= ksmbd_ipc_tree_connect_request(sess
,
55 status
.ret
= resp
->status
;
56 if (status
.ret
!= KSMBD_TREE_CONN_STATUS_OK
)
59 tree_conn
->flags
= resp
->connection_flags
;
60 if (test_tree_conn_flag(tree_conn
, KSMBD_TREE_CONN_FLAG_UPDATE
)) {
61 struct ksmbd_share_config
*new_sc
;
63 ksmbd_share_config_del(sc
);
64 new_sc
= ksmbd_share_config_get(conn
->um
, share_name
);
66 pr_err("Failed to update stale share config\n");
70 ksmbd_share_config_put(sc
);
74 tree_conn
->user
= sess
->user
;
75 tree_conn
->share_conf
= sc
;
76 status
.tree_conn
= tree_conn
;
78 ret
= xa_err(xa_store(&sess
->tree_conns
, tree_conn
->id
, tree_conn
,
89 ksmbd_release_tree_conn_id(sess
, tree_conn
->id
);
90 ksmbd_share_config_put(sc
);
96 int ksmbd_tree_conn_disconnect(struct ksmbd_session
*sess
,
97 struct ksmbd_tree_connect
*tree_conn
)
101 ret
= ksmbd_ipc_tree_disconnect_request(sess
->id
, tree_conn
->id
);
102 ksmbd_release_tree_conn_id(sess
, tree_conn
->id
);
103 xa_erase(&sess
->tree_conns
, tree_conn
->id
);
104 ksmbd_share_config_put(tree_conn
->share_conf
);
109 struct ksmbd_tree_connect
*ksmbd_tree_conn_lookup(struct ksmbd_session
*sess
,
112 struct ksmbd_tree_connect
*tcon
;
114 tcon
= xa_load(&sess
->tree_conns
, id
);
116 if (test_bit(TREE_CONN_EXPIRE
, &tcon
->status
))
123 int ksmbd_tree_conn_session_logoff(struct ksmbd_session
*sess
)
126 struct ksmbd_tree_connect
*tc
;
132 xa_for_each(&sess
->tree_conns
, id
, tc
)
133 ret
|= ksmbd_tree_conn_disconnect(sess
, tc
);
134 xa_destroy(&sess
->tree_conns
);