2021-03-16 04:49:09 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright ( C ) 2018 Samsung Electronics Co . , Ltd .
*/
# include <linux/list.h>
# include <linux/slab.h>
2021-04-01 11:45:33 +03:00
# include <linux/xarray.h>
2021-03-16 04:49:09 +03:00
# include "../transport_ipc.h"
# include "../connection.h"
# include "tree_connect.h"
# include "user_config.h"
# include "share_config.h"
# include "user_session.h"
struct ksmbd_tree_conn_status
2022-07-25 07:36:52 +03:00
ksmbd_tree_conn_connect ( struct ksmbd_conn * conn , struct ksmbd_session * sess ,
2022-09-15 16:49:11 +03:00
const char * share_name )
2021-03-16 04:49:09 +03:00
{
2022-08-08 15:56:48 +03:00
struct ksmbd_tree_conn_status status = { - ENOENT , NULL } ;
2021-03-16 04:49:09 +03:00
struct ksmbd_tree_connect_response * resp = NULL ;
struct ksmbd_share_config * sc ;
struct ksmbd_tree_connect * tree_conn = NULL ;
struct sockaddr * peer_addr ;
2021-04-01 11:45:33 +03:00
int ret ;
2021-03-16 04:49:09 +03:00
2022-10-03 02:09:34 +03:00
sc = ksmbd_share_config_get ( conn - > um , share_name ) ;
2021-03-16 04:49:09 +03:00
if ( ! sc )
return status ;
2021-04-02 06:47:14 +03:00
tree_conn = kzalloc ( sizeof ( struct ksmbd_tree_connect ) , GFP_KERNEL ) ;
2021-03-16 04:49:09 +03:00
if ( ! tree_conn ) {
status . ret = - ENOMEM ;
goto out_error ;
}
tree_conn - > id = ksmbd_acquire_tree_conn_id ( sess ) ;
if ( tree_conn - > id < 0 ) {
status . ret = - EINVAL ;
goto out_error ;
}
2022-07-25 07:36:52 +03:00
peer_addr = KSMBD_TCP_PEER_SOCKADDR ( conn ) ;
2021-03-16 04:49:09 +03:00
resp = ksmbd_ipc_tree_connect_request ( sess ,
sc ,
tree_conn ,
peer_addr ) ;
if ( ! resp ) {
status . ret = - EINVAL ;
goto out_error ;
}
status . ret = resp - > status ;
if ( status . ret ! = KSMBD_TREE_CONN_STATUS_OK )
goto out_error ;
tree_conn - > flags = resp - > connection_flags ;
2022-08-09 01:02:14 +03:00
if ( test_tree_conn_flag ( tree_conn , KSMBD_TREE_CONN_FLAG_UPDATE ) ) {
struct ksmbd_share_config * new_sc ;
ksmbd_share_config_del ( sc ) ;
2022-10-03 02:09:34 +03:00
new_sc = ksmbd_share_config_get ( conn - > um , share_name ) ;
2022-08-09 01:02:14 +03:00
if ( ! new_sc ) {
pr_err ( " Failed to update stale share config \n " ) ;
status . ret = - ESTALE ;
goto out_error ;
}
ksmbd_share_config_put ( sc ) ;
sc = new_sc ;
}
2021-03-16 04:49:09 +03:00
tree_conn - > user = sess - > user ;
tree_conn - > share_conf = sc ;
status . tree_conn = tree_conn ;
2021-04-01 11:45:33 +03:00
ret = xa_err ( xa_store ( & sess - > tree_conns , tree_conn - > id , tree_conn ,
2021-06-01 07:18:44 +03:00
GFP_KERNEL ) ) ;
2021-04-01 11:45:33 +03:00
if ( ret ) {
status . ret = - ENOMEM ;
goto out_error ;
}
2021-04-02 06:47:14 +03:00
kvfree ( resp ) ;
2021-03-16 04:49:09 +03:00
return status ;
out_error :
if ( tree_conn )
ksmbd_release_tree_conn_id ( sess , tree_conn - > id ) ;
ksmbd_share_config_put ( sc ) ;
2021-04-02 06:47:14 +03:00
kfree ( tree_conn ) ;
kvfree ( resp ) ;
2021-03-16 04:49:09 +03:00
return status ;
}
int ksmbd_tree_conn_disconnect ( struct ksmbd_session * sess ,
struct ksmbd_tree_connect * tree_conn )
{
int ret ;
ret = ksmbd_ipc_tree_disconnect_request ( sess - > id , tree_conn - > id ) ;
ksmbd_release_tree_conn_id ( sess , tree_conn - > id ) ;
2021-04-01 11:45:33 +03:00
xa_erase ( & sess - > tree_conns , tree_conn - > id ) ;
2021-03-16 04:49:09 +03:00
ksmbd_share_config_put ( tree_conn - > share_conf ) ;
2021-04-02 06:47:14 +03:00
kfree ( tree_conn ) ;
2021-03-16 04:49:09 +03:00
return ret ;
}
struct ksmbd_tree_connect * ksmbd_tree_conn_lookup ( struct ksmbd_session * sess ,
unsigned int id )
{
2021-04-01 11:45:33 +03:00
return xa_load ( & sess - > tree_conns , id ) ;
2021-03-16 04:49:09 +03:00
}
struct ksmbd_share_config * ksmbd_tree_conn_share ( struct ksmbd_session * sess ,
unsigned int id )
{
struct ksmbd_tree_connect * tc ;
tc = ksmbd_tree_conn_lookup ( sess , id ) ;
if ( tc )
return tc - > share_conf ;
return NULL ;
}
int ksmbd_tree_conn_session_logoff ( struct ksmbd_session * sess )
{
int ret = 0 ;
2021-04-01 11:45:33 +03:00
struct ksmbd_tree_connect * tc ;
unsigned long id ;
2021-03-16 04:49:09 +03:00
2021-04-01 11:45:33 +03:00
xa_for_each ( & sess - > tree_conns , id , tc )
2021-03-16 04:49:09 +03:00
ret | = ksmbd_tree_conn_disconnect ( sess , tc ) ;
2021-04-01 11:45:33 +03:00
xa_destroy ( & sess - > tree_conns ) ;
2021-03-16 04:49:09 +03:00
return ret ;
}