* Output of lfs quota has been made less detailed by default,
old (verbose) output can be obtained by using -v option.
+
Severity : normal
Bugzilla : 16907
Description: Prevent import from entering FULL state when server in recovery
old (verbose) output can be obtained by using -v option.
Severity : normal
+Bugzilla : 15975
+Frequency : only patchless client
+Description: add workaround for race between add/remove dentry from hash
+
+Severity : normal
Bugzilla : 15139
Frequency : rare
Description: avoid ASSERTION(client_stat->nid_exp_ref_count == 0) failed
#include "llite_internal.h"
+spinlock_t ll_lookup_lock = SPIN_LOCK_UNLOCKED;
+
/* should NOT be called with the dcache lock, see fs/dcache.c */
void ll_release(struct dentry *de)
{
__d_drop(dentry);
unlock_dentry(dentry);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
dput(dentry);
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
return 1;
}
inode->i_ino, inode->i_generation, inode);
head = &inode->i_dentry;
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
restart:
tmp = head;
goto restart;
}
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
+
EXIT;
}
/* unfortunately ll_intent_lock may cause a callback and revoke our
* dentry */
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
lock_dentry(de);
__d_drop(de);
unlock_dentry(de);
d_rehash_cond(de, 0);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
out:
/* We do not free request as it may be reused during following lookup
here to preserve get_cwd functionality on 2.6.
Bug 10503 */
if (!dentry->d_inode->i_nlink) {
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
ll_drop_dentry(dentry);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
}
ll_lookup_finish_locks(&oit, dentry);
return (inode->i_size + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
}
-/* llite/namei.c */
int ll_objects_destroy(struct ptlrpc_request *request, struct inode *dir);
struct inode *ll_iget(struct super_block *sb, ino_t hash,
struct lustre_md *lic);
int num_bytes);
/* llite/dcache.c */
+/* llite/namei.c */
+/**
+ * protect race ll_find_aliases vs ll_revalidate_it vs ll_unhash_aliases
+ */
+extern spinlock_t ll_lookup_lock;
extern struct dentry_operations ll_init_d_ops;
extern struct dentry_operations ll_d_ops;
extern struct dentry_operations ll_fini_d_ops;
{
struct dentry *dentry, *tmp_alias, *tmp_subdir;
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
restart:
list_for_each_entry_safe(dentry, tmp_alias,
}
}
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
}
int ll_mdc_blocking_ast(struct ldlm_lock *lock, struct ldlm_lock_desc *desc,
struct dentry *dentry;
struct dentry *last_discon = NULL;
+ spin_lock(&ll_lookup_lock);
spin_lock(&dcache_lock);
list_for_each(tmp, &inode->i_dentry) {
dentry = list_entry(tmp, struct dentry, d_alias);
unlock_dentry(dentry);
d_rehash_cond(dentry, 0); /* avoid taking dcache_lock inside */
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
iput(inode);
CDEBUG(D_DENTRY, "alias dentry %.*s (%p) parent %p inode %p "
"refc %d\n", de->d_name.len, de->d_name.name, de,
spin_unlock(&dcache_lock);
d_rehash(de);
d_move(last_discon, de);
+ spin_unlock(&ll_lookup_lock);
+
iput(inode);
return last_discon;
}
ll_d_add(de, inode);
spin_unlock(&dcache_lock);
+ spin_unlock(&ll_lookup_lock);
return de;
}