Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / lvfs / fsfilt_ext3.c
index 6164a09..e65ce42 100644 (file)
@@ -44,7 +44,6 @@
 #include <libcfs/kp30.h>
 #include <lustre_fsfilt.h>
 #include <obd.h>
-#include <obd_class.h>
 #include <lustre_quota.h>
 #include <linux/lustre_compat25.h>
 #include <linux/lprocfs_status.h>
 #define FSFILT_DELETE_TRANS_BLOCKS(sb)    EXT3_DELETE_TRANS_BLOCKS(sb)
 #endif
 
+#ifdef EXT3_SINGLEDATA_TRANS_BLOCKS_HAS_SB
+/* for kernels 2.6.18 and later */
+#define FSFILT_SINGLEDATA_TRANS_BLOCKS(sb) EXT3_SINGLEDATA_TRANS_BLOCKS(sb)
+#else
+#define FSFILT_SINGLEDATA_TRANS_BLOCKS(sb) EXT3_SINGLEDATA_TRANS_BLOCKS
+#endif
+
 #define fsfilt_ext3_journal_start(inode, nblocks) ext3_journal_start(inode, nblocks)
 #define fsfilt_ext3_journal_stop(handle)          ext3_journal_stop(handle)
 
@@ -91,9 +97,7 @@ static int fsfilt_ext3_set_label(struct super_block *sb, char *label)
         int err;
 
         journal = EXT3_SB(sb)->s_journal;
-        lock_24kernel();
         handle = journal_start(journal, 1);
-        unlock_24kernel();
         if (IS_ERR(handle)) {
                 CERROR("can't start transaction\n");
                 return(PTR_ERR(handle));
@@ -109,9 +113,7 @@ static int fsfilt_ext3_set_label(struct super_block *sb, char *label)
         err = ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
 
 out:
-        lock_24kernel();
         journal_stop(handle);
-        unlock_24kernel();
 
         return(err);
 }
@@ -153,7 +155,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                                int logs)
 {
         /* For updates to the last received file */
-        int nblocks = EXT3_SINGLEDATA_TRANS_BLOCKS;
+        int nblocks = FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb);
         journal_t *journal;
         void *handle;
 
@@ -169,11 +171,11 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                 /* delete one file + create/update logs for each stripe */
                 nblocks += FSFILT_DELETE_TRANS_BLOCKS(inode->i_sb);
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                            EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
+                            FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb)) * logs;
                 break;
         case FSFILT_OP_RENAME:
                 /* modify additional directory */
-                nblocks += EXT3_SINGLEDATA_TRANS_BLOCKS;
+                nblocks += FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb);
                 /* no break */
         case FSFILT_OP_SYMLINK:
                 /* additional block + block bitmap + GDT for long symlink */
@@ -207,7 +209,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                          FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
                 /* create/update logs for each stripe */
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                            EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
+                            FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb)) * logs;
                 break;
         case FSFILT_OP_SETATTR:
                 /* Setattr on inode */
@@ -216,7 +218,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                          FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
                 /* quota chown log for each stripe */
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                            EXT3_SINGLEDATA_TRANS_BLOCKS) * logs;
+                            FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb)) * logs;
                 break;
         case FSFILT_OP_CANCEL_UNLINK:
                 /* blocks for log header bitmap update OR
@@ -232,7 +234,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
                 /*create array log for head file*/
                 nblocks += 3;
                 nblocks += (EXT3_INDEX_EXTRA_TRANS_BLOCKS +
-                            EXT3_SINGLEDATA_TRANS_BLOCKS);
+                            FSFILT_SINGLEDATA_TRANS_BLOCKS(inode->i_sb));
                 /*update head file array */
                 nblocks += EXT3_INDEX_EXTRA_TRANS_BLOCKS +
                          FSFILT_DATA_TRANS_BLOCKS(inode->i_sb);
