From: Sage Weil Date: Tue, 17 Mar 2009 19:54:03 +0000 (-0700) Subject: kclient: fix file refs vs special files X-Git-Tag: v0.7.2~144 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3f9b566d7ff22b98e690d245a4efe8ff48d658b7;p=ceph.git kclient: fix file refs vs special files Special inodes get their own fops, so we don't get a ceph_release call. Therefore, we need to drop any fmode refs we took in ceph_init_file for those files (that is, any file where we don't have i_fop->release set to ceph_release). Add some BUG_ON's to ensure as much. --- diff --git a/src/kernel/file.c b/src/kernel/file.c index 0c379bd18871..35abc32ca39b 100644 --- a/src/kernel/file.c +++ b/src/kernel/file.c @@ -56,15 +56,35 @@ out: static int ceph_init_file(struct inode *inode, struct file *file, int fmode) { struct ceph_file_info *cf; + int ret = 0; + + switch (inode->i_mode & S_IFMT) { + case S_IFREG: + case S_IFDIR: + dout(20, "init_file %p 0%o (regular)\n", inode, inode->i_mode); + cf = kzalloc(sizeof(*cf), GFP_NOFS); + if (cf == NULL) { + ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */ + return -ENOMEM; + } + cf->fmode = fmode; + file->private_data = cf; + BUG_ON(inode->i_fop->release != ceph_release); + break; - cf = kzalloc(sizeof(*cf), GFP_NOFS); - if (cf == NULL) { + default: + dout(20, "init_file %p 0%o (special)\n", inode, inode->i_mode); + /* + * we need to drop the open ref now, since we don't + * have .release set to ceph_release. + */ ceph_put_fmode(ceph_inode(inode), fmode); /* clean up */ - return -ENOMEM; + BUG_ON(inode->i_fop->release == ceph_release); + + /* call the proper open fop */ + ret = inode->i_fop->open(inode, file); } - cf->fmode = fmode; - file->private_data = cf; - return 0; + return ret; } /* @@ -766,4 +786,3 @@ const struct file_operations ceph_file_fops = { .unlocked_ioctl = ceph_ioctl, }; -