aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/dcache.c')
-rw-r--r--fs/dcache.c177
1 files changed, 88 insertions, 89 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 2398f9f94337..32ceae3e6112 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1745,13 +1745,12 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
1745 unsigned add_flags = d_flags_for_inode(inode); 1745 unsigned add_flags = d_flags_for_inode(inode);
1746 1746
1747 spin_lock(&dentry->d_lock); 1747 spin_lock(&dentry->d_lock);
1748 if (inode) 1748 hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
1749 hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
1750 raw_write_seqcount_begin(&dentry->d_seq); 1749 raw_write_seqcount_begin(&dentry->d_seq);
1751 __d_set_inode_and_type(dentry, inode, add_flags); 1750 __d_set_inode_and_type(dentry, inode, add_flags);
1752 raw_write_seqcount_end(&dentry->d_seq); 1751 raw_write_seqcount_end(&dentry->d_seq);
1752 __fsnotify_d_instantiate(dentry);
1753 spin_unlock(&dentry->d_lock); 1753 spin_unlock(&dentry->d_lock);
1754 fsnotify_d_instantiate(dentry, inode);
1755} 1754}
1756 1755
1757/** 1756/**
@@ -1772,91 +1771,16 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
1772void d_instantiate(struct dentry *entry, struct inode * inode) 1771void d_instantiate(struct dentry *entry, struct inode * inode)
1773{ 1772{
1774 BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); 1773 BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
1775 if (inode) 1774 if (inode) {
1776 spin_lock(&inode->i_lock); 1775 spin_lock(&inode->i_lock);
1777 __d_instantiate(entry, inode); 1776 __d_instantiate(entry, inode);
1778 if (inode)
1779 spin_unlock(&inode->i_lock); 1777 spin_unlock(&inode->i_lock);
1778 }
1780 security_d_instantiate(entry, inode); 1779 security_d_instantiate(entry, inode);
1781} 1780}
1782EXPORT_SYMBOL(d_instantiate); 1781EXPORT_SYMBOL(d_instantiate);
1783 1782
1784/** 1783/**
1785 * d_instantiate_unique - instantiate a non-aliased dentry
1786 * @entry: dentry to instantiate
1787 * @inode: inode to attach to this dentry
1788 *
1789 * Fill in inode information in the entry. On success, it returns NULL.
1790 * If an unhashed alias of "entry" already exists, then we return the
1791 * aliased dentry instead and drop one reference to inode.
1792 *
1793 * Note that in order to avoid conflicts with rename() etc, the caller
1794 * had better be holding the parent directory semaphore.
1795 *
1796 * This also assumes that the inode count has been incremented
1797 * (or otherwise set) by the caller to indicate that it is now
1798 * in use by the dcache.
1799 */
1800static struct dentry *__d_instantiate_unique(struct dentry *entry,
1801 struct inode *inode)
1802{
1803 struct dentry *alias;
1804 int len = entry->d_name.len;
1805 const char *name = entry->d_name.name;
1806 unsigned int hash = entry->d_name.hash;
1807
1808 if (!inode) {
1809 __d_instantiate(entry, NULL);
1810 return NULL;
1811 }
1812
1813 hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
1814 /*
1815 * Don't need alias->d_lock here, because aliases with
1816 * d_parent == entry->d_parent are not subject to name or
1817 * parent changes, because the parent inode i_mutex is held.
1818 */
1819 if (alias->d_name.hash != hash)
1820 continue;
1821 if (alias->d_parent != entry->d_parent)
1822 continue;
1823 if (alias->d_name.len != len)
1824 continue;
1825 if (dentry_cmp(alias, name, len))
1826 continue;
1827 __dget(alias);
1828 return alias;
1829 }
1830
1831 __d_instantiate(entry, inode);
1832 return NULL;
1833}
1834
1835struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
1836{
1837 struct dentry *result;
1838
1839 BUG_ON(!hlist_unhashed(&entry->d_u.d_alias));
1840
1841 if (inode)
1842 spin_lock(&inode->i_lock);
1843 result = __d_instantiate_unique(entry, inode);
1844 if (inode)
1845 spin_unlock(&inode->i_lock);
1846
1847 if (!result) {
1848 security_d_instantiate(entry, inode);
1849 return NULL;
1850 }
1851
1852 BUG_ON(!d_unhashed(result));
1853 iput(inode);
1854 return result;
1855}
1856
1857EXPORT_SYMBOL(d_instantiate_unique);
1858
1859/**
1860 * d_instantiate_no_diralias - instantiate a non-aliased dentry 1784 * d_instantiate_no_diralias - instantiate a non-aliased dentry
1861 * @entry: dentry to complete 1785 * @entry: dentry to complete
1862 * @inode: inode to attach to this dentry 1786 * @inode: inode to attach to this dentry
@@ -2436,6 +2360,86 @@ void d_rehash(struct dentry * entry)
2436} 2360}
2437EXPORT_SYMBOL(d_rehash); 2361EXPORT_SYMBOL(d_rehash);
2438 2362
2363
2364/* inode->i_lock held if inode is non-NULL */
2365
2366static inline void __d_add(struct dentry *dentry, struct inode *inode)
2367{
2368 if (inode) {
2369 __d_instantiate(dentry, inode);
2370 spin_unlock(&inode->i_lock);
2371 }
2372 security_d_instantiate(dentry, inode);
2373 d_rehash(dentry);
2374}
2375
2376/**
2377 * d_add - add dentry to hash queues
2378 * @entry: dentry to add
2379 * @inode: The inode to attach to this dentry
2380 *
2381 * This adds the entry to the hash queues and initializes @inode.
2382 * The entry was actually filled in earlier during d_alloc().
2383 */
2384
2385void d_add(struct dentry *entry, struct inode *inode)
2386{
2387 if (inode)
2388 spin_lock(&inode->i_lock);
2389 __d_add(entry, inode);
2390}
2391EXPORT_SYMBOL(d_add);
2392
2393/**
2394 * d_exact_alias - find and hash an exact unhashed alias
2395 * @entry: dentry to add
2396 * @inode: The inode to go with this dentry
2397 *
2398 * If an unhashed dentry with the same name/parent and desired
2399 * inode already exists, hash and return it. Otherwise, return
2400 * NULL.
2401 *
2402 * Parent directory should be locked.
2403 */
2404struct dentry *d_exact_alias(struct dentry *entry, struct inode *inode)
2405{
2406 struct dentry *alias;
2407 int len = entry->d_name.len;
2408 const char *name = entry->d_name.name;
2409 unsigned int hash = entry->d_name.hash;
2410
2411 spin_lock(&inode->i_lock);
2412 hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
2413 /*
2414 * Don't need alias->d_lock here, because aliases with
2415 * d_parent == entry->d_parent are not subject to name or
2416 * parent changes, because the parent inode i_mutex is held.
2417 */
2418 if (alias->d_name.hash != hash)
2419 continue;
2420 if (alias->d_parent != entry->d_parent)
2421 continue;
2422 if (alias->d_name.len != len)
2423 continue;
2424 if (dentry_cmp(alias, name, len))
2425 continue;
2426 spin_lock(&alias->d_lock);
2427 if (!d_unhashed(alias)) {
2428 spin_unlock(&alias->d_lock);
2429 alias = NULL;
2430 } else {
2431 __dget_dlock(alias);
2432 _d_rehash(alias);
2433 spin_unlock(&alias->d_lock);
2434 }
2435 spin_unlock(&inode->i_lock);
2436 return alias;
2437 }
2438 spin_unlock(&inode->i_lock);
2439 return NULL;
2440}
2441EXPORT_SYMBOL(d_exact_alias);
2442
2439/** 2443/**
2440 * dentry_update_name_case - update case insensitive dentry with a new name 2444 * dentry_update_name_case - update case insensitive dentry with a new name
2441 * @dentry: dentry to be updated 2445 * @dentry: dentry to be updated
@@ -2772,10 +2776,9 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
2772 2776
2773 BUG_ON(!d_unhashed(dentry)); 2777 BUG_ON(!d_unhashed(dentry));
2774 2778
2775 if (!inode) { 2779 if (!inode)
2776 __d_instantiate(dentry, NULL);
2777 goto out; 2780 goto out;
2778 } 2781
2779 spin_lock(&inode->i_lock); 2782 spin_lock(&inode->i_lock);
2780 if (S_ISDIR(inode->i_mode)) { 2783 if (S_ISDIR(inode->i_mode)) {
2781 struct dentry *new = __d_find_any_alias(inode); 2784 struct dentry *new = __d_find_any_alias(inode);
@@ -2809,12 +2812,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
2809 return new; 2812 return new;
2810 } 2813 }
2811 } 2814 }
2812 /* already taking inode->i_lock, so d_add() by hand */
2813 __d_instantiate(dentry, inode);
2814 spin_unlock(&inode->i_lock);
2815out: 2815out:
2816 security_d_instantiate(dentry, inode); 2816 __d_add(dentry, inode);
2817 d_rehash(dentry);
2818 return NULL; 2817 return NULL;
2819} 2818}
2820EXPORT_SYMBOL(d_splice_alias); 2819EXPORT_SYMBOL(d_splice_alias);