@@ -251,9 +253,7 @@ static void *fsfilt_ext3_start(struct inode *inode, int op, void *desc_private,
 
  journal_start:
         LASSERTF(nblocks > 0, "can't start %d credit transaction\n", nblocks);
-        lock_24kernel();
         handle = fsfilt_ext3_journal_start(inode, nblocks);
-        unlock_24kernel();
 
         if (!IS_ERR(handle))
                 LASSERT(current->journal_info == handle);
@@ -340,7 +340,7 @@ static int fsfilt_ext3_credits_needed(int objcount, struct fsfilt_objinfo *fso,
          * quota file that is active.  This is at least true for now.
          */
         needed += hweight32(sb_any_quota_enabled(sb)) *
-                EXT3_SINGLEDATA_TRANS_BLOCKS;
+                FSFILT_SINGLEDATA_TRANS_BLOCKS(sb);
 #endif
 
         return needed;
@@ -390,9 +390,7 @@ static void *fsfilt_ext3_brw_start(int objcount, struct fsfilt_objinfo *fso,
         }
 
         LASSERTF(needed > 0, "can't start %d credit transaction\n", needed);
-        lock_24kernel();
         handle = fsfilt_ext3_journal_start(fso->fso_dentry->d_inode, needed);
-        unlock_24kernel();
         if (IS_ERR(handle)) {
                 CERROR("can't get handle for %d credits: rc = %ld\n", needed,
                        PTR_ERR(handle));
@@ -432,9 +430,7 @@ static int fsfilt_ext3_commit(struct inode *inode, void *h, int force_sync)
         if (force_sync)
                 handle->h_sync = 1; /* recovery likes this */
 
-        lock_24kernel();
         rc = fsfilt_ext3_journal_stop(handle);
-        unlock_24kernel();
 
         return rc;
 }
@@ -450,7 +446,6 @@ static int fsfilt_ext3_commit_async(struct inode *inode, void *h,
 
         LASSERT(current->journal_info == handle);
 
-        lock_24kernel();
         transaction = handle->h_transaction;
         journal = transaction->t_journal;
         tid = transaction->t_tid;
@@ -459,18 +454,9 @@ static int fsfilt_ext3_commit_async(struct inode *inode, void *h,
         rc = fsfilt_ext3_journal_stop(handle);
         if (rc) {
                 CERROR("error while stopping transaction: %d\n", rc);
-                unlock_24kernel();
                 return rc;
         }
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-        rtid = log_start_commit(journal, transaction);
-        if (rtid != tid)
-                CERROR("strange race: %lu != %lu\n",
-                       (unsigned long) tid, (unsigned long) rtid);
-#else
         log_start_commit(journal, tid);
-#endif
-        unlock_24kernel();
 
         *wait_handle = (void *) tid;
         CDEBUG(D_INODE, "commit async: %lu\n", (unsigned long) tid);
@@ -499,8 +485,6 @@ static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle,
         struct inode *inode = dentry->d_inode;
         int rc = 0;
 
-        lock_kernel();
-
         /* Avoid marking the inode dirty on the superblock list unnecessarily.
          * We are already writing the inode to disk as part of this
          * transaction and want to avoid a lot of extra inode writeout
@@ -551,7 +535,6 @@ static int fsfilt_ext3_setattr(struct dentry *dentry, void *handle,
         }
 
  out:
-        unlock_kernel();
         RETURN(rc);
 }
 
@@ -582,13 +565,11 @@ static int fsfilt_ext3_set_md(struct inode *inode, void *handle,
 
         LASSERT(TRYLOCK_INODE_MUTEX(inode) == 0);
 
-        lock_24kernel();
         rc = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_TRUSTED,
                                    name, lmm, lmm_size, 0);
 
-        unlock_24kernel();
 
-        if (rc)
+        if (rc && rc != -EROFS)
                 CERROR("error adding MD data to inode %lu: rc = %d\n",
                        inode->i_ino, rc);
         return rc;
@@ -601,11 +582,9 @@ static int fsfilt_ext3_get_md(struct inode *inode, void *lmm, int lmm_size,
         int rc;
 
         LASSERT(TRYLOCK_INODE_MUTEX(inode) == 0);
-        lock_24kernel();
 
         rc = ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED,
                             name, lmm, lmm_size);
-        unlock_24kernel();
 
         /* This gives us the MD size */
         if (lmm == NULL)
@@ -709,10 +688,8 @@ static int fsfilt_ext3_add_journal_cb(struct obd_device *obd, __u64 last_rcvd,
         fcb->cb_data = cb_data;
 
         CDEBUG(D_EXT2, "set callback for last_rcvd: "LPD64"\n", last_rcvd);
-        lock_24kernel();
         journal_callback_set(handle, fsfilt_ext3_cb_func,
                              (struct journal_callback *)fcb);
-        unlock_24kernel();
 
         return 0;
 }
@@ -764,6 +741,25 @@ static int fsfilt_ext3_sync(struct super_block *sb)
 #define ext3_down_truncate_sem(inode)  mutex_lock(&EXT3_I(inode)->truncate_mutex);
 #endif
 
+#ifndef EXT_ASSERT
+#define EXT_ASSERT(cond)  BUG_ON(!(cond))
+#endif
+
+#ifdef EXT3_EXT_HAS_NO_TREE
+/* for kernels 2.6.18 and later */
+#define ext3_ext_base                   inode
+#define ext3_ext_base2inode(inode)      (inode)
+#define EXT_DEPTH(inode)                ext_depth(inode)
+#define EXT_GENERATION(inode)           ext_generation(inode)
+#define fsfilt_ext3_ext_walk_space(inode, block, num, cb, cbdata) \
+                        ext3_ext_walk_space(inode, block, num, cb, cbdata);
+#else
+#define ext3_ext_base                   ext3_extents_tree
+#define ext3_ext_base2inode(tree)       (tree->inode)
+#define fsfilt_ext3_ext_walk_space(tree, block, num, cb, cbdata) \
+                        ext3_ext_walk_space(tree, block, num, cb);
+#endif
+
 #include <linux/lustre_version.h>
 #if EXT3_EXT_MAGIC == 0xf301
 #define ee_start e_start
@@ -828,43 +824,43 @@ static int ext3_ext_find_goal(struct inode *inode, struct ext3_ext_path *path,
         unmap_underlying_metadata((sb)->s_bdev, blocknr)
 
 #ifndef EXT3_MB_HINT_GROUP_ALLOC
-static unsigned long new_blocks(handle_t *handle, struct ext3_extents_tree *tree,
+static unsigned long new_blocks(handle_t *handle, struct ext3_ext_base *base,
                                 struct ext3_ext_path *path, unsigned long block,
-                                int *count, int *err)
+                                unsigned long *count, int *err)
 {
         unsigned long pblock, goal;
         int aflags = 0;
+        struct inode *inode = ext3_ext_base2inode(base);
 
-        goal = ext3_ext_find_goal(tree->inode, path, block, &aflags);
+        goal = ext3_ext_find_goal(inode, path, block, &aflags);
         aflags |= 2; /* block have been already reserved */
-        lock_24kernel();
-        pblock = ext3_mb_new_blocks(handle, tree->inode, goal, count, aflags, err);
-        unlock_24kernel();
+        pblock = ext3_mb_new_blocks(handle, inode, goal, count, aflags, err);
         return pblock;
 
 }
 #else
-static unsigned long new_blocks(handle_t *handle, struct ext3_extents_tree *tree,
+static unsigned long new_blocks(handle_t *handle, struct ext3_ext_base *base,
                                 struct ext3_ext_path *path, unsigned long block,
-                                int *count, int *err)
+                                unsigned long *count, int *err)
 {
+        struct inode *inode = ext3_ext_base2inode(base);
         struct ext3_allocation_request ar;
         unsigned long pblock;
         int aflags;
 
         /* find neighbour allocated blocks */
         ar.lleft = block;
-        *err = ext3_ext_search_left(tree, path, &ar.lleft, &ar.pleft);
+        *err = ext3_ext_search_left(base, path, &ar.lleft, &ar.pleft);
         if (*err)
                 return 0;
         ar.lright = block;
-        *err = ext3_ext_search_right(tree, path, &ar.lright, &ar.pright);
+        *err = ext3_ext_search_right(base, path, &ar.lright, &ar.pright);
         if (*err)
                 return 0;
 
         /* allocate new block */
-        ar.goal = ext3_ext_find_goal(tree->inode, path, block, &aflags);
-        ar.inode = tree->inode;
+        ar.goal = ext3_ext_find_goal(inode, path, block, &aflags);
+        ar.inode = inode;
         ar.logical = block;
         ar.len = *count;
         ar.flags = EXT3_MB_HINT_DATA;
@@ -875,19 +871,29 @@ static unsigned long new_blocks(handle_t *handle, struct ext3_extents_tree *tree
 }
 #endif
 
-static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
+#ifdef EXT3_EXT_HAS_NO_TREE
+static int ext3_ext_new_extent_cb(struct ext3_ext_base *base,
+                                  struct ext3_ext_path *path,
+                                  struct ext3_ext_cache *cex,
+                                  void *cbdata)
+{
+        struct bpointers *bp = cbdata;
+#else
+static int ext3_ext_new_extent_cb(struct ext3_ext_base *base,
                                   struct ext3_ext_path *path,
                                   struct ext3_ext_cache *cex)
 {
-        struct inode *inode = tree->inode;
-        struct bpointers *bp = tree->private;
+        struct bpointers *bp = base->private;
+#endif
+        struct inode *inode = ext3_ext_base2inode(base);
         struct ext3_extent nex;
         unsigned long pblock;
         unsigned long tgen;
-        int count, err, i;
+        int err, i;
+        unsigned long count;
         handle_t *handle;
 
-        i = EXT_DEPTH(tree);
+        i = EXT_DEPTH(base);
         EXT_ASSERT(i == path->p_depth);
         EXT_ASSERT(path[i].p_hdr);
 
@@ -915,29 +921,25 @@ static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
                 return EXT_CONTINUE;
         }
 
-        tgen = EXT_GENERATION(tree);
-        count = ext3_ext_calc_credits_for_insert(tree, path);
+        tgen = EXT_GENERATION(base);
+        count = ext3_ext_calc_credits_for_insert(base, path);
         ext3_up_truncate_sem(inode);
 
-        lock_24kernel();
         handle = fsfilt_ext3_journal_start(inode, count+EXT3_ALLOC_NEEDED+1);
-        unlock_24kernel();
         if (IS_ERR(handle)) {
                 ext3_down_truncate_sem(inode);
                 return PTR_ERR(handle);
         }
 
         ext3_down_truncate_sem(inode);
-        if (tgen != EXT_GENERATION(tree)) {
+        if (tgen != EXT_GENERATION(base)) {
                 /* the tree has changed. so path can be invalid at moment */
-                lock_24kernel();
                 fsfilt_ext3_journal_stop(handle);
-                unlock_24kernel();
                 return EXT_REPEAT;
         }
 
         count = cex->ec_len;
-        pblock = new_blocks(handle, tree, path, cex->ec_block, &count, &err);
+        pblock = new_blocks(handle, base, path, cex->ec_block, &count, &err);
         if (!pblock)
                 goto out;
         EXT_ASSERT(count <= cex->ec_len);
@@ -946,7 +948,7 @@ static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
         nex.ee_block = cex->ec_block;
         nex.ee_start = pblock;
         nex.ee_len = count;
-        err = ext3_ext_insert_extent(handle, tree, path, &nex);
+        err = ext3_ext_insert_extent(handle, base, path, &nex);
         if (err) {
                 CERROR("can't insert extent: %d\n", err);
                 /* XXX: export ext3_free_blocks() */
@@ -965,9 +967,7 @@ static int ext3_ext_new_extent_cb(struct ext3_extents_tree *tree,
         BUG_ON(nex.ee_block != cex->ec_block);
 
 out:
-        lock_24kernel();
         fsfilt_ext3_journal_stop(handle);
-        unlock_24kernel();
 map:
         if (err >= 0) {
                 /* map blocks */
@@ -1009,15 +1009,22 @@ int fsfilt_map_nblocks(struct inode *inode, unsigned long block,
                        unsigned long num, unsigned long *blocks,
                        int *created, int create)
 {
+#ifdef EXT3_EXT_HAS_NO_TREE
+        struct ext3_ext_base *base = inode;
+#else
         struct ext3_extents_tree tree;
+        struct ext3_ext_base *base = &tree;
+#endif
         struct bpointers bp;
         int err;
 
         CDEBUG(D_OTHER, "blocks %lu-%lu requested for inode %u\n",
                block, block + num - 1, (unsigned) inode->i_ino);
 
-        ext3_init_tree_desc(&tree, inode);
+#ifndef EXT3_EXT_HAS_NO_TREE
+        ext3_init_tree_desc(base, inode);
         tree.private = &bp;
+#endif
         bp.blocks = blocks;
         bp.created = created;
         bp.start = block;
@@ -1025,8 +1032,9 @@ int fsfilt_map_nblocks(struct inode *inode, unsigned long block,
         bp.create = create;
 
         ext3_down_truncate_sem(inode);
-        err = ext3_ext_walk_space(&tree, block, num, ext3_ext_new_extent_cb);
-        ext3_ext_invalidate_cache(&tree);
+        err = fsfilt_ext3_ext_walk_space(base, block, num,
+                                         ext3_ext_new_extent_cb, &bp);
+        ext3_ext_invalidate_cache(base);
         ext3_up_truncate_sem(inode);
 
         return err;
@@ -1260,10 +1268,8 @@ static int fsfilt_ext3_write_record(struct file *file, void *buf, int bufsize,
         block_count = (*offs & (blocksize - 1)) + bufsize;
         block_count = (block_count + blocksize - 1) >> inode->i_blkbits;
 
-        lock_24kernel();
         handle = fsfilt_ext3_journal_start(inode,
                                block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2);
-        unlock_24kernel();
         if (IS_ERR(handle)) {
                 CERROR("can't start transaction for %d blocks (%d bytes)\n",
                        block_count * FSFILT_DATA_TRANS_BLOCKS(inode->i_sb) + 2, bufsize);
@@ -1275,9 +1281,7 @@ static int fsfilt_ext3_write_record(struct file *file, void *buf, int bufsize,
         if (!err && force_sync)
                 handle->h_sync = 1; /* recovery likes this */
 
-        lock_24kernel();
         fsfilt_ext3_journal_stop(handle);
-        unlock_24kernel();
 
         return err;
 }
@@ -1768,7 +1772,7 @@ static int commit_chkquot(struct super_block *sb, struct qchk_ctxt *qctxt,
         if (!oqc)
                 RETURN(-ENOMEM);
 
-        now = CURRENT_SECONDS;
+        now = cfs_time_current_sec();
 
         if (cdqb->dqb_bsoftlimit &&
             toqb(cdqb->dqb_curspace) >= cdqb->dqb_bsoftlimit &&
@@ -2064,7 +2068,7 @@ static int __init fsfilt_ext3_init(void)
         int rc;
 
         fcb_cache = cfs_mem_cache_create("fsfilt_ext3_fcb",
-                                      sizeof(struct fsfilt_cb_data), 0, 0);
+                                         sizeof(struct fsfilt_cb_data), 0, 0);
         if (!fcb_cache) {
                 CERROR("error allocating fsfilt journal callback cache\n");
                 GOTO(out, rc = -ENOMEM);