Whamcloud - gitweb
b=16395
[fs/lustre-release.git] / lustre / kernel_patches / patches / jbd-jcberr-2.6.18-vanilla.patch
1 Index: linux-2.6/include/linux/jbd.h
2 ===================================================================
3 --- linux-2.6.orig/include/linux/jbd.h  2006-07-15 16:08:35.000000000 +0800
4 +++ linux-2.6/include/linux/jbd.h       2006-07-15 16:13:01.000000000 +0800
5 @@ -356,6 +356,27 @@ static inline void jbd_unlock_bh_journal
6         bit_spin_unlock(BH_JournalHead, &bh->b_state);
7  }
8  
9 +#define HAVE_JOURNAL_CALLBACK_STATUS
10 +/**
11 + *   struct journal_callback - Base structure for callback information.
12 + *   @jcb_list: list information for other callbacks attached to the same handle.
13 + *   @jcb_func: Function to call with this callback structure. 
14 + *
15 + *   This struct is a 'seed' structure for a using with your own callback
16 + *   structs. If you are using callbacks you must allocate one of these
17 + *   or another struct of your own definition which has this struct 
18 + *   as it's first element and pass it to journal_callback_set().
19 + *
20 + *   This is used internally by jbd to maintain callback information.
21 + *
22 + *   See journal_callback_set for more information.
23 + **/
24 +struct journal_callback {
25 +       struct list_head jcb_list;              /* t_jcb_lock */
26 +       void (*jcb_func)(struct journal_callback *jcb, int error);
27 +       /* user data goes here */
28 +};
29 +
30  struct jbd_revoke_table_s;
31  
32  /**
33 @@ -364,6 +385,7 @@ struct jbd_revoke_table_s;
34   * @h_transaction: Which compound transaction is this update a part of?
35   * @h_buffer_credits: Number of remaining buffers we are allowed to dirty.
36   * @h_ref: Reference count on this handle
37 + * @h_jcb: List of application registered callbacks for this handle.
38   * @h_err: Field for caller's use to track errors through large fs operations
39   * @h_sync: flag for sync-on-close
40   * @h_jdata: flag to force data journaling
41 @@ -389,6 +411,13 @@ struct handle_s 
42         /* operations */
43         int                     h_err;
44  
45 +       /*
46 +        * List of application registered callbacks for this handle. The
47 +        * function(s) will be called after the transaction that this handle is
48 +        * part of has been committed to disk. [t_jcb_lock]
49 +        */
50 +       struct list_head        h_jcb;
51 +
52         /* Flags [no locking] */
53         unsigned int    h_sync:         1;      /* sync-on-close */
54         unsigned int    h_jdata:        1;      /* force data journaling */
55 @@ -430,6 +459,8 @@ struct handle_s 
56   *    j_state_lock
57   *    ->j_list_lock                    (journal_unmap_buffer)
58   *
59 + *    t_handle_lock
60 + *    ->t_jcb_lock
61   */
62  
63  struct transaction_s 
64 @@ -559,6 +590,15 @@ struct transaction_s 
65          */
66         int t_handle_count;
67  
68 +       /*
69 +        * Protects the callback list
70 +        */
71 +       spinlock_t              t_jcb_lock;
72 +       /*
73 +        * List of registered callback functions for this transaction.
74 +        * Called when the transaction is committed. [t_jcb_lock]
75 +        */
76 +       struct list_head        t_jcb;
77  };
78  
79  /**
80 @@ -906,6 +946,10 @@ extern void         journal_invalidatepage(jour
81  extern int      journal_try_to_free_buffers(journal_t *, struct page *, gfp_t);
82  extern int      journal_stop(handle_t *);
83  extern int      journal_flush (journal_t *);
84 +extern void     journal_callback_set(handle_t *handle,
85 +                                     void (*fn)(struct journal_callback *,int),
86 +                                     struct journal_callback *jcb);
87 +
88  extern void     journal_lock_updates (journal_t *);
89  extern void     journal_unlock_updates (journal_t *);
90  
91 Index: linux-2.6/fs/jbd/checkpoint.c
92 ===================================================================
93 --- linux-2.6.orig/fs/jbd/checkpoint.c  2006-07-15 16:08:36.000000000 +0800
94 +++ linux-2.6/fs/jbd/checkpoint.c       2006-07-15 16:13:01.000000000 +0800
95 @@ -688,6 +688,7 @@ void __journal_drop_transaction(journal_
96         J_ASSERT(transaction->t_checkpoint_list == NULL);
97         J_ASSERT(transaction->t_checkpoint_io_list == NULL);
98         J_ASSERT(transaction->t_updates == 0);
99 +       J_ASSERT(list_empty(&transaction->t_jcb));
100         J_ASSERT(journal->j_committing_transaction != transaction);
101         J_ASSERT(journal->j_running_transaction != transaction);
102  
103 Index: linux-2.6/fs/jbd/commit.c
104 ===================================================================
105 --- linux-2.6.orig/fs/jbd/commit.c      2006-07-15 16:08:36.000000000 +0800
106 +++ linux-2.6/fs/jbd/commit.c   2006-07-15 16:13:01.000000000 +0800
107 @@ -708,6 +708,30 @@ wait_for_iobuf:
108             transaction can be removed from any checkpoint list it was on
109             before. */
110  
111 +       /*
112 +        * Call any callbacks that had been registered for handles in this
113 +        * transaction.  It is up to the callback to free any allocated
114 +        * memory.
115 +        *
116 +        * The spinlocking (t_jcb_lock) here is surely unnecessary...
117 +        */
118 +       spin_lock(&commit_transaction->t_jcb_lock);
119 +       if (!list_empty(&commit_transaction->t_jcb)) {
120 +               struct list_head *p, *n;
121 +               int error = is_journal_aborted(journal);
122 +
123 +               list_for_each_safe(p, n, &commit_transaction->t_jcb) {
124 +                       struct journal_callback *jcb;
125 +
126 +                       jcb = list_entry(p, struct journal_callback, jcb_list);
127 +                       list_del(p);
128 +                       spin_unlock(&commit_transaction->t_jcb_lock);
129 +                       jcb->jcb_func(jcb, error);
130 +                       spin_lock(&commit_transaction->t_jcb_lock);
131 +               }
132 +       }
133 +       spin_unlock(&commit_transaction->t_jcb_lock);
134 +
135         jbd_debug(3, "JBD: commit phase 7\n");
136  
137         J_ASSERT(commit_transaction->t_sync_datalist == NULL);
138 Index: linux-2.6/fs/jbd/journal.c
139 ===================================================================
140 --- linux-2.6.orig/fs/jbd/journal.c     2006-07-15 16:08:36.000000000 +0800
141 +++ linux-2.6/fs/jbd/journal.c  2006-07-15 16:13:01.000000000 +0800
142 @@ -58,6 +58,7 @@ EXPORT_SYMBOL(journal_sync_buffer);
143  #endif
144  EXPORT_SYMBOL(journal_flush);
145  EXPORT_SYMBOL(journal_revoke);
146 +EXPORT_SYMBOL(journal_callback_set);
147  
148  EXPORT_SYMBOL(journal_init_dev);
149  EXPORT_SYMBOL(journal_init_inode);
150 @@ -80,6 +81,7 @@ EXPORT_SYMBOL(journal_wipe);
151  EXPORT_SYMBOL(journal_blocks_per_page);
152  EXPORT_SYMBOL(journal_invalidatepage);
153  EXPORT_SYMBOL(journal_try_to_free_buffers);
154 +EXPORT_SYMBOL(journal_bmap);
155  EXPORT_SYMBOL(journal_force_commit);
156  
157  static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *);
158 Index: linux-2.6/fs/jbd/transaction.c
159 ===================================================================
160 --- linux-2.6.orig/fs/jbd/transaction.c 2006-07-15 16:08:35.000000000 +0800
161 +++ linux-2.6/fs/jbd/transaction.c      2006-07-15 16:13:01.000000000 +0800
162 @@ -50,7 +50,9 @@ get_transaction(journal_t *journal, tran
163         transaction->t_state = T_RUNNING;
164         transaction->t_tid = journal->j_transaction_sequence++;
165         transaction->t_expires = jiffies + journal->j_commit_interval;
166 +       INIT_LIST_HEAD(&transaction->t_jcb);
167         spin_lock_init(&transaction->t_handle_lock);
168 +       spin_lock_init(&transaction->t_jcb_lock);
169  
170         /* Set up the commit timer for the new transaction. */
171         journal->j_commit_timer.expires = transaction->t_expires;
172 @@ -241,6 +243,7 @@ static handle_t *new_handle(int nblocks)
173         memset(handle, 0, sizeof(*handle));
174         handle->h_buffer_credits = nblocks;
175         handle->h_ref = 1;
176 +       INIT_LIST_HEAD(&handle->h_jcb);
177  
178         return handle;
179  }
180 @@ -1291,6 +1294,36 @@ drop:
181  }
182  
183  /**
184 + * void journal_callback_set() -  Register a callback function for this handle.
185 + * @handle: handle to attach the callback to.
186 + * @func: function to callback.
187 + * @jcb:  structure with additional information required by func() , and
188 + *        some space for jbd internal information.
189 + * 
190 + * The function will be
191 + * called when the transaction that this handle is part of has been
192 + * committed to disk with the original callback data struct and the
193 + * error status of the journal as parameters.  There is no guarantee of
194 + * ordering between handles within a single transaction, nor between
195 + * callbacks registered on the same handle.
196 + *
197 + * The caller is responsible for allocating the journal_callback struct.
198 + * This is to allow the caller to add as much extra data to the callback
199 + * as needed, but reduce the overhead of multiple allocations.  The caller
200 + * allocated struct must start with a struct journal_callback at offset 0,
201 + * and has the caller-specific data afterwards.
202 + */
203 +void journal_callback_set(handle_t *handle,
204 +                       void (*func)(struct journal_callback *jcb, int error),
205 +                       struct journal_callback *jcb)
206 +{
207 +       spin_lock(&handle->h_transaction->t_jcb_lock);
208 +       list_add_tail(&jcb->jcb_list, &handle->h_jcb);
209 +       spin_unlock(&handle->h_transaction->t_jcb_lock);
210 +       jcb->jcb_func = func;
211 +}
212 +
213 +/**
214   * int journal_stop() - complete a transaction
215   * @handle: tranaction to complete.
216   * 
217 @@ -1363,6 +1396,11 @@ int journal_stop(handle_t *handle)
218                         wake_up(&journal->j_wait_transaction_locked);
219         }
220  
221 +       /* Move callbacks from the handle to the transaction. */
222 +       spin_lock(&transaction->t_jcb_lock);
223 +       list_splice(&handle->h_jcb, &transaction->t_jcb);
224 +       spin_unlock(&transaction->t_jcb_lock);
225 +
226         /*
227          * If the handle is marked SYNC, we need to set another commit
228          * going!  We also want to force a commit if the current