aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/dcache.c108
-rw-r--r--include/linux/dcache.h1
2 files changed, 37 insertions, 72 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index d45ff7f5ecc2..1710d2484fd9 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1111,70 +1111,6 @@ static inline struct hlist_head *d_hash(struct dentry *parent,
1111} 1111}
1112 1112
1113/** 1113/**
1114 * d_alloc_anon - allocate an anonymous dentry
1115 * @inode: inode to allocate the dentry for
1116 *
1117 * This is similar to d_alloc_root. It is used by filesystems when
1118 * creating a dentry for a given inode, often in the process of
1119 * mapping a filehandle to a dentry. The returned dentry may be
1120 * anonymous, or may have a full name (if the inode was already
1121 * in the cache). The file system may need to make further
1122 * efforts to connect this dentry into the dcache properly.
1123 *
1124 * When called on a directory inode, we must ensure that
1125 * the inode only ever has one dentry. If a dentry is
1126 * found, that is returned instead of allocating a new one.
1127 *
1128 * On successful return, the reference to the inode has been transferred
1129 * to the dentry. If %NULL is returned (indicating kmalloc failure),
1130 * the reference on the inode has not been released.
1131 */
1132
1133struct dentry * d_alloc_anon(struct inode *inode)
1134{
1135 static const struct qstr anonstring = { .name = "" };
1136 struct dentry *tmp;
1137 struct dentry *res;
1138
1139 if ((res = d_find_alias(inode))) {
1140 iput(inode);
1141 return res;
1142 }
1143
1144 tmp = d_alloc(NULL, &anonstring);
1145 if (!tmp)
1146 return NULL;
1147
1148 tmp->d_parent = tmp; /* make sure dput doesn't croak */
1149
1150 spin_lock(&dcache_lock);
1151 res = __d_find_alias(inode, 0);
1152 if (!res) {
1153 /* attach a disconnected dentry */
1154 res = tmp;
1155 tmp = NULL;
1156 spin_lock(&res->d_lock);
1157 res->d_sb = inode->i_sb;
1158 res->d_parent = res;
1159 res->d_inode = inode;
1160 res->d_flags |= DCACHE_DISCONNECTED;
1161 res->d_flags &= ~DCACHE_UNHASHED;
1162 list_add(&res->d_alias, &inode->i_dentry);
1163 hlist_add_head(&res->d_hash, &inode->i_sb->s_anon);
1164 spin_unlock(&res->d_lock);
1165
1166 inode = NULL; /* don't drop reference */
1167 }
1168 spin_unlock(&dcache_lock);
1169
1170 if (inode)
1171 iput(inode);
1172 if (tmp)
1173 dput(tmp);
1174 return res;
1175}
1176
1177/**
1178 * d_obtain_alias - find or allocate a dentry for a given inode 1114 * d_obtain_alias - find or allocate a dentry for a given inode
1179 * @inode: inode to allocate the dentry for 1115 * @inode: inode to allocate the dentry for
1180 * 1116 *
@@ -1194,19 +1130,50 @@ struct dentry * d_alloc_anon(struct inode *inode)
1194 */ 1130 */
1195struct dentry *d_obtain_alias(struct inode *inode) 1131struct dentry *d_obtain_alias(struct inode *inode)
1196{ 1132{
1197 struct dentry *dentry; 1133 static const struct qstr anonstring = { .name = "" };
1134 struct dentry *tmp;
1135 struct dentry *res;
1198 1136
1199 if (!inode) 1137 if (!inode)
1200 return ERR_PTR(-ESTALE); 1138 return ERR_PTR(-ESTALE);
1201 if (IS_ERR(inode)) 1139 if (IS_ERR(inode))
1202 return ERR_CAST(inode); 1140 return ERR_CAST(inode);
1203 1141
1204 dentry = d_alloc_anon(inode); 1142 res = d_find_alias(inode);
1205 if (!dentry) { 1143 if (res)
1206 iput(inode); 1144 goto out_iput;
1207 dentry = ERR_PTR(-ENOMEM); 1145
1146 tmp = d_alloc(NULL, &anonstring);
1147 if (!tmp) {
1148 res = ERR_PTR(-ENOMEM);
1149 goto out_iput;
1208 } 1150 }
1209 return dentry; 1151 tmp->d_parent = tmp; /* make sure dput doesn't croak */
1152
1153 spin_lock(&dcache_lock);
1154 res = __d_find_alias(inode, 0);
1155 if (res) {
1156 spin_unlock(&dcache_lock);
1157 dput(tmp);
1158 goto out_iput;
1159 }
1160
1161 /* attach a disconnected dentry */
1162 spin_lock(&tmp->d_lock);
1163 tmp->d_sb = inode->i_sb;
1164 tmp->d_inode = inode;
1165 tmp->d_flags |= DCACHE_DISCONNECTED;
1166 tmp->d_flags &= ~DCACHE_UNHASHED;
1167 list_add(&tmp->d_alias, &inode->i_dentry);
1168 hlist_add_head(&tmp->d_hash, &inode->i_sb->s_anon);
1169 spin_unlock(&tmp->d_lock);
1170
1171 spin_unlock(&dcache_lock);
1172 return tmp;
1173
1174 out_iput:
1175 iput(inode);
1176 return res;
1210} 1177}
1211EXPORT_SYMBOL_GPL(d_obtain_alias); 1178EXPORT_SYMBOL_GPL(d_obtain_alias);
1212 1179
@@ -2379,7 +2346,6 @@ void __init vfs_caches_init(unsigned long mempages)
2379} 2346}
2380 2347
2381EXPORT_SYMBOL(d_alloc); 2348EXPORT_SYMBOL(d_alloc);
2382EXPORT_SYMBOL(d_alloc_anon);
2383EXPORT_SYMBOL(d_alloc_root); 2349EXPORT_SYMBOL(d_alloc_root);
2384EXPORT_SYMBOL(d_delete); 2350EXPORT_SYMBOL(d_delete);
2385EXPORT_SYMBOL(d_find_alias); 2351EXPORT_SYMBOL(d_find_alias);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 2404257d6c67..74c64ae30cf0 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -228,7 +228,6 @@ extern void d_delete(struct dentry *);
228 228
229/* allocate/de-allocate */ 229/* allocate/de-allocate */
230extern struct dentry * d_alloc(struct dentry *, const struct qstr *); 230extern struct dentry * d_alloc(struct dentry *, const struct qstr *);
231extern struct dentry * d_alloc_anon(struct inode *);
232extern struct dentry * d_splice_alias(struct inode *, struct dentry *); 231extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
233extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *); 232extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qstr *);
234extern struct dentry * d_obtain_alias(struct inode *); 233extern struct dentry * d_obtain_alias(struct inode *);