Two -rc1 regression fixes: one in the auth code affecting old clusters
and one in the filesystem for proper propagation of MDS request errors. Also included a locking fix for async creates, marked for stable. -----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmDV440THGlkcnlvbW92 QGdtYWlsLmNvbQAKCRBKf944AhHzi3CXB/0aA0Ka+weQtIxxX3zl1thsE1APxoKe va77EfTJZbN12UHKAJ6sJUpXCLFc5hVJETw7w3qyz22VvJIPUQWd+h4w4eTXJ4QK Fab6+HT0/p0NxZ29rxa1bkHnrRAD30cpNd6WXcAeMJ3ZKvZfPtPnIWXSmCbJYGLV xhwx8y6kzjE60B60bjcQzuSpsMQkq0OpdXYdyxq3RysCjTCyDfpGuFnDHSv3aklm d6tyv2nUDM/oF/CEFZrTeaLrIZsYxxkpJHKkm7Xy70bUv8IMW97CKJSFjKYucyYd iV7VbtIKPq3sbGrmkaWm4nET5Z0C+m+JD2AhR17ylbdQy91hKaGrbnpw =RTBT -----END PGP SIGNATURE----- Merge tag 'ceph-for-5.13-rc8' of https://github.com/ceph/ceph-client Pull ceph fixes from Ilya Dryomov: "Two regression fixes from the merge window: one in the auth code affecting old clusters and one in the filesystem for proper propagation of MDS request errors. Also included a locking fix for async creates, marked for stable" * tag 'ceph-for-5.13-rc8' of https://github.com/ceph/ceph-client: libceph: set global_id as soon as we get an auth ticket libceph: don't pass result into ac->ops->handle_reply() ceph: fix error handling in ceph_atomic_open and ceph_lookup ceph: must hold snap_rwsem when filling inode for async create
This commit is contained in:
Коммит
edf54d9d0a
|
@ -668,14 +668,13 @@ out:
|
|||
* Handle lookups for the hidden .snap directory.
|
||||
*/
|
||||
struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
|
||||
struct dentry *dentry, int err)
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
|
||||
struct inode *parent = d_inode(dentry->d_parent); /* we hold i_mutex */
|
||||
|
||||
/* .snap dir? */
|
||||
if (err == -ENOENT &&
|
||||
ceph_snap(parent) == CEPH_NOSNAP &&
|
||||
if (ceph_snap(parent) == CEPH_NOSNAP &&
|
||||
strcmp(dentry->d_name.name, fsc->mount_options->snapdir_name) == 0) {
|
||||
struct dentry *res;
|
||||
struct inode *inode = ceph_get_snapdir(parent);
|
||||
|
@ -742,7 +741,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
|
|||
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
|
||||
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
|
||||
struct ceph_mds_request *req;
|
||||
struct dentry *res;
|
||||
int op;
|
||||
int mask;
|
||||
int err;
|
||||
|
@ -793,12 +791,16 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
|
|||
req->r_parent = dir;
|
||||
set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags);
|
||||
err = ceph_mdsc_do_request(mdsc, NULL, req);
|
||||
res = ceph_handle_snapdir(req, dentry, err);
|
||||
if (IS_ERR(res)) {
|
||||
err = PTR_ERR(res);
|
||||
} else {
|
||||
dentry = res;
|
||||
err = 0;
|
||||
if (err == -ENOENT) {
|
||||
struct dentry *res;
|
||||
|
||||
res = ceph_handle_snapdir(req, dentry);
|
||||
if (IS_ERR(res)) {
|
||||
err = PTR_ERR(res);
|
||||
} else {
|
||||
dentry = res;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
dentry = ceph_finish_lookup(req, dentry, err);
|
||||
ceph_mdsc_put_request(req); /* will dput(dentry) */
|
||||
|
|
|
@ -578,6 +578,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
|
|||
struct ceph_inode_info *ci = ceph_inode(dir);
|
||||
struct inode *inode;
|
||||
struct timespec64 now;
|
||||
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
|
||||
struct ceph_vino vino = { .ino = req->r_deleg_ino,
|
||||
.snap = CEPH_NOSNAP };
|
||||
|
||||
|
@ -615,8 +616,10 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,
|
|||
|
||||
ceph_file_layout_to_legacy(lo, &in.layout);
|
||||
|
||||
down_read(&mdsc->snap_rwsem);
|
||||
ret = ceph_fill_inode(inode, NULL, &iinfo, NULL, req->r_session,
|
||||
req->r_fmode, NULL);
|
||||
up_read(&mdsc->snap_rwsem);
|
||||
if (ret) {
|
||||
dout("%s failed to fill inode: %d\n", __func__, ret);
|
||||
ceph_dir_clear_complete(dir);
|
||||
|
@ -739,14 +742,16 @@ retry:
|
|||
err = ceph_mdsc_do_request(mdsc,
|
||||
(flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
|
||||
req);
|
||||
dentry = ceph_handle_snapdir(req, dentry, err);
|
||||
if (IS_ERR(dentry)) {
|
||||
err = PTR_ERR(dentry);
|
||||
goto out_req;
|
||||
if (err == -ENOENT) {
|
||||
dentry = ceph_handle_snapdir(req, dentry);
|
||||
if (IS_ERR(dentry)) {
|
||||
err = PTR_ERR(dentry);
|
||||
goto out_req;
|
||||
}
|
||||
err = 0;
|
||||
}
|
||||
err = 0;
|
||||
|
||||
if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
|
||||
if (!err && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
|
||||
err = ceph_handle_notrace_create(dir, dentry);
|
||||
|
||||
if (d_in_lookup(dentry)) {
|
||||
|
|
|
@ -777,6 +777,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
|
|||
umode_t mode = le32_to_cpu(info->mode);
|
||||
dev_t rdev = le32_to_cpu(info->rdev);
|
||||
|
||||
lockdep_assert_held(&mdsc->snap_rwsem);
|
||||
|
||||
dout("%s %p ino %llx.%llx v %llu had %llu\n", __func__,
|
||||
inode, ceph_vinop(inode), le64_to_cpu(info->version),
|
||||
ci->i_version);
|
||||
|
|
|
@ -1218,7 +1218,7 @@ extern const struct dentry_operations ceph_dentry_ops;
|
|||
extern loff_t ceph_make_fpos(unsigned high, unsigned off, bool hash_order);
|
||||
extern int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry);
|
||||
extern struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
|
||||
struct dentry *dentry, int err);
|
||||
struct dentry *dentry);
|
||||
extern struct dentry *ceph_finish_lookup(struct ceph_mds_request *req,
|
||||
struct dentry *dentry, int err);
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ struct ceph_auth_client_ops {
|
|||
* another request.
|
||||
*/
|
||||
int (*build_request)(struct ceph_auth_client *ac, void *buf, void *end);
|
||||
int (*handle_reply)(struct ceph_auth_client *ac, int result,
|
||||
int (*handle_reply)(struct ceph_auth_client *ac, u64 global_id,
|
||||
void *buf, void *end, u8 *session_key,
|
||||
int *session_key_len, u8 *con_secret,
|
||||
int *con_secret_len);
|
||||
|
@ -104,6 +104,8 @@ struct ceph_auth_client {
|
|||
struct mutex mutex;
|
||||
};
|
||||
|
||||
void ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id);
|
||||
|
||||
struct ceph_auth_client *ceph_auth_init(const char *name,
|
||||
const struct ceph_crypto_key *key,
|
||||
const int *con_modes);
|
||||
|
|
|
@ -36,7 +36,7 @@ static int init_protocol(struct ceph_auth_client *ac, int proto)
|
|||
}
|
||||
}
|
||||
|
||||
static void set_global_id(struct ceph_auth_client *ac, u64 global_id)
|
||||
void ceph_auth_set_global_id(struct ceph_auth_client *ac, u64 global_id)
|
||||
{
|
||||
dout("%s global_id %llu\n", __func__, global_id);
|
||||
|
||||
|
@ -260,19 +260,22 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac,
|
|||
ac->negotiating = false;
|
||||
}
|
||||
|
||||
ret = ac->ops->handle_reply(ac, result, payload, payload_end,
|
||||
if (result) {
|
||||
pr_err("auth protocol '%s' mauth authentication failed: %d\n",
|
||||
ceph_auth_proto_name(ac->protocol), result);
|
||||
ret = result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ac->ops->handle_reply(ac, global_id, payload, payload_end,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (ret == -EAGAIN) {
|
||||
ret = build_request(ac, true, reply_buf, reply_len);
|
||||
goto out;
|
||||
} else if (ret) {
|
||||
pr_err("auth protocol '%s' mauth authentication failed: %d\n",
|
||||
ceph_auth_proto_name(ac->protocol), result);
|
||||
goto out;
|
||||
}
|
||||
|
||||
set_global_id(ac, global_id);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ac->mutex);
|
||||
return ret;
|
||||
|
@ -498,11 +501,10 @@ int ceph_auth_handle_reply_done(struct ceph_auth_client *ac,
|
|||
int ret;
|
||||
|
||||
mutex_lock(&ac->mutex);
|
||||
ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len,
|
||||
ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len,
|
||||
session_key, session_key_len,
|
||||
con_secret, con_secret_len);
|
||||
if (!ret)
|
||||
set_global_id(ac, global_id);
|
||||
WARN_ON(ret == -EAGAIN || ret > 0);
|
||||
mutex_unlock(&ac->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ static int build_request(struct ceph_auth_client *ac, void *buf, void *end)
|
|||
* the generic auth code decode the global_id, and we carry no actual
|
||||
* authenticate state, so nothing happens here.
|
||||
*/
|
||||
static int handle_reply(struct ceph_auth_client *ac, int result,
|
||||
static int handle_reply(struct ceph_auth_client *ac, u64 global_id,
|
||||
void *buf, void *end, u8 *session_key,
|
||||
int *session_key_len, u8 *con_secret,
|
||||
int *con_secret_len)
|
||||
|
@ -77,7 +77,8 @@ static int handle_reply(struct ceph_auth_client *ac, int result,
|
|||
struct ceph_auth_none_info *xi = ac->private;
|
||||
|
||||
xi->starting = false;
|
||||
return result;
|
||||
ceph_auth_set_global_id(ac, global_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ceph_auth_none_destroy_authorizer(struct ceph_authorizer *a)
|
||||
|
|
|
@ -597,7 +597,7 @@ bad:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int handle_auth_session_key(struct ceph_auth_client *ac,
|
||||
static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
|
||||
void **p, void *end,
|
||||
u8 *session_key, int *session_key_len,
|
||||
u8 *con_secret, int *con_secret_len)
|
||||
|
@ -613,6 +613,7 @@ static int handle_auth_session_key(struct ceph_auth_client *ac,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ceph_auth_set_global_id(ac, global_id);
|
||||
if (*p == end) {
|
||||
/* pre-nautilus (or didn't request service tickets!) */
|
||||
WARN_ON(session_key || con_secret);
|
||||
|
@ -661,7 +662,7 @@ e_inval:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
|
||||
static int ceph_x_handle_reply(struct ceph_auth_client *ac, u64 global_id,
|
||||
void *buf, void *end,
|
||||
u8 *session_key, int *session_key_len,
|
||||
u8 *con_secret, int *con_secret_len)
|
||||
|
@ -669,13 +670,11 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
|
|||
struct ceph_x_info *xi = ac->private;
|
||||
struct ceph_x_ticket_handler *th;
|
||||
int len = end - buf;
|
||||
int result;
|
||||
void *p;
|
||||
int op;
|
||||
int ret;
|
||||
|
||||
if (result)
|
||||
return result; /* XXX hmm? */
|
||||
|
||||
if (xi->starting) {
|
||||
/* it's a hello */
|
||||
struct ceph_x_server_challenge *sc = buf;
|
||||
|
@ -697,9 +696,9 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result,
|
|||
switch (op) {
|
||||
case CEPHX_GET_AUTH_SESSION_KEY:
|
||||
/* AUTH ticket + [connection secret] + service tickets */
|
||||
ret = handle_auth_session_key(ac, &p, end, session_key,
|
||||
session_key_len, con_secret,
|
||||
con_secret_len);
|
||||
ret = handle_auth_session_key(ac, global_id, &p, end,
|
||||
session_key, session_key_len,
|
||||
con_secret, con_secret_len);
|
||||
break;
|
||||
|
||||
case CEPHX_GET_PRINCIPAL_SESSION_KEY:
|
||||
|
|
Загрузка…
Ссылка в новой задаче