Commit 5c1a712f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ceph-for-6.2-rc3' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
 "Two file locking fixes from Xiubo"

* tag 'ceph-for-6.2-rc3' of https://github.com/ceph/ceph-client:
  ceph: avoid use-after-free in ceph_fl_release_lock()
  ceph: switch to vfs_inode_has_locks() to fix file lock bug
parents 7b8c854c 8e185871
...@@ -2913,7 +2913,7 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got ...@@ -2913,7 +2913,7 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got
while (true) { while (true) {
flags &= CEPH_FILE_MODE_MASK; flags &= CEPH_FILE_MODE_MASK;
if (atomic_read(&fi->num_locks)) if (vfs_inode_has_locks(inode))
flags |= CHECK_FILELOCK; flags |= CHECK_FILELOCK;
_got = 0; _got = 0;
ret = try_get_cap_refs(inode, need, want, endoff, ret = try_get_cap_refs(inode, need, want, endoff,
......
...@@ -32,24 +32,36 @@ void __init ceph_flock_init(void) ...@@ -32,24 +32,36 @@ void __init ceph_flock_init(void)
static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src) static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
{ {
struct ceph_file_info *fi = dst->fl_file->private_data;
struct inode *inode = file_inode(dst->fl_file); struct inode *inode = file_inode(dst->fl_file);
atomic_inc(&ceph_inode(inode)->i_filelock_ref); atomic_inc(&ceph_inode(inode)->i_filelock_ref);
atomic_inc(&fi->num_locks); dst->fl_u.ceph.inode = igrab(inode);
} }
/*
* Do not use the 'fl->fl_file' in release function, which
* is possibly already released by another thread.
*/
static void ceph_fl_release_lock(struct file_lock *fl) static void ceph_fl_release_lock(struct file_lock *fl)
{ {
struct ceph_file_info *fi = fl->fl_file->private_data; struct inode *inode = fl->fl_u.ceph.inode;
struct inode *inode = file_inode(fl->fl_file); struct ceph_inode_info *ci;
struct ceph_inode_info *ci = ceph_inode(inode);
atomic_dec(&fi->num_locks); /*
* If inode is NULL it should be a request file_lock,
* nothing we can do.
*/
if (!inode)
return;
ci = ceph_inode(inode);
if (atomic_dec_and_test(&ci->i_filelock_ref)) { if (atomic_dec_and_test(&ci->i_filelock_ref)) {
/* clear error when all locks are released */ /* clear error when all locks are released */
spin_lock(&ci->i_ceph_lock); spin_lock(&ci->i_ceph_lock);
ci->i_ceph_flags &= ~CEPH_I_ERROR_FILELOCK; ci->i_ceph_flags &= ~CEPH_I_ERROR_FILELOCK;
spin_unlock(&ci->i_ceph_lock); spin_unlock(&ci->i_ceph_lock);
} }
fl->fl_u.ceph.inode = NULL;
iput(inode);
} }
static const struct file_lock_operations ceph_fl_lock_ops = { static const struct file_lock_operations ceph_fl_lock_ops = {
......
...@@ -790,7 +790,6 @@ struct ceph_file_info { ...@@ -790,7 +790,6 @@ struct ceph_file_info {
struct list_head rw_contexts; struct list_head rw_contexts;
u32 filp_gen; u32 filp_gen;
atomic_t num_locks;
}; };
struct ceph_dir_file_info { struct ceph_dir_file_info {
......
...@@ -1119,6 +1119,9 @@ struct file_lock { ...@@ -1119,6 +1119,9 @@ struct file_lock {
int state; /* state of grant or error if -ve */ int state; /* state of grant or error if -ve */
unsigned int debug_id; unsigned int debug_id;
} afs; } afs;
struct {
struct inode *inode;
} ceph;
} fl_u; } fl_u;
} __randomize_layout; } __randomize_layout;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment