mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client
Pull two ceph fixes from Sage Weil: "The first patch fixes up the old crufty open intent code to use the atomic_open stuff properly, and the second fixes a possible null deref and memory leak with the crypto keys." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client: libceph: fix crypto key null deref, memory leak ceph: simplify+fix atomic_open
This commit is contained in:
commit
c8924234bd
@ -633,44 +633,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
return dentry;
|
return dentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
|
||||||
struct file *file, unsigned flags, umode_t mode,
|
|
||||||
int *opened)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
struct dentry *res = NULL;
|
|
||||||
|
|
||||||
if (!(flags & O_CREAT)) {
|
|
||||||
if (dentry->d_name.len > NAME_MAX)
|
|
||||||
return -ENAMETOOLONG;
|
|
||||||
|
|
||||||
err = ceph_init_dentry(dentry);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d_unhashed(dentry)) {
|
|
||||||
res = ceph_lookup(dir, dentry, 0);
|
|
||||||
if (IS_ERR(res))
|
|
||||||
return PTR_ERR(res);
|
|
||||||
|
|
||||||
if (res)
|
|
||||||
dentry = res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We don't deal with positive dentries here */
|
|
||||||
if (dentry->d_inode)
|
|
||||||
return finish_no_open(file, res);
|
|
||||||
|
|
||||||
*opened |= FILE_CREATED;
|
|
||||||
err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
|
|
||||||
dput(res);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we do a create but get no trace back from the MDS, follow up with
|
* If we do a create but get no trace back from the MDS, follow up with
|
||||||
* a lookup (the VFS expects us to link up the provided dentry).
|
* a lookup (the VFS expects us to link up the provided dentry).
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
|
#include <linux/mount.h>
|
||||||
#include <linux/namei.h>
|
#include <linux/namei.h>
|
||||||
#include <linux/writeback.h>
|
#include <linux/writeback.h>
|
||||||
|
|
||||||
@ -106,9 +107,6 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the filp already has private_data, that means the file was
|
|
||||||
* already opened by intent during lookup, and we do nothing.
|
|
||||||
*
|
|
||||||
* If we already have the requisite capabilities, we can satisfy
|
* If we already have the requisite capabilities, we can satisfy
|
||||||
* the open request locally (no need to request new caps from the
|
* the open request locally (no need to request new caps from the
|
||||||
* MDS). We do, however, need to inform the MDS (asynchronously)
|
* MDS). We do, however, need to inform the MDS (asynchronously)
|
||||||
@ -207,24 +205,29 @@ out:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a lookup + open with a single request.
|
* Do a lookup + open with a single request. If we get a non-existent
|
||||||
*
|
* file or symlink, return 1 so the VFS can retry.
|
||||||
* If this succeeds, but some subsequent check in the vfs
|
|
||||||
* may_open() fails, the struct *file gets cleaned up (i.e.
|
|
||||||
* ceph_release gets called). So fear not!
|
|
||||||
*/
|
*/
|
||||||
int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
|
int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||||
struct file *file, unsigned flags, umode_t mode,
|
struct file *file, unsigned flags, umode_t mode,
|
||||||
int *opened)
|
int *opened)
|
||||||
{
|
{
|
||||||
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
|
struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
|
||||||
struct ceph_mds_client *mdsc = fsc->mdsc;
|
struct ceph_mds_client *mdsc = fsc->mdsc;
|
||||||
struct ceph_mds_request *req;
|
struct ceph_mds_request *req;
|
||||||
struct dentry *ret;
|
struct dentry *dn;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
|
dout("atomic_open %p dentry %p '%.*s' %s flags %d mode 0%o\n",
|
||||||
dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
|
dir, dentry, dentry->d_name.len, dentry->d_name.name,
|
||||||
|
d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode);
|
||||||
|
|
||||||
|
if (dentry->d_name.len > NAME_MAX)
|
||||||
|
return -ENAMETOOLONG;
|
||||||
|
|
||||||
|
err = ceph_init_dentry(dentry);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
/* do the open */
|
/* do the open */
|
||||||
req = prepare_open_request(dir->i_sb, flags, mode);
|
req = prepare_open_request(dir->i_sb, flags, mode);
|
||||||
@ -241,22 +244,31 @@ int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
|
|||||||
(flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
|
(flags & (O_CREAT|O_TRUNC)) ? dir : NULL,
|
||||||
req);
|
req);
|
||||||
err = ceph_handle_snapdir(req, dentry, err);
|
err = ceph_handle_snapdir(req, dentry, err);
|
||||||
if (err)
|
if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
|
||||||
goto out;
|
|
||||||
if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry)
|
|
||||||
err = ceph_handle_notrace_create(dir, dentry);
|
err = ceph_handle_notrace_create(dir, dentry);
|
||||||
|
|
||||||
|
if (d_unhashed(dentry)) {
|
||||||
|
dn = ceph_finish_lookup(req, dentry, err);
|
||||||
|
if (IS_ERR(dn))
|
||||||
|
err = PTR_ERR(dn);
|
||||||
|
} else {
|
||||||
|
/* we were given a hashed negative dentry */
|
||||||
|
dn = NULL;
|
||||||
|
}
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out_err;
|
||||||
err = finish_open(file, req->r_dentry, ceph_open, opened);
|
if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) {
|
||||||
out:
|
/* make vfs retry on splice, ENOENT, or symlink */
|
||||||
ret = ceph_finish_lookup(req, dentry, err);
|
dout("atomic_open finish_no_open on dn %p\n", dn);
|
||||||
|
err = finish_no_open(file, dn);
|
||||||
|
} else {
|
||||||
|
dout("atomic_open finish_open on dn %p\n", dn);
|
||||||
|
err = finish_open(file, dentry, ceph_open, opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_err:
|
||||||
ceph_mdsc_put_request(req);
|
ceph_mdsc_put_request(req);
|
||||||
dout("ceph_lookup_open result=%p\n", ret);
|
dout("atomic_open result=%d\n", err);
|
||||||
|
|
||||||
if (IS_ERR(ret))
|
|
||||||
return PTR_ERR(ret);
|
|
||||||
|
|
||||||
dput(ret);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
|
|||||||
loff_t off, size_t len);
|
loff_t off, size_t len);
|
||||||
extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
|
extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
|
||||||
extern int ceph_open(struct inode *inode, struct file *file);
|
extern int ceph_open(struct inode *inode, struct file *file);
|
||||||
extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
|
extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
|
||||||
struct file *od, unsigned flags,
|
struct file *file, unsigned flags, umode_t mode,
|
||||||
umode_t mode, int *opened);
|
int *opened);
|
||||||
extern int ceph_release(struct inode *inode, struct file *filp);
|
extern int ceph_release(struct inode *inode, struct file *filp);
|
||||||
|
|
||||||
/* dir.c */
|
/* dir.c */
|
||||||
|
@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) {
|
|||||||
struct ceph_crypto_key *ckey = key->payload.data;
|
struct ceph_crypto_key *ckey = key->payload.data;
|
||||||
|
|
||||||
ceph_crypto_key_destroy(ckey);
|
ceph_crypto_key_destroy(ckey);
|
||||||
|
kfree(ckey);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct key_type key_type_ceph = {
|
struct key_type key_type_ceph = {
|
||||||
|
@ -16,7 +16,8 @@ struct ceph_crypto_key {
|
|||||||
|
|
||||||
static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
|
static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key)
|
||||||
{
|
{
|
||||||
kfree(key->key);
|
if (key)
|
||||||
|
kfree(key->key);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
|
extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
|
||||||
|
Loading…
Reference in New Issue
Block a user