mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'ceph-for-6.18-rc1' of https://github.com/ceph/ceph-client
Pull ceph updates from Ilya Dryomov: - some messenger improvements (Eric and Max) - address an issue (also affected userspace) of incorrect permissions being granted to users who have access to multiple different CephFS instances within the same cluster (Kotresh) - a bunch of assorted CephFS fixes (Slava) * tag 'ceph-for-6.18-rc1' of https://github.com/ceph/ceph-client: ceph: add bug tracking system info to MAINTAINERS ceph: fix multifs mds auth caps issue ceph: cleanup in ceph_alloc_readdir_reply_buffer() ceph: fix potential NULL dereference issue in ceph_fill_trace() libceph: add empty check to ceph_con_get_out_msg() libceph: pass the message pointer instead of loading con->out_msg libceph: make ceph_con_get_out_msg() return the message pointer ceph: fix potential race condition on operations with CEPH_I_ODIRECT flag ceph: refactor wake_up_bit() pattern of calling ceph: fix potential race condition in ceph_ioctl_lazyio() ceph: fix overflowed constant issue in ceph_do_objects_copy() ceph: fix wrong sizeof argument issue in register_session() ceph: add checking of wait_for_completion_killable() return value ceph: make ceph_start_io_*() killable libceph: Use HMAC-SHA256 library instead of crypto_shash
This commit is contained in:
@@ -5694,6 +5694,7 @@ M: Xiubo Li <xiubli@redhat.com>
|
||||
L: ceph-devel@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://ceph.com/
|
||||
B: https://tracker.ceph.com/
|
||||
T: git https://github.com/ceph/ceph-client.git
|
||||
F: include/linux/ceph/
|
||||
F: include/linux/crush/
|
||||
@@ -5705,6 +5706,7 @@ M: Ilya Dryomov <idryomov@gmail.com>
|
||||
L: ceph-devel@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://ceph.com/
|
||||
B: https://tracker.ceph.com/
|
||||
T: git https://github.com/ceph/ceph-client.git
|
||||
F: Documentation/filesystems/ceph.rst
|
||||
F: fs/ceph/
|
||||
@@ -21357,6 +21359,7 @@ R: Dongsheng Yang <dongsheng.yang@easystack.cn>
|
||||
L: ceph-devel@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://ceph.com/
|
||||
B: https://tracker.ceph.com/
|
||||
T: git https://github.com/ceph/ceph-client.git
|
||||
F: Documentation/ABI/testing/sysfs-bus-rbd
|
||||
F: drivers/block/rbd.c
|
||||
|
||||
+1
-2
@@ -1260,8 +1260,7 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc,
|
||||
spin_unlock(&fsc->async_unlink_conflict_lock);
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
di->flags &= ~CEPH_DENTRY_ASYNC_UNLINK;
|
||||
wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT);
|
||||
clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
+15
-15
@@ -579,8 +579,7 @@ static void wake_async_create_waiters(struct inode *inode,
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) {
|
||||
ci->i_ceph_flags &= ~CEPH_I_ASYNC_CREATE;
|
||||
wake_up_bit(&ci->i_ceph_flags, CEPH_ASYNC_CREATE_BIT);
|
||||
clear_and_wake_up_bit(CEPH_ASYNC_CREATE_BIT, &ci->i_ceph_flags);
|
||||
|
||||
if (ci->i_ceph_flags & CEPH_I_ASYNC_CHECK_CAPS) {
|
||||
ci->i_ceph_flags &= ~CEPH_I_ASYNC_CHECK_CAPS;
|
||||
@@ -762,8 +761,7 @@ static int ceph_finish_async_create(struct inode *dir, struct inode *inode,
|
||||
}
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
di->flags &= ~CEPH_DENTRY_ASYNC_CREATE;
|
||||
wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_CREATE_BIT);
|
||||
clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_CREATE_BIT, &di->flags);
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
||||
return ret;
|
||||
@@ -2121,10 +2119,10 @@ again:
|
||||
if (ceph_inode_is_shutdown(inode))
|
||||
return -ESTALE;
|
||||
|
||||
if (direct_lock)
|
||||
ceph_start_io_direct(inode);
|
||||
else
|
||||
ceph_start_io_read(inode);
|
||||
ret = direct_lock ? ceph_start_io_direct(inode) :
|
||||
ceph_start_io_read(inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(fi->flags & CEPH_F_SYNC) && !direct_lock)
|
||||
want |= CEPH_CAP_FILE_CACHE;
|
||||
@@ -2277,7 +2275,9 @@ static ssize_t ceph_splice_read(struct file *in, loff_t *ppos,
|
||||
(fi->flags & CEPH_F_SYNC))
|
||||
return copy_splice_read(in, ppos, pipe, len, flags);
|
||||
|
||||
ceph_start_io_read(inode);
|
||||
ret = ceph_start_io_read(inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
want = CEPH_CAP_FILE_CACHE;
|
||||
if (fi->fmode & CEPH_FILE_MODE_LAZY)
|
||||
@@ -2356,10 +2356,10 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
direct_lock = true;
|
||||
|
||||
retry_snap:
|
||||
if (direct_lock)
|
||||
ceph_start_io_direct(inode);
|
||||
else
|
||||
ceph_start_io_write(inode);
|
||||
err = direct_lock ? ceph_start_io_direct(inode) :
|
||||
ceph_start_io_write(inode);
|
||||
if (err)
|
||||
goto out_unlocked;
|
||||
|
||||
if (iocb->ki_flags & IOCB_APPEND) {
|
||||
err = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE, false);
|
||||
@@ -2878,7 +2878,7 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off
|
||||
struct ceph_object_id src_oid, dst_oid;
|
||||
struct ceph_osd_client *osdc;
|
||||
struct ceph_osd_request *req;
|
||||
size_t bytes = 0;
|
||||
ssize_t bytes = 0;
|
||||
u64 src_objnum, src_objoff, dst_objnum, dst_objoff;
|
||||
u32 src_objlen, dst_objlen;
|
||||
u32 object_size = src_ci->i_layout.object_size;
|
||||
@@ -2928,7 +2928,7 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off
|
||||
"OSDs don't support copy-from2; disabling copy offload\n");
|
||||
}
|
||||
doutc(cl, "returned %d\n", ret);
|
||||
if (!bytes)
|
||||
if (bytes <= 0)
|
||||
bytes = ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1794,6 +1794,11 @@ retry_lookup:
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (unlikely(!in)) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* attach proper inode */
|
||||
if (d_really_is_negative(dn)) {
|
||||
ceph_dir_clear_ordered(dir);
|
||||
@@ -1829,6 +1834,12 @@ retry_lookup:
|
||||
doutc(cl, " linking snapped dir %p to dn %p\n", in,
|
||||
req->r_dentry);
|
||||
ceph_dir_clear_ordered(dir);
|
||||
|
||||
if (unlikely(!in)) {
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ihold(in);
|
||||
err = splice_dentry(&req->r_dentry, in);
|
||||
if (err < 0)
|
||||
|
||||
+75
-25
@@ -21,14 +21,23 @@
|
||||
/* Call with exclusively locked inode->i_rwsem */
|
||||
static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode)
|
||||
{
|
||||
bool is_odirect;
|
||||
|
||||
lockdep_assert_held_write(&inode->i_rwsem);
|
||||
|
||||
if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) {
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
ci->i_ceph_flags &= ~CEPH_I_ODIRECT;
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
inode_dio_wait(inode);
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
/* ensure that bit state is consistent */
|
||||
smp_mb__before_atomic();
|
||||
is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT;
|
||||
if (is_odirect) {
|
||||
clear_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags);
|
||||
/* ensure modified bit is visible */
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
if (is_odirect)
|
||||
inode_dio_wait(inode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,20 +56,35 @@ static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode)
|
||||
* Note that buffered writes and truncates both take a write lock on
|
||||
* inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
|
||||
*/
|
||||
void
|
||||
ceph_start_io_read(struct inode *inode)
|
||||
int ceph_start_io_read(struct inode *inode)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
bool is_odirect;
|
||||
int err;
|
||||
|
||||
/* Be an optimist! */
|
||||
down_read(&inode->i_rwsem);
|
||||
if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT))
|
||||
return;
|
||||
err = down_read_killable(&inode->i_rwsem);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
/* ensure that bit state is consistent */
|
||||
smp_mb__before_atomic();
|
||||
is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT;
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
if (!is_odirect)
|
||||
return 0;
|
||||
up_read(&inode->i_rwsem);
|
||||
|
||||
/* Slow path.... */
|
||||
down_write(&inode->i_rwsem);
|
||||
err = down_write_killable(&inode->i_rwsem);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ceph_block_o_direct(ci, inode);
|
||||
downgrade_write(&inode->i_rwsem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,11 +107,12 @@ ceph_end_io_read(struct inode *inode)
|
||||
* Declare that a buffered write operation is about to start, and ensure
|
||||
* that we block all direct I/O.
|
||||
*/
|
||||
void
|
||||
ceph_start_io_write(struct inode *inode)
|
||||
int ceph_start_io_write(struct inode *inode)
|
||||
{
|
||||
down_write(&inode->i_rwsem);
|
||||
ceph_block_o_direct(ceph_inode(inode), inode);
|
||||
int err = down_write_killable(&inode->i_rwsem);
|
||||
if (!err)
|
||||
ceph_block_o_direct(ceph_inode(inode), inode);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,12 +131,22 @@ ceph_end_io_write(struct inode *inode)
|
||||
/* Call with exclusively locked inode->i_rwsem */
|
||||
static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode)
|
||||
{
|
||||
bool is_odirect;
|
||||
|
||||
lockdep_assert_held_write(&inode->i_rwsem);
|
||||
|
||||
if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) {
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
ci->i_ceph_flags |= CEPH_I_ODIRECT;
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
/* ensure that bit state is consistent */
|
||||
smp_mb__before_atomic();
|
||||
is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT;
|
||||
if (!is_odirect) {
|
||||
set_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags);
|
||||
/* ensure modified bit is visible */
|
||||
smp_mb__after_atomic();
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
if (!is_odirect) {
|
||||
/* FIXME: unmap_mapping_range? */
|
||||
filemap_write_and_wait(inode->i_mapping);
|
||||
}
|
||||
@@ -133,20 +168,35 @@ static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode)
|
||||
* Note that buffered writes and truncates both take a write lock on
|
||||
* inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
|
||||
*/
|
||||
void
|
||||
ceph_start_io_direct(struct inode *inode)
|
||||
int ceph_start_io_direct(struct inode *inode)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
bool is_odirect;
|
||||
int err;
|
||||
|
||||
/* Be an optimist! */
|
||||
down_read(&inode->i_rwsem);
|
||||
if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)
|
||||
return;
|
||||
err = down_read_killable(&inode->i_rwsem);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
/* ensure that bit state is consistent */
|
||||
smp_mb__before_atomic();
|
||||
is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT;
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
if (is_odirect)
|
||||
return 0;
|
||||
up_read(&inode->i_rwsem);
|
||||
|
||||
/* Slow path.... */
|
||||
down_write(&inode->i_rwsem);
|
||||
err = down_write_killable(&inode->i_rwsem);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ceph_block_buffered(ci, inode);
|
||||
downgrade_write(&inode->i_rwsem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
-3
@@ -2,11 +2,13 @@
|
||||
#ifndef _FS_CEPH_IO_H
|
||||
#define _FS_CEPH_IO_H
|
||||
|
||||
void ceph_start_io_read(struct inode *inode);
|
||||
#include <linux/compiler_attributes.h>
|
||||
|
||||
int __must_check ceph_start_io_read(struct inode *inode);
|
||||
void ceph_end_io_read(struct inode *inode);
|
||||
void ceph_start_io_write(struct inode *inode);
|
||||
int __must_check ceph_start_io_write(struct inode *inode);
|
||||
void ceph_end_io_write(struct inode *inode);
|
||||
void ceph_start_io_direct(struct inode *inode);
|
||||
int __must_check ceph_start_io_direct(struct inode *inode);
|
||||
void ceph_end_io_direct(struct inode *inode);
|
||||
|
||||
#endif /* FS_CEPH_IO_H */
|
||||
|
||||
+12
-5
@@ -246,21 +246,28 @@ static long ceph_ioctl_lazyio(struct file *file)
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
|
||||
struct ceph_client *cl = mdsc->fsc->client;
|
||||
bool is_file_already_lazy = false;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
fi->fmode |= CEPH_FILE_MODE_LAZY;
|
||||
ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++;
|
||||
__ceph_touch_fmode(ci, mdsc, fi->fmode);
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
} else {
|
||||
is_file_already_lazy = true;
|
||||
}
|
||||
spin_unlock(&ci->i_ceph_lock);
|
||||
|
||||
if (is_file_already_lazy) {
|
||||
doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode,
|
||||
ceph_vinop(inode));
|
||||
} else {
|
||||
doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode,
|
||||
ceph_vinop(inode));
|
||||
|
||||
ceph_check_caps(ci, 0);
|
||||
} else {
|
||||
doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode,
|
||||
ceph_vinop(inode));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -221,7 +221,10 @@ static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc,
|
||||
if (err && err != -ERESTARTSYS)
|
||||
return err;
|
||||
|
||||
wait_for_completion_killable(&req->r_safe_completion);
|
||||
err = wait_for_completion_killable(&req->r_safe_completion);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -979,14 +979,15 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
|
||||
if (mds >= mdsc->max_sessions) {
|
||||
int newmax = 1 << get_count_order(mds + 1);
|
||||
struct ceph_mds_session **sa;
|
||||
size_t ptr_size = sizeof(struct ceph_mds_session *);
|
||||
|
||||
doutc(cl, "realloc to %d\n", newmax);
|
||||
sa = kcalloc(newmax, sizeof(void *), GFP_NOFS);
|
||||
sa = kcalloc(newmax, ptr_size, GFP_NOFS);
|
||||
if (!sa)
|
||||
goto fail_realloc;
|
||||
if (mdsc->sessions) {
|
||||
memcpy(sa, mdsc->sessions,
|
||||
mdsc->max_sessions * sizeof(void *));
|
||||
mdsc->max_sessions * ptr_size);
|
||||
kfree(mdsc->sessions);
|
||||
}
|
||||
mdsc->sessions = sa;
|
||||
@@ -2532,6 +2533,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
|
||||
struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
|
||||
size_t size = sizeof(struct ceph_mds_reply_dir_entry);
|
||||
unsigned int num_entries;
|
||||
u64 bytes_count;
|
||||
int order;
|
||||
|
||||
spin_lock(&ci->i_ceph_lock);
|
||||
@@ -2540,7 +2542,11 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
|
||||
num_entries = max(num_entries, 1U);
|
||||
num_entries = min(num_entries, opt->max_readdir);
|
||||
|
||||
order = get_order(size * num_entries);
|
||||
bytes_count = (u64)size * num_entries;
|
||||
if (unlikely(bytes_count > ULONG_MAX))
|
||||
bytes_count = ULONG_MAX;
|
||||
|
||||
order = get_order((unsigned long)bytes_count);
|
||||
while (order >= 0) {
|
||||
rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL |
|
||||
__GFP_NOWARN |
|
||||
@@ -2550,7 +2556,7 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
|
||||
break;
|
||||
order--;
|
||||
}
|
||||
if (!rinfo->dir_entries)
|
||||
if (!rinfo->dir_entries || unlikely(order < 0))
|
||||
return -ENOMEM;
|
||||
|
||||
num_entries = (PAGE_SIZE << order) / size;
|
||||
@@ -5649,11 +5655,19 @@ static int ceph_mds_auth_match(struct ceph_mds_client *mdsc,
|
||||
u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid);
|
||||
u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid);
|
||||
struct ceph_client *cl = mdsc->fsc->client;
|
||||
const char *fs_name = mdsc->fsc->mount_options->mds_namespace;
|
||||
const char *spath = mdsc->fsc->mount_options->server_path;
|
||||
bool gid_matched = false;
|
||||
u32 gid, tlen, len;
|
||||
int i, j;
|
||||
|
||||
doutc(cl, "fsname check fs_name=%s match.fs_name=%s\n",
|
||||
fs_name, auth->match.fs_name ? auth->match.fs_name : "");
|
||||
if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) {
|
||||
/* fsname mismatch, try next one */
|
||||
return 0;
|
||||
}
|
||||
|
||||
doutc(cl, "match.uid %lld\n", auth->match.uid);
|
||||
if (auth->match.uid != MDS_AUTH_UID_ANY) {
|
||||
if (auth->match.uid != caller_uid)
|
||||
|
||||
+13
-1
@@ -353,10 +353,22 @@ struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p,
|
||||
__decode_and_drop_type(p, end, u8, bad_ext);
|
||||
}
|
||||
if (mdsmap_ev >= 8) {
|
||||
u32 fsname_len;
|
||||
/* enabled */
|
||||
ceph_decode_8_safe(p, end, m->m_enabled, bad_ext);
|
||||
/* fs_name */
|
||||
ceph_decode_skip_string(p, end, bad_ext);
|
||||
ceph_decode_32_safe(p, end, fsname_len, bad_ext);
|
||||
|
||||
/* validate fsname against mds_namespace */
|
||||
if (!namespace_equals(mdsc->fsc->mount_options, *p,
|
||||
fsname_len)) {
|
||||
pr_warn_client(cl, "fsname %*pE doesn't match mds_namespace %s\n",
|
||||
(int)fsname_len, (char *)*p,
|
||||
mdsc->fsc->mount_options->mds_namespace);
|
||||
goto bad;
|
||||
}
|
||||
/* skip fsname after validation */
|
||||
ceph_decode_skip_n(p, end, fsname_len, bad);
|
||||
}
|
||||
/* damaged */
|
||||
if (mdsmap_ev >= 9) {
|
||||
|
||||
@@ -246,20 +246,6 @@ static void canonicalize_path(char *path)
|
||||
path[j] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the mds namespace in ceph_mount_options matches
|
||||
* the passed in namespace string. First time match (when
|
||||
* ->mds_namespace is NULL) is treated specially, since
|
||||
* ->mds_namespace needs to be initialized by the caller.
|
||||
*/
|
||||
static int namespace_equals(struct ceph_mount_options *fsopt,
|
||||
const char *namespace, size_t len)
|
||||
{
|
||||
return !(fsopt->mds_namespace &&
|
||||
(strlen(fsopt->mds_namespace) != len ||
|
||||
strncmp(fsopt->mds_namespace, namespace, len)));
|
||||
}
|
||||
|
||||
static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end,
|
||||
struct fs_context *fc)
|
||||
{
|
||||
|
||||
+16
-1
@@ -104,6 +104,20 @@ struct ceph_mount_options {
|
||||
struct fscrypt_dummy_policy dummy_enc_policy;
|
||||
};
|
||||
|
||||
/*
|
||||
* Check if the mds namespace in ceph_mount_options matches
|
||||
* the passed in namespace string. First time match (when
|
||||
* ->mds_namespace is NULL) is treated specially, since
|
||||
* ->mds_namespace needs to be initialized by the caller.
|
||||
*/
|
||||
static inline int namespace_equals(struct ceph_mount_options *fsopt,
|
||||
const char *namespace, size_t len)
|
||||
{
|
||||
return !(fsopt->mds_namespace &&
|
||||
(strlen(fsopt->mds_namespace) != len ||
|
||||
strncmp(fsopt->mds_namespace, namespace, len)));
|
||||
}
|
||||
|
||||
/* mount state */
|
||||
enum {
|
||||
CEPH_MOUNT_MOUNTING,
|
||||
@@ -639,7 +653,8 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
|
||||
#define CEPH_I_FLUSH_SNAPS (1 << 8) /* need flush snapss */
|
||||
#define CEPH_I_ERROR_WRITE (1 << 9) /* have seen write errors */
|
||||
#define CEPH_I_ERROR_FILELOCK (1 << 10) /* have seen file lock errors */
|
||||
#define CEPH_I_ODIRECT (1 << 11) /* inode in direct I/O mode */
|
||||
#define CEPH_I_ODIRECT_BIT (11) /* inode in direct I/O mode */
|
||||
#define CEPH_I_ODIRECT (1 << CEPH_I_ODIRECT_BIT)
|
||||
#define CEPH_ASYNC_CREATE_BIT (12) /* async create in flight for this */
|
||||
#define CEPH_I_ASYNC_CREATE (1 << CEPH_ASYNC_CREATE_BIT)
|
||||
#define CEPH_I_SHUTDOWN (1 << 13) /* inode is no longer usable */
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef __FS_CEPH_MESSENGER_H
|
||||
#define __FS_CEPH_MESSENGER_H
|
||||
|
||||
#include <crypto/sha2.h>
|
||||
#include <linux/bvec.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/kref.h>
|
||||
@@ -412,7 +413,8 @@ struct ceph_connection_v2_info {
|
||||
struct ceph_msg_data_cursor in_cursor;
|
||||
struct ceph_msg_data_cursor out_cursor;
|
||||
|
||||
struct crypto_shash *hmac_tfm; /* post-auth signature */
|
||||
struct hmac_sha256_key hmac_key; /* post-auth signature */
|
||||
bool hmac_key_set;
|
||||
struct crypto_aead *gcm_tfm; /* on-wire encryption */
|
||||
struct aead_request *gcm_req;
|
||||
struct crypto_wait gcm_wait;
|
||||
@@ -548,12 +550,12 @@ void ceph_addr_set_port(struct ceph_entity_addr *addr, int p);
|
||||
void ceph_con_process_message(struct ceph_connection *con);
|
||||
int ceph_con_in_msg_alloc(struct ceph_connection *con,
|
||||
struct ceph_msg_header *hdr, int *skip);
|
||||
void ceph_con_get_out_msg(struct ceph_connection *con);
|
||||
struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con);
|
||||
|
||||
/* messenger_v1.c */
|
||||
int ceph_con_v1_try_read(struct ceph_connection *con);
|
||||
int ceph_con_v1_try_write(struct ceph_connection *con);
|
||||
void ceph_con_v1_revoke(struct ceph_connection *con);
|
||||
void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg);
|
||||
void ceph_con_v1_revoke_incoming(struct ceph_connection *con);
|
||||
bool ceph_con_v1_opened(struct ceph_connection *con);
|
||||
void ceph_con_v1_reset_session(struct ceph_connection *con);
|
||||
@@ -562,7 +564,7 @@ void ceph_con_v1_reset_protocol(struct ceph_connection *con);
|
||||
/* messenger_v2.c */
|
||||
int ceph_con_v2_try_read(struct ceph_connection *con);
|
||||
int ceph_con_v2_try_write(struct ceph_connection *con);
|
||||
void ceph_con_v2_revoke(struct ceph_connection *con);
|
||||
void ceph_con_v2_revoke(struct ceph_connection *con, struct ceph_msg *msg);
|
||||
void ceph_con_v2_revoke_incoming(struct ceph_connection *con);
|
||||
bool ceph_con_v2_opened(struct ceph_connection *con);
|
||||
void ceph_con_v2_reset_session(struct ceph_connection *con);
|
||||
|
||||
+1
-2
@@ -6,8 +6,7 @@ config CEPH_LIB
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_CBC
|
||||
select CRYPTO_GCM
|
||||
select CRYPTO_HMAC
|
||||
select CRYPTO_SHA256
|
||||
select CRYPTO_LIB_SHA256
|
||||
select CRYPTO
|
||||
select KEYS
|
||||
default n
|
||||
|
||||
@@ -1794,9 +1794,9 @@ void ceph_msg_revoke(struct ceph_msg *msg)
|
||||
WARN_ON(con->state != CEPH_CON_S_OPEN);
|
||||
dout("%s con %p msg %p was sending\n", __func__, con, msg);
|
||||
if (ceph_msgr2(from_msgr(con->msgr)))
|
||||
ceph_con_v2_revoke(con);
|
||||
ceph_con_v2_revoke(con, msg);
|
||||
else
|
||||
ceph_con_v1_revoke(con);
|
||||
ceph_con_v1_revoke(con, msg);
|
||||
ceph_msg_put(con->out_msg);
|
||||
con->out_msg = NULL;
|
||||
} else {
|
||||
@@ -2111,11 +2111,13 @@ int ceph_con_in_msg_alloc(struct ceph_connection *con,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ceph_con_get_out_msg(struct ceph_connection *con)
|
||||
struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con)
|
||||
{
|
||||
struct ceph_msg *msg;
|
||||
|
||||
BUG_ON(list_empty(&con->out_queue));
|
||||
if (list_empty(&con->out_queue))
|
||||
return NULL;
|
||||
|
||||
msg = list_first_entry(&con->out_queue, struct ceph_msg, list_head);
|
||||
WARN_ON(msg->con != con);
|
||||
|
||||
@@ -2142,7 +2144,7 @@ void ceph_con_get_out_msg(struct ceph_connection *con)
|
||||
* message or in case of a fault.
|
||||
*/
|
||||
WARN_ON(con->out_msg);
|
||||
con->out_msg = ceph_msg_get(msg);
|
||||
return con->out_msg = ceph_msg_get(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+26
-30
@@ -169,10 +169,9 @@ static void prepare_message_data(struct ceph_msg *msg, u32 data_len)
|
||||
* Prepare footer for currently outgoing message, and finish things
|
||||
* off. Assumes out_kvec* are already valid.. we just add on to the end.
|
||||
*/
|
||||
static void prepare_write_message_footer(struct ceph_connection *con)
|
||||
static void prepare_write_message_footer(struct ceph_connection *con,
|
||||
struct ceph_msg *m)
|
||||
{
|
||||
struct ceph_msg *m = con->out_msg;
|
||||
|
||||
m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE;
|
||||
|
||||
dout("prepare_write_message_footer %p\n", con);
|
||||
@@ -192,9 +191,9 @@ static void prepare_write_message_footer(struct ceph_connection *con)
|
||||
/*
|
||||
* Prepare headers for the next outgoing message.
|
||||
*/
|
||||
static void prepare_write_message(struct ceph_connection *con)
|
||||
static void prepare_write_message(struct ceph_connection *con,
|
||||
struct ceph_msg *m)
|
||||
{
|
||||
struct ceph_msg *m;
|
||||
u32 crc;
|
||||
|
||||
con_out_kvec_reset(con);
|
||||
@@ -210,9 +209,6 @@ static void prepare_write_message(struct ceph_connection *con)
|
||||
&con->v1.out_temp_ack);
|
||||
}
|
||||
|
||||
ceph_con_get_out_msg(con);
|
||||
m = con->out_msg;
|
||||
|
||||
dout("prepare_write_message %p seq %lld type %d len %d+%d+%zd\n",
|
||||
m, con->out_seq, le16_to_cpu(m->hdr.type),
|
||||
le32_to_cpu(m->hdr.front_len), le32_to_cpu(m->hdr.middle_len),
|
||||
@@ -231,31 +227,31 @@ static void prepare_write_message(struct ceph_connection *con)
|
||||
|
||||
/* fill in hdr crc and finalize hdr */
|
||||
crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc));
|
||||
con->out_msg->hdr.crc = cpu_to_le32(crc);
|
||||
memcpy(&con->v1.out_hdr, &con->out_msg->hdr, sizeof(con->v1.out_hdr));
|
||||
m->hdr.crc = cpu_to_le32(crc);
|
||||
memcpy(&con->v1.out_hdr, &m->hdr, sizeof(con->v1.out_hdr));
|
||||
|
||||
/* fill in front and middle crc, footer */
|
||||
crc = crc32c(0, m->front.iov_base, m->front.iov_len);
|
||||
con->out_msg->footer.front_crc = cpu_to_le32(crc);
|
||||
m->footer.front_crc = cpu_to_le32(crc);
|
||||
if (m->middle) {
|
||||
crc = crc32c(0, m->middle->vec.iov_base,
|
||||
m->middle->vec.iov_len);
|
||||
con->out_msg->footer.middle_crc = cpu_to_le32(crc);
|
||||
m->footer.middle_crc = cpu_to_le32(crc);
|
||||
} else
|
||||
con->out_msg->footer.middle_crc = 0;
|
||||
m->footer.middle_crc = 0;
|
||||
dout("%s front_crc %u middle_crc %u\n", __func__,
|
||||
le32_to_cpu(con->out_msg->footer.front_crc),
|
||||
le32_to_cpu(con->out_msg->footer.middle_crc));
|
||||
con->out_msg->footer.flags = 0;
|
||||
le32_to_cpu(m->footer.front_crc),
|
||||
le32_to_cpu(m->footer.middle_crc));
|
||||
m->footer.flags = 0;
|
||||
|
||||
/* is there a data payload? */
|
||||
con->out_msg->footer.data_crc = 0;
|
||||
m->footer.data_crc = 0;
|
||||
if (m->data_length) {
|
||||
prepare_message_data(con->out_msg, m->data_length);
|
||||
prepare_message_data(m, m->data_length);
|
||||
con->v1.out_more = 1; /* data + footer will follow */
|
||||
} else {
|
||||
/* no, queue up footer too and be done */
|
||||
prepare_write_message_footer(con);
|
||||
prepare_write_message_footer(con, m);
|
||||
}
|
||||
|
||||
ceph_con_flag_set(con, CEPH_CON_F_WRITE_PENDING);
|
||||
@@ -462,9 +458,9 @@ out:
|
||||
* 0 -> socket full, but more to do
|
||||
* <0 -> error
|
||||
*/
|
||||
static int write_partial_message_data(struct ceph_connection *con)
|
||||
static int write_partial_message_data(struct ceph_connection *con,
|
||||
struct ceph_msg *msg)
|
||||
{
|
||||
struct ceph_msg *msg = con->out_msg;
|
||||
struct ceph_msg_data_cursor *cursor = &msg->cursor;
|
||||
bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC);
|
||||
u32 crc;
|
||||
@@ -516,7 +512,7 @@ static int write_partial_message_data(struct ceph_connection *con)
|
||||
else
|
||||
msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC;
|
||||
con_out_kvec_reset(con);
|
||||
prepare_write_message_footer(con);
|
||||
prepare_write_message_footer(con, msg);
|
||||
|
||||
return 1; /* must return > 0 to indicate success */
|
||||
}
|
||||
@@ -1472,6 +1468,7 @@ bad_tag:
|
||||
*/
|
||||
int ceph_con_v1_try_write(struct ceph_connection *con)
|
||||
{
|
||||
struct ceph_msg *msg;
|
||||
int ret = 1;
|
||||
|
||||
dout("try_write start %p state %d\n", con, con->state);
|
||||
@@ -1518,14 +1515,15 @@ more:
|
||||
}
|
||||
|
||||
/* msg pages? */
|
||||
if (con->out_msg) {
|
||||
msg = con->out_msg;
|
||||
if (msg) {
|
||||
if (con->v1.out_msg_done) {
|
||||
ceph_msg_put(con->out_msg);
|
||||
ceph_msg_put(msg);
|
||||
con->out_msg = NULL; /* we're done with this one */
|
||||
goto do_next;
|
||||
}
|
||||
|
||||
ret = write_partial_message_data(con);
|
||||
ret = write_partial_message_data(con, msg);
|
||||
if (ret == 1)
|
||||
goto more; /* we need to send the footer, too! */
|
||||
if (ret == 0)
|
||||
@@ -1545,8 +1543,8 @@ do_next:
|
||||
goto more;
|
||||
}
|
||||
/* is anything else pending? */
|
||||
if (!list_empty(&con->out_queue)) {
|
||||
prepare_write_message(con);
|
||||
if ((msg = ceph_con_get_out_msg(con)) != NULL) {
|
||||
prepare_write_message(con, msg);
|
||||
goto more;
|
||||
}
|
||||
if (con->in_seq > con->in_seq_acked) {
|
||||
@@ -1564,10 +1562,8 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ceph_con_v1_revoke(struct ceph_connection *con)
|
||||
void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg)
|
||||
{
|
||||
struct ceph_msg *msg = con->out_msg;
|
||||
|
||||
WARN_ON(con->v1.out_skip);
|
||||
/* footer */
|
||||
if (con->v1.out_msg_done) {
|
||||
|
||||
+110
-136
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user