#include <linux/ceph/ceph_debug.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/ratelimit.h>
#include <linux/bits.h>
#include <linux/ktime.h>
#include <linux/bitmap.h>
#include <linux/mnt_idmapping.h>
#include "super.h"
#include "mds_client.h"
#include "crypto.h"
#include <linux/ceph/ceph_features.h>
#include <linux/ceph/messenger.h>
#include <linux/ceph/decode.h>
#include <linux/ceph/pagelist.h>
#include <linux/ceph/auth.h>
#include <linux/ceph/debugfs.h>
#define RECONNECT_MAX_SIZE …
struct ceph_reconnect_state { … };
static void __wake_requests(struct ceph_mds_client *mdsc,
struct list_head *head);
static void ceph_cap_release_work(struct work_struct *work);
static void ceph_cap_reclaim_work(struct work_struct *work);
static const struct ceph_connection_operations mds_con_ops;
static int parse_reply_info_quota(void **p, void *end,
struct ceph_mds_reply_info_in *info)
{ … }
static int parse_reply_info_in(void **p, void *end,
struct ceph_mds_reply_info_in *info,
u64 features)
{ … }
static int parse_reply_info_dir(void **p, void *end,
struct ceph_mds_reply_dirfrag **dirfrag,
u64 features)
{ … }
static int parse_reply_info_lease(void **p, void *end,
struct ceph_mds_reply_lease **lease,
u64 features, u32 *altname_len, u8 **altname)
{ … }
static int parse_reply_info_trace(void **p, void *end,
struct ceph_mds_reply_info_parsed *info,
u64 features)
{ … }
static int parse_reply_info_readdir(void **p, void *end,
struct ceph_mds_request *req,
u64 features)
{ … }
static int parse_reply_info_filelock(void **p, void *end,
struct ceph_mds_reply_info_parsed *info,
u64 features)
{ … }
#if BITS_PER_LONG == 64
#define DELEGATED_INO_AVAILABLE …
static int ceph_parse_deleg_inos(void **p, void *end,
struct ceph_mds_session *s)
{ … }
u64 ceph_get_deleg_ino(struct ceph_mds_session *s)
{ … }
int ceph_restore_deleg_ino(struct ceph_mds_session *s, u64 ino)
{ … }
#else
static int ceph_parse_deleg_inos(void **p, void *end,
struct ceph_mds_session *s)
{
u32 sets;
ceph_decode_32_safe(p, end, sets, bad);
if (sets)
ceph_decode_skip_n(p, end, sets * 2 * sizeof(__le64), bad);
return 0;
bad:
return -EIO;
}
u64 ceph_get_deleg_ino(struct ceph_mds_session *s)
{
return 0;
}
int ceph_restore_deleg_ino(struct ceph_mds_session *s, u64 ino)
{
return 0;
}
#endif
static int parse_reply_info_create(void **p, void *end,
struct ceph_mds_reply_info_parsed *info,
u64 features, struct ceph_mds_session *s)
{ … }
static int parse_reply_info_getvxattr(void **p, void *end,
struct ceph_mds_reply_info_parsed *info,
u64 features)
{ … }
static int parse_reply_info_extra(void **p, void *end,
struct ceph_mds_request *req,
u64 features, struct ceph_mds_session *s)
{ … }
static int parse_reply_info(struct ceph_mds_session *s, struct ceph_msg *msg,
struct ceph_mds_request *req, u64 features)
{ … }
static void destroy_reply_info(struct ceph_mds_reply_info_parsed *info)
{ … }
int ceph_wait_on_conflict_unlink(struct dentry *dentry)
{ … }
const char *ceph_session_state_name(int s)
{ … }
struct ceph_mds_session *ceph_get_mds_session(struct ceph_mds_session *s)
{ … }
void ceph_put_mds_session(struct ceph_mds_session *s)
{ … }
struct ceph_mds_session *__ceph_lookup_mds_session(struct ceph_mds_client *mdsc,
int mds)
{ … }
static bool __have_session(struct ceph_mds_client *mdsc, int mds)
{ … }
static int __verify_registered_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s)
{ … }
static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
int mds)
{ … }
static void __unregister_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *s)
{ … }
static void put_request_session(struct ceph_mds_request *req)
{ … }
void ceph_mdsc_iterate_sessions(struct ceph_mds_client *mdsc,
void (*cb)(struct ceph_mds_session *),
bool check_state)
{ … }
void ceph_mdsc_release_request(struct kref *kref)
{ … }
DEFINE_RB_FUNCS(…) …
static struct ceph_mds_request *
lookup_get_request(struct ceph_mds_client *mdsc, u64 tid)
{ … }
static void __register_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req,
struct inode *dir)
{ … }
static void __unregister_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{ … }
static struct inode *get_nonsnap_parent(struct dentry *dentry)
{ … }
static int __choose_mds(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req,
bool *random)
{ … }
struct ceph_msg *ceph_create_session_msg(u32 op, u64 seq)
{ … }
static const unsigned char feature_bits[] = …;
#define FEATURE_BYTES(c) …
static int encode_supported_features(void **p, void *end)
{ … }
static const unsigned char metric_bits[] = …;
#define METRIC_BYTES(cnt) …
static int encode_metric_spec(void **p, void *end)
{ … }
static struct ceph_msg *
create_session_full_msg(struct ceph_mds_client *mdsc, int op, u64 seq)
{ … }
static int __open_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static struct ceph_mds_session *
__open_export_target_session(struct ceph_mds_client *mdsc, int target)
{ … }
struct ceph_mds_session *
ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target)
{ … }
static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static void detach_cap_releases(struct ceph_mds_session *session,
struct list_head *target)
{ … }
static void dispose_cap_releases(struct ceph_mds_client *mdsc,
struct list_head *dispose)
{ … }
static void cleanup_session_requests(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
int ceph_iterate_session_caps(struct ceph_mds_session *session,
int (*cb)(struct inode *, int mds, void *),
void *arg)
{ … }
static int remove_session_caps_cb(struct inode *inode, int mds, void *arg)
{ … }
static void remove_session_caps(struct ceph_mds_session *session)
{ … }
enum { … };
static int wake_up_session_cb(struct inode *inode, int mds, void *arg)
{ … }
static void wake_up_session_caps(struct ceph_mds_session *session, int ev)
{ … }
static int send_renew_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static int send_flushmsg_ack(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session, u64 seq)
{ … }
static void renewed_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session, int is_renew)
{ … }
static int request_close_session(struct ceph_mds_session *session)
{ … }
static int __close_session(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static bool drop_negative_children(struct dentry *dentry)
{ … }
static int trim_caps_cb(struct inode *inode, int mds, void *arg)
{ … }
int ceph_trim_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
int max_caps)
{ … }
static int check_caps_flush(struct ceph_mds_client *mdsc,
u64 want_flush_tid)
{ … }
static void wait_caps_flush(struct ceph_mds_client *mdsc,
u64 want_flush_tid)
{ … }
static void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static void ceph_cap_release_work(struct work_struct *work)
{ … }
void ceph_flush_cap_releases(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
void __ceph_queue_cap_release(struct ceph_mds_session *session,
struct ceph_cap *cap)
{ … }
static void ceph_cap_reclaim_work(struct work_struct *work)
{ … }
void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc)
{ … }
void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr)
{ … }
void ceph_queue_cap_unlink_work(struct ceph_mds_client *mdsc)
{ … }
static void ceph_cap_unlink_work(struct work_struct *work)
{ … }
int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
struct inode *dir)
{ … }
struct ceph_mds_request *
ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
{ … }
static struct ceph_mds_request *__get_oldest_req(struct ceph_mds_client *mdsc)
{ … }
static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc)
{ … }
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
{ … }
#else
static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen)
{
*plen = 0;
return NULL;
}
#endif
char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
int *plen, u64 *pbase, int for_wire)
{ … }
static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
struct inode *dir, const char **ppath, int *ppathlen,
u64 *pino, bool *pfreepath, bool parent_locked)
{ … }
static int build_inode_path(struct inode *inode,
const char **ppath, int *ppathlen, u64 *pino,
bool *pfreepath)
{ … }
static int set_request_path_attr(struct ceph_mds_client *mdsc, struct inode *rinode,
struct dentry *rdentry, struct inode *rdiri,
const char *rpath, u64 rino, const char **ppath,
int *pathlen, u64 *ino, bool *freepath,
bool parent_locked)
{ … }
static void encode_mclientrequest_tail(void **p,
const struct ceph_mds_request *req)
{ … }
static inline u16 mds_supported_head_version(struct ceph_mds_session *session)
{ … }
static struct ceph_mds_request_head_legacy *
find_legacy_request_head(void *p, u64 features)
{ … }
static struct ceph_msg *create_request_message(struct ceph_mds_session *session,
struct ceph_mds_request *req,
bool drop_cap_releases)
{ … }
static void complete_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{ … }
static int __prepare_send_request(struct ceph_mds_session *session,
struct ceph_mds_request *req,
bool drop_cap_releases)
{ … }
static int __send_request(struct ceph_mds_session *session,
struct ceph_mds_request *req,
bool drop_cap_releases)
{ … }
static void __do_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req)
{ … }
static void __wake_requests(struct ceph_mds_client *mdsc,
struct list_head *head)
{ … }
static void kick_requests(struct ceph_mds_client *mdsc, int mds)
{ … }
int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir,
struct ceph_mds_request *req)
{ … }
int ceph_mdsc_wait_request(struct ceph_mds_client *mdsc,
struct ceph_mds_request *req,
ceph_mds_request_wait_callback_t wait_func)
{ … }
int ceph_mdsc_do_request(struct ceph_mds_client *mdsc,
struct inode *dir,
struct ceph_mds_request *req)
{ … }
void ceph_invalidate_dir_request(struct ceph_mds_request *req)
{ … }
static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
{ … }
static void handle_forward(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{ … }
static int __decode_session_metadata(void **p, void *end,
bool *blocklisted)
{ … }
static void handle_session(struct ceph_mds_session *session,
struct ceph_msg *msg)
{ … }
void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req)
{ … }
void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req)
{ … }
static void replay_unsafe_requests(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static int send_reconnect_partial(struct ceph_reconnect_state *recon_state)
{ … }
static struct dentry* d_find_primary(struct inode *inode)
{ … }
static int reconnect_caps_cb(struct inode *inode, int mds, void *arg)
{ … }
static int encode_snap_realms(struct ceph_mds_client *mdsc,
struct ceph_reconnect_state *recon_state)
{ … }
static void send_mds_reconnect(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
static void check_new_map(struct ceph_mds_client *mdsc,
struct ceph_mdsmap *newmap,
struct ceph_mdsmap *oldmap)
{ … }
void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry)
{ … }
static void handle_lease(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_msg *msg)
{ … }
void ceph_mdsc_lease_send_msg(struct ceph_mds_session *session,
struct dentry *dentry, char action,
u32 seq)
{ … }
static void lock_unlock_session(struct ceph_mds_session *s)
{ … }
static void maybe_recover_session(struct ceph_mds_client *mdsc)
{ … }
bool check_session_state(struct ceph_mds_session *s)
{ … }
void inc_session_sequence(struct ceph_mds_session *s)
{ … }
static void schedule_delayed(struct ceph_mds_client *mdsc, unsigned long delay)
{ … }
static void delayed_work(struct work_struct *work)
{ … }
int ceph_mdsc_init(struct ceph_fs_client *fsc)
{ … }
static void wait_requests(struct ceph_mds_client *mdsc)
{ … }
void send_flush_mdlog(struct ceph_mds_session *s)
{ … }
static int ceph_mds_auth_match(struct ceph_mds_client *mdsc,
struct ceph_mds_cap_auth *auth,
char *tpath)
{ … }
int ceph_mds_check_access(struct ceph_mds_client *mdsc, char *tpath, int mask)
{ … }
void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc)
{ … }
static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *mdsc,
u64 want_tid)
{ … }
void ceph_mdsc_sync(struct ceph_mds_client *mdsc)
{ … }
static bool done_closing_sessions(struct ceph_mds_client *mdsc, int skipped)
{ … }
void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc)
{ … }
void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc)
{ … }
static void ceph_mdsc_stop(struct ceph_mds_client *mdsc)
{ … }
void ceph_mdsc_destroy(struct ceph_fs_client *fsc)
{ … }
void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
{ … }
void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
{ … }
static struct ceph_connection *mds_get_con(struct ceph_connection *con)
{ … }
static void mds_put_con(struct ceph_connection *con)
{ … }
static void mds_peer_reset(struct ceph_connection *con)
{ … }
static void mds_dispatch(struct ceph_connection *con, struct ceph_msg *msg)
{ … }
static struct ceph_auth_handshake *
mds_get_authorizer(struct ceph_connection *con, int *proto, int force_new)
{ … }
static int mds_add_authorizer_challenge(struct ceph_connection *con,
void *challenge_buf, int challenge_buf_len)
{ … }
static int mds_verify_authorizer_reply(struct ceph_connection *con)
{ … }
static int mds_invalidate_authorizer(struct ceph_connection *con)
{ … }
static int mds_get_auth_request(struct ceph_connection *con,
void *buf, int *buf_len,
void **authorizer, int *authorizer_len)
{ … }
static int mds_handle_auth_reply_more(struct ceph_connection *con,
void *reply, int reply_len,
void *buf, int *buf_len,
void **authorizer, int *authorizer_len)
{ … }
static int mds_handle_auth_done(struct ceph_connection *con,
u64 global_id, void *reply, int reply_len,
u8 *session_key, int *session_key_len,
u8 *con_secret, int *con_secret_len)
{ … }
static int mds_handle_auth_bad_method(struct ceph_connection *con,
int used_proto, int result,
const int *allowed_protos, int proto_cnt,
const int *allowed_modes, int mode_cnt)
{ … }
static struct ceph_msg *mds_alloc_msg(struct ceph_connection *con,
struct ceph_msg_header *hdr, int *skip)
{ … }
static int mds_sign_message(struct ceph_msg *msg)
{ … }
static int mds_check_message_signature(struct ceph_msg *msg)
{ … }
static const struct ceph_connection_operations mds_con_ops = …;