CLI_RM_ENTRY = 1 << 1,
CLI_HASH64 = 1 << 2,
CLI_API32 = 1 << 3,
- CLI_READENT_END = 1 << 4,
};
#endif /*LCLIENT_H */
struct page **, struct ptlrpc_request **);
int (*m_read_entry)(struct obd_export *, struct md_op_data *,
- struct md_callback *cb_op, struct lu_dirent **ld);
+ struct md_callback *cb_op, struct lu_dirent **ld,
+ struct page **ppage);
int (*m_unlink)(struct obd_export *, struct md_op_data *,
struct ptlrpc_request **);
static inline int md_read_entry(struct obd_export *exp,
struct md_op_data *op_data,
struct md_callback *cb_op,
- struct lu_dirent **ld)
+ struct lu_dirent **ld,
+ struct page **ppage)
{
int rc;
ENTRY;
EXP_CHECK_MD_OP(exp, read_entry);
EXP_MD_COUNTER_INCREMENT(exp, read_entry);
- rc = MDP(exp->exp_obd, read_entry)(exp, op_data, cb_op, ld);
+ rc = MDP(exp->exp_obd, read_entry)(exp, op_data, cb_op, ld, ppage);
RETURN(rc);
}
* ll_dir_entry_end: release the last page.
**/
struct lu_dirent *ll_dir_entry_start(struct inode *dir,
- struct md_op_data *op_data)
+ struct md_op_data *op_data,
+ struct page **ppage)
{
struct lu_dirent *entry;
struct md_callback cb_op;
int rc;
+ LASSERT(*ppage == NULL);
cb_op.md_blocking_ast = ll_md_blocking_ast;
- rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry);
+ rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry, ppage);
if (rc != 0)
entry = ERR_PTR(rc);
return entry;
struct lu_dirent *ll_dir_entry_next(struct inode *dir,
struct md_op_data *op_data,
- struct lu_dirent *ent)
+ struct lu_dirent *ent,
+ struct page **ppage)
{
struct lu_dirent *entry;
struct md_callback cb_op;
int rc;
+ LASSERT(*ppage != NULL);
cb_op.md_blocking_ast = ll_md_blocking_ast;
op_data->op_hash_offset = le64_to_cpu(ent->lde_hash);
- rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry);
+ kunmap(*ppage);
+ page_cache_release(*ppage);
+ *ppage = NULL;
+ rc = md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry, ppage);
if (rc != 0)
entry = ERR_PTR(rc);
return entry;
}
-void ll_dir_entry_end(struct inode *dir, struct md_op_data *op_data,
- struct lu_dirent *ent)
-{
- struct lu_dirent *entry;
- struct md_callback cb_op;
-
- cb_op.md_blocking_ast = ll_md_blocking_ast;
- op_data->op_cli_flags = CLI_READENT_END;
- md_read_entry(ll_i2mdexp(dir), op_data, &cb_op, &entry);
- return;
-}
-
int ll_dir_read(struct inode *inode, struct md_op_data *op_data,
void *cookie, filldir_t filldir)
{
int rc = 0;
__u64 hash = MDS_DIR_END_OFF;
__u64 last_hash = MDS_DIR_END_OFF;
+ struct page *page = NULL;
ENTRY;
ll_dir_chain_init(&chain);
- for (ent = ll_dir_entry_start(inode, op_data);
+ for (ent = ll_dir_entry_start(inode, op_data, &page);
ent != NULL && !IS_ERR(ent) && !done;
- ent = ll_dir_entry_next(inode, op_data, ent)) {
+ ent = ll_dir_entry_next(inode, op_data, ent, &page)) {
__u16 type;
int namelen;
struct lu_fid fid;
if (IS_ERR(ent))
rc = PTR_ERR(ent);
- else if (ent != NULL)
- ll_dir_entry_end(inode, op_data, ent);
+
+ if (page != NULL) {
+ kunmap(page);
+ page_cache_release(page);
+ }
ll_dir_chain_fini(&chain);
RETURN(rc);
int ll_get_mdt_idx(struct inode *inode);
struct lu_dirent *ll_dir_entry_start(struct inode *dir,
- struct md_op_data *op_data);
+ struct md_op_data *op_data,
+ struct page **ppage);
struct lu_dirent *ll_dir_entry_next(struct inode *dir,
struct md_op_data *op_data,
- struct lu_dirent *ent);
-void ll_dir_entry_end(struct inode *dir, struct md_op_data *op_data,
- struct lu_dirent *ent);
+ struct lu_dirent *ent,
+ struct page **ppage);
/* llite/namei.c */
int ll_objects_destroy(struct ptlrpc_request *request,
struct inode *dir);
struct ll_dir_chain chain;
struct l_wait_info lwi = { 0 };
struct lu_dirent *ent;
+ struct page *page = NULL;
ENTRY;
CDEBUG(D_READA, "statahead thread started: [pid %d] [parent %.*s]\n",
wake_up(&thread->t_ctl_waitq);
ll_dir_chain_init(&chain);
- for (ent = ll_dir_entry_start(dir, op_data);
+ for (ent = ll_dir_entry_start(dir, op_data, &page);
ent != NULL && !IS_ERR(ent);
- ent = ll_dir_entry_next(dir, op_data, ent)) {
+ ent = ll_dir_entry_next(dir, op_data, ent, &page)) {
__u64 hash;
int namelen;
char *name;
ll_statahead_one(parent, name, namelen);
}
- if (ent != NULL && !IS_ERR(ent))
- ll_dir_entry_end(dir, op_data, ent);
+ if (page != NULL) {
+ kunmap(page);
+ page_cache_release(page);
+ }
/*
* End of directory reached.
struct md_op_data *op_data;
int dot_de;
struct lu_dirent *ent;
+ struct page *page = NULL;
int rc = LS_NONE_FIRST_DE;
ENTRY;
op_data->op_max_pages =
ll_i2sbi(dir)->ll_md_brw_size >> PAGE_CACHE_SHIFT;
- for (ent = ll_dir_entry_start(dir, op_data);
+ for (ent = ll_dir_entry_start(dir, op_data, &page);
ent != NULL && !IS_ERR(ent);
- ent = ll_dir_entry_next(dir, op_data, ent)) {
+ ent = ll_dir_entry_next(dir, op_data, ent, &page)) {
__u64 hash;
int namelen;
char *name;
break;
}
EXIT;
- if (ent != NULL && !IS_ERR(ent))
- ll_dir_entry_end(dir, op_data, ent);
+
+ if (page != NULL) {
+ kunmap(page);
+ page_cache_release(page);
+ }
ll_finish_md_op_data(op_data);
out:
ll_dir_chain_fini(&chain);
#define NORMAL_MAX_STRIPES 4
int lmv_read_entry(struct obd_export *exp, struct md_op_data *op_data,
- struct md_callback *cb_op, struct lu_dirent **ldp)
+ struct md_callback *cb_op, struct lu_dirent **ldp,
+ struct page **ppage)
{
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
int stripe_count;
__u64 min_hash;
int min_idx = 0;
+ struct page *min_page = NULL;
int i;
int rc;
ENTRY;
min_hash = MDS_DIR_END_OFF;
for (i = 0; i < stripe_count; i++) {
struct lmv_tgt_desc *tgt;
+ struct page *page = NULL;
if (likely(lsm == NULL)) {
tgt = lmv_find_target(lmv, &op_data->op_fid1);
op_data->op_stripe_offset = i;
}
- rc = md_read_entry(tgt->ltd_exp, op_data, cb_op, &ents[i]);
+ rc = md_read_entry(tgt->ltd_exp, op_data, cb_op, &ents[i],
+ &page);
if (rc != 0)
GOTO(out, rc);
if (ents[i] != NULL &&
le64_to_cpu(ents[i]->lde_hash) <= min_hash) {
+ if (min_page != NULL)
+ page_cache_release(min_page);
+ min_page = page;
min_hash = le64_to_cpu(ents[i]->lde_hash);
min_idx = i;
}
if (stripe_count > NORMAL_MAX_STRIPES && ents != NULL)
OBD_FREE(ents, sizeof(ents[0]) * stripe_count);
+ if (rc != 0 && min_page != NULL) {
+ kunmap(min_page);
+ page_cache_release(min_page);
+ } else {
+ *ppage = min_page;
+ }
+
RETURN(rc);
}
#ifdef __KERNEL__
static void mdc_release_page(struct page *page, int remove)
{
- kunmap(page);
if (remove) {
lock_page(page);
if (likely(page->mapping != NULL))
CDEBUG(D_VFSTRACE, "page%lu [%llu %llu], hash"LPU64"\n",
offset, *start, *end, *hash);
if (*hash > *end) {
+ kunmap(page);
mdc_release_page(page, 0);
page = NULL;
} else if (*end != *start && *hash == *end) {
* ll_get_dir_page() will issue RPC to fetch
* the page we want.
*/
+ kunmap(page);
mdc_release_page(page,
le32_to_cpu(dp->ldp_flags) & LDF_COLLIDE);
page = NULL;
* Read one directory entry from the cache.
*/
int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
- struct md_callback *cb_op, struct lu_dirent **entp)
+ struct md_callback *cb_op, struct lu_dirent **entp,
+ struct page **ppage)
{
struct page *page = NULL;
struct lu_dirpage *dp;
struct lu_dirent *ent;
int rc = 0;
- int index = 0;
ENTRY;
- if (op_data->op_hash_offset == MDS_DIR_END_OFF) {
- *entp = NULL;
+ CDEBUG(D_INFO, DFID "offset = "LPU64"\n", PFID(&op_data->op_fid1),
+ op_data->op_hash_offset);
+
+ *ppage = NULL;
+ *entp = NULL;
+
+ if (op_data->op_hash_offset == MDS_DIR_END_OFF)
RETURN(0);
- }
rc = mdc_read_page(exp, op_data, cb_op, &page);
if (rc != 0)
RETURN(rc);
- if (op_data->op_cli_flags & CLI_READENT_END) {
- mdc_release_page(page, 0);
- RETURN(0);
- }
-
- dp = kmap(page);
+ dp = page_address(page);
for (ent = lu_dirent_start(dp); ent != NULL;
ent = lu_dirent_next(ent)) {
- index++;
- if (ent->lde_hash > op_data->op_hash_offset)
+ /* Skip dummy entry */
+ if (le16_to_cpu(ent->lde_namelen) == 0)
+ continue;
+
+ if (le64_to_cpu(ent->lde_hash) > op_data->op_hash_offset)
break;
}
- kunmap(page);
/* If it can not find entry in current page, try next page. */
if (ent == NULL) {
RETURN(rc);
if (page != NULL) {
- dp = kmap(page);
+ dp = page_address(page);
ent = lu_dirent_start(dp);
- kunmap(page);
}
op_data->op_hash_offset = orig_offset;
}
+ *ppage = page;
*entp = ent;
RETURN(rc);
}
int mdc_read_entry(struct obd_export *exp, struct md_op_data *op_data,
- struct md_callback *cb_op, struct lu_dirent **entp)
+ struct md_callback *cb_op, struct lu_dirent **entp,
+ struct page **ppage)
{
struct page *page = NULL;
struct lu_dirpage *dp;