diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-07 15:03:58 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-07-20 01:44:17 -0400 |
commit | a4464dbc0ca6a3ab8e9d1206bc05059dae2a559d (patch) | |
tree | d3c9332ab72cf5a4eba483ba1ff83c54ca4c42a0 /fs/dcache.c | |
parent | e3c3d9c838d48c0341c40ea45ee087e3d8c8ea39 (diff) |
Make ->d_sb assign-once and always non-NULL
New helper (non-exported, fs/internal.h-only): __d_alloc(sb, name).
Allocates dentry, sets its ->d_sb to given superblock and sets
->d_op accordingly. Old d_alloc(NULL, name) callers are converted
to that (all of them know what superblock they want). d_alloc()
itself is left only for parent != NULl case; uses __d_alloc(),
inserts result into the list of parent's children.
Note that now ->d_sb is assign-once and never NULL *and*
->d_parent is never NULL either.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/dcache.c')
-rw-r--r-- | fs/dcache.c | 75 |
1 files changed, 39 insertions, 36 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index d3902139b533..c61edd0318c3 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1275,8 +1275,8 @@ static struct shrinker dcache_shrinker = { | |||
1275 | }; | 1275 | }; |
1276 | 1276 | ||
1277 | /** | 1277 | /** |
1278 | * d_alloc - allocate a dcache entry | 1278 | * __d_alloc - allocate a dcache entry |
1279 | * @parent: parent of entry to allocate | 1279 | * @sb: filesystem it will belong to |
1280 | * @name: qstr of the name | 1280 | * @name: qstr of the name |
1281 | * | 1281 | * |
1282 | * Allocates a dentry. It returns %NULL if there is insufficient memory | 1282 | * Allocates a dentry. It returns %NULL if there is insufficient memory |
@@ -1284,7 +1284,7 @@ static struct shrinker dcache_shrinker = { | |||
1284 | * copied and the copy passed in may be reused after this call. | 1284 | * copied and the copy passed in may be reused after this call. |
1285 | */ | 1285 | */ |
1286 | 1286 | ||
1287 | struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | 1287 | struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) |
1288 | { | 1288 | { |
1289 | struct dentry *dentry; | 1289 | struct dentry *dentry; |
1290 | char *dname; | 1290 | char *dname; |
@@ -1314,8 +1314,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1314 | spin_lock_init(&dentry->d_lock); | 1314 | spin_lock_init(&dentry->d_lock); |
1315 | seqcount_init(&dentry->d_seq); | 1315 | seqcount_init(&dentry->d_seq); |
1316 | dentry->d_inode = NULL; | 1316 | dentry->d_inode = NULL; |
1317 | dentry->d_parent = NULL; | 1317 | dentry->d_parent = dentry; |
1318 | dentry->d_sb = NULL; | 1318 | dentry->d_sb = sb; |
1319 | dentry->d_op = NULL; | 1319 | dentry->d_op = NULL; |
1320 | dentry->d_fsdata = NULL; | 1320 | dentry->d_fsdata = NULL; |
1321 | INIT_HLIST_BL_NODE(&dentry->d_hash); | 1321 | INIT_HLIST_BL_NODE(&dentry->d_hash); |
@@ -1323,36 +1323,47 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | |||
1323 | INIT_LIST_HEAD(&dentry->d_subdirs); | 1323 | INIT_LIST_HEAD(&dentry->d_subdirs); |
1324 | INIT_LIST_HEAD(&dentry->d_alias); | 1324 | INIT_LIST_HEAD(&dentry->d_alias); |
1325 | INIT_LIST_HEAD(&dentry->d_u.d_child); | 1325 | INIT_LIST_HEAD(&dentry->d_u.d_child); |
1326 | 1326 | d_set_d_op(dentry, dentry->d_sb->s_d_op); | |
1327 | if (parent) { | ||
1328 | spin_lock(&parent->d_lock); | ||
1329 | /* | ||
1330 | * don't need child lock because it is not subject | ||
1331 | * to concurrency here | ||
1332 | */ | ||
1333 | __dget_dlock(parent); | ||
1334 | dentry->d_parent = parent; | ||
1335 | dentry->d_sb = parent->d_sb; | ||
1336 | d_set_d_op(dentry, dentry->d_sb->s_d_op); | ||
1337 | list_add(&dentry->d_u.d_child, &parent->d_subdirs); | ||
1338 | spin_unlock(&parent->d_lock); | ||
1339 | } | ||
1340 | 1327 | ||
1341 | this_cpu_inc(nr_dentry); | 1328 | this_cpu_inc(nr_dentry); |
1342 | 1329 | ||
1343 | return dentry; | 1330 | return dentry; |
1344 | } | 1331 | } |
1332 | |||
1333 | /** | ||
1334 | * d_alloc - allocate a dcache entry | ||
1335 | * @parent: parent of entry to allocate | ||
1336 | * @name: qstr of the name | ||
1337 | * | ||
1338 | * Allocates a dentry. It returns %NULL if there is insufficient memory | ||
1339 | * available. On a success the dentry is returned. The name passed in is | ||
1340 | * copied and the copy passed in may be reused after this call. | ||
1341 | */ | ||
1342 | struct dentry *d_alloc(struct dentry * parent, const struct qstr *name) | ||
1343 | { | ||
1344 | struct dentry *dentry = __d_alloc(parent->d_sb, name); | ||
1345 | if (!dentry) | ||
1346 | return NULL; | ||
1347 | |||
1348 | spin_lock(&parent->d_lock); | ||
1349 | /* | ||
1350 | * don't need child lock because it is not subject | ||
1351 | * to concurrency here | ||
1352 | */ | ||
1353 | __dget_dlock(parent); | ||
1354 | dentry->d_parent = parent; | ||
1355 | list_add(&dentry->d_u.d_child, &parent->d_subdirs); | ||
1356 | spin_unlock(&parent->d_lock); | ||
1357 | |||
1358 | return dentry; | ||
1359 | } | ||
1345 | EXPORT_SYMBOL(d_alloc); | 1360 | EXPORT_SYMBOL(d_alloc); |
1346 | 1361 | ||
1347 | struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name) | 1362 | struct dentry *d_alloc_pseudo(struct super_block *sb, const struct qstr *name) |
1348 | { | 1363 | { |
1349 | struct dentry *dentry = d_alloc(NULL, name); | 1364 | struct dentry *dentry = __d_alloc(sb, name); |
1350 | if (dentry) { | 1365 | if (dentry) |
1351 | dentry->d_sb = sb; | ||
1352 | d_set_d_op(dentry, dentry->d_sb->s_d_op); | ||
1353 | dentry->d_parent = dentry; | ||
1354 | dentry->d_flags |= DCACHE_DISCONNECTED; | 1366 | dentry->d_flags |= DCACHE_DISCONNECTED; |
1355 | } | ||
1356 | return dentry; | 1367 | return dentry; |
1357 | } | 1368 | } |
1358 | EXPORT_SYMBOL(d_alloc_pseudo); | 1369 | EXPORT_SYMBOL(d_alloc_pseudo); |
@@ -1522,13 +1533,9 @@ struct dentry * d_alloc_root(struct inode * root_inode) | |||
1522 | if (root_inode) { | 1533 | if (root_inode) { |
1523 | static const struct qstr name = { .name = "/", .len = 1 }; | 1534 | static const struct qstr name = { .name = "/", .len = 1 }; |
1524 | 1535 | ||
1525 | res = d_alloc(NULL, &name); | 1536 | res = __d_alloc(root_inode->i_sb, &name); |
1526 | if (res) { | 1537 | if (res) |
1527 | res->d_sb = root_inode->i_sb; | ||
1528 | d_set_d_op(res, res->d_sb->s_d_op); | ||
1529 | res->d_parent = res; | ||
1530 | d_instantiate(res, root_inode); | 1538 | d_instantiate(res, root_inode); |
1531 | } | ||
1532 | } | 1539 | } |
1533 | return res; | 1540 | return res; |
1534 | } | 1541 | } |
@@ -1589,13 +1596,11 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1589 | if (res) | 1596 | if (res) |
1590 | goto out_iput; | 1597 | goto out_iput; |
1591 | 1598 | ||
1592 | tmp = d_alloc(NULL, &anonstring); | 1599 | tmp = __d_alloc(inode->i_sb, &anonstring); |
1593 | if (!tmp) { | 1600 | if (!tmp) { |
1594 | res = ERR_PTR(-ENOMEM); | 1601 | res = ERR_PTR(-ENOMEM); |
1595 | goto out_iput; | 1602 | goto out_iput; |
1596 | } | 1603 | } |
1597 | tmp->d_parent = tmp; /* make sure dput doesn't croak */ | ||
1598 | |||
1599 | 1604 | ||
1600 | spin_lock(&inode->i_lock); | 1605 | spin_lock(&inode->i_lock); |
1601 | res = __d_find_any_alias(inode); | 1606 | res = __d_find_any_alias(inode); |
@@ -1607,8 +1612,6 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1607 | 1612 | ||
1608 | /* attach a disconnected dentry */ | 1613 | /* attach a disconnected dentry */ |
1609 | spin_lock(&tmp->d_lock); | 1614 | spin_lock(&tmp->d_lock); |
1610 | tmp->d_sb = inode->i_sb; | ||
1611 | d_set_d_op(tmp, tmp->d_sb->s_d_op); | ||
1612 | tmp->d_inode = inode; | 1615 | tmp->d_inode = inode; |
1613 | tmp->d_flags |= DCACHE_DISCONNECTED; | 1616 | tmp->d_flags |= DCACHE_DISCONNECTED; |
1614 | list_add(&tmp->d_alias, &inode->i_dentry); | 1617 | list_add(&tmp->d_alias, &inode->i_dentry); |