fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / ocfs2 / dir.c
index 57158fa..66821e1 100644 (file)
@@ -74,29 +74,38 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
 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);
 
@@ -104,24 +113,29 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
                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:
@@ -193,9 +207,9 @@ 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;
@@ -212,11 +226,9 @@ int ocfs2_find_files_on_disk(const char *name,
                             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) {
@@ -255,8 +267,8 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
        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);
@@ -287,9 +299,8 @@ int ocfs2_empty_dir(struct inode *inode)
        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;
        }
 
@@ -300,9 +311,8 @@ int ocfs2_empty_dir(struct inode *inode)
                        !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;
        }
@@ -314,9 +324,8 @@ int ocfs2_empty_dir(struct inode *inode)
                        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;
                        }
@@ -340,7 +349,7 @@ int ocfs2_empty_dir(struct inode *inode)
 
 /* 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,
@@ -398,7 +407,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        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;
@@ -406,15 +415,8 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        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);
@@ -428,8 +430,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                }
 
                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);
@@ -437,7 +438,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                        }
                }
 
-               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);
@@ -450,7 +451,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
                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;
@@ -496,7 +497,7 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
        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);
@@ -531,8 +532,8 @@ int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
 
        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;