Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+43 -67
-38
fs/ceph/dir.c
··· 633 633 return dentry; 634 634 } 635 635 636 - int ceph_atomic_open(struct inode *dir, struct dentry *dentry, 637 - struct file *file, unsigned flags, umode_t mode, 638 - int *opened) 639 - { 640 - int err; 641 - struct dentry *res = NULL; 642 - 643 - if (!(flags & O_CREAT)) { 644 - if (dentry->d_name.len > NAME_MAX) 645 - return -ENAMETOOLONG; 646 - 647 - err = ceph_init_dentry(dentry); 648 - if (err < 0) 649 - return err; 650 - 651 - return ceph_lookup_open(dir, dentry, file, flags, mode, opened); 652 - } 653 - 654 - if (d_unhashed(dentry)) { 655 - res = ceph_lookup(dir, dentry, 0); 656 - if (IS_ERR(res)) 657 - return PTR_ERR(res); 658 - 659 - if (res) 660 - dentry = res; 661 - } 662 - 663 - /* We don't deal with positive dentries here */ 664 - if (dentry->d_inode) 665 - return finish_no_open(file, res); 666 - 667 - *opened |= FILE_CREATED; 668 - err = ceph_lookup_open(dir, dentry, file, flags, mode, opened); 669 - dput(res); 670 - 671 - return err; 672 - } 673 - 674 636 /* 675 637 * If we do a create but get no trace back from the MDS, follow up with 676 638 * a lookup (the VFS expects us to link up the provided dentry).
+37 -25
fs/ceph/file.c
··· 4 4 #include <linux/sched.h> 5 5 #include <linux/slab.h> 6 6 #include <linux/file.h> 7 + #include <linux/mount.h> 7 8 #include <linux/namei.h> 8 9 #include <linux/writeback.h> 9 10 ··· 107 106 } 108 107 109 108 /* 110 - * If the filp already has private_data, that means the file was 111 - * already opened by intent during lookup, and we do nothing. 112 - * 113 109 * If we already have the requisite capabilities, we can satisfy 114 110 * the open request locally (no need to request new caps from the 115 111 * MDS). We do, however, need to inform the MDS (asynchronously) ··· 205 207 206 208 207 209 /* 208 - * Do a lookup + open with a single request. 209 - * 210 - * If this succeeds, but some subsequent check in the vfs 211 - * may_open() fails, the struct *file gets cleaned up (i.e. 212 - * ceph_release gets called). So fear not! 210 + * Do a lookup + open with a single request. If we get a non-existent 211 + * file or symlink, return 1 so the VFS can retry. 213 212 */ 214 - int ceph_lookup_open(struct inode *dir, struct dentry *dentry, 213 + int ceph_atomic_open(struct inode *dir, struct dentry *dentry, 215 214 struct file *file, unsigned flags, umode_t mode, 216 215 int *opened) 217 216 { 218 217 struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); 219 218 struct ceph_mds_client *mdsc = fsc->mdsc; 220 219 struct ceph_mds_request *req; 221 - struct dentry *ret; 220 + struct dentry *dn; 222 221 int err; 223 222 224 - dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n", 225 - dentry, dentry->d_name.len, dentry->d_name.name, flags, mode); 223 + dout("atomic_open %p dentry %p '%.*s' %s flags %d mode 0%o\n", 224 + dir, dentry, dentry->d_name.len, dentry->d_name.name, 225 + d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode); 226 + 227 + if (dentry->d_name.len > NAME_MAX) 228 + return -ENAMETOOLONG; 229 + 230 + err = ceph_init_dentry(dentry); 231 + if (err < 0) 232 + return err; 226 233 227 234 /* do the open */ 228 235 req = prepare_open_request(dir->i_sb, flags, mode); ··· 244 241 (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, 245 242 req); 246 243 err = ceph_handle_snapdir(req, dentry, err); 247 - if (err) 248 - goto out; 249 - if ((flags & O_CREAT) && !req->r_reply_info.head->is_dentry) 244 + if (err == 0 && (flags & O_CREAT) && !req->r_reply_info.head->is_dentry) 250 245 err = ceph_handle_notrace_create(dir, dentry); 246 + 247 + if (d_unhashed(dentry)) { 248 + dn = ceph_finish_lookup(req, dentry, err); 249 + if (IS_ERR(dn)) 250 + err = PTR_ERR(dn); 251 + } else { 252 + /* we were given a hashed negative dentry */ 253 + dn = NULL; 254 + } 251 255 if (err) 252 - goto out; 253 - err = finish_open(file, req->r_dentry, ceph_open, opened); 254 - out: 255 - ret = ceph_finish_lookup(req, dentry, err); 256 + goto out_err; 257 + if (dn || dentry->d_inode == NULL || S_ISLNK(dentry->d_inode->i_mode)) { 258 + /* make vfs retry on splice, ENOENT, or symlink */ 259 + dout("atomic_open finish_no_open on dn %p\n", dn); 260 + err = finish_no_open(file, dn); 261 + } else { 262 + dout("atomic_open finish_open on dn %p\n", dn); 263 + err = finish_open(file, dentry, ceph_open, opened); 264 + } 265 + 266 + out_err: 256 267 ceph_mdsc_put_request(req); 257 - dout("ceph_lookup_open result=%p\n", ret); 258 - 259 - if (IS_ERR(ret)) 260 - return PTR_ERR(ret); 261 - 262 - dput(ret); 268 + dout("atomic_open result=%d\n", err); 263 269 return err; 264 270 } 265 271
+3 -3
fs/ceph/super.h
··· 806 806 loff_t off, size_t len); 807 807 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags); 808 808 extern int ceph_open(struct inode *inode, struct file *file); 809 - extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry, 810 - struct file *od, unsigned flags, 811 - umode_t mode, int *opened); 809 + extern int ceph_atomic_open(struct inode *dir, struct dentry *dentry, 810 + struct file *file, unsigned flags, umode_t mode, 811 + int *opened); 812 812 extern int ceph_release(struct inode *inode, struct file *filp); 813 813 814 814 /* dir.c */
+1
net/ceph/crypto.c
··· 466 466 struct ceph_crypto_key *ckey = key->payload.data; 467 467 468 468 ceph_crypto_key_destroy(ckey); 469 + kfree(ckey); 469 470 } 470 471 471 472 struct key_type key_type_ceph = {
+2 -1
net/ceph/crypto.h
··· 16 16 17 17 static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) 18 18 { 19 - kfree(key->key); 19 + if (key) 20 + kfree(key->key); 20 21 } 21 22 22 23 extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst,