Al Viro
2014-10-21 01:13:46 UTC
a) what protects ->d_name in ll_intent_file_open()? It copies
->d_name.name and ->d_name.len into local variables and proceeds to
use those; what's to guarantee that dentry won't get hit with d_move()
halfway through that? None of the locks that would give an exclusion
against d_move() appear to be held...
b) what stabilizes *dentryp->d_name in do_statahead_enter()?
c) what stabilizes fdentry->d_parent->d_name in llog_lvfs_destroy()?
Unless I'm missing something subtle, all three can race with d_move(),
with obvious unpleasant results. The next bunch doesn't (the callers
are holding ->i_mutex on parents), but it's also bloody odd - why are we
playing these games in llite/namei.c?
static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode)
{
return ll_mkdir_generic(dir, &dentry->d_name, mode, dentry);
}
static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
int mode, struct dentry *dchild)
{
int err;
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
name->len, name->name, dir->i_ino, dir->i_generation, dir);
if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir)))
mode &= ~current_umask();
mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
err = ll_new_node(dir, name, NULL, mode, 0, dchild, LUSTRE_OPC_MKDIR);
if (!err)
ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1);
return err;
}
and that's the only caller of ll_mkdir_generic(). What's the point of
passing this qstr separately, when you are passing dentry itself anyway?
Both to ll_mkdir_generic() *and* to ll_new_node(). And AFAICS all callers
of ll_new_node() have the second argument equal to address of ->d_name of
the 6th one... I thought you guys had some stack footprint problems?
While we are at it, where is ll_new_inode() ever called with NULL dchild?
Similar to that, where is ll_d_mountpoint() ever called with NULL dchild,
why do you have
if (unlikely(dchild))
in there when it's true on every call and why does it exist in the first
place? All its callers are reachable only from vfs_{unlink,rmdir,rename}
and we *do* d_mountpoint() checks there.
Comments?
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
->d_name.name and ->d_name.len into local variables and proceeds to
use those; what's to guarantee that dentry won't get hit with d_move()
halfway through that? None of the locks that would give an exclusion
against d_move() appear to be held...
b) what stabilizes *dentryp->d_name in do_statahead_enter()?
c) what stabilizes fdentry->d_parent->d_name in llog_lvfs_destroy()?
Unless I'm missing something subtle, all three can race with d_move(),
with obvious unpleasant results. The next bunch doesn't (the callers
are holding ->i_mutex on parents), but it's also bloody odd - why are we
playing these games in llite/namei.c?
static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode)
{
return ll_mkdir_generic(dir, &dentry->d_name, mode, dentry);
}
static int ll_mkdir_generic(struct inode *dir, struct qstr *name,
int mode, struct dentry *dchild)
{
int err;
CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p)\n",
name->len, name->name, dir->i_ino, dir->i_generation, dir);
if (!IS_POSIXACL(dir) || !exp_connect_umask(ll_i2mdexp(dir)))
mode &= ~current_umask();
mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
err = ll_new_node(dir, name, NULL, mode, 0, dchild, LUSTRE_OPC_MKDIR);
if (!err)
ll_stats_ops_tally(ll_i2sbi(dir), LPROC_LL_MKDIR, 1);
return err;
}
and that's the only caller of ll_mkdir_generic(). What's the point of
passing this qstr separately, when you are passing dentry itself anyway?
Both to ll_mkdir_generic() *and* to ll_new_node(). And AFAICS all callers
of ll_new_node() have the second argument equal to address of ->d_name of
the 6th one... I thought you guys had some stack footprint problems?
While we are at it, where is ll_new_inode() ever called with NULL dchild?
Similar to that, where is ll_d_mountpoint() ever called with NULL dchild,
why do you have
if (unlikely(dchild))
in there when it's true on every call and why does it exist in the first
place? All its callers are reachable only from vfs_{unlink,rmdir,rename}
and we *do* d_mountpoint() checks there.
Comments?
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to ***@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html