Whamcloud - gitweb
310957b9a027fd880ea7e4313121ea1a4a56082a
[fs/lustre-release.git] / lustre / kernel_patches / patches / jbd2-jcberr-2.6-rhel6.patch
1 This patch is no longer needed for Lustre, since Lustre 2.2.  It is kept
2 in the kernel patch series for compatibility with older Lustre releases
3 to simplify the upgrade process so that both the kernel and Lustre do
4 not need to be upgraded at the same time.  See Jira issue LU-433.
5
6 This allows the jbd transaction commit callbacks to be registered.
7 The ext4 jbd2 code has a different commit callback (one per transaction)
8 that could be used to provide equivalent functionality.  This would
9 require modifying the existing ext4 commit callback (used by mballoc
10 when freeing data blocks) to be mutiplexed so it will store 2 different
11 callback functions and 2 different lists of callback data.
12
13 Index: linux+rh+chaos/include/linux/jbd2.h
14 ===================================================================
15 --- linux+rh+chaos.orig/include/linux/jbd2.h
16 +++ linux+rh+chaos/include/linux/jbd2.h
17 @@ -415,6 +415,27 @@ struct jbd2_inode {
18         unsigned int i_flags;
19  };
20  
21 +#define HAVE_JOURNAL_CALLBACK_STATUS
22 +/**
23 + *   struct journal_callback - Base structure for callback information.
24 + *   @jcb_list: list information for other callbacks attached to the same handle.
25 + *   @jcb_func: Function to call with this callback structure.
26 + *
27 + *   This struct is a 'seed' structure for a using with your own callback
28 + *   structs. If you are using callbacks you must allocate one of these
29 + *   or another struct of your own definition which has this struct
30 + *   as it's first element and pass it to journal_callback_set().
31 + *
32 + *   This is used internally by jbd2 to maintain callback information.
33 + *
34 + *   See journal_callback_set for more information.
35 + **/
36 +struct journal_callback {
37 +       struct list_head jcb_list;              /* t_jcb_lock */
38 +       void (*jcb_func)(struct journal_callback *jcb, int error);
39 +       /* user data goes here */
40 +};
41 +
42  struct jbd2_revoke_table_s;
43  
44  /**
45 @@ -423,6 +444,7 @@ struct jbd2_revoke_table_s;
46   * @h_transaction: Which compound transaction is this update a part of?
47   * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
48   * @h_ref: Reference count on this handle
49 + * @h_jcb: List of application registered callbacks for this handle.
50   * @h_err: Field for caller's use to track errors through large fs operations
51   * @h_sync: flag for sync-on-close
52   * @h_jdata: flag to force data journaling
53 @@ -448,6 +470,13 @@ struct handle_s
54         /* operations */
55         int                     h_err;
56  
57 +       /*
58 +        * List of application registered callbacks for this handle. The
59 +        * function(s) will be called after the transaction that this handle is
60 +        * part of has been committed to disk. [t_jcb_lock]
61 +        */
62 +       struct list_head        h_jcb;
63 +
64         /* Flags [no locking] */
65         unsigned int    h_sync:         1;      /* sync-on-close */
66         unsigned int    h_jdata:        1;      /* force data journaling */
67 @@ -503,6 +532,8 @@ struct transaction_chp_stats_s {
68   *    j_state_lock
69   *    ->j_list_lock                    (journal_unmap_buffer)
70   *
71 + *    t_handle_lock
72 + *    ->t_jcb_lock
73   */
74  
75  struct transaction_s
76 @@ -659,6 +690,16 @@ struct transaction_s
77          * structures associated with the transaction
78          */
79         struct list_head        t_private_list;
80
81 +       /*
82 +        * Protects the callback list
83 +        */
84 +       spinlock_t              t_jcb_lock;
85 +       /*
86 +        * List of registered callback functions for this transaction.
87 +        * Called when the transaction is committed. [t_jcb_lock]
88 +        */
89 +       struct list_head        t_jcb;
90  };
91  
92  struct transaction_run_stats_s {
93 @@ -1115,6 +1156,9 @@ extern int         jbd2_journal_stop(handle_t *
94  extern int      jbd2_journal_flush (journal_t *);
95  extern void     jbd2_journal_lock_updates (journal_t *);
96  extern void     jbd2_journal_unlock_updates (journal_t *);
97 +extern void     jbd2_journal_callback_set(handle_t *handle,
98 +                                      void (*fn)(struct journal_callback *,int),
99 +                                      struct journal_callback *jcb);
100  
101  extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
102                                 struct block_device *fs_dev,
103 Index: linux+rh+chaos/fs/jbd2/checkpoint.c
104 ===================================================================
105 --- linux+rh+chaos.orig/fs/jbd2/checkpoint.c
106 +++ linux+rh+chaos/fs/jbd2/checkpoint.c
107 @@ -759,6 +759,7 @@ void __jbd2_journal_drop_transaction(jou
108         J_ASSERT(transaction->t_checkpoint_list == NULL);
109         J_ASSERT(transaction->t_checkpoint_io_list == NULL);
110         J_ASSERT(transaction->t_updates == 0);
111 +       J_ASSERT(list_empty(&transaction->t_jcb));
112         J_ASSERT(journal->j_committing_transaction != transaction);
113         J_ASSERT(journal->j_running_transaction != transaction);
114  
115 Index: linux+rh+chaos/fs/jbd2/commit.c
116 ===================================================================
117 --- linux+rh+chaos.orig/fs/jbd2/commit.c
118 +++ linux+rh+chaos/fs/jbd2/commit.c
119 @@ -857,6 +857,30 @@ wait_for_iobuf:
120             transaction can be removed from any checkpoint list it was on
121             before. */
122  
123 +       /*
124 +        * Call any callbacks that had been registered for handles in this
125 +        * transaction.  It is up to the callback to free any allocated
126 +        * memory.
127 +        *
128 +        * The spinlocking (t_jcb_lock) here is surely unnecessary...
129 +        */
130 +       spin_lock(&commit_transaction->t_jcb_lock);
131 +       if (!list_empty(&commit_transaction->t_jcb)) {
132 +               struct list_head *p, *n;
133 +               int error = is_journal_aborted(journal);
134 +
135 +               list_for_each_safe(p, n, &commit_transaction->t_jcb) {
136 +                       struct journal_callback *jcb;
137 +
138 +                       jcb = list_entry(p, struct journal_callback, jcb_list);
139 +                       list_del(p);
140 +                       spin_unlock(&commit_transaction->t_jcb_lock);
141 +                       jcb->jcb_func(jcb, error);
142 +                       spin_lock(&commit_transaction->t_jcb_lock);
143 +               }
144 +       }
145 +       spin_unlock(&commit_transaction->t_jcb_lock);
146 +
147         jbd_debug(3, "JBD: commit phase 6\n");
148  
149         J_ASSERT(list_empty(&commit_transaction->t_inode_list));
150 Index: linux+rh+chaos/fs/jbd2/journal.c
151 ===================================================================
152 --- linux+rh+chaos.orig/fs/jbd2/journal.c
153 +++ linux+rh+chaos/fs/jbd2/journal.c
154 @@ -90,6 +90,8 @@ EXPORT_SYMBOL(jbd2_journal_file_inode);
155  EXPORT_SYMBOL(jbd2_journal_init_jbd_inode);
156  EXPORT_SYMBOL(jbd2_journal_release_jbd_inode);
157  EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate);
158 +EXPORT_SYMBOL(jbd2_journal_callback_set);
159 +EXPORT_SYMBOL(jbd2_journal_bmap);
160  
161  static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
162  static void __journal_abort_soft (journal_t *journal, int errno);
163 Index: linux+rh+chaos/fs/jbd2/transaction.c
164 ===================================================================
165 --- linux+rh+chaos.orig/fs/jbd2/transaction.c
166 +++ linux+rh+chaos/fs/jbd2/transaction.c
167 @@ -52,7 +52,9 @@ jbd2_get_transaction(journal_t *journal,
168         transaction->t_start_time = ktime_get();
169         transaction->t_tid = journal->j_transaction_sequence++;
170         transaction->t_expires = jiffies + journal->j_commit_interval;
171 +       INIT_LIST_HEAD(&transaction->t_jcb);
172         spin_lock_init(&transaction->t_handle_lock);
173 +       spin_lock_init(&transaction->t_jcb_lock);
174         INIT_LIST_HEAD(&transaction->t_inode_list);
175         INIT_LIST_HEAD(&transaction->t_private_list);
176  
177 @@ -257,6 +259,7 @@ static handle_t *new_handle(int nblocks)
178         memset(handle, 0, sizeof(*handle));
179         handle->h_buffer_credits = nblocks;
180         handle->h_ref = 1;
181 +       INIT_LIST_HEAD(&handle->h_jcb);
182  
183         lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle",
184                                                 &jbd2_handle_key, 0);
185 @@ -1216,6 +1219,36 @@ drop:
186  }
187  
188  /**
189 + * void jbd2_journal_callback_set() -  Register a callback function for this handle.
190 + * @handle: handle to attach the callback to.
191 + * @func: function to callback.
192 + * @jcb:  structure with additional information required by func() , and
193 + *     some space for jbd2 internal information.
194 + *
195 + * The function will be
196 + * called when the transaction that this handle is part of has been
197 + * committed to disk with the original callback data struct and the
198 + * error status of the journal as parameters.  There is no guarantee of
199 + * ordering between handles within a single transaction, nor between
200 + * callbacks registered on the same handle.
201 + *
202 + * The caller is responsible for allocating the journal_callback struct.
203 + * This is to allow the caller to add as much extra data to the callback
204 + * as needed, but reduce the overhead of multiple allocations.  The caller
205 + * allocated struct must start with a struct journal_callback at offset 0,
206 + * and has the caller-specific data afterwards.
207 + */
208 +void jbd2_journal_callback_set(handle_t *handle,
209 +                     void (*func)(struct journal_callback *jcb, int error),
210 +                     struct journal_callback *jcb)
211 +{
212 +       spin_lock(&handle->h_transaction->t_jcb_lock);
213 +       list_add_tail(&jcb->jcb_list, &handle->h_jcb);
214 +       spin_unlock(&handle->h_transaction->t_jcb_lock);
215 +       jcb->jcb_func = func;
216 +}
217 +
218 +/**
219   * int jbd2_journal_stop() - complete a transaction
220   * @handle: tranaction to complete.
221   *
222 @@ -1321,6 +1354,11 @@ int jbd2_journal_stop(handle_t *handle)
223                         wake_up(&journal->j_wait_transaction_locked);
224         }
225  
226 +       /* Move callbacks from the handle to the transaction. */
227 +       spin_lock(&transaction->t_jcb_lock);
228 +       list_splice(&handle->h_jcb, &transaction->t_jcb);
229 +       spin_unlock(&transaction->t_jcb_lock);
230 +
231         /*
232          * If the handle is marked SYNC, we need to set another commit
233          * going!  We also want to force a commit if the current