aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:43 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:24 -0500
commitdc0474be3e27463d4d4a2793f82366eed906f223 (patch)
tree41f75e638442cb343bacdcfbabb17ffc3bd5b4ce
parent357f8e658bba8a085c4a5d4331e30894be8096b8 (diff)
fs: dcache rationalise dget variants
dget_locked was a shortcut to avoid the lazy lru manipulation when we already held dcache_lock (lru manipulation was relatively cheap at that point). However, how that the lru lock is an innermost one, we never hold it at any caller, so the lock cost can now be avoided. We already have well working lazy dcache LRU, so it should be fine to defer LRU manipulations to scan time. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r--arch/powerpc/platforms/cell/spufs/inode.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_fs.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_fs.c2
-rw-r--r--drivers/staging/smbfs/cache.c2
-rw-r--r--fs/configfs/inode.c2
-rw-r--r--fs/dcache.c36
-rw-r--r--fs/exportfs/expfs.c2
-rw-r--r--fs/ncpfs/dir.c2
-rw-r--r--fs/ocfs2/dcache.c2
-rw-r--r--include/linux/dcache.h15
-rw-r--r--kernel/cgroup.c2
-rw-r--r--security/selinux/selinuxfs.c2
12 files changed, 24 insertions, 47 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index 2662b50ea8d4..03185de7cd4a 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -161,7 +161,7 @@ static void spufs_prune_dir(struct dentry *dir)
161 list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) { 161 list_for_each_entry_safe(dentry, tmp, &dir->d_subdirs, d_u.d_child) {
162 spin_lock(&dentry->d_lock); 162 spin_lock(&dentry->d_lock);
163 if (!(d_unhashed(dentry)) && dentry->d_inode) { 163 if (!(d_unhashed(dentry)) && dentry->d_inode) {
164 dget_locked_dlock(dentry); 164 dget_dlock(dentry);
165 __d_drop(dentry); 165 __d_drop(dentry);
166 spin_unlock(&dentry->d_lock); 166 spin_unlock(&dentry->d_lock);
167 simple_unlink(dir->d_inode, dentry); 167 simple_unlink(dir->d_inode, dentry);
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index 925e88227ded..31ae1b108aea 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -279,7 +279,7 @@ static int remove_file(struct dentry *parent, char *name)
279 279
280 spin_lock(&tmp->d_lock); 280 spin_lock(&tmp->d_lock);
281 if (!(d_unhashed(tmp) && tmp->d_inode)) { 281 if (!(d_unhashed(tmp) && tmp->d_inode)) {
282 dget_locked_dlock(tmp); 282 dget_dlock(tmp);
283 __d_drop(tmp); 283 __d_drop(tmp);
284 spin_unlock(&tmp->d_lock); 284 spin_unlock(&tmp->d_lock);
285 simple_unlink(parent->d_inode, tmp); 285 simple_unlink(parent->d_inode, tmp);
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
index 49af4a6538ba..df7fa251dcdc 100644
--- a/drivers/infiniband/hw/qib/qib_fs.c
+++ b/drivers/infiniband/hw/qib/qib_fs.c
@@ -455,7 +455,7 @@ static int remove_file(struct dentry *parent, char *name)
455 455
456 spin_lock(&tmp->d_lock); 456 spin_lock(&tmp->d_lock);
457 if (!(d_unhashed(tmp) && tmp->d_inode)) { 457 if (!(d_unhashed(tmp) && tmp->d_inode)) {
458 dget_locked_dlock(tmp); 458 dget_dlock(tmp);
459 __d_drop(tmp); 459 __d_drop(tmp);
460 spin_unlock(&tmp->d_lock); 460 spin_unlock(&tmp->d_lock);
461 simple_unlink(parent->d_inode, tmp); 461 simple_unlink(parent->d_inode, tmp);
diff --git a/drivers/staging/smbfs/cache.c b/drivers/staging/smbfs/cache.c
index 75dfd403fb90..f2a1323ca827 100644
--- a/drivers/staging/smbfs/cache.c
+++ b/drivers/staging/smbfs/cache.c
@@ -102,7 +102,7 @@ smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
102 dent = list_entry(next, struct dentry, d_u.d_child); 102 dent = list_entry(next, struct dentry, d_u.d_child);
103 if ((unsigned long)dent->d_fsdata == fpos) { 103 if ((unsigned long)dent->d_fsdata == fpos) {
104 if (dent->d_inode) 104 if (dent->d_inode)
105 dget_locked(dent); 105 dget(dent);
106 else 106 else
107 dent = NULL; 107 dent = NULL;
108 goto out_unlock; 108 goto out_unlock;
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index fb3a55fff82a..c83f4768eeaa 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -252,7 +252,7 @@ void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent)
252 if (dentry) { 252 if (dentry) {
253 spin_lock(&dentry->d_lock); 253 spin_lock(&dentry->d_lock);
254 if (!(d_unhashed(dentry) && dentry->d_inode)) { 254 if (!(d_unhashed(dentry) && dentry->d_inode)) {
255 dget_locked_dlock(dentry); 255 dget_dlock(dentry);
256 __d_drop(dentry); 256 __d_drop(dentry);
257 spin_unlock(&dentry->d_lock); 257 spin_unlock(&dentry->d_lock);
258 simple_unlink(parent->d_inode, dentry); 258 simple_unlink(parent->d_inode, dentry);
diff --git a/fs/dcache.c b/fs/dcache.c
index 01f016799fd4..b4d2e28eef5b 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -429,32 +429,17 @@ int d_invalidate(struct dentry * dentry)
429EXPORT_SYMBOL(d_invalidate); 429EXPORT_SYMBOL(d_invalidate);
430 430
431/* This must be called with d_lock held */ 431/* This must be called with d_lock held */
432static inline struct dentry * __dget_locked_dlock(struct dentry *dentry) 432static inline void __dget_dlock(struct dentry *dentry)
433{ 433{
434 dentry->d_count++; 434 dentry->d_count++;
435 dentry_lru_del(dentry);
436 return dentry;
437} 435}
438 436
439/* This must be called with d_lock held */ 437static inline void __dget(struct dentry *dentry)
440static inline struct dentry * __dget_locked(struct dentry *dentry)
441{ 438{
442 spin_lock(&dentry->d_lock); 439 spin_lock(&dentry->d_lock);
443 __dget_locked_dlock(dentry); 440 __dget_dlock(dentry);
444 spin_unlock(&dentry->d_lock); 441 spin_unlock(&dentry->d_lock);
445 return dentry;
446}
447
448struct dentry * dget_locked_dlock(struct dentry *dentry)
449{
450 return __dget_locked_dlock(dentry);
451}
452
453struct dentry * dget_locked(struct dentry *dentry)
454{
455 return __dget_locked(dentry);
456} 442}
457EXPORT_SYMBOL(dget_locked);
458 443
459struct dentry *dget_parent(struct dentry *dentry) 444struct dentry *dget_parent(struct dentry *dentry)
460{ 445{
@@ -512,7 +497,7 @@ again:
512 (alias->d_flags & DCACHE_DISCONNECTED)) { 497 (alias->d_flags & DCACHE_DISCONNECTED)) {
513 discon_alias = alias; 498 discon_alias = alias;
514 } else if (!want_discon) { 499 } else if (!want_discon) {
515 __dget_locked_dlock(alias); 500 __dget_dlock(alias);
516 spin_unlock(&alias->d_lock); 501 spin_unlock(&alias->d_lock);
517 return alias; 502 return alias;
518 } 503 }
@@ -525,7 +510,7 @@ again:
525 if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) { 510 if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
526 if (IS_ROOT(alias) && 511 if (IS_ROOT(alias) &&
527 (alias->d_flags & DCACHE_DISCONNECTED)) { 512 (alias->d_flags & DCACHE_DISCONNECTED)) {
528 __dget_locked_dlock(alias); 513 __dget_dlock(alias);
529 spin_unlock(&alias->d_lock); 514 spin_unlock(&alias->d_lock);
530 return alias; 515 return alias;
531 } 516 }
@@ -561,7 +546,7 @@ restart:
561 list_for_each_entry(dentry, &inode->i_dentry, d_alias) { 546 list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
562 spin_lock(&dentry->d_lock); 547 spin_lock(&dentry->d_lock);
563 if (!dentry->d_count) { 548 if (!dentry->d_count) {
564 __dget_locked_dlock(dentry); 549 __dget_dlock(dentry);
565 __d_drop(dentry); 550 __d_drop(dentry);
566 spin_unlock(&dentry->d_lock); 551 spin_unlock(&dentry->d_lock);
567 spin_unlock(&dcache_inode_lock); 552 spin_unlock(&dcache_inode_lock);
@@ -1257,7 +1242,8 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
1257 * don't need child lock because it is not subject 1242 * don't need child lock because it is not subject
1258 * to concurrency here 1243 * to concurrency here
1259 */ 1244 */
1260 dentry->d_parent = dget_dlock(parent); 1245 __dget_dlock(parent);
1246 dentry->d_parent = parent;
1261 dentry->d_sb = parent->d_sb; 1247 dentry->d_sb = parent->d_sb;
1262 list_add(&dentry->d_u.d_child, &parent->d_subdirs); 1248 list_add(&dentry->d_u.d_child, &parent->d_subdirs);
1263 spin_unlock(&parent->d_lock); 1249 spin_unlock(&parent->d_lock);
@@ -1360,7 +1346,7 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
1360 continue; 1346 continue;
1361 if (memcmp(qstr->name, name, len)) 1347 if (memcmp(qstr->name, name, len))
1362 continue; 1348 continue;
1363 dget_locked(alias); 1349 __dget(alias);
1364 return alias; 1350 return alias;
1365 } 1351 }
1366 1352
@@ -1613,7 +1599,7 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
1613 * reference to it, move it in place and use it. 1599 * reference to it, move it in place and use it.
1614 */ 1600 */
1615 new = list_entry(inode->i_dentry.next, struct dentry, d_alias); 1601 new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
1616 dget_locked(new); 1602 __dget(new);
1617 spin_unlock(&dcache_inode_lock); 1603 spin_unlock(&dcache_inode_lock);
1618 security_d_instantiate(found, inode); 1604 security_d_instantiate(found, inode);
1619 d_move(new, found); 1605 d_move(new, found);
@@ -1789,7 +1775,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)
1789 list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) { 1775 list_for_each_entry(child, &dparent->d_subdirs, d_u.d_child) {
1790 if (dentry == child) { 1776 if (dentry == child) {
1791 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); 1777 spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
1792 __dget_locked_dlock(dentry); 1778 __dget_dlock(dentry);
1793 spin_unlock(&dentry->d_lock); 1779 spin_unlock(&dentry->d_lock);
1794 spin_unlock(&dparent->d_lock); 1780 spin_unlock(&dparent->d_lock);
1795 return 1; 1781 return 1;
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 53a5c08fb63c..f06a940065f6 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -49,7 +49,7 @@ find_acceptable_alias(struct dentry *result,
49 49
50 spin_lock(&dcache_inode_lock); 50 spin_lock(&dcache_inode_lock);
51 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) { 51 list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
52 dget_locked(dentry); 52 dget(dentry);
53 spin_unlock(&dcache_inode_lock); 53 spin_unlock(&dcache_inode_lock);
54 if (toput) 54 if (toput)
55 dput(toput); 55 dput(toput);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index de15c533311c..0ba3cdc95a44 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -397,7 +397,7 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
397 dent = list_entry(next, struct dentry, d_u.d_child); 397 dent = list_entry(next, struct dentry, d_u.d_child);
398 if ((unsigned long)dent->d_fsdata == fpos) { 398 if ((unsigned long)dent->d_fsdata == fpos) {
399 if (dent->d_inode) 399 if (dent->d_inode)
400 dget_locked(dent); 400 dget(dent);
401 else 401 else
402 dent = NULL; 402 dent = NULL;
403 spin_unlock(&parent->d_lock); 403 spin_unlock(&parent->d_lock);
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index b7de749bdd12..4d54c60ceee4 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -178,7 +178,7 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
178 mlog(0, "dentry found: %.*s\n", 178 mlog(0, "dentry found: %.*s\n",
179 dentry->d_name.len, dentry->d_name.name); 179 dentry->d_name.len, dentry->d_name.name);
180 180
181 dget_locked_dlock(dentry); 181 dget_dlock(dentry);
182 spin_unlock(&dentry->d_lock); 182 spin_unlock(&dentry->d_lock);
183 break; 183 break;
184 } 184 }
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index a2ceb94b0e38..ca648685f0cc 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -287,23 +287,17 @@ extern char *dentry_path(struct dentry *, char *, int);
287/* Allocation counts.. */ 287/* Allocation counts.. */
288 288
289/** 289/**
290 * dget, dget_locked - get a reference to a dentry 290 * dget, dget_dlock - get a reference to a dentry
291 * @dentry: dentry to get a reference to 291 * @dentry: dentry to get a reference to
292 * 292 *
293 * Given a dentry or %NULL pointer increment the reference count 293 * Given a dentry or %NULL pointer increment the reference count
294 * if appropriate and return the dentry. A dentry will not be 294 * if appropriate and return the dentry. A dentry will not be
295 * destroyed when it has references. dget() should never be 295 * destroyed when it has references.
296 * called for dentries with zero reference counter. For these cases
297 * (preferably none, functions in dcache.c are sufficient for normal
298 * needs and they take necessary precautions) you should hold d_lock
299 * and call dget_dlock() instead of dget().
300 */ 296 */
301static inline struct dentry *dget_dlock(struct dentry *dentry) 297static inline struct dentry *dget_dlock(struct dentry *dentry)
302{ 298{
303 if (dentry) { 299 if (dentry)
304 BUG_ON(!dentry->d_count);
305 dentry->d_count++; 300 dentry->d_count++;
306 }
307 return dentry; 301 return dentry;
308} 302}
309 303
@@ -317,9 +311,6 @@ static inline struct dentry *dget(struct dentry *dentry)
317 return dentry; 311 return dentry;
318} 312}
319 313
320extern struct dentry * dget_locked(struct dentry *);
321extern struct dentry * dget_locked_dlock(struct dentry *);
322
323extern struct dentry *dget_parent(struct dentry *dentry); 314extern struct dentry *dget_parent(struct dentry *dentry);
324 315
325/** 316/**
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 1864cb6a6a59..9f41470c3949 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -887,7 +887,7 @@ static void cgroup_clear_directory(struct dentry *dentry)
887 /* This should never be called on a cgroup 887 /* This should never be called on a cgroup
888 * directory with child cgroups */ 888 * directory with child cgroups */
889 BUG_ON(d->d_inode->i_mode & S_IFDIR); 889 BUG_ON(d->d_inode->i_mode & S_IFDIR);
890 dget_locked_dlock(d); 890 dget_dlock(d);
891 spin_unlock(&d->d_lock); 891 spin_unlock(&d->d_lock);
892 spin_unlock(&dentry->d_lock); 892 spin_unlock(&dentry->d_lock);
893 d_delete(d); 893 d_delete(d);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 2285d693f296..43deac219491 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1154,7 +1154,7 @@ static void sel_remove_entries(struct dentry *de)
1154 list_del_init(node); 1154 list_del_init(node);
1155 1155
1156 if (d->d_inode) { 1156 if (d->d_inode) {
1157 dget_locked_dlock(d); 1157 dget_dlock(d);
1158 spin_unlock(&de->d_lock); 1158 spin_unlock(&de->d_lock);
1159 spin_unlock(&d->d_lock); 1159 spin_unlock(&d->d_lock);
1160 d_delete(d); 1160 d_delete(d);