Loading fs/ocfs2/dir.c +56 −47 Original line number Diff line number Diff line Loading @@ -414,11 +414,8 @@ int __ocfs2_add_entry(handle_t *handle, return retval; } /* * ocfs2_readdir() * */ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version, loff_t *f_pos, void *priv, filldir_t filldir) { int error = 0; unsigned long offset, blk, last_ra_blk = 0; Loading @@ -426,45 +423,23 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct buffer_head * bh, * tmp; struct ocfs2_dir_entry * de; int err; struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb = inode->i_sb; unsigned int ra_sectors = 16; int lock_level = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); stored = 0; bh = NULL; 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_nolock; } offset = filp->f_pos & (sb->s_blocksize - 1); offset = (*f_pos) & (sb->s_blocksize - 1); while (!error && !stored && filp->f_pos < i_size_read(inode)) { blk = (filp->f_pos) >> sb->s_blocksize_bits; while (!error && !stored && *f_pos < i_size_read(inode)) { blk = (*f_pos) >> sb->s_blocksize_bits; bh = ocfs2_bread(inode, blk, &err, 0); if (!bh) { 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; *f_pos); *f_pos += sb->s_blocksize - offset; continue; } Loading @@ -490,7 +465,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) * readdir(2), then we might be pointing to an invalid * dirent right now. Scan from the start of the block * to make sure. */ if (filp->f_version != inode->i_version) { if (*f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { de = (struct ocfs2_dir_entry *) (bh->b_data + i); /* It's too expensive to do a full Loading @@ -505,21 +480,20 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) i += le16_to_cpu(de->rec_len); } offset = i; filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) | offset; filp->f_version = inode->i_version; *f_version = inode->i_version; } while (!error && filp->f_pos < i_size_read(inode) while (!error && *f_pos < i_size_read(inode) && offset < sb->s_blocksize) { de = (struct ocfs2_dir_entry *) (bh->b_data + offset); if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { /* On error, skip the f_pos to the next block. */ filp->f_pos = (filp->f_pos | (sb->s_blocksize - 1)) + 1; *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; brelse(bh); goto bail; goto out; } offset += le16_to_cpu(de->rec_len); if (le64_to_cpu(de->inode)) { Loading @@ -530,36 +504,71 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) * not the directory has been modified * during the copy operation. */ unsigned long version = filp->f_version; unsigned long version = *f_version; unsigned char d_type = DT_UNKNOWN; if (de->file_type < OCFS2_FT_MAX) d_type = ocfs2_filetype_table[de->file_type]; error = filldir(dirent, de->name, error = filldir(priv, de->name, de->name_len, filp->f_pos, *f_pos, ino_from_blkno(sb, le64_to_cpu(de->inode)), d_type); if (error) break; if (version != filp->f_version) if (version != *f_version) goto revalidate; stored ++; } filp->f_pos += le16_to_cpu(de->rec_len); *f_pos += le16_to_cpu(de->rec_len); } offset = 0; brelse(bh); } stored = 0; bail: out: return stored; } /* * ocfs2_readdir() * */ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) { int error = 0; struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); 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. */ goto bail_nolock; } error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, dirent, filldir); ocfs2_meta_unlock(inode, lock_level); bail_nolock: mlog_exit(stored); mlog_exit(error); return stored; return error; } /* Loading Loading
fs/ocfs2/dir.c +56 −47 Original line number Diff line number Diff line Loading @@ -414,11 +414,8 @@ int __ocfs2_add_entry(handle_t *handle, return retval; } /* * ocfs2_readdir() * */ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version, loff_t *f_pos, void *priv, filldir_t filldir) { int error = 0; unsigned long offset, blk, last_ra_blk = 0; Loading @@ -426,45 +423,23 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) struct buffer_head * bh, * tmp; struct ocfs2_dir_entry * de; int err; struct inode *inode = filp->f_path.dentry->d_inode; struct super_block * sb = inode->i_sb; unsigned int ra_sectors = 16; int lock_level = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); stored = 0; bh = NULL; 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_nolock; } offset = filp->f_pos & (sb->s_blocksize - 1); offset = (*f_pos) & (sb->s_blocksize - 1); while (!error && !stored && filp->f_pos < i_size_read(inode)) { blk = (filp->f_pos) >> sb->s_blocksize_bits; while (!error && !stored && *f_pos < i_size_read(inode)) { blk = (*f_pos) >> sb->s_blocksize_bits; bh = ocfs2_bread(inode, blk, &err, 0); if (!bh) { 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; *f_pos); *f_pos += sb->s_blocksize - offset; continue; } Loading @@ -490,7 +465,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) * readdir(2), then we might be pointing to an invalid * dirent right now. Scan from the start of the block * to make sure. */ if (filp->f_version != inode->i_version) { if (*f_version != inode->i_version) { for (i = 0; i < sb->s_blocksize && i < offset; ) { de = (struct ocfs2_dir_entry *) (bh->b_data + i); /* It's too expensive to do a full Loading @@ -505,21 +480,20 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) i += le16_to_cpu(de->rec_len); } offset = i; filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) | offset; filp->f_version = inode->i_version; *f_version = inode->i_version; } while (!error && filp->f_pos < i_size_read(inode) while (!error && *f_pos < i_size_read(inode) && offset < sb->s_blocksize) { de = (struct ocfs2_dir_entry *) (bh->b_data + offset); if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { /* On error, skip the f_pos to the next block. */ filp->f_pos = (filp->f_pos | (sb->s_blocksize - 1)) + 1; *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; brelse(bh); goto bail; goto out; } offset += le16_to_cpu(de->rec_len); if (le64_to_cpu(de->inode)) { Loading @@ -530,36 +504,71 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) * not the directory has been modified * during the copy operation. */ unsigned long version = filp->f_version; unsigned long version = *f_version; unsigned char d_type = DT_UNKNOWN; if (de->file_type < OCFS2_FT_MAX) d_type = ocfs2_filetype_table[de->file_type]; error = filldir(dirent, de->name, error = filldir(priv, de->name, de->name_len, filp->f_pos, *f_pos, ino_from_blkno(sb, le64_to_cpu(de->inode)), d_type); if (error) break; if (version != filp->f_version) if (version != *f_version) goto revalidate; stored ++; } filp->f_pos += le16_to_cpu(de->rec_len); *f_pos += le16_to_cpu(de->rec_len); } offset = 0; brelse(bh); } stored = 0; bail: out: return stored; } /* * ocfs2_readdir() * */ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) { int error = 0; struct inode *inode = filp->f_path.dentry->d_inode; int lock_level = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); 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. */ goto bail_nolock; } error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, dirent, filldir); ocfs2_meta_unlock(inode, lock_level); bail_nolock: mlog_exit(stored); mlog_exit(error); return stored; return error; } /* Loading