{"id":494,"url":"http://patchwork.ozlabs.org/api/1.0/patches/494/?format=json","project":{"id":1,"url":"http://patchwork.ozlabs.org/api/1.0/projects/1/?format=json","name":"Cell Broadband Engine development","link_name":"cbe-oss-dev","list_id":"cbe-oss-dev.ozlabs.org","list_email":"cbe-oss-dev@ozlabs.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<1221727767.137344.685272968033.1.gpush@pingu>","date":"2008-09-18T08:49:27","name":"[RFC] powerpc/spufs: fix gang destruction vs readdir(\"/spu\") race","commit_ref":null,"pull_url":null,"state":"under-review","archived":false,"hash":"defa7deda87adb14fd7c7a272a968d84a1027ba1","submitter":{"id":1,"url":"http://patchwork.ozlabs.org/api/1.0/people/1/?format=json","name":"Jeremy Kerr","email":"jk@ozlabs.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/cbe-oss-dev/patch/1221727767.137344.685272968033.1.gpush@pingu/mbox/","series":[],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/494/checks/","tags":{},"headers":{"Return-Path":"<cbe-oss-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org>","X-Original-To":["patchwork-incoming@ozlabs.org","cbe-oss-dev@ozlabs.org"],"Delivered-To":["patchwork-incoming@ozlabs.org","cbe-oss-dev@ozlabs.org"],"Received":["from ozlabs.org (localhost [127.0.0.1])\n\tby ozlabs.org (Postfix) with ESMTP id D54D1DE050\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 18 Sep 2008 18:49:39 +1000 (EST)","by ozlabs.org (Postfix, from userid 1023)\n\tid 5AC83DDE07; Thu, 18 Sep 2008 18:49:32 +1000 (EST)"],"MIME-Version":"1.0","Message-Id":"<1221727767.137344.685272968033.1.gpush@pingu>","To":"<cbe-oss-dev@ozlabs.org>","From":"Jeremy Kerr <jk@ozlabs.org>","Date":"Thu, 18 Sep 2008 18:49:27 +1000","Subject":"[Cbe-oss-dev] [RFC,\n\tPATCH] powerpc/spufs: fix gang destruction vs readdir(\"/spu\") race","X-BeenThere":"cbe-oss-dev@ozlabs.org","X-Mailman-Version":"2.1.11","Precedence":"list","List-Id":"Discussion about Open Source Software for the Cell Broadband Engine\n\t<cbe-oss-dev.ozlabs.org>","List-Unsubscribe":"<https://ozlabs.org/mailman/options/cbe-oss-dev>,\n\t<mailto:cbe-oss-dev-request@ozlabs.org?subject=unsubscribe>","List-Archive":"<http://ozlabs.org/pipermail/cbe-oss-dev>","List-Post":"<mailto:cbe-oss-dev@ozlabs.org>","List-Help":"<mailto:cbe-oss-dev-request@ozlabs.org?subject=help>","List-Subscribe":"<https://ozlabs.org/mailman/listinfo/cbe-oss-dev>,\n\t<mailto:cbe-oss-dev-request@ozlabs.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Sender":"cbe-oss-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org","Errors-To":"cbe-oss-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org"},"content":"At present, there seems to be a race with SPU gang destruction and\ncalling dcache_readdir on the top level directory of a spufs mount.\ndcache_readdir expects the parent directory's inode to be locked for any\noperations that remove subdirs, but this isn't true for the spufs\ngang destruction path:\n\n sys_close -> gang->file_operations->dcache_dir_close() -> dput()\n\nThis dput() will cause the gang's dentry to be unhashed without the\nparent's dcache mutex held. This breaks dcache_readdir's assumption\nabout locked dentries.\n\nThis change uses a spufs-specific file_operations->release callback for\ngangs, which does an explicit d_drop() with the parent's mutex held.\n\nHowever, we do end up changing the dentry lifetime semantics for SPU\ngangs.  Currently, the dentry will still be present for a gang that has\nbeen close()ed, but still has active contexts. With this change, the\ngang may be unhashed (and so not appear in readdir(\"/spu\")), but still\nhave active contexts.\n\nHowever, I believe that this lifetime behaviour is more consistent with\nnon-gang SPU contexts at the moment - contexts are unhashed at close()\ntime.\n\nSigned-off-by: Jeremy Kerr <jk@ozlabs.org>","diff":"diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c\nindex 690ca7b..555fc19 100644\n--- a/arch/powerpc/platforms/cell/spufs/inode.c\n+++ b/arch/powerpc/platforms/cell/spufs/inode.c\n@@ -548,6 +548,30 @@ out:\n \treturn ret;\n }\n \n+static int spufs_gang_close(struct inode *inode, struct file *file)\n+{\n+\tstruct dentry *dir;\n+\tstruct inode *parent;\n+\n+\tdir = file->f_path.dentry;\n+\tparent = dir->d_parent->d_inode;\n+\n+\tmutex_lock_nested(&parent->i_mutex, I_MUTEX_PARENT);\n+\td_drop(dir);\n+\tmutex_unlock(&parent->i_mutex);\n+\n+\treturn dcache_dir_close(inode, file);\n+}\n+\n+const struct file_operations spufs_gang_fops = {\n+\t.open\t\t= dcache_dir_open,\n+\t.release\t= spufs_gang_close,\n+\t.llseek\t\t= dcache_dir_lseek,\n+\t.read\t\t= generic_read_dir,\n+\t.readdir\t= dcache_readdir,\n+\t.fsync\t\t= simple_sync_file,\n+};\n+\n static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)\n {\n \tint ret;\n@@ -567,7 +591,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)\n \t\tgoto out;\n \t}\n \n-\tfilp->f_op = &simple_dir_operations;\n+\tfilp->f_op = &spufs_gang_fops;\n \tfd_install(ret, filp);\n out:\n \treturn ret;\n","prefixes":["RFC"]}