aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c34
-rw-r--r--fs/namei.c49
-rw-r--r--include/linux/dcache.h7
3 files changed, 88 insertions, 2 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 6e4ea6d87774..d3902139b533 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -344,6 +344,24 @@ void d_drop(struct dentry *dentry)
344EXPORT_SYMBOL(d_drop); 344EXPORT_SYMBOL(d_drop);
345 345
346/* 346/*
347 * d_clear_need_lookup - drop a dentry from cache and clear the need lookup flag
348 * @dentry: dentry to drop
349 *
350 * This is called when we do a lookup on a placeholder dentry that needed to be
351 * looked up. The dentry should have been hashed in order for it to be found by
352 * the lookup code, but now needs to be unhashed while we do the actual lookup
353 * and clear the DCACHE_NEED_LOOKUP flag.
354 */
355void d_clear_need_lookup(struct dentry *dentry)
356{
357 spin_lock(&dentry->d_lock);
358 __d_drop(dentry);
359 dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
360 spin_unlock(&dentry->d_lock);
361}
362EXPORT_SYMBOL(d_clear_need_lookup);
363
364/*
347 * Finish off a dentry we've decided to kill. 365 * Finish off a dentry we've decided to kill.
348 * dentry->d_lock must be held, returns with it unlocked. 366 * dentry->d_lock must be held, returns with it unlocked.
349 * If ref is non-zero, then decrement the refcount too. 367 * If ref is non-zero, then decrement the refcount too.
@@ -432,8 +450,13 @@ repeat:
432 if (d_unhashed(dentry)) 450 if (d_unhashed(dentry))
433 goto kill_it; 451 goto kill_it;
434 452
435 /* Otherwise leave it cached and ensure it's on the LRU */ 453 /*
436 dentry->d_flags |= DCACHE_REFERENCED; 454 * If this dentry needs lookup, don't set the referenced flag so that it
455 * is more likely to be cleaned up by the dcache shrinker in case of
456 * memory pressure.
457 */
458 if (!d_need_lookup(dentry))
459 dentry->d_flags |= DCACHE_REFERENCED;
437 dentry_lru_add(dentry); 460 dentry_lru_add(dentry);
438 461
439 dentry->d_count--; 462 dentry->d_count--;
@@ -1708,6 +1731,13 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
1708 } 1731 }
1709 1732
1710 /* 1733 /*
1734 * We are going to instantiate this dentry, unhash it and clear the
1735 * lookup flag so we can do that.
1736 */
1737 if (unlikely(d_need_lookup(found)))
1738 d_clear_need_lookup(found);
1739
1740 /*
1711 * Negative dentry: instantiate it unless the inode is a directory and 1741 * Negative dentry: instantiate it unless the inode is a directory and
1712 * already has a dentry. 1742 * already has a dentry.
1713 */ 1743 */
diff --git a/fs/namei.c b/fs/namei.c
index 14ab8d3f2f0c..5ba42c453e31 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1134,6 +1134,30 @@ static struct dentry *d_alloc_and_lookup(struct dentry *parent,
1134} 1134}
1135 1135
1136/* 1136/*
1137 * We already have a dentry, but require a lookup to be performed on the parent
1138 * directory to fill in d_inode. Returns the new dentry, or ERR_PTR on error.
1139 * parent->d_inode->i_mutex must be held. d_lookup must have verified that no
1140 * child exists while under i_mutex.
1141 */
1142static struct dentry *d_inode_lookup(struct dentry *parent, struct dentry *dentry,
1143 struct nameidata *nd)
1144{
1145 struct inode *inode = parent->d_inode;
1146 struct dentry *old;
1147
1148 /* Don't create child dentry for a dead directory. */
1149 if (unlikely(IS_DEADDIR(inode)))
1150 return ERR_PTR(-ENOENT);
1151
1152 old = inode->i_op->lookup(inode, dentry, nd);
1153 if (unlikely(old)) {
1154 dput(dentry);
1155 dentry = old;
1156 }
1157 return dentry;
1158}
1159
1160/*
1137 * It's more convoluted than I'd like it to be, but... it's still fairly 1161 * It's more convoluted than I'd like it to be, but... it's still fairly
1138 * small and for now I'd prefer to have fast path as straight as possible. 1162 * small and for now I'd prefer to have fast path as straight as possible.
1139 * It _is_ time-critical. 1163 * It _is_ time-critical.
@@ -1172,6 +1196,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
1172 goto unlazy; 1196 goto unlazy;
1173 } 1197 }
1174 } 1198 }
1199 if (unlikely(d_need_lookup(dentry)))
1200 goto unlazy;
1175 path->mnt = mnt; 1201 path->mnt = mnt;
1176 path->dentry = dentry; 1202 path->dentry = dentry;
1177 if (unlikely(!__follow_mount_rcu(nd, path, inode))) 1203 if (unlikely(!__follow_mount_rcu(nd, path, inode)))
@@ -1186,6 +1212,10 @@ unlazy:
1186 dentry = __d_lookup(parent, name); 1212 dentry = __d_lookup(parent, name);
1187 } 1213 }
1188 1214
1215 if (dentry && unlikely(d_need_lookup(dentry))) {
1216 dput(dentry);
1217 dentry = NULL;
1218 }
1189retry: 1219retry:
1190 if (unlikely(!dentry)) { 1220 if (unlikely(!dentry)) {
1191 struct inode *dir = parent->d_inode; 1221 struct inode *dir = parent->d_inode;
@@ -1202,6 +1232,15 @@ retry:
1202 /* known good */ 1232 /* known good */
1203 need_reval = 0; 1233 need_reval = 0;
1204 status = 1; 1234 status = 1;
1235 } else if (unlikely(d_need_lookup(dentry))) {
1236 dentry = d_inode_lookup(parent, dentry, nd);
1237 if (IS_ERR(dentry)) {
1238 mutex_unlock(&dir->i_mutex);
1239 return PTR_ERR(dentry);
1240 }
1241 /* known good */
1242 need_reval = 0;
1243 status = 1;
1205 } 1244 }
1206 mutex_unlock(&dir->i_mutex); 1245 mutex_unlock(&dir->i_mutex);
1207 } 1246 }
@@ -1683,6 +1722,16 @@ static struct dentry *__lookup_hash(struct qstr *name,
1683 */ 1722 */
1684 dentry = d_lookup(base, name); 1723 dentry = d_lookup(base, name);
1685 1724
1725 if (dentry && d_need_lookup(dentry)) {
1726 /*
1727 * __lookup_hash is called with the parent dir's i_mutex already
1728 * held, so we are good to go here.
1729 */
1730 dentry = d_inode_lookup(base, dentry, nd);
1731 if (IS_ERR(dentry))
1732 return dentry;
1733 }
1734
1686 if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE)) 1735 if (dentry && (dentry->d_flags & DCACHE_OP_REVALIDATE))
1687 dentry = do_revalidate(dentry, nd); 1736 dentry = do_revalidate(dentry, nd);
1688 1737
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 19d90a55541d..5fa5bd33b979 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -216,6 +216,7 @@ struct dentry_operations {
216#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */ 216#define DCACHE_MOUNTED 0x10000 /* is a mountpoint */
217#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */ 217#define DCACHE_NEED_AUTOMOUNT 0x20000 /* handle automount on this dir */
218#define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */ 218#define DCACHE_MANAGE_TRANSIT 0x40000 /* manage transit from this dirent */
219#define DCACHE_NEED_LOOKUP 0x80000 /* dentry requires i_op->lookup */
219#define DCACHE_MANAGED_DENTRY \ 220#define DCACHE_MANAGED_DENTRY \
220 (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) 221 (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
221 222
@@ -416,6 +417,12 @@ static inline bool d_mountpoint(struct dentry *dentry)
416 return dentry->d_flags & DCACHE_MOUNTED; 417 return dentry->d_flags & DCACHE_MOUNTED;
417} 418}
418 419
420static inline bool d_need_lookup(struct dentry *dentry)
421{
422 return dentry->d_flags & DCACHE_NEED_LOOKUP;
423}
424
425extern void d_clear_need_lookup(struct dentry *dentry);
419extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); 426extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
420 427
421extern int sysctl_vfs_cache_pressure; 428extern int sysctl_vfs_cache_pressure;