#include <linux/ceph/ceph_debug.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/writeback.h>
#include <linux/iversion.h>
#include <linux/filelock.h>
#include "super.h"
#include "mds_client.h"
#include "cache.h"
#include "crypto.h"
#include <linux/ceph/decode.h>
#include <linux/ceph/messenger.h>
static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc);
static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_inode_info *ci,
u64 oldest_flush_tid);
#define MAX_CAP_STR …
static char cap_str[MAX_CAP_STR][40];
static DEFINE_SPINLOCK(cap_str_lock);
static int last_cap_str;
static char *gcap_string(char *s, int c)
{ … }
const char *ceph_cap_string(int caps)
{ … }
void ceph_caps_init(struct ceph_mds_client *mdsc)
{ … }
void ceph_caps_finalize(struct ceph_mds_client *mdsc)
{ … }
void ceph_adjust_caps_max_min(struct ceph_mds_client *mdsc,
struct ceph_mount_options *fsopt)
{ … }
static void __ceph_unreserve_caps(struct ceph_mds_client *mdsc, int nr_caps)
{ … }
int ceph_reserve_caps(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx, int need)
{ … }
void ceph_unreserve_caps(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx)
{ … }
struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc,
struct ceph_cap_reservation *ctx)
{ … }
void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap)
{ … }
void ceph_reservation_status(struct ceph_fs_client *fsc,
int *total, int *avail, int *used, int *reserved,
int *min)
{ … }
struct ceph_cap *__get_cap_for_mds(struct ceph_inode_info *ci, int mds)
{ … }
struct ceph_cap *ceph_get_cap_for_mds(struct ceph_inode_info *ci, int mds)
{ … }
static void __insert_cap_node(struct ceph_inode_info *ci,
struct ceph_cap *new)
{ … }
static void __cap_set_timeouts(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{ … }
static void __cap_delay_requeue(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{ … }
static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{ … }
static void __cap_delay_cancel(struct ceph_mds_client *mdsc,
struct ceph_inode_info *ci)
{ … }
static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap,
unsigned issued)
{ … }
void change_auth_cap_ses(struct ceph_inode_info *ci,
struct ceph_mds_session *session)
{ … }
void ceph_add_cap(struct inode *inode,
struct ceph_mds_session *session, u64 cap_id,
unsigned issued, unsigned wanted,
unsigned seq, unsigned mseq, u64 realmino, int flags,
struct ceph_cap **new_cap)
{ … }
static int __cap_is_valid(struct ceph_cap *cap)
{ … }
int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented)
{ … }
int __ceph_caps_issued_other(struct ceph_inode_info *ci, struct ceph_cap *ocap)
{ … }
static void __touch_cap(struct ceph_cap *cap)
{ … }
int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)
{ … }
int __ceph_caps_issued_mask_metric(struct ceph_inode_info *ci, int mask,
int touch)
{ … }
int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
struct ceph_cap *ocap, int mask)
{ … }
int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
{ … }
int __ceph_caps_used(struct ceph_inode_info *ci)
{ … }
#define FMODE_WAIT_BIAS …
int __ceph_caps_file_wanted(struct ceph_inode_info *ci)
{ … }
int __ceph_caps_wanted(struct ceph_inode_info *ci)
{ … }
int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check)
{ … }
int ceph_is_any_caps(struct inode *inode)
{ … }
void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
{ … }
void ceph_remove_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
bool queue_release)
{ … }
struct cap_msg_args { … };
static void encode_cap_msg(struct ceph_msg *msg, struct cap_msg_args *arg)
{ … }
void __ceph_remove_caps(struct ceph_inode_info *ci)
{ … }
static void __prep_cap(struct cap_msg_args *arg, struct ceph_cap *cap,
int op, int flags, int used, int want, int retain,
int flushing, u64 flush_tid, u64 oldest_flush_tid)
{ … }
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
#define CAP_MSG_FIXED_FIELDS …
static inline int cap_msg_size(struct cap_msg_args *arg)
{ … }
#else
#define CAP_MSG_FIXED_FIELDS …
static inline int cap_msg_size(struct cap_msg_args *arg)
{
return CAP_MSG_FIXED_FIELDS;
}
#endif
static void __send_cap(struct cap_msg_args *arg, struct ceph_inode_info *ci)
{ … }
static inline int __send_flush_snap(struct inode *inode,
struct ceph_mds_session *session,
struct ceph_cap_snap *capsnap,
u32 mseq, u64 oldest_flush_tid)
{ … }
static void __ceph_flush_snaps(struct ceph_inode_info *ci,
struct ceph_mds_session *session)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{ … }
void ceph_flush_snaps(struct ceph_inode_info *ci,
struct ceph_mds_session **psession)
{ … }
int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
struct ceph_cap_flush **pcf)
{ … }
struct ceph_cap_flush *ceph_alloc_cap_flush(void)
{ … }
void ceph_free_cap_flush(struct ceph_cap_flush *cf)
{ … }
static u64 __get_oldest_flush_tid(struct ceph_mds_client *mdsc)
{ … }
static bool __detach_cap_flush_from_mdsc(struct ceph_mds_client *mdsc,
struct ceph_cap_flush *cf)
{ … }
static bool __detach_cap_flush_from_ci(struct ceph_inode_info *ci,
struct ceph_cap_flush *cf)
{ … }
static u64 __mark_caps_flushing(struct inode *inode,
struct ceph_mds_session *session, bool wake,
u64 *oldest_flush_tid)
{ … }
static int try_nonblocking_invalidate(struct inode *inode)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{ … }
bool __ceph_should_report_size(struct ceph_inode_info *ci)
{ … }
void ceph_check_caps(struct ceph_inode_info *ci, int flags)
{ … }
static int try_flush_caps(struct inode *inode, u64 *ptid)
{ … }
static int caps_are_flushed(struct inode *inode, u64 flush_tid)
{ … }
static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode)
{ … }
int ceph_fsync(struct file *file, loff_t start, loff_t end, int datasync)
{ … }
int ceph_write_inode(struct inode *inode, struct writeback_control *wbc)
{ … }
static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
struct ceph_inode_info *ci,
u64 oldest_flush_tid)
__releases(ci->i_ceph_lock)
__acquires(ci->i_ceph_lock)
{ … }
void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session)
{ … }
void ceph_kick_flushing_inode_caps(struct ceph_mds_session *session,
struct ceph_inode_info *ci)
{ … }
void ceph_take_cap_refs(struct ceph_inode_info *ci, int got,
bool snap_rwsem_locked)
{ … }
enum { … };
static int try_get_cap_refs(struct inode *inode, int need, int want,
loff_t endoff, int flags, int *got)
{ … }
static void check_max_size(struct inode *inode, loff_t endoff)
{ … }
static inline int get_used_fmode(int caps)
{ … }
int ceph_try_get_caps(struct inode *inode, int need, int want,
bool nonblock, int *got)
{ … }
int __ceph_get_caps(struct inode *inode, struct ceph_file_info *fi, int need,
int want, loff_t endoff, int *got)
{ … }
int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff,
int *got)
{ … }
void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps)
{ … }
static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci,
struct ceph_cap_snap *capsnap)
{ … }
enum put_cap_refs_mode { … };
static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
enum put_cap_refs_mode mode)
{ … }
void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
{ … }
void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had)
{ … }
void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr,
struct ceph_snap_context *snapc)
{ … }
static void invalidate_aliases(struct inode *inode)
{ … }
struct cap_extra_info { … };
static void handle_cap_grant(struct inode *inode,
struct ceph_mds_session *session,
struct ceph_cap *cap,
struct ceph_mds_caps *grant,
struct ceph_buffer *xattr_buf,
struct cap_extra_info *extra_info)
__releases(ci->i_ceph_lock)
__releases(session->s_mdsc->snap_rwsem)
{ … }
static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
struct ceph_mds_caps *m,
struct ceph_mds_session *session,
struct ceph_cap *cap)
__releases(ci->i_ceph_lock)
{ … }
void __ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc)
{ … }
void ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap,
bool *wake_ci, bool *wake_mdsc)
{ … }
static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid,
struct ceph_mds_caps *m,
struct ceph_mds_session *session)
{ … }
static bool handle_cap_trunc(struct inode *inode,
struct ceph_mds_caps *trunc,
struct ceph_mds_session *session,
struct cap_extra_info *extra_info)
{ … }
static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
struct ceph_mds_cap_peer *ph,
struct ceph_mds_session *session)
{ … }
static void handle_cap_import(struct ceph_mds_client *mdsc,
struct inode *inode, struct ceph_mds_caps *im,
struct ceph_mds_cap_peer *ph,
struct ceph_mds_session *session,
struct ceph_cap **target_cap, int *old_issued)
{ … }
#ifdef CONFIG_FS_ENCRYPTION
static int parse_fscrypt_fields(void **p, void *end,
struct cap_extra_info *extra)
{ … }
#else
static int parse_fscrypt_fields(void **p, void *end,
struct cap_extra_info *extra)
{
u32 len;
ceph_decode_32_safe(p, end, len, bad);
if (len)
ceph_decode_skip_n(p, end, len, bad);
ceph_decode_32_safe(p, end, len, bad);
if (len)
ceph_decode_skip_n(p, end, len, bad);
return 0;
bad:
return -EIO;
}
#endif
void ceph_handle_caps(struct ceph_mds_session *session,
struct ceph_msg *msg)
{ … }
unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
{ … }
static void flush_dirty_session_caps(struct ceph_mds_session *s)
{ … }
void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc)
{ … }
void __ceph_touch_fmode(struct ceph_inode_info *ci,
struct ceph_mds_client *mdsc, int fmode)
{ … }
void ceph_get_fmode(struct ceph_inode_info *ci, int fmode, int count)
{ … }
void ceph_put_fmode(struct ceph_inode_info *ci, int fmode, int count)
{ … }
int ceph_drop_caps_for_unlink(struct inode *inode)
{ … }
int ceph_encode_inode_release(void **p, struct inode *inode,
int mds, int drop, int unless, int force)
{ … }
int ceph_encode_dentry_release(void **p, struct dentry *dentry,
struct inode *dir,
int mds, int drop, int unless)
{ … }
static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode)
{ … }
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate)
{ … }