int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
int error = 0;
- unsigned long offset, blk;
- int i, num, stored;
+ unsigned long offset, blk, last_ra_blk = 0;
+ int i, stored;
struct buffer_head * bh, * tmp;
struct ocfs2_dir_entry * de;
int err;
- struct inode *inode = filp->f_dentry->d_inode;
+ struct inode *inode = filp->f_path.dentry->d_inode;
struct super_block * sb = inode->i_sb;
- int have_disk_lock = 0;
+ unsigned int ra_sectors = 16;
+ int lock_level = 0;
- mlog_entry("dirino=%"MLFu64"\n", OCFS2_I(inode)->ip_blkno);
+ mlog_entry("dirino=%llu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
stored = 0;
bh = NULL;
- error = ocfs2_meta_lock(inode, NULL, NULL, 0);
+ error = ocfs2_meta_lock_atime(inode, filp->f_vfsmnt, &lock_level);
+ if (lock_level && error >= 0) {
+ /* We release EX lock which used to update atime
+ * and get PR lock again to reduce contention
+ * on commonly accessed directories. */
+ ocfs2_meta_unlock(inode, 1);
+ lock_level = 0;
+ error = ocfs2_meta_lock(inode, NULL, 0);
+ }
if (error < 0) {
if (error != -ENOENT)
mlog_errno(error);
/* we haven't got any yet, so propagate the error. */
stored = error;
- goto bail;
+ goto bail_nolock;
}
- have_disk_lock = 1;
offset = filp->f_pos & (sb->s_blocksize - 1);
blk = (filp->f_pos) >> sb->s_blocksize_bits;
bh = ocfs2_bread(inode, blk, &err, 0);
if (!bh) {
- mlog(ML_ERROR, "directory #%"MLFu64" contains a hole "
- "at offset %lld\n",
- OCFS2_I(inode)->ip_blkno,
+ mlog(ML_ERROR,
+ "directory #%llu contains a hole at offset %lld\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno,
filp->f_pos);
filp->f_pos += sb->s_blocksize - offset;
continue;
}
- /*
- * Do the readahead (8k)
- */
- if (!offset) {
- for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0;
+ /* The idea here is to begin with 8k read-ahead and to stay
+ * 4k ahead of our current position.
+ *
+ * TODO: Use the pagecache for this. We just need to
+ * make sure it's cluster-safe... */
+ if (!last_ra_blk
+ || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
+ for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
i > 0; i--) {
tmp = ocfs2_bread(inode, ++blk, &err, 1);
if (tmp)
brelse(tmp);
}
+ last_ra_blk = blk;
+ ra_sectors = 8;
}
revalidate:
stored = 0;
bail:
- if (have_disk_lock)
- ocfs2_meta_unlock(inode, 0);
+ ocfs2_meta_unlock(inode, lock_level);
+bail_nolock:
mlog_exit(stored);
return stored;
struct ocfs2_dir_entry **dirent)
{
int status = -ENOENT;
- struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
- mlog_entry("(osb=%p, parent=%"MLFu64", name='%.*s', blkno=%p, "
- "inode=%p)\n",
- osb, OCFS2_I(inode)->ip_blkno, namelen, name, blkno, inode);
+ mlog_entry("(name=%.*s, blkno=%p, inode=%p, dirent_bh=%p, dirent=%p)\n",
+ namelen, name, blkno, inode, dirent_bh, dirent);
*dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent);
if (!*dirent_bh || !*dirent) {
struct buffer_head *dirent_bh = NULL;
struct ocfs2_dir_entry *dirent = NULL;
- mlog_entry("dir %"MLFu64", name '%.*s'\n", OCFS2_I(dir)->ip_blkno,
- namelen, name);
+ mlog_entry("dir %llu, name '%.*s'\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
ret = -EEXIST;
dirent_bh = ocfs2_find_entry(name, namelen, dir, &dirent);
if ((i_size_read(inode) <
(OCFS2_DIR_REC_LEN(1) + OCFS2_DIR_REC_LEN(2))) ||
!(bh = ocfs2_bread(inode, 0, &err, 0))) {
- mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
- "no data block\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "bad directory (dir #%llu) - no data block\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
return 1;
}
!le64_to_cpu(de1->inode) ||
strcmp(".", de->name) ||
strcmp("..", de1->name)) {
- mlog(ML_ERROR, "bad directory (dir #%"MLFu64") - "
- "no `.' or `..'\n",
- OCFS2_I(inode)->ip_blkno);
+ mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno);
brelse(bh);
return 1;
}
bh = ocfs2_bread(inode,
offset >> sb->s_blocksize_bits, &err, 0);
if (!bh) {
- mlog(ML_ERROR, "directory #%"MLFu64" contains "
- "a hole at offset %lu\n",
- OCFS2_I(inode)->ip_blkno, offset);
+ mlog(ML_ERROR, "dir %llu has a hole at %lu\n",
+ (unsigned long long)OCFS2_I(inode)->ip_blkno, offset);
offset += sb->s_blocksize;
continue;
}
/* returns a bh of the 1st new block in the allocation. */
int ocfs2_do_extend_dir(struct super_block *sb,
- struct ocfs2_journal_handle *handle,
+ handle_t *handle,
struct inode *dir,
struct buffer_head *parent_fe_bh,
struct ocfs2_alloc_context *data_ac,
struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
struct ocfs2_alloc_context *data_ac = NULL;
struct ocfs2_alloc_context *meta_ac = NULL;
- struct ocfs2_journal_handle *handle = NULL;
+ handle_t *handle = NULL;
struct buffer_head *new_bh = NULL;
struct ocfs2_dir_entry * de;
struct super_block *sb = osb->sb;
mlog_entry_void();
dir_i_size = i_size_read(dir);
- mlog(0, "extending dir %"MLFu64" (i_size = %lld)\n",
- OCFS2_I(dir)->ip_blkno, dir_i_size);
-
- handle = ocfs2_alloc_handle(osb);
- if (handle == NULL) {
- status = -ENOMEM;
- mlog_errno(status);
- goto bail;
- }
+ mlog(0, "extending dir %llu (i_size = %lld)\n",
+ (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size);
/* dir->i_size is always block aligned. */
spin_lock(&OCFS2_I(dir)->ip_lock);
}
if (!num_free_extents) {
- status = ocfs2_reserve_new_metadata(osb, handle,
- fe, &meta_ac);
+ status = ocfs2_reserve_new_metadata(osb, fe, &meta_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
}
}
- status = ocfs2_reserve_clusters(osb, handle, 1, &data_ac);
+ status = ocfs2_reserve_clusters(osb, 1, &data_ac);
if (status < 0) {
if (status != -ENOSPC)
mlog_errno(status);
credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
}
- handle = ocfs2_start_trans(osb, handle, credits);
+ handle = ocfs2_start_trans(osb, credits);
if (IS_ERR(handle)) {
status = PTR_ERR(handle);
handle = NULL;
get_bh(*new_de_bh);
bail:
if (handle)
- ocfs2_commit_trans(handle);
+ ocfs2_commit_trans(osb, handle);
if (data_ac)
ocfs2_free_alloc_context(data_ac);
mlog_entry_void();
- mlog(0, "getting ready to insert namelen %d into dir %"MLFu64"\n",
- namelen, OCFS2_I(dir)->ip_blkno);
+ mlog(0, "getting ready to insert namelen %d into dir %llu\n",
+ namelen, (unsigned long long)OCFS2_I(dir)->ip_blkno);
BUG_ON(!S_ISDIR(dir->i_mode));
fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;