hash = fd->fd_dir.lfd_next;
} else {
- struct ll_inode_info *lli = ll_i2info(inode);
-
- cfs_spin_lock(&lli->lli_sa_lock);
- if (lli->lli_sai)
- LASSERT(lli->lli_sai->sai_pid == cfs_curproc_pid());
- else
- LASSERT(lli->lli_opendir_pid == cfs_curproc_pid());
- hash = lli->lli_sa_pos;
- cfs_spin_unlock(&lli->lli_sa_lock);
+ hash = ll_i2info(inode)->lli_sa_pos;
}
CDEBUG(D_VFSTRACE, "VFS Op:inode=%lu/%u(%p) hash "LPU64"\n",
inode->i_ino, inode->i_generation, inode, hash);
SetPageChecked(page);
}
-static void ll_release_page(struct page *page, __u64 hash,
- __u64 start, __u64 end)
+void ll_release_page(struct page *page, int remove)
{
kunmap(page);
- lock_page(page);
- if (likely(page->mapping != NULL)) {
- ll_truncate_complete_page(page);
- unlock_page(page);
- } else {
+ if (remove) {
+ lock_page(page);
+ if (likely(page->mapping != NULL))
+ ll_truncate_complete_page(page);
unlock_page(page);
- CWARN("NULL mapping page %p, truncated by others: "
- "hash("LPX64") | start("LPX64") | end("LPX64")\n",
- page, hash, start, end);
}
page_cache_release(page);
}
LPX64",hash = "LPX64"\n", *start, *end, *hash);
CDEBUG(D_VFSTRACE, "page %lu [%llu %llu], hash "LPU64"\n",
offset, *start, *end, *hash);
- if (*hash > *end || (*end != *start && *hash == *end)) {
+ if (*hash > *end) {
+ ll_release_page(page, 0);
+ page = NULL;
+ } else if (*end != *start && *hash == *end) {
/*
* upon hash collision, remove this page,
* otherwise put page reference, and
* ll_get_dir_page() will issue RPC to fetch
* the page we want.
*/
- if (dp->ldp_flags & cpu_to_le32(LDF_COLLIDE)) {
- ll_release_page(page, *hash, *start, *end);
- } else {
- cfs_kunmap(page);
- page_cache_release(page);
- }
+ ll_release_page(page,
+ le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
page = NULL;
}
} else {
}
struct page *ll_get_dir_page(struct file *filp, struct inode *dir, __u64 hash,
- int exact, struct ll_dir_chain *chain)
+ struct ll_dir_chain *chain)
{
ldlm_policy_data_t policy = {.l_inodebits = {MDS_INODELOCK_UPDATE} };
struct address_space *mapping = dir->i_mapping;
CERROR("dir page locate: "DFID" at "LPU64": rc %ld\n",
PFID(ll_inode2fid(dir)), lhash, PTR_ERR(page));
GOTO(out_unlock, page);
- }
-
- if (page != NULL) {
+ } else if (page != NULL) {
/*
* XXX nikita: not entirely correct handling of a corner case:
* suppose hash chain of entries with hash value HASH crosses
* it as an "overflow" page. 1. invalidate all pages at
* once. 2. use HASH|1 as an index for P1.
*/
- if (exact && lhash != start) {
- /*
- * readdir asked for a page starting _exactly_ from
- * given hash, but cache contains stale page, with
- * entries with smaller hash values. Stale page should
- * be invalidated, and new one fetched.
- */
- CDEBUG(D_OTHER, "Stale readpage page %p: "
- "start = "LPX64",end = "LPX64"hash ="LPX64"\n",
- page, start, end, lhash);
- ll_release_page(page, lhash, start, end);
- } else {
- GOTO(hash_collision, page);
- }
+ GOTO(hash_collision, page);
}
page = read_cache_page(mapping, hash_x_index(hash, hash64),
return page;
fail:
- ll_put_page(page);
+ ll_release_page(page, 1);
page = ERR_PTR(-EIO);
goto out_unlock;
}
ll_dir_chain_init(&chain);
fd->fd_dir.lfd_next = pos;
- page = ll_get_dir_page(filp, inode, pos, 0, &chain);
+ page = ll_get_dir_page(filp, inode, pos, &chain);
while (rc == 0 && !done) {
struct lu_dirpage *dp;
lhash, ino, type);
}
next = le64_to_cpu(dp->ldp_hash_end);
- ll_put_page(page);
if (!done) {
pos = next;
if (pos == MDS_DIR_END_OFF) {
* End of directory reached.
*/
done = 1;
+ ll_release_page(page, 0);
} else if (1 /* chain is exhausted*/) {
/*
* Normal case: continue to the next
* page.
*/
+ ll_release_page(page,
+ le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
fd->fd_dir.lfd_next = pos;
page = ll_get_dir_page(filp, inode, pos,
- 1, &chain);
+ &chain);
} else {
/*
* go into overflow page.
*/
+ LASSERT(le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
+ ll_release_page(page, 1);
}
} else {
pos = hash;
+ ll_release_page(page, 0);
}
} else {
rc = PTR_ERR(page);
/* for struct cl_lock_descr and struct cl_io */
#include <cl_object.h>
#include <lclient.h>
+#include <lustre_mdc.h>
#ifndef FMODE_EXEC
#define FMODE_EXEC 0
/* llite/dir.c */
-static inline void ll_put_page(struct page *page)
-{
- kunmap(page);
- page_cache_release(page);
-}
-
+void ll_release_page(struct page *page, int remove);
extern struct file_operations ll_dir_operations;
extern struct inode_operations ll_dir_inode_operations;
struct page *ll_get_dir_page(struct file *filp, struct inode *dir, __u64 hash,
- int exact, struct ll_dir_chain *chain);
+ struct ll_dir_chain *chain);
int ll_readdir(struct file *filp, void *cookie, filldir_t filldir);
int ll_get_mdt_idx(struct inode *inode);
int ll_fid2path(struct obd_export *exp, void *arg);
/* llite/dcache.c */
-/* llite/namei.c */
-/**
- * protect race ll_find_aliases vs ll_revalidate_it vs ll_unhash_aliases
- */
int ll_dops_init(struct dentry *de, int block, int init_sa);
extern cfs_spinlock_t ll_lookup_lock;
extern struct dentry_operations ll_d_ops;
void ll_intent_drop_lock(struct lookup_intent *);
void ll_intent_release(struct lookup_intent *);
int ll_drop_dentry(struct dentry *dentry);
-int ll_drop_dentry(struct dentry *dentry);
void ll_unhash_aliases(struct inode *);
void ll_frob_intent(struct lookup_intent **itp, struct lookup_intent *deft);
void ll_lookup_finish_locks(struct lookup_intent *it, struct dentry *dentry);
cfs_list_t sai_entries_sent; /* entries sent out */
cfs_list_t sai_entries_received; /* entries returned */
cfs_list_t sai_entries_stated; /* entries stated */
- pid_t sai_pid; /* pid of statahead itself */
};
int do_statahead_enter(struct inode *dir, struct dentry **dentry, int lookup);
cfs_waitq_signal(&thread->t_ctl_waitq);
CDEBUG(D_READA, "start doing statahead for %s\n", parent->d_name.name);
- sai->sai_pid = cfs_curproc_pid();
lli->lli_sa_pos = 0;
ll_dir_chain_init(&chain);
- page = ll_get_dir_page(NULL, dir, pos, 0, &chain);
+ page = ll_get_dir_page(NULL, dir, pos, &chain);
while (1) {
struct l_wait_info lwi = { 0 };
do_statahead_interpret(sai);
if (unlikely(!sa_is_running(sai))) {
- ll_put_page(page);
+ ll_release_page(page, 0);
GOTO(out, rc);
}
rc = ll_statahead_one(parent, name, namelen);
if (rc < 0) {
- ll_put_page(page);
+ ll_release_page(page, 0);
GOTO(out, rc);
}
}
pos = le64_to_cpu(dp->ldp_hash_end);
- ll_put_page(page);
if (pos == MDS_DIR_END_OFF) {
/*
* End of directory reached.
*/
+ ll_release_page(page, 0);
while (1) {
l_wait_event(thread->t_ctl_waitq,
!sa_is_running(sai) ||
* chain is exhausted.
* Normal case: continue to the next page.
*/
+ ll_release_page(page, le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
lli->lli_sa_pos = pos;
- page = ll_get_dir_page(NULL, dir, pos, 1, &chain);
+ page = ll_get_dir_page(NULL, dir, pos, &chain);
} else {
+ LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
+ ll_release_page(page, 1);
/*
* go into overflow page.
*/
lli->lli_sa_pos = 0;
ll_dir_chain_init(&chain);
- page = ll_get_dir_page(NULL, dir, pos, 0, &chain);
+ page = ll_get_dir_page(NULL, dir, pos, &chain);
while (1) {
struct lu_dirpage *dp;
else
rc = LS_FIRST_DOT_DE;
- ll_put_page(page);
+ ll_release_page(page, 0);
GOTO(out, rc);
}
pos = le64_to_cpu(dp->ldp_hash_end);
- ll_put_page(page);
if (pos == MDS_DIR_END_OFF) {
/*
* End of directory reached.
*/
+ ll_release_page(page, 0);
break;
} else if (1) {
/*
* chain is exhausted
* Normal case: continue to the next page.
*/
+ ll_release_page(page, le32_to_cpu(dp->ldp_flags) &
+ LDF_COLLIDE);
lli->lli_sa_pos = pos;
- page = ll_get_dir_page(NULL, dir, pos, 1, &chain);
+ page = ll_get_dir_page(NULL, dir, pos, &chain);
} else {
/*
* go into overflow page.
*/
+ LASSERT(le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
+ ll_release_page(page, 1);
}
}
EXIT;