+
+ scand_process = kthread_run(gfs2_scand, NULL, "gfs2_scand");
+ if (IS_ERR(scand_process))
+ return PTR_ERR(scand_process);
+
+ glock_workqueue = create_workqueue("glock_workqueue");
+ if (IS_ERR(glock_workqueue)) {
+ kthread_stop(scand_process);
+ return PTR_ERR(glock_workqueue);
+ }
+
+ return 0;
+}
+
+void gfs2_glock_exit(void)
+{
+ destroy_workqueue(glock_workqueue);
+ kthread_stop(scand_process);
+}
+
+module_param(scand_secs, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(scand_secs, "The number of seconds between scand runs");
+
+static int gfs2_glock_iter_next(struct glock_iter *gi)
+{
+ struct gfs2_glock *gl;
+
+restart:
+ read_lock(gl_lock_addr(gi->hash));
+ gl = gi->gl;
+ if (gl) {
+ gi->gl = hlist_entry(gl->gl_list.next,
+ struct gfs2_glock, gl_list);
+ if (gi->gl)
+ gfs2_glock_hold(gi->gl);
+ }
+ read_unlock(gl_lock_addr(gi->hash));
+ if (gl)
+ gfs2_glock_put(gl);
+ if (gl && gi->gl == NULL)
+ gi->hash++;
+ while(gi->gl == NULL) {
+ if (gi->hash >= GFS2_GL_HASH_SIZE)
+ return 1;
+ read_lock(gl_lock_addr(gi->hash));
+ gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
+ struct gfs2_glock, gl_list);
+ if (gi->gl)
+ gfs2_glock_hold(gi->gl);
+ read_unlock(gl_lock_addr(gi->hash));
+ gi->hash++;
+ }
+
+ if (gi->sdp != gi->gl->gl_sbd)
+ goto restart;
+
+ return 0;
+}
+
+static void gfs2_glock_iter_free(struct glock_iter *gi)
+{
+ if (gi->gl)
+ gfs2_glock_put(gi->gl);
+ kfree(gi);
+}
+
+static struct glock_iter *gfs2_glock_iter_init(struct gfs2_sbd *sdp)
+{
+ struct glock_iter *gi;
+
+ gi = kmalloc(sizeof (*gi), GFP_KERNEL);
+ if (!gi)
+ return NULL;
+
+ gi->sdp = sdp;
+ gi->hash = 0;
+ gi->seq = NULL;
+ gi->gl = NULL;
+ memset(gi->string, 0, sizeof(gi->string));
+
+ if (gfs2_glock_iter_next(gi)) {
+ gfs2_glock_iter_free(gi);
+ return NULL;
+ }
+
+ return gi;
+}
+
+static void *gfs2_glock_seq_start(struct seq_file *file, loff_t *pos)
+{
+ struct glock_iter *gi;
+ loff_t n = *pos;
+
+ gi = gfs2_glock_iter_init(file->private);
+ if (!gi)
+ return NULL;
+
+ while(n--) {
+ if (gfs2_glock_iter_next(gi)) {
+ gfs2_glock_iter_free(gi);
+ return NULL;
+ }
+ }
+
+ return gi;
+}
+
+static void *gfs2_glock_seq_next(struct seq_file *file, void *iter_ptr,
+ loff_t *pos)
+{
+ struct glock_iter *gi = iter_ptr;
+
+ (*pos)++;
+
+ if (gfs2_glock_iter_next(gi)) {
+ gfs2_glock_iter_free(gi);
+ return NULL;
+ }
+
+ return gi;
+}
+
+static void gfs2_glock_seq_stop(struct seq_file *file, void *iter_ptr)
+{
+ struct glock_iter *gi = iter_ptr;
+ if (gi)
+ gfs2_glock_iter_free(gi);
+}
+
+static int gfs2_glock_seq_show(struct seq_file *file, void *iter_ptr)
+{
+ struct glock_iter *gi = iter_ptr;
+
+ gi->seq = file;
+ dump_glock(gi, gi->gl);
+