[Ocfs2-commits] rev 11 - in trunk: . src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Thu Dec 18 23:17:30 CST 2003
Author: manish
Date: 2003-12-18 17:17:02 -0600 (Thu, 18 Dec 2003)
New Revision: 11
Added:
trunk/src/
trunk/src/alloc.c
trunk/src/bitmap.c
trunk/src/dcache.c
trunk/src/dir.c
trunk/src/divdi3.c
trunk/src/dlm.c
trunk/src/extmap.c
trunk/src/file.c
trunk/src/hash.c
trunk/src/heartbeat.c
trunk/src/inode.c
trunk/src/ioctl.c
trunk/src/journal.c
trunk/src/namei.c
trunk/src/nm.c
trunk/src/oin.c
trunk/src/osb.c
trunk/src/proc.c
trunk/src/sem.c
trunk/src/super.c
trunk/src/symlink.c
trunk/src/sysfile.c
trunk/src/util.c
trunk/src/ver.c
trunk/src/volcfg.c
trunk/src/vote.c
Removed:
trunk/alloc.c
trunk/bitmap.c
trunk/dcache.c
trunk/dir.c
trunk/divdi3.c
trunk/dlm.c
trunk/extmap.c
trunk/file.c
trunk/hash.c
trunk/heartbeat.c
trunk/inode.c
trunk/ioctl.c
trunk/journal.c
trunk/namei.c
trunk/nm.c
trunk/oin.c
trunk/osb.c
trunk/proc.c
trunk/sem.c
trunk/super.c
trunk/symlink.c
trunk/sysfile.c
trunk/util.c
trunk/ver.c
trunk/volcfg.c
trunk/vote.c
Log:
reorg
Deleted: trunk/alloc.c
===================================================================
--- trunk/alloc.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/alloc.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,3984 +0,0 @@
-#ifdef __KERNEL__
-#include <ocfs.h>
-#else
-#include <debugocfs.h>
-#endif
-
-#ifndef USERSPACE_TOOL
-
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-static int ocfs_allocate_new_data_node (ocfs_super * osb,
- ocfs_file_entry * FileEntry,
- __u64 actualDiskOffset, __u64 actualLength,
- struct buffer_head * extent_header_bh,
- __u64 * NewExtentOffset,
- ocfs_journal_handle *handle, struct inode *inode);
-
-static int ocfs_grow_extent_tree (ocfs_super * osb, struct buffer_head *fe_bh,
- ocfs_journal_handle *handle, __u64 disk_off,
- __u64 length, struct inode *inode);
-
-static int _squish_extent_entries(ocfs_super *osb, ocfs_alloc_ext *extarr,
- __u32 *freeExtent,
- ocfs_bitmap_free_head * free_head,
- __u64 FileSize, bool flag, struct inode *inode) ;
-
-static int ocfs_fix_extent_group(ocfs_super *osb, struct buffer_head *group_bh, struct inode *inode);
-
-static int ocfs_split_this_tree(ocfs_super * osb,
- struct buffer_head *extent_grp_bh,
- ocfs_bitmap_free_head *free_head,
- ocfs_file_entry *fe,
- ocfs_journal_handle *handle, struct inode *inode);
-
-static int ocfs_update_last_ext_ptr(ocfs_super *osb, ocfs_file_entry *fe, struct inode *inode);
-
-static int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_rec * FreeLog,
- __u32 NodeNum, __u32 Type);
-
-static int ocfs_free_disk_bitmap (ocfs_super * osb, ocfs_free_rec *free_log);
-
-static inline int ocfs_free_main_bitmap(ocfs_super *osb,
- ocfs_free_rec *freelog);
-
-static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh);
-static int ocfs_sync_local_to_main(ocfs_super *osb,
- ocfs_bitmap_free_head **f,
- struct buffer_head *local_alloc_bh,
- struct buffer_head *bm_lock_bh);
-static __u32 ocfs_alloc_count_bits(ocfs_local_alloc *alloc);
-static void ocfs_clear_local_alloc(ocfs_local_alloc *alloc);
-static int ocfs_find_space_from_local(ocfs_super *osb, __u32 bitswanted,
- __u64 * bitoff, __u64 * bitcount,
- ocfs_journal_handle *handle);
-static int ocfs_local_find_clear_bits(ocfs_super *osb, ocfs_local_alloc *alloc, __u32 numbits);
-
-/* this is a good candidate for an inline function. */
-int ocfs_process_bitmap_free_head(ocfs_super *osb, ocfs_bitmap_free_head *f)
-{
- struct list_head *p, *n;
- ocfs_free_rec *log;
- int status = 0, tmpstat;
-
- LOG_ENTRY_ARGS("(osb=0x%08x, f=0x%08x, f->num_logs = %d)\n", osb, f,
- f->num_logs);
-
- ocfs_take_trans_lock(osb);
-
- list_for_each_safe(p, n, &(f->free_logs)) {
- LOG_TRACE_ARGS("f->num_logs = %d\n", f->num_logs);
- log = list_entry(p, ocfs_free_rec, log_list);
- tmpstat = ocfs_free_disk_bitmap(osb, log);
- if (tmpstat)
- status = tmpstat;
- list_del(&(log->log_list));
- ocfs_safefree(log);
- f->num_logs--;
- }
-
- ocfs_release_trans_lock(osb);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-int ocfs_add_to_bitmap_free_head(ocfs_super *osb, ocfs_bitmap_free_head *f,
- u32 len, __u32 fileoff, __u32 nodenum, __u32 type)
-{
- int status = 0, n;
- ocfs_free_rec *log;
- ocfs_bitmap_update *fb;
-
- LOG_ENTRY_ARGS("(len = %u, fileoff = %u, nodenum = %u, "
- "type=%d (\"%s\")\n", len, fileoff, nodenum, type,
- (type == DISK_ALLOC_VOLUME) ? "DISK_ALLOC_VOLUME" :
- ( (type == DISK_ALLOC_EXTENT_NODE) ?
- "DISK_ALLOC_EXTENT_NODE" : "DISK_ALLOC_DIR_NODE" ));
-
- log = f->tail;
-
- /* need a new one? */
- if (list_empty(&(f->free_logs)) ||
- log->num_updates >= FREE_LOG_SIZE) {
- LOG_TRACE_STR("Adding a new list entry.");
- log = ocfs_malloc(sizeof(ocfs_free_rec));
- if (log == NULL) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto done;
- }
- memset(log, 0, sizeof(ocfs_free_rec));
- INIT_LIST_HEAD(&(log->log_list));
- list_add_tail(&(log->log_list), &(f->free_logs));
- f->tail = log;
- f->num_logs++;
- }
-
- n = log->num_updates;
- fb = &(log->update[n]);
-
- fb->length = len;
- fb->file_off = fileoff;
- fb->type = type;
- fb->node_num = nodenum;
-
- log->num_updates++;
-done:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * ocfs_free_disk_bitmap()
- *
- */
-static int ocfs_free_disk_bitmap (ocfs_super * osb, ocfs_free_rec *free_log)
-{
- int status = 0;
- __u32 num_upd;
- __u32 i;
- __u32 node_num;
- ocfs_free_rec **free_dir_node = NULL;
- ocfs_free_rec **free_ext_node = NULL;
- ocfs_free_rec *free_vol_bits = NULL;
- ocfs_lock_res **dirnode_lockres = NULL;
- ocfs_lock_res **extnode_lockres = NULL;
- ocfs_lock_res *vol_lockres = NULL;
- ocfs_free_rec *tmp_log;
- __u32 tmp_indx;
- __u64 lock_id;
- struct buffer_head *globalbh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", osb, free_log);
-
-#define ALLOC_BLOCK(ptr, len, err) \
- do { \
- (ptr) = ocfs_malloc (len); \
- if (!(ptr)) { \
- LOG_ERROR_STATUS ((err) = -ENOMEM); \
- goto finally; \
- } \
- } while (0)
-
- ALLOC_BLOCK(free_dir_node,
- OCFS_MAXIMUM_NODES * sizeof (ocfs_free_rec *), status);
- ALLOC_BLOCK(free_ext_node,
- OCFS_MAXIMUM_NODES * sizeof (ocfs_free_rec *), status);
- ALLOC_BLOCK(dirnode_lockres,
- OCFS_MAXIMUM_NODES * sizeof (ocfs_lock_res *), status);
- ALLOC_BLOCK(extnode_lockres,
- OCFS_MAXIMUM_NODES * sizeof (ocfs_lock_res *), status);
-
- /* init */
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- free_dir_node[i] = NULL;
- free_ext_node[i] = NULL;
- }
-
- /* alloc memory */
- num_upd = free_log->num_updates;
- for (i = 0; i < num_upd; i++) {
- switch (free_log->update[i].type) {
- case DISK_ALLOC_DIR_NODE:
- node_num = free_log->update[i].node_num;
- if (free_dir_node[node_num] == NULL) {
- free_dir_node[node_num] =
- ocfs_malloc (sizeof (ocfs_free_rec));
- if (free_dir_node[node_num] == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- free_dir_node[node_num]->num_updates = 0;
- }
- tmp_log = free_dir_node[node_num];
- break;
-
- case DISK_ALLOC_EXTENT_NODE:
- node_num = free_log->update[i].node_num;
- if (free_ext_node[node_num] == NULL) {
- free_ext_node[node_num] =
- ocfs_malloc (sizeof (ocfs_free_rec));
- if (free_ext_node[node_num] == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- free_ext_node[node_num]->num_updates = 0;
- }
- tmp_log = free_ext_node[node_num];
- break;
-
- case DISK_ALLOC_VOLUME:
- if (free_vol_bits == NULL) {
- free_vol_bits =
- ocfs_malloc (sizeof (ocfs_free_rec));
- if (free_vol_bits == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- free_vol_bits->num_updates = 0;
- }
- tmp_log = free_vol_bits;
- break;
-
- default:
- tmp_log = NULL;
- break;
- }
-
- if (tmp_log) {
- ocfs_bitmap_update *fb1, *fb2;
-
- tmp_indx = tmp_log->num_updates;
-
- fb1 = &(tmp_log->update[tmp_indx]);
- fb2 = &(free_log->update[i]);
-
- fb1->length = fb2->length;
- fb1->file_off = fb2->file_off;
- fb1->type = fb2->type;
- fb1->node_num = fb2->node_num;
-
- tmp_log->num_updates++;
- }
- }
-
- /* Get all the locks we need. do global bitmap last to
- * preserve lock ordering with extend/create */
-
- lock_id = (OCFS_FILE_DIR_ALLOC_BITMAP * osb->sect_size) +
- osb->vol_layout.root_int_off;
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
- if (free_dir_node[i] != NULL) {
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- &(dirnode_lockres[i]), NULL, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- }
-
- lock_id = (OCFS_FILE_FILE_ALLOC_BITMAP * osb->sect_size) +
- osb->vol_layout.root_int_off;
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
- if (free_ext_node[i] != NULL) {
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- &(extnode_lockres[i]), NULL, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- }
-
- if (free_vol_bits != NULL) {
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, &vol_lockres, &globalbh, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
-
- /* free vol block */
- if (free_vol_bits != NULL)
- ocfs_free_vol_block (osb, free_vol_bits, -1, DISK_ALLOC_VOLUME);
-
- /* We can potentiallly loose some allocation for dirNodes or extent */
- /* nodes but they should not be much... */
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- if (free_dir_node[i] != NULL)
- ocfs_free_vol_block (osb, free_dir_node[i], i,
- DISK_ALLOC_DIR_NODE);
-
- if (free_ext_node[i] != NULL)
- ocfs_free_vol_block (osb, free_ext_node[i], i,
- DISK_ALLOC_EXTENT_NODE);
- }
-
- /* release all locks */
- if (free_vol_bits != NULL) {
- ocfs_bitmap_lock *bm_lock;
-
- bm_lock = (ocfs_bitmap_lock *)OCFS_BH_GET_DATA(globalbh);
- bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
- OCFS_BH_PUT_DATA(globalbh);
-
-/* status = ocfs_write_force_disk(osb, bm_lock, OCFS_SECTOR_SIZE,
- OCFS_BITMAP_LOCK_OFFSET);*/
- status = ocfs_write_bh(osb, globalbh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- status = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, vol_lockres, globalbh, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- lock_id = (OCFS_FILE_DIR_ALLOC_BITMAP * osb->sect_size) +
- osb->vol_layout.root_int_off;
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
- if (free_dir_node[i] != NULL) {
- status = ocfs_release_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- dirnode_lockres[i], NULL, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- }
-
- lock_id = (OCFS_FILE_FILE_ALLOC_BITMAP * osb->sect_size) +
- osb->vol_layout.root_int_off;
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++, lock_id += osb->sect_size) {
- if (free_ext_node[i] != NULL) {
- status = ocfs_release_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- extnode_lockres[i], NULL, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- }
-
-finally:
-
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- if (free_dir_node[i])
- ocfs_put_lockres (dirnode_lockres[i]);
- if (free_ext_node[i])
- ocfs_put_lockres (extnode_lockres[i]);
- }
- if (globalbh)
- brelse(globalbh);
-
- ocfs_put_lockres (vol_lockres);
-
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- ocfs_safefree (free_dir_node[i]);
- ocfs_safefree (free_ext_node[i]);
- }
-
- ocfs_safefree (free_dir_node);
- ocfs_safefree (free_ext_node);
- ocfs_safefree (dirnode_lockres);
- ocfs_safefree (extnode_lockres);
-
- ocfs_safefree (free_vol_bits);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_free_disk_bitmap */
-
-static inline int ocfs_free_main_bitmap(ocfs_super *osb, ocfs_free_rec *freelog)
-{
- int i;
- ocfs_alloc_bm *bitmap;
- int status;
- __u32 bitmapblocks; /* we only care about the valid blocks */
-
- bitmap = &osb->cluster_bitmap;
-
- bitmapblocks = (OCFS_ALIGN(bitmap->validbits, OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
- /* TODO: Fix this so that we only read and write which sectors
- * off disk that we actually need instead of the whole honkin'
- * bitmap at once...
- *
- * Also, can the reads/writes be cached?
- */
- status = ocfs_read_bhs(osb, osb->vol_layout.bitmap_off,
- bitmapblocks * osb->sect_size,
- bitmap->chunk, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- for (i = 0; i < freelog->num_updates; i++)
- ocfs_clear_bits(bitmap, freelog->update[i].file_off, freelog->update[i].length);
-
- status = ocfs_write_bhs(osb, bitmap->chunk, bitmapblocks, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = 0;
-bail:
- return(0);
-}
-
-/*
- * ocfs_free_vol_block()
- *
- */
-static int ocfs_free_vol_block (ocfs_super * osb, ocfs_free_rec * FreeLog, __u32 NodeNum, __u32 Type)
-{
- int status = 0;
- __u64 fileSize = 0;
- __u64 offset = 0;
- __u64 allocSize = 0;
- __u32 foundBit = -1;
- __u32 blockSize = 0;
- __u32 fileId = 0;
- __u32 bitmapblocks = 0;
- ocfs_alloc_bm AllocBitmap;
- ocfs_alloc_bm *tmpbitmap = NULL;
- __u32 i;
- bool needs_uninit = false;
-
- LOG_ENTRY ();
-
- ocfs_down_sem (&(osb->dir_alloc_lock), true);
- ocfs_down_sem (&(osb->file_alloc_lock), true);
- ocfs_down_sem (&(osb->vol_alloc_lock), true);
-
- LOG_TRACE_ARGS("Free Log Details (type = %d):\n", Type);
- LOG_TRACE_ARGS("num_updates = %u\n", FreeLog->num_updates);
- for(i = 0; i < FreeLog->num_updates; i++)
- LOG_TRACE_ARGS("(upd=%u, length=%u.%u, file_off=%u.%u, type=%d, node_num=%d)\n", i, HILO(FreeLog->update[i].length), HILO(FreeLog->update[i].file_off), FreeLog->update[i].type, FreeLog->update[i].node_num);
-
- switch (Type) {
- case DISK_ALLOC_DIR_NODE:
- fileId = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
- blockSize = (__u32) osb->vol_layout.dir_node_size;
-
- if (!IS_VALID_NODE_NUM (NodeNum)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto leave;
- }
- break;
-
- case DISK_ALLOC_EXTENT_NODE:
- fileId = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
- blockSize = (__u32) osb->vol_layout.file_node_size;
-
- if (!IS_VALID_NODE_NUM (NodeNum)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto leave;
- }
- break;
-
- case DISK_ALLOC_VOLUME:
- break;
-
- default:
- goto leave;
- }
-
- if (Type == DISK_ALLOC_VOLUME) {
- /* don't need to read it here as
- * ocfs_free_main_bitmap handles that for us. */
- tmpbitmap = &osb->cluster_bitmap;
- } else {
- /* Read in the bitmap file for the dir alloc and look for the */
- /* required space, if found */
-
- status = ocfs_get_system_file_size (osb, fileId, &fileSize, &allocSize);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- ocfs_initialize_bitmap(&AllocBitmap, fileSize * 8, allocSize * 8);
- tmpbitmap = &AllocBitmap;
- needs_uninit = true;
- bitmapblocks = (OCFS_ALIGN(tmpbitmap->validbits, OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
-
- status = ocfs_read_system_file(osb, fileId, AllocBitmap.chunk,
- bitmapblocks * osb->sect_size,
- offset);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- }
-
- if (Type == DISK_ALLOC_VOLUME) {
- status = ocfs_free_main_bitmap(osb, FreeLog);
- if (status < 0){
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else {
- for (i = 0; i < FreeLog->num_updates; i++) {
- if (FreeLog->update[i].file_off == 0 && Type == 0) {
- LOG_ERROR_ARGS ("offset=0, type=%x, blksz=%d", Type,
- blockSize);
- }
-
- if (Type == DISK_ALLOC_VOLUME)
- foundBit = (__u32) FreeLog->update[i].file_off;
- else
- foundBit = (__u32)
- (FreeLog->update[i].file_off /
- blockSize);
-
- ocfs_clear_bits(tmpbitmap, (__u32) foundBit,
- (__u32) FreeLog->update[i].length);
- }
- }
-
- /* ocfs_free_main_bitmap handles all the reads/writes for the
- * main bitmap */
- if (Type != DISK_ALLOC_VOLUME) {
- status = ocfs_write_system_file(osb, fileId, tmpbitmap->chunk,
- bitmapblocks * osb->sect_size,
- offset);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-leave:
- ocfs_up_sem (&(osb->vol_alloc_lock));
- ocfs_up_sem (&(osb->file_alloc_lock));
- ocfs_up_sem (&(osb->dir_alloc_lock));
-
- if (needs_uninit)
- ocfs_uninitialize_bitmap(tmpbitmap);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_free_vol_block */
-
-
-/* ocfs_allocate_new_data_node()
- *
- */
-static int ocfs_allocate_new_data_node (ocfs_super * osb,
- ocfs_file_entry * FileEntry,
- __u64 actualDiskOffset, __u64 actualLength,
- struct buffer_head * extent_header_bh,
- __u64 * NewExtentOffset, ocfs_journal_handle *handle, struct inode *inode)
-{
- int status = 0;
- __u8 *buff = NULL;
- __u32 k, i;
- __u32 depth;
- __u32 allocSize;
- __u64 upHeaderPtr;
- __u64 physicalOffset;
- __u64 fileOffset = 0;
- __u64 numSectorsAlloc = 0;
- __u64 lastExtPointer;
- ocfs_extent_group* extent_header = NULL;
- struct buffer_head **header_bhs = NULL;
- struct buffer_head *bh = NULL;
- int bh_locked = 0;
- int size;
-
- LOG_ENTRY ();
-
- if (extent_header_bh) {
- if (handle) {
- status = ocfs_journal_access(handle, extent_header_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
-
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
- extent_header = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_header_bh);
- bh_locked = 1;
- }
- if (extent_header != NULL) {
- depth = extent_header->granularity;
- upHeaderPtr = extent_header->this_ext;
- } else {
- depth = FileEntry->granularity;
- upHeaderPtr = FileEntry->this_sector;
- }
-
- numSectorsAlloc = NUM_SECTORS_IN_LEAF_NODE + depth;
- allocSize = (numSectorsAlloc * OCFS_SECTOR_SIZE);
-
- /* allocate contiguous blocks on disk */
- status = ocfs_alloc_node_block (osb, allocSize, &physicalOffset,
- &fileOffset, osb->node_num,
- DISK_ALLOC_EXTENT_NODE, handle);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- size = sizeof(struct buffer_head *) * numSectorsAlloc;
- header_bhs = ocfs_malloc(size);
- if (header_bhs == NULL) {
- status = -ENOMEM;
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- memset(header_bhs, 0, size);
-
- status = ocfs_read_bhs(osb, physicalOffset, numSectorsAlloc * osb->sect_size, header_bhs, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* zero them all out */
- for(i = 0; i < numSectorsAlloc; i++) {
- if (handle) {
- status = ocfs_journal_access(handle, header_bhs[i],
- OCFS_JOURNAL_ACCESS_WRITE);
-
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
- buff = OCFS_BH_GET_DATA(header_bhs[i]);
- memset(buff, 0, osb->sect_size);
-
- /* TODO: Do we really need to do this? */
-#ifdef LINUX_2_5
- set_buffer_uptodate(header_bhs[i]);
-#else
- mark_buffer_uptodate(header_bhs[i], true);
-#endif
- OCFS_BH_PUT_DATA(header_bhs[i]);
- }
-
- if (fileOffset == 0) {
- LOG_ERROR_ARGS ("offset=0, file=%s", FileEntry->filename);
- }
-
- if (extent_header != NULL) {
- k = extent_header->next_free_ext;
- extent_header->extents[k].file_off = FileEntry->alloc_size;
- extent_header->extents[k].num_bytes = actualLength;
- extent_header->extents[k].disk_off = physicalOffset;
- extent_header->next_free_ext++;
- } else {
- k = FileEntry->next_free_ext;
- FileEntry->extents[k].file_off = FileEntry->alloc_size;
- FileEntry->extents[k].num_bytes = actualLength;
- FileEntry->extents[k].disk_off = physicalOffset;
- FileEntry->next_free_ext++;
- }
-
-
- lastExtPointer = FileEntry->last_ext_ptr;
-
- /* Fill in all the headers and the leaf */
- for (i = 0; i <= depth; i++) {
- ocfs_extent_group *ext;
- ext = (ocfs_extent_group *) OCFS_BH_GET_DATA(header_bhs[i]);
-
- ext->last_ext_ptr = lastExtPointer;
- ext->up_hdr_node_ptr = upHeaderPtr;
- ext->next_free_ext = 1;
- ext->alloc_file_off = fileOffset + (OCFS_SECTOR_SIZE * i);
- ext->alloc_node = osb->node_num;
- ext->extents[0].file_off = FileEntry->alloc_size;
- ext->extents[0].num_bytes = actualLength;
- ext->this_ext = (__u64) (physicalOffset + (OCFS_SECTOR_SIZE * i));
-
- if (i != depth) {
- /* fill in each header */
- ext->type = OCFS_EXTENT_HEADER;
- ext->extents[0].disk_off = (__u64) (physicalOffset + (OCFS_SECTOR_SIZE * (i + 1)));
- ext->granularity = (depth - 1 - i);
- strcpy (ext->signature, OCFS_EXTENT_HEADER_SIGNATURE);
- } else {
- /* fill in the leaf */
- ext->type = OCFS_EXTENT_DATA;
- ext->extents[0].disk_off = actualDiskOffset;
- ext->curr_sect = 1;
- ext->max_sects = NUM_SECTORS_IN_LEAF_NODE;
- strcpy (ext->signature, OCFS_EXTENT_DATA_SIGNATURE);
- (*NewExtentOffset) = FileEntry->last_ext_ptr = ext->this_ext;
- }
-
- upHeaderPtr = lastExtPointer = ext->this_ext;
- OCFS_BH_PUT_DATA(header_bhs[i]);
- }
-
- if (handle) {
- for(i = 0; i < numSectorsAlloc; i++) {
- status = ocfs_journal_dirty(handle, header_bhs[i]);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- } else {
- /* Write the extents to disk */
- status = ocfs_write_bhs(osb, header_bhs, numSectorsAlloc, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- if (extent_header != NULL) {
- /* both needed below in for loop */
- __u64 up_hdr_node_ptr = extent_header->up_hdr_node_ptr;
- int granularity = extent_header->granularity;
-
- OCFS_BH_PUT_DATA(extent_header_bh);
- bh_locked = 0;
- extent_header = NULL;
- if (handle)
- status = ocfs_journal_dirty(handle, extent_header_bh);
- else
- status = ocfs_write_bh(osb, extent_header_bh, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* gotta fix up his parent extents now. We totally
- * reuse the extent_header variable now as it's no
- * longer needed for it's original purpose. */
- for (i = granularity + 1; i < FileEntry->granularity; i++) {
- bh = NULL;
- status = ocfs_read_bh (osb, up_hdr_node_ptr, &bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- if (handle) {
- status = ocfs_journal_access(handle, bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
- extent_header = (ocfs_extent_group *) OCFS_BH_GET_DATA(bh);
- if (!IS_VALID_EXTENT_HEADER(extent_header)) {
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- if (extent_header->next_free_ext == 0) {
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- LOG_ERROR_STATUS (status = -EFAIL);
- goto finally;
- }
-
- k = extent_header->next_free_ext - 1;
- extent_header->extents[k].num_bytes += actualLength;
-
- up_hdr_node_ptr = extent_header->up_hdr_node_ptr;
- OCFS_BH_PUT_DATA(bh);
-
- if (handle)
- status = ocfs_journal_dirty(handle, bh);
- else
- status = ocfs_write_bh(osb, bh, 0, inode);
- if (status < 0) {
- brelse(bh);
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- brelse(bh);
- }
- k = FileEntry->next_free_ext - 1;
- FileEntry->extents[k].num_bytes += actualLength;
- }
-finally:
- if (bh_locked)
- OCFS_BH_PUT_DATA(extent_header_bh);
- if (header_bhs) {
- for (i = 0; i < numSectorsAlloc; i++)
- if (header_bhs[i])
- brelse(header_bhs[i]);
- ocfs_free(header_bhs);
- }
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_allocate_new_data_node */
-
-/* ocfs_grow_extent_tree()
- *
- */
-int ocfs_grow_extent_tree (ocfs_super * osb, struct buffer_head *fe_bh, ocfs_journal_handle *handle, __u64 disk_off, __u64 length, struct inode *inode)
-{
- int status = 0;
- __s32 k, i;
- ocfs_extent_group *OcfsExtent = NULL;
- ocfs_extent_group *ExtentHeader = NULL;
- ocfs_extent_group *ext = NULL;
- __u64 physicalOffset;
- __u64 fileOffset = 0;
- __u64 upHeaderPtr, lastExtentPtr;
- __u32 AllocSize;
- __u64 new_up_hdr_ptr = 0;
- struct buffer_head **bhs = NULL;
- int numbhs = 0;
- void *buf;
- ocfs_file_entry * fe = NULL, *real_fe = NULL;
-
- LOG_ENTRY_ARGS("(0x%08x, 0x%08x, %u.%u, %u.%u\n", osb, fe, HILO(disk_off), HILO(length));
-
- /* too complicated to deal with both reads and writes to the structure */
- /* just save off a copy and replace the fe_bh with the new data at the end */
- fe = ocfs_allocate_file_entry();
- if (fe == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- real_fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
- memcpy(fe, real_fe, 512);
- OCFS_BH_PUT_DATA(fe_bh);
- real_fe = NULL;
-
- AllocSize = ((fe->granularity + 2) * OCFS_SECTOR_SIZE);
-
- numbhs = fe->granularity + 2;
- bhs = ocfs_malloc(numbhs * sizeof(*bhs));
- if (bhs == NULL) {
- status = -ENOMEM;
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto finally;
- }
- memset(bhs, 0, numbhs * sizeof(*bhs));
-
- /* Allocate the space from the Extent file. This function should */
- /* return contigous disk blocks requested. */
- status = ocfs_alloc_node_block (osb, AllocSize, &physicalOffset,
- &fileOffset, osb->node_num,
- DISK_ALLOC_EXTENT_NODE, handle);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- for (i = 0; i < numbhs; i++) {
- bhs[i] = getblk(OCFS_GET_BLOCKDEV(osb->sb), (physicalOffset + i * osb->sect_size) / osb->sect_size, osb->sb->s_blocksize);
- if (bhs[i] == NULL) {
- status = -EIO;
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- buf = OCFS_BH_GET_DATA(bhs[i]);
- memset(buf, 0, osb->sect_size);
-#ifdef LINUX_2_5
- set_buffer_uptodate(bhs[i]);
-#else
- mark_buffer_uptodate(bhs[i], true);
-#endif
- OCFS_BH_PUT_DATA(bhs[i]);
- }
-
- if (fileOffset == 0) {
- LOG_TRACE_ARGS ("offset=0, file=%s\n", fe->filename);
- }
-
- if (physicalOffset == 0) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto finally;
- }
-
- OcfsExtent = (ocfs_extent_group *) OCFS_BH_GET_DATA(bhs[0]);
- /* Copy the File Entry information in to the newly allocated sector */
- for (k = 0; k < OCFS_MAX_FILE_ENTRY_EXTENTS; k++) {
- OcfsExtent->extents[k].file_off = fe->extents[k].file_off;
- OcfsExtent->extents[k].num_bytes = fe->extents[k].num_bytes;
- OcfsExtent->extents[k].disk_off = fe->extents[k].disk_off;
- }
-
- OcfsExtent->last_ext_ptr = fe->last_ext_ptr;
- lastExtentPtr = fe->last_ext_ptr;
- OcfsExtent->this_ext = new_up_hdr_ptr = physicalOffset;
- OcfsExtent->alloc_file_off = fileOffset;
- OcfsExtent->alloc_node = osb->node_num;
- OcfsExtent->next_data_ext = 0;
- fe->local_ext = false;
- fe->granularity++;
-
- LOG_TRACE_ARGS ("Granularity is: %d\n", fe->granularity);
-
- OCFS_BH_PUT_DATA(bhs[0]);
-
- /* If granularity is zero now, the for loop will not execute. */
- /* First time a file is created ,granularity = -1 and local_ext flag */
- /* is set to true */
-
- upHeaderPtr = fe->this_sector;
-
- for (i = 0; i < fe->granularity; i++) {
- ExtentHeader = (ocfs_extent_group *) OCFS_BH_GET_DATA(bhs[i]);
-
- ExtentHeader->type = OCFS_EXTENT_HEADER;
- ExtentHeader->granularity = (fe->granularity - 1) - i;
-
- strcpy (ExtentHeader->signature, OCFS_EXTENT_HEADER_SIGNATURE);
-
- if (i == 0) {
- ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].disk_off = physicalOffset + OCFS_SECTOR_SIZE;
- ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].file_off = fe->alloc_size;
- ExtentHeader->extents[OCFS_MAX_FILE_ENTRY_EXTENTS].num_bytes = length;
-
- ExtentHeader->next_free_ext = OCFS_MAX_FILE_ENTRY_EXTENTS + 1;
- ExtentHeader->this_ext = physicalOffset;
- ExtentHeader->last_ext_ptr = lastExtentPtr;
- ExtentHeader->up_hdr_node_ptr = upHeaderPtr;
-
- upHeaderPtr = ExtentHeader->this_ext;
- lastExtentPtr = ExtentHeader->this_ext;
- } else {
- ExtentHeader->extents[0].disk_off = physicalOffset + (OCFS_SECTOR_SIZE * (i + 1));
- ExtentHeader->extents[0].file_off = fe->alloc_size;
- ExtentHeader->extents[0].num_bytes = length;
- ExtentHeader->next_free_ext = 1;
- ExtentHeader->alloc_file_off = fileOffset + (OCFS_SECTOR_SIZE * i);
- ExtentHeader->alloc_node = osb->node_num;
- ExtentHeader->this_ext = physicalOffset + (OCFS_SECTOR_SIZE * i);
- ExtentHeader->up_hdr_node_ptr = upHeaderPtr;
- ExtentHeader->last_ext_ptr = lastExtentPtr;
-
- upHeaderPtr = ExtentHeader->this_ext;
- lastExtentPtr = ExtentHeader->this_ext;
- }
- OCFS_BH_PUT_DATA(bhs[i]);
- }
-
- /* Update the Data Segment, which is the last one in our array */
- OcfsExtent = (ocfs_extent_group *) OCFS_BH_GET_DATA(bhs[fe->granularity]);
-
- i = (fe->granularity) ? 0 : OCFS_MAX_FILE_ENTRY_EXTENTS;
-
- LOG_TRACE_ARGS ("EntryAvailable is: %d\n", OcfsExtent->next_free_ext);
-
- /* For the time being we are assuming that the newly allocated Extent */
- /* will have one more entry to accomodate the latest allocation */
-
- strcpy (OcfsExtent->signature, OCFS_EXTENT_DATA_SIGNATURE);
-
- OcfsExtent->extents[i].file_off = fe->alloc_size;
- OcfsExtent->extents[i].num_bytes = length;
- OcfsExtent->extents[i].disk_off = disk_off;
- OcfsExtent->curr_sect = 1;
- OcfsExtent->max_sects = NUM_SECTORS_IN_LEAF_NODE;
- OcfsExtent->type = OCFS_EXTENT_DATA;
- OcfsExtent->next_free_ext = i + 1;
- OcfsExtent->alloc_file_off = fileOffset + (fe->granularity * OCFS_SECTOR_SIZE);
- OcfsExtent->alloc_node = osb->node_num;
- OcfsExtent->this_ext = physicalOffset + (fe->granularity * OCFS_SECTOR_SIZE);
- OcfsExtent->up_hdr_node_ptr = upHeaderPtr;
- OcfsExtent->last_ext_ptr = lastExtentPtr;
- OcfsExtent->next_data_ext = 0;
-
- upHeaderPtr = OcfsExtent->this_ext;
- lastExtentPtr = OcfsExtent->this_ext;
-
- OCFS_BH_PUT_DATA(bhs[fe->granularity]);
-
- /* This needs to be a sync write OR journalled to be safe. */
- status = ocfs_write_bhs(osb, bhs, numbhs, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* Update the Previous Last Data Extent with this new Data
- * Extent Pointer */
- if (fe->last_ext_ptr != 0) {
- struct buffer_head *bh = NULL;
-
- status = ocfs_read_bh(osb, fe->last_ext_ptr, &bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- if (handle) {
- status = ocfs_journal_access(handle, bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- ext = (ocfs_extent_group *) OCFS_BH_GET_DATA(bh);
- if (!IS_VALID_EXTENT_DATA(ext)) {
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- ext->next_data_ext = OcfsExtent->this_ext;
- OCFS_BH_PUT_DATA(bh);
-
- if (handle)
- status = ocfs_journal_dirty(handle, bh);
- else
- status = ocfs_write_bh(osb, bh, 0, inode);
- brelse(bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- /* Update the uphdrptr of the three extents pointed to by fe */
- if (fe->granularity > 0) {
- int i;
- __u64 offset;
- struct buffer_head *bh = NULL;
-
- status = 0;
- for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; ++i) {
- offset = fe->extents[i].disk_off;
- status = ocfs_read_bh(osb, offset, &bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- brelse(bh);
- break;
- }
-
- if (handle) {
- status = ocfs_journal_access(handle, bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- ext = (ocfs_extent_group *) OCFS_BH_GET_DATA(bh);
- ext->up_hdr_node_ptr = new_up_hdr_ptr;
- OCFS_BH_PUT_DATA(bh);
-
- if (handle)
- status = ocfs_journal_dirty(handle, bh);
- else
- status = ocfs_write_bh(osb, bh, 0, inode);
- brelse(bh);
- bh = NULL;
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
- }
-
- /* Clear all the extent information from File Entry */
- for (i = 0; i < OCFS_MAX_FILE_ENTRY_EXTENTS; i++) {
- fe->extents[i].file_off = 0;
- fe->extents[i].num_bytes = 0;
- fe->extents[i].disk_off = 0;
- }
-
- /* Update the File Entry Extent */
- fe->local_ext = false;
-
- LOG_TRACE_ARGS("fe->alloc_size = %u.%u\n", HILO(fe->alloc_size));
- fe->extents[0].file_off = 0;
- fe->extents[0].num_bytes = fe->alloc_size + length;
- fe->extents[0].disk_off = physicalOffset;
- fe->last_ext_ptr = lastExtentPtr;
- fe->next_free_ext = 1;
-
-finally:
-
- if (fe) {
- real_fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
- memcpy(real_fe, fe, 512);
- OCFS_BH_PUT_DATA(fe_bh);
- real_fe = NULL;
- ocfs_release_file_entry(fe);
- }
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_grow_extent_tree */
-
-/*
- * ocfs_allocate_extent()
- *
- */
-int ocfs_allocate_extent (ocfs_super * osb, ocfs_inode * oin, struct buffer_head *fe_bh, ocfs_journal_handle *handle, __u64 actualDiskOffset, __u64 actualLength, struct inode *inode)
-{
- int status = 0;
- bool IncreaseTreeDepth = false;
- __u32 k = 0, i;
- ocfs_extent_group *extent = NULL, *extent_header = NULL;
- struct buffer_head *extent_bh = NULL, *extent_header_bh = NULL;
- bool UpdateParent = false;
- __u64 newExtentOff, up_ptr;
- ocfs_file_entry * FileEntry = NULL;
-
- LOG_ENTRY_ARGS("(actualDiskOffset=%u.%u, actualLength=%u.%u)\n", actualDiskOffset, actualLength);
-
- FileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
- OCFS_ASSERT (FileEntry);
-
- if (!IS_VALID_FILE_ENTRY (FileEntry)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto finally;
- }
-
- if (FileEntry->local_ext) {
- /* We are still using the local extents of File Entry */
- if (FileEntry->next_free_ext > OCFS_MAX_FILE_ENTRY_EXTENTS) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto finally;
- }
-
- k = FileEntry->next_free_ext - 1;
- if (k >= 0 && OCFS_EXTENT_MERGEABLE (&FileEntry->extents[k], actualDiskOffset)) {
- /* See if we can merge the extents and just increase the length */
- LOG_TRACE_ARGS ("Using local_ext for extent Entry = %u\n", k);
- FileEntry->extents[k].num_bytes += actualLength;
- goto finally;
- }
-
- /* We cannot merge try to give him the next extent */
- k = FileEntry->next_free_ext;
- if (k != OCFS_MAX_FILE_ENTRY_EXTENTS) {
- /* file_off for the new extent will be equal
- * to the previous allocation size of file */
- FileEntry->extents[k].file_off = FileEntry->alloc_size;
- FileEntry->extents[k].num_bytes = actualLength;
- FileEntry->extents[k].disk_off = actualDiskOffset;
- FileEntry->next_free_ext++;
- goto finally;
- }
- /* We have no more room in the fe, must increase
- * granularity */
- IncreaseTreeDepth = true;
- goto increase_depth;
- }
-
- /*** Nonlocal Extents ***/
- if (FileEntry->granularity > 3)
- LOG_ERROR_ARGS ("granularity=%d", FileEntry->granularity);
-
- /* This File is no longer using Local Extents */
- IncreaseTreeDepth = false;
-
- status = ocfs_read_bh(osb, FileEntry->last_ext_ptr, &extent_bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
- if (!IS_VALID_EXTENT_DATA(extent)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- k = extent->next_free_ext - 1;
- LOG_TRACE_ARGS ("Using local_ext for extent Entry = %u\n", k);
- if (extent->next_free_ext < 1)
- LOG_ERROR_ARGS ("next_free_ext=%d", extent->next_free_ext);
-
- /* See if we can merge the extents and just increase
- * the length */
- if (k >= 0 && OCFS_EXTENT_MERGEABLE (&(extent->extents[k]), actualDiskOffset)) {
- if (handle) {
- OCFS_BH_PUT_DATA(extent_bh);
- ocfs_journal_access(handle, extent_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- extent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(extent_bh);
- }
- extent->extents[k].num_bytes += actualLength;
- status = 0;
- UpdateParent = true;
- goto do_update_parent;
- }
-
- /* We cannot merge, give him the next extent */
- k = extent->next_free_ext;
-
- if (k != OCFS_MAX_DATA_EXTENTS) {
- /* we can just add next extent */
- if (handle) {
- OCFS_BH_PUT_DATA(extent_bh);
- ocfs_journal_access(handle, extent_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- extent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(extent_bh);
- }
- extent->extents[k].file_off = FileEntry->alloc_size;
- extent->extents[k].num_bytes = actualLength;
- extent->extents[k].disk_off = actualDiskOffset;
- extent->next_free_ext++;
- UpdateParent = true;
- } else {
- __u64 up_hdr_node_ptr = 0;
-
- /* Read the last extent and keep traversing
- * upward till we find a free extent or we are
- * at the top and need to create another
- * level. */
- if (FileEntry->granularity > 0)
- up_hdr_node_ptr = extent->up_hdr_node_ptr;
-
- for (i = 0; i < FileEntry->granularity; i++) {
- /* if we loop back around */
- if (extent_header) {
- OCFS_BH_PUT_DATA(extent_header_bh);
- brelse(extent_header_bh);
- extent_header = NULL;
- extent_header_bh =NULL;
- }
- status = ocfs_read_bh (osb, up_hdr_node_ptr, &extent_header_bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- extent_header = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_header_bh);
- if (!IS_VALID_EXTENT_HEADER(extent_header)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- if (extent_header->granularity != i ||
- extent_header->next_free_ext > OCFS_MAX_DATA_EXTENTS) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto finally;
- }
-
- if (extent_header->next_free_ext != OCFS_MAX_DATA_EXTENTS)
- break;
-
- up_hdr_node_ptr = extent_header->up_hdr_node_ptr;
- } /* for (i = 0; i < FileEntry->granularity; i++) */
-
- if (extent_header) {
- OCFS_BH_PUT_DATA(extent_header_bh);
- extent_header = NULL;
- /* we may still need the bh so don't brelse */
- }
-
- /* if we got to the top, then we're at the FE. Check
- * if the FE is full -- if so, then we need to
- * increase the granularity. */
- if (i == FileEntry->granularity &&
- FileEntry->next_free_ext == OCFS_MAX_FILE_ENTRY_EXTENTS) {
- IncreaseTreeDepth = true;
- goto increase_depth;
- }
- /* ok, we need to add a branch. pass in NULL
- * if we need a whole branch, otherwise the
- * extent which needs the new leaf */
- status = ocfs_allocate_new_data_node (osb, FileEntry,
- actualDiskOffset,
- actualLength,
- extent_header_bh,
- &newExtentOff, handle, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- if (handle) {
- OCFS_BH_PUT_DATA(extent_bh);
- ocfs_journal_access(handle, extent_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- extent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(extent_bh);
- }
-
- extent->next_data_ext = newExtentOff;
- FileEntry->last_ext_ptr = newExtentOff;
- }
-
-do_update_parent:
- /* before we put the variable away, save off up_ptr as
- * we may need it if we update parent */
- up_ptr = extent->up_hdr_node_ptr;
-
- /* gotta put it away to write it ;) */
- OCFS_BH_PUT_DATA(extent_bh);
- extent = NULL;
- if (handle)
- status = ocfs_journal_dirty(handle, extent_bh);
- else
- status = ocfs_write_bh(osb, extent_bh, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- if (!IncreaseTreeDepth && UpdateParent) {
- for (i = 0; i < FileEntry->granularity; i++) {
-
- /* next two if's are for loop around */
- if (extent_header_bh) {
- if (extent_header) {
- OCFS_BH_PUT_DATA(extent_header_bh);
- extent_header = NULL;
- }
- brelse(extent_header_bh);
- extent_header_bh = NULL;
- }
- /* TODO: Can we do a cached read here? */
- status = ocfs_read_bh(osb, up_ptr, &extent_header_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- if (handle) {
- status = ocfs_journal_access(handle,
- extent_header_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
-
- extent_header = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(extent_header_bh);
- if (!IS_VALID_EXTENT_HEADER(extent_header)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- if (extent_header->next_free_ext == 0) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto finally;
- }
-
- k = extent_header->next_free_ext - 1;
-
- extent_header->extents[k].num_bytes += actualLength;
-
- /* gonna need it if we loop around */
- up_ptr = extent_header->up_hdr_node_ptr;
-
- OCFS_BH_PUT_DATA(extent_header_bh);
- extent_header = NULL;
- if (handle)
- status = ocfs_journal_dirty(handle,
- extent_header_bh);
- else
- status= ocfs_write_bh(osb, extent_header_bh,0, inode);
- if (status < 0) {
- goto finally;
- }
- }
-
- k = FileEntry->next_free_ext - 1;
-
- FileEntry->extents[k].num_bytes += actualLength;
- }
-
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
-increase_depth:
- if (IncreaseTreeDepth) {
- OCFS_BH_PUT_DATA(fe_bh);
- FileEntry = NULL;
- if (extent_bh && extent) {
- OCFS_BH_PUT_DATA(extent_bh);
- extent = NULL;
- }
- if (extent_header_bh && extent_header) {
- OCFS_BH_PUT_DATA(extent_header_bh);
- extent_header = NULL;
- }
-
- status = ocfs_grow_extent_tree(osb, fe_bh, handle, actualDiskOffset, actualLength, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
-
-finally:
- if ((status == 0) && (oin != NULL)) {
- __s64 Vbo = 0;
- __s64 Lbo = 0;
-
- /* Add this Entry in to extent map. If a new mapping
- * run to be added overlaps an existing mapping run,
- * ocfs_add_extent_map_entry merges them into a single
- * mapping run.So just adding this entry will be
- * fine. */
- if (FileEntry == NULL)
- FileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
-
- Vbo = FileEntry->alloc_size;
- Lbo = actualDiskOffset;
-
- /* Add the Entry to the extent map list */
- if (!ocfs_add_extent_map_entry (osb, &oin->map, Vbo, Lbo,
- actualLength))
- LOG_ERROR_STATUS (status = -EFAIL);
- }
-
- /* Buffers are always null if they haven't been mapped and
- * non-null if they have.
- * Buffer heads are non-NULL if they need to be brelsed */
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
-
- if (extent_header_bh) {
- if (extent_header)
- OCFS_BH_PUT_DATA(extent_header_bh);
- brelse(extent_header_bh);
- }
- if (FileEntry) {
- OCFS_BH_PUT_DATA(fe_bh);
- }
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_allocate_extent */
-
-#endif /* !USERSPACE_TOOL */
-
-
-#ifndef USERSPACE_TOOL
-
-/*
- * _squish_extent_entries()
- * FileSize is the allocated size of the file after the truncate.
- * 'flag' seems to be an indicator that (if true) tells us that we already know
- * we're gonna have to clear out all of extarr.
- */
-int _squish_extent_entries(ocfs_super *osb, ocfs_alloc_ext *extarr, __u32 *freeExtent, ocfs_bitmap_free_head *free_head, __u64 FileSize, bool flag, struct inode *inode)
-{
- int status = 0;
- bool FirstTime = true;
- ocfs_alloc_ext *ext;
- __u32 i, csize = osb->vol_layout.cluster_size,
- numBitsAllocated = 0, bitmapOffset = 0,
- firstfree = *freeExtent;
- __u64 bytes, foff, doff,
- dstart = osb->vol_layout.data_start_off,
- diskOffsetTobeFreed, lengthTobeFreed = 0,
- actualSize = 0, origLength = 0;
-
- LOG_ENTRY ();
-
- firstfree = *freeExtent;
- /* loop through the used alloc_extents */
- for (i = 0; i < firstfree; i++) {
- ext = &(extarr[i]);
- bytes = ext->num_bytes;
- foff = ext->file_off;
- doff = ext->disk_off;
- actualSize = (bytes + foff);
- if (flag || actualSize > FileSize) {
- if (flag || foff >= FileSize) {
- if (!flag && FirstTime) {
- *freeExtent = i;
- FirstTime = false;
- }
- numBitsAllocated = (__u32) (bytes/csize);
- bitmapOffset = (__u32) ((doff - dstart) / csize);
- ext->num_bytes = ext->disk_off = ext->file_off = 0;
- } else {
- if (FirstTime) {
- *freeExtent = i + 1;
- FirstTime = false;
- }
- origLength = bytes;
- ext->num_bytes = bytes = FileSize - foff;
- lengthTobeFreed = origLength - bytes;
- if (lengthTobeFreed == 0) {
- continue;
- }
- numBitsAllocated = (__u32) (lengthTobeFreed / csize);
- diskOffsetTobeFreed = doff + bytes;
- bitmapOffset = (__u32) ((diskOffsetTobeFreed - dstart) / csize);
- }
- status = ocfs_add_to_bitmap_free_head(osb, free_head, numBitsAllocated, bitmapOffset, -1, DISK_ALLOC_VOLUME);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- break;
- }
- }
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* _squish_extent_entries */
-
-#endif /* !USERSPACE_TOOL */
-
-/* used by ocfs_kill_this_tree and ocfs_split_this_tree */
-/* This value needs to be removed in a future version and set to
- * granularity + 1, dynamically */
-#define OCFS_TREE_STACK_SIZE 8
-
-/*
- * ocfs_kill_this_tree
- *
- * Given an extent_group (can be a DAT or header), delete everything,
- * including itself, it's children, and any data blocks they point to.
- * Works fine with any granularity (up to 4, in which case we'd need
- * more stack space)
- */
-
-/* We can't recurse, so we keep a simple stack of ocfs_extent_groups. */
-int ocfs_kill_this_tree(ocfs_super *osb, struct buffer_head *extent_grp_bh, ocfs_bitmap_free_head *free_head, struct inode *inode)
-{
- int status = -EFAIL;
- int i;
- __u32 victim;
- __u32 csize = osb->vol_layout.cluster_size;
- __u64 dstart = osb->vol_layout.data_start_off;
- __u64 tmp_off;
- __u32 num_sectors = 0, bitmap_offset = 0;
- ocfs_alloc_ext *ext;
- struct buffer_head * bh_stack[OCFS_TREE_STACK_SIZE];
- ocfs_extent_group * cur_extent; /* convenience, points to TOS */
- int tos = 0;
-
- LOG_ENTRY();
-
- for (i =0; i < OCFS_TREE_STACK_SIZE; i++)
- bh_stack[i] = NULL;
-
- bh_stack[tos] = extent_grp_bh;
-
- do {
- cur_extent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(bh_stack[tos]);
-
- if (!IS_VALID_EXTENT_DATA(cur_extent) &&
- !IS_VALID_EXTENT_HEADER(cur_extent)) {
- LOG_ERROR_STR("Invalid extent group!");
- goto bail;
- }
-
- if (IS_VALID_EXTENT_DATA(cur_extent)) {
- LOG_PID_PRINTK("found some data to free (%u.%u)\n", HI(cur_extent->this_ext), LO(cur_extent->this_ext));
- for(i = 0; i < cur_extent->next_free_ext; i++) {
- /* Free the data associated with each header */
- ext = &cur_extent->extents[i];
- num_sectors = (__u32) (ext->num_bytes / csize);
- bitmap_offset = (__u32) ((ext->disk_off - dstart) / csize);
- status = ocfs_add_to_bitmap_free_head(osb, free_head, num_sectors, bitmap_offset, -1, DISK_ALLOC_VOLUME);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- }
- } else {
- /* Ok, we're a header. */
-
- /* Did we already kill all his children, or
- * are they already dead? */
- if (cur_extent->next_free_ext == 0) {
- LOG_PID_PRINTK("Popping this header (%u.%u)\n", HI(cur_extent->this_ext), LO(cur_extent->this_ext), cur_extent->next_free_ext);
- goto free_meta;
- }
-
- /* We're gonna read in our last used extent
- * and put him at the top of the stack. We
- * also update our next_free_ext so that next
- * time we read in the next to last one and so
- * on until we've finished all of them
- */
-
- /* grow the stack, gotta save off a couple
- * things 1st. */
- victim = cur_extent->next_free_ext - 1;
- tmp_off = cur_extent->extents[victim].disk_off;
- cur_extent->next_free_ext--;
-
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- cur_extent = NULL;
- tos++;
-
- /* should already be null, but we can do this
- * just in case. */
- bh_stack[tos] = NULL;
-
- status = ocfs_read_bh(osb, tmp_off, &bh_stack[tos],
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* We only want to free on our way back up the tree */
- continue;
- }
-
- free_meta:
- /* Free the metadata associated with this extent group */
- status = ocfs_add_to_bitmap_free_head(osb, free_head, 1, cur_extent->alloc_file_off, cur_extent->alloc_node, DISK_ALLOC_EXTENT_NODE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- /* Pop one off the stack */
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- brelse(bh_stack[tos]);
- bh_stack[tos] = NULL;
- cur_extent = NULL;
- tos--;
- } while (tos >= 0);
-
- status = 0;
-bail:
- if (cur_extent)
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- /* brelse the stack. We never brelse the bottom of the stack
- * because we were passed that guy from the caller */
- for(i = 1; i < OCFS_TREE_STACK_SIZE; i++)
- if (bh_stack[i])
- brelse(bh_stack[i]);
-
- LOG_EXIT_STATUS (status);
- return(status);
-} /* ocfs_kill_this_tree */
-
-#ifndef USERSPACE_TOOL
-
-int ocfs_fix_extent_group(ocfs_super *osb, struct buffer_head *group_bh, struct inode *inode)
-{
- ocfs_alloc_ext *ext;
- ocfs_extent_group *group = NULL;
- int status=-EFAIL;
- int i;
-
- LOG_ENTRY ();
-
- if (!group_bh) {
- LOG_ERROR_STR("Invalid extent group bh (NULL)!");
- goto bail;
- }
-
- group = (ocfs_extent_group *) OCFS_BH_GET_DATA(group_bh);
-
- if (!IS_VALID_EXTENT_DATA(group) &&
- !IS_VALID_EXTENT_HEADER(group)) {
- LOG_ERROR_STR("Invalid extent group!");
- goto bail;
- }
-
- ext = group->extents;
-
- for(i=group->next_free_ext; i < OCFS_MAX_DATA_EXTENTS; i++) {
- ext[i].num_bytes = 0;
- ext[i].disk_off = 0;
- ext[i].file_off = 0;
- }
-
- OCFS_BH_PUT_DATA(group_bh);
- group = NULL;
-
- status=0;
-bail:
- if (group)
- OCFS_BH_PUT_DATA(group_bh);
-
- LOG_EXIT_STATUS (status);
- return(status);
-}
-
-
-/*
- * ocfs_split_this_tree
- *
- * Given an extent_group (DAT or HDR) takes the new alloc_size from fe
- * and splits this tree into two parts, one of which is deleted.
- *
- * TODO: This function can likely be combined with the above, we will try to
- * write it so that it can.
- * TODO: This function should be split up into a couple smaller ones.
-*/
-static int ocfs_split_this_tree(ocfs_super * osb, struct buffer_head *extent_grp_bh, ocfs_bitmap_free_head *free_head, ocfs_file_entry *fe, ocfs_journal_handle *handle, struct inode *inode)
-{
- int status = -EFAIL;
- __u64 newsize = fe->alloc_size;
- ocfs_alloc_ext *ext;
- struct buffer_head * bh_stack[OCFS_TREE_STACK_SIZE];
- ocfs_extent_group * AllocExtent = NULL;/* convenience, points to TOS */
- ocfs_extent_group *extent_grp;
- struct buffer_head *tmp_bh = NULL, *tmp_bh2 = NULL;
- int tos = 0;
- int i, victim;
- __u64 bytes, foff, doff, orig_bytes, dstart = osb->vol_layout.data_start_off, total_bytes, csize = osb->vol_layout.cluster_size, tmp_off;
- __u32 num_sectors, bitmap_offset;
- bool done = false;
- int gran = fe->granularity;
- bool needs_brelse = false;
-
- LOG_ENTRY();
-
- /* This is a similar hack to the one below, untested for gran = 3 files
- because I can't recreate one. */
- if (gran == 3) {
- LOG_ERROR_STR("Truncating file with granularity 3, this is not tested and may be unsafe!");
- LOG_PID_STR("Found a granularity 3 tree, trimming it.\n");
-
- status = ocfs_journal_access(handle, extent_grp_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- extent_grp = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_grp_bh);
- for(i = (extent_grp->next_free_ext - 1); i>=0; i--) {
- ext = &extent_grp->extents[i];
-
- if (tmp_bh2)
- brelse(tmp_bh2);
- tmp_bh2 = NULL;
- status = ocfs_read_bh(osb, ext->disk_off, &tmp_bh2,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
- brelse(tmp_bh2);
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (ext->file_off >= newsize) {
- /* Trim this whole subtree */
- status = ocfs_kill_this_tree(osb, tmp_bh2,
- free_head, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
- brelse(tmp_bh2);
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ext->file_off = 0;
- ext->disk_off = 0;
- ext->num_bytes = 0;
- extent_grp->next_free_ext = i;
- } else { /* This is the one we want to split. */
- ext->num_bytes = newsize - ext->file_off;
- break;
- }
- }
-
- /* Write out our new top of the tree duder */
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
-
- status = ocfs_journal_dirty(handle, extent_grp_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- /* Make our new TOS the header we want to split. */
- if (tmp_bh2 == NULL) {
- LOG_ERROR_STATUS(-EFAIL);
- goto bail;
- }
- extent_grp_bh = tmp_bh2;
- LOG_PID_STR("Ok, continuing as if granularity = 2");
-
- /* We want to do the next bit of stuff too */
- gran = 2;
- needs_brelse = true;
- }
-
- /* This is a hack, but i have little time to make this function right*/
- /* get rid of everything from the top level HDR that we can, then
- proceeed as if we're granularity 1 (which we know works) */
- if (gran == 2) {
- LOG_PID_STR("Found a granularity 2 tree, trimming it.\n");
-
- status = ocfs_journal_access(handle, extent_grp_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- extent_grp = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_grp_bh);
- for(i = (extent_grp->next_free_ext - 1); i>=0; i--) {
- ext = &extent_grp->extents[i];
-
- if (tmp_bh)
- brelse(tmp_bh);
- tmp_bh = NULL;
-
- status = ocfs_read_bh(osb, ext->disk_off, &tmp_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
- brelse(tmp_bh);
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (ext->file_off >= newsize) {
- /* Trim this whole subtree */
- status = ocfs_kill_this_tree(osb, tmp_bh,
- free_head, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
- brelse(tmp_bh);
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ext->file_off = 0;
- ext->disk_off = 0;
- ext->num_bytes = 0;
- extent_grp->next_free_ext = i;
- } else { /* This is the one we want to split. */
- ext->num_bytes = newsize - ext->file_off;
- break;
- }
- }
- /* Write out our new top of the tree duder */
- OCFS_BH_PUT_DATA(extent_grp_bh);
- extent_grp = NULL;
-
- status = ocfs_journal_dirty(handle, extent_grp_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- /* Make our new TOS the header we want to split. */
- if (tmp_bh == NULL) {
- LOG_ERROR_STATUS(-EFAIL);
- goto bail;
- }
-
- extent_grp_bh = tmp_bh;
- LOG_PID_STR("Ok, continuing as if granularity = 1");
-
- /* Right now, we don't use 'gran' below here, but just
- * in case */
- gran = 1;
- if (needs_brelse)
- brelse(tmp_bh2);
- needs_brelse = true;
- }
-
- for (i =0; i < OCFS_TREE_STACK_SIZE; i++)
- bh_stack[i] = NULL;
-
- bh_stack[tos] = extent_grp_bh;
-
- /* Ok, find the splitting point (can be a DAT or HDR) */
- do {
- /* it's perfectly legal to get_access a block but
- * never dirty it, so lets just pre-emptively do it
- * now. */
- status = ocfs_journal_access(handle, bh_stack[tos],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- AllocExtent = (ocfs_extent_group *) OCFS_BH_GET_DATA(bh_stack[tos]);
-
- if (!IS_VALID_EXTENT_DATA(AllocExtent) &&
- !IS_VALID_EXTENT_HEADER(AllocExtent)) {
- LOG_ERROR_STR("Invalid extent group!");
- goto bail;
- }
-
- if (IS_VALID_EXTENT_DATA(AllocExtent)) {
- /* shall we just do away with him? */
- LOG_PID_STR("Found a whole data extent!");
- /* changed this from > to >= */
- if (AllocExtent->extents[0].file_off >= newsize) {
- LOG_PID_PRINTK("Killing this data extent (%u, %u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
- /* Boundary case - what if this guy is
- * the last DAT we should delete
- * (i.e., split no more ;) */
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
- status = ocfs_kill_this_tree(osb, bh_stack[tos], free_head, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- /* silly, but what to do? */
- AllocExtent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(bh_stack[tos]);
- } else {
- /* Alright, we know for sure that
- * we're splitting in this guy. */
- LOG_PID_PRINTK("Splitting this data extent (%u, %u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
- fe->last_ext_ptr = AllocExtent->this_ext;
- AllocExtent->next_data_ext = 0;
- /* total_bytes is used below to know
- * how much total we've whacked off
- * this extent*/
- total_bytes = 0;
-
- /* there is a chance the split is at a
- * header boundary. this will catch
- * it: */
- ext = &AllocExtent->extents[AllocExtent->next_free_ext - 1];
- if ((ext->file_off + ext->num_bytes)==newsize){
- LOG_PID_STR("Ok, hit that boundary in the DAT");
- goto fix_headers;
- }
-
- /* Either kill the data or resize it */
- for(i = (AllocExtent->next_free_ext - 1); i>=0; i--) {
- ext = &AllocExtent->extents[i];
-
- /* changed this from > to >= */
- /* Do we delete it completely? */
- if (ext->file_off >= newsize) {
- total_bytes+=ext->num_bytes;
-
- num_sectors = (__u32) (ext->num_bytes / csize);
- bitmap_offset = (__u32) ((ext->disk_off - dstart) / csize);
- ext->file_off = 0;
- ext->num_bytes = 0;
- ext->disk_off = 0;
- } else {
- /* Do we shrink it? */
- orig_bytes = ext->num_bytes;
- doff = ext->disk_off;
- foff = ext->file_off;
- bytes = ext->num_bytes = newsize - foff;
- num_sectors = (__u32) ((orig_bytes - bytes) / csize);
- bitmap_offset = (__u32) (((doff + bytes) - dstart) / csize);
- /* we want to exit the
- * for loop now */
- total_bytes+= (orig_bytes - bytes);
- done = true;
- }
- status = ocfs_add_to_bitmap_free_head(osb, free_head, num_sectors, bitmap_offset, -1, DISK_ALLOC_VOLUME);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (done) {
- AllocExtent->next_free_ext=i+1;
- break;
- }
- } /* For loop */
-
- LOG_PID_PRINTK("Writing that data extent back out to disk now (%u,%u)\n", HI(AllocExtent->this_ext), LO(AllocExtent->this_ext));
- /* Either way, we need to write this back out*/
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
-
- status = ocfs_journal_dirty(handle, bh_stack[tos]);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- LOG_PID_PRINTK("Fixing the headers above us! (tos=%d)\n", tos);
- fix_headers:
- /*And here we should fix the headers above us*/
- tos--;
- while (tos >= 0) {
- LOG_PID_PRINTK("at top of loop, tos=%d\n", tos);
- status = ocfs_journal_access(handle, bh_stack[tos], OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- AllocExtent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(bh_stack[tos]);
- victim = AllocExtent->next_free_ext;
- AllocExtent->next_free_ext++;
- /* need to also update
- * numbytes on these guys */
- ext = &AllocExtent->extents[victim];
- ext->num_bytes-= total_bytes;
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
- status = ocfs_fix_extent_group(osb,
- bh_stack[tos], inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- status = ocfs_journal_dirty(handle,
- bh_stack[tos]);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- tos--;
- }
- LOG_PID_STR("breaking to end function now!");
- /* Ok, done! */
- break;
- }
- } else { /* It's a header extent */
-
- /* Did we already kill all his children, or
- * are they already dead? */
- if (AllocExtent->next_free_ext == 0) {
- /*Ok, we're done with this guy, pop the stack*/
- LOG_PID_PRINTK("Popping this header (%u.%u)\n",
- HI(AllocExtent->this_ext),
- LO(AllocExtent->this_ext),
- AllocExtent->next_free_ext);
-
- status = ocfs_add_to_bitmap_free_head(osb, free_head, 1, AllocExtent->alloc_file_off, AllocExtent->alloc_node, DISK_ALLOC_EXTENT_NODE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- brelse(bh_stack[tos]);
- AllocExtent = NULL;
- bh_stack[tos] = NULL;
- tos--;
- continue;
- }
- /* changed this from > to >= */
- /* Do we just delete this whole part of the tree? */
- if (AllocExtent->extents[0].file_off >= newsize) {
- LOG_PID_PRINTK("whacking this tree: (%u.%u)\n",
- HI(AllocExtent->this_ext),
- LO(AllocExtent->this_ext));
-
- if (AllocExtent->extents[0].file_off ==newsize)
- done = true;
-
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
- ocfs_kill_this_tree(osb, bh_stack[tos],
- free_head, inode);
- brelse(bh_stack[tos]);
- AllocExtent = NULL;
- bh_stack[tos] = NULL;
- tos--;
- if (tos < 0) {
- LOG_ERROR_STR("End of stack reached.");
- goto bail;
- }
- /* I just have to fix my parent,
- * right? Yes, but only because our
- * max granularity is 2. if it were
- * more, we'd have to fix his
- * parents parent. */
- status = ocfs_journal_access(handle, bh_stack[tos], OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- AllocExtent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(bh_stack[tos]);
-
- victim = AllocExtent->next_free_ext;
- AllocExtent->extents[victim].file_off = 0;
- AllocExtent->extents[victim].num_bytes = 0;
- AllocExtent->extents[victim].disk_off = 0;
- AllocExtent->next_free_ext--;
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
- /* Here's an interesting boundary
- * case. What if we're truncating on a
- * boundary between two headers and
- * this is the one we just deleted. In
- * that case we're done, but need to
- * write the parent out before we leave
- * again, this bit of code depends on
- * granularity of 2. */
- if (done) {
- LOG_TRACE_STR("Found a boundary " \
- "header, almost done " \
- " (gonna quit)");
- status = ocfs_fix_extent_group(osb,
- bh_stack[tos], inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_journal_dirty(handle,
- bh_stack[tos]);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- /* decrement tos so we dont
- * trigger an error
- * condition */
- brelse(bh_stack[tos]);
- bh_stack[tos] = NULL;
- tos--;
- break;
- }
-
- status = ocfs_journal_dirty(handle,
- bh_stack[tos]);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
-
- /* Ok, we're not a boundary case, continue */
- continue;
- }
-
- /* need to get the next offset to read */
- AllocExtent = (ocfs_extent_group *)
- OCFS_BH_GET_DATA(bh_stack[tos]);
- AllocExtent->next_free_ext--;
- victim = AllocExtent->next_free_ext;
- ext = &AllocExtent->extents[victim];
- tmp_off = ext->disk_off;
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- AllocExtent = NULL;
-
- status = ocfs_journal_dirty(handle, bh_stack[tos]);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* grow the stack. */
- tos++;
- /* should never be true. */
- if (bh_stack[tos] != NULL)
- LOG_ERROR_STR("uhoh, not brelsing a buffer " \
- "on our stack!\n");
-
- status = ocfs_read_bh(osb, tmp_off, &bh_stack[tos],
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* We only want to free on our way up the tree */
- continue;
- }
- if (AllocExtent)
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- brelse(bh_stack[tos]);
- bh_stack[tos] = NULL;
- AllocExtent = NULL;
- tos--;
- } while (tos >= 0);
-
- if (tos >= 0)
- LOG_ERROR_ARGS("Quitting main loop while top of stack >= 0 " \
- " (tos=%d)\n", tos);
-
- status=0;
-bail:
- /* brelse the stack. We only brelse the bottom of the stack if
- * we know for sure that it wasn't passed from the caller */
- if (AllocExtent)
- OCFS_BH_PUT_DATA(bh_stack[tos]);
- if (needs_brelse)
- brelse(bh_stack[0]);
- for(i = 1; i < OCFS_TREE_STACK_SIZE; i++)
- if (bh_stack[i])
- brelse(bh_stack[i]);
-
- LOG_EXIT_STATUS (status);
- return(status);
-} /* ocfs_split_this_tree */
-
-
-/*
- * ocfs_update_last_ext_ptr
- *
- * Travel all the way to the rightmost DAT and set fe->last_ext_ptr
- * to it.
- *
- * We do cached reads here because we ought to have already read the
- * various ext headers and dats off the system previously in the
- * truncate path.
- */
-int ocfs_update_last_ext_ptr(ocfs_super *osb, ocfs_file_entry *fe, struct inode *inode)
-{
- int status = -EFAIL;
- ocfs_extent_group *extent = NULL;
- struct buffer_head *extent_bh = NULL;
- __u64 next_ext;
- int victim;
-
- LOG_ENTRY ();
-
- if (fe->next_free_ext == 0) {
- LOG_PID_STR("setting to zero as there isn't any used extents");
- fe->last_ext_ptr = 0;
- status = 0;
- goto bail;
- }
-
- victim = fe->next_free_ext - 1;
- status = ocfs_read_bh(osb, fe->extents[victim].disk_off, &extent_bh,
- OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
-
- if (!IS_VALID_EXTENT_DATA(extent) &&
- !IS_VALID_EXTENT_HEADER(extent)) {
- LOG_ERROR_STR("Invalid extent group!");
- goto bail;
- }
-
- while (!IS_VALID_EXTENT_DATA(extent)) {
- if (!IS_VALID_EXTENT_HEADER(extent)) {
- LOG_ERROR_STR("Invalid extent group!");
- goto bail;
- }
-
- next_ext = extent->extents[extent->next_free_ext - 1].disk_off;
-
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- extent = NULL;
- extent_bh = NULL;
-
- status = ocfs_read_bh(osb, next_ext, &extent_bh,
- OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
- }
-
- fe->last_ext_ptr = extent->this_ext;
- status = 0;
-bail:
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * ocfs_free_extents_for_truncate()
- *
- * You know, it's funny -- you'd expect that we'd flush out the fe
- * before leaving this function, but that's pretty much up to the
- * caller!
- */
-int ocfs_free_extents_for_truncate (ocfs_super * osb, ocfs_file_entry * FileEntry, ocfs_journal_handle *handle, ocfs_bitmap_free_head *free_head, struct inode *inode)
-{
- int status = 0;
- struct buffer_head *extent_bh = NULL;
- __u64 alloc_size;
- int i, j;
- bool updated_lep; /* used to mark whether fe->last_ext_ptr has
- * been updated */
-
- LOG_ENTRY ();
-
- alloc_size = FileEntry->alloc_size;
-
- if (free_head == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- /* local extents */
- if (FileEntry->local_ext) {
- LOG_PID_STR("local extents, calling _squish_extent_entries");
- status = _squish_extent_entries(osb, FileEntry->extents, (__u32 *)&FileEntry->next_free_ext, free_head, alloc_size, false, inode);
- LOG_PID_PRINTK("return from _squish_extent_entries, status=%d", status);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- goto finally;
- }
-
- LOG_PID_PRINTK("non-local extents. taking that code path, truncating to alloc_size of (%u.%u)\n", HI(alloc_size), LO(alloc_size));
- /* non-local extents */
-
- updated_lep = false;
-
- /* Loop backwards through only the used free extent headers here */
- for (i = (FileEntry->next_free_ext - 1); i >= 0; i--) {
- LOG_PID_PRINTK("at top of loop, i = %d\n", i);
- /* Go ahead and read that bit of the tree - we'll need it. */
- status = ocfs_read_bh(osb, FileEntry->extents[i].disk_off,
- &extent_bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- /* Figure out, do we want to kill this whole tree? */
- if (FileEntry->extents[i].file_off >= alloc_size) {
- LOG_PID_PRINTK("Found an entire tree to delete!\n");
-
- status = ocfs_kill_this_tree(osb, extent_bh, free_head, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- /* Ok, update the FileEntry */
- FileEntry->extents[i].file_off = 0;
- FileEntry->extents[i].disk_off = 0;
- FileEntry->extents[i].num_bytes = 0;
- FileEntry->next_free_ext = i;
- } else { /* Ok, we only want part of it. */
- /* Actually, the truth is we might NOT want to
- * split this tree, but we call this function
- * anyways in order to update last_ext_ptr. */
-
- LOG_PID_PRINTK("Splitting this tree!\n");
- status = ocfs_split_this_tree(osb, extent_bh, free_head, FileEntry, handle, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- /* Ok, update the FileEntry */
- LOG_PID_PRINTK("Alright. num_bytes = (%u,%u), alloc_size = (%u,%u) file_off = (%u,%u)\n", HI(FileEntry->extents[i].num_bytes), LO(FileEntry->extents[i].num_bytes), HI(alloc_size), LO(alloc_size), HI(FileEntry->extents[i].file_off), LO(FileEntry->extents[i].file_off));
- FileEntry->extents[i].num_bytes = alloc_size;
- for (j=0; j < i; j++)
- FileEntry->extents[i].num_bytes += FileEntry->extents[j].num_bytes;
-
- FileEntry->next_free_ext = i + 1;
- /* We're done - we can't split more than one
- * parts of the tree. */
- updated_lep = true;
- break;
- }
- brelse(extent_bh);
- extent_bh = NULL;
- }
-
- /* Ok, trunc to zero is a special case, doofus */
- if (alloc_size == 0) {
- FileEntry->last_ext_ptr = 0;
- FileEntry->granularity = -1;
- FileEntry->local_ext = true;
- updated_lep = true;
- }
-
- if (!updated_lep) {
- LOG_PID_STR("Updating FileEntry->last_ext_ptr");
- status = ocfs_update_last_ext_ptr(osb, FileEntry, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
-
- LOG_PID_PRINTK("non-local extents, out of loop now, i = %d\n", i);
-
-finally:
- if (extent_bh)
- brelse(extent_bh);
-
- LOG_EXIT_ULONG (status);
- return status;
-} /* ocfs_free_extents_for_truncate */
-
-#endif /* !USERSPACE_TOOL */
-
-/*
- * ocfs_lookup_file_allocation()
- *
- * This routine looks up the existing mapping of VBO to LBO for a file.
- * The information it queries is either stored in the extent map field
- * of the oin or is stored in the allocation file and needs to be retrieved,
- * decoded and updated in the extent map.
- *
- */
-int ocfs_lookup_file_allocation (ocfs_super * osb, ocfs_inode * oin, __s64 Vbo, __s64 * Lbo, __u32 sectors, u32 *sector_count, struct inode *inode)
-{
- int status = -EFAIL;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *fe_bh = NULL;
- ocfs_extent_group *OcfsExtent = NULL;
- struct buffer_head *ext_bh = NULL;
- __u64 next_data_ext;
- __u64 remainingLength = 0;
- __s64 localVbo;
- __u64 cnt;
- __u32 NumIndex;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (osb);
- OCFS_ASSERT (oin);
-
- if (oin->journal_inode || Vbo < oin->alloc_size) {
- if (ocfs_lookup_extent_map_entry (osb, &(oin->map),
- Vbo, Lbo, &cnt, &NumIndex) && cnt >= sectors) {
- status = 0;
- goto finally;
- }
- }
-
- remainingLength = sectors;
- localVbo = Vbo;
-
- /* We are looking for a Vbo, but it is not in the Map or not Valid. */
- /* Thus we have to go to the disk, and update the Map */
-
- /* Read the file Entry corresponding to this */
- status = ocfs_read_bh(osb, oin->file_disk_off, &fe_bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- if (!oin->journal_inode && Vbo >= (__s64) fe->alloc_size) {
- LOG_ERROR_ARGS ("vbo=%u.%u, fe->alloc_sz=%u.%u oin->alloc_size=%u.%u",
- HILO (Vbo), HILO (fe->alloc_size),
- HILO (oin->alloc_size));
- status = -EFAIL;
- goto finally;
- }
-
- if (fe->local_ext) {
- status = ocfs_update_extent_map (osb, &oin->map, fe,
- NULL, NULL, LOCAL_EXT);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- } else {
- /* Extents are branched and we are no longer using
- * Local Extents for this File Entry. */
-
- status = ocfs_get_leaf_extent (osb, fe, localVbo, &ext_bh, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- OcfsExtent = (ocfs_extent_group *) OCFS_BH_GET_DATA(ext_bh);
- while (1) {
- status = ocfs_update_extent_map (osb, &oin->map, OcfsExtent,
- &localVbo, &remainingLength, NONLOCAL_EXT);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- if (remainingLength > 0) {
- if (!OcfsExtent->next_data_ext) {
- LOG_ERROR_ARGS ("vbo=%u.%u, "
- "oin->alloc_size=%u.%u, "
- " thisext=%u.%u",
- HILO(localVbo),
- HILO(oin->alloc_size),
- HILO(OcfsExtent->this_ext));
- status = -EFAIL;
- goto finally;
- }
-
- next_data_ext = OcfsExtent->next_data_ext;
-
- OCFS_BH_PUT_DATA(ext_bh);
- brelse(ext_bh);
- ext_bh = NULL;
- OcfsExtent = NULL;
-
- status = ocfs_read_bh(osb, next_data_ext,
- &ext_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- OcfsExtent = (ocfs_extent_group *) OCFS_BH_GET_DATA(ext_bh);
- if (!IS_VALID_EXTENT_DATA(OcfsExtent)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
- } else {
- break;
- }
- }
- }
-
- if (ocfs_lookup_extent_map_entry (osb, &(oin->map), Vbo, Lbo, &cnt, &NumIndex) &&
- cnt >= sectors) {
- status = 0;
- } else
- status = -EFAIL;
-
- /* want to return cnt only if asked for it */
- if (sector_count)
- *sector_count = (u32) cnt;
-
-finally:
- if (fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- if (ext_bh) {
- if (OcfsExtent)
- OCFS_BH_PUT_DATA(ext_bh);
- brelse(ext_bh);
- }
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_lookup_file_allocation */
-
-
-/* ocfs_get_leaf_extent()
- * '*data_exent_bh' should be NULL.
- */
-int ocfs_get_leaf_extent (ocfs_super * osb, ocfs_file_entry * FileEntry, __s64 Vbo, struct buffer_head **data_extent_bh, struct inode *inode)
-{
- int status = 0, tempstat;
- __u32 i, j;
- ocfs_extent_group *ExtentHeader = NULL;
- struct buffer_head *ext_bh = NULL;
- ocfs_extent_group *tmp = NULL;
- __u64 childDiskOffset = 0;
-
- LOG_ENTRY ();
-
- for (i = 0; i < FileEntry->next_free_ext; i++) {
- if ((__s64) (FileEntry->extents[i].file_off +
- FileEntry->extents[i].num_bytes) > Vbo) {
- childDiskOffset = FileEntry->extents[i].disk_off;
- break;
- }
- }
-
- if (childDiskOffset == 0) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- for (i = 0; i < FileEntry->granularity; i++) {
- tempstat = ocfs_read_bh(osb, childDiskOffset, &ext_bh, OCFS_BH_COND_CACHED, inode);
- if (tempstat < 0) {
- LOG_ERROR_STATUS (status = tempstat);
- goto finally;
- }
-
- ExtentHeader = (ocfs_extent_group *) OCFS_BH_GET_DATA(ext_bh);
- if (!IS_VALID_EXTENT_HEADER(ExtentHeader)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto finally;
- }
-
- for (j = 0; j < ExtentHeader->next_free_ext; j++) {
- if ((__s64) (ExtentHeader->extents[j].file_off +
- ExtentHeader->extents[j].num_bytes) > Vbo)
- {
- childDiskOffset =
- ExtentHeader->extents[j].disk_off;
- break;
- }
- }
-
- OCFS_BH_PUT_DATA(ext_bh);
- brelse(ext_bh);
- ext_bh = NULL;
- ExtentHeader = NULL;
- }
-
- if (*data_extent_bh) {
- LOG_ERROR_ARGS("*data_extent_bh should be NULL, but is " \
- "%p -- setting it to NULL!\n", *data_extent_bh);
- *data_extent_bh = NULL;
- }
-
- tempstat = ocfs_read_bh(osb, childDiskOffset, data_extent_bh, OCFS_BH_COND_CACHED, inode);
- if (tempstat < 0) {
- LOG_ERROR_STATUS (status = tempstat);
- goto finally;
- }
-
- tmp = (ocfs_extent_group *) OCFS_BH_GET_DATA(*data_extent_bh);
- if (!IS_VALID_EXTENT_DATA(tmp)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- OCFS_BH_PUT_DATA(*data_extent_bh);
- brelse(*data_extent_bh);
- *data_extent_bh = NULL;
- goto finally;
- }
-
- OCFS_BH_PUT_DATA(*data_extent_bh);
-finally:
- if (ext_bh) {
- if (ExtentHeader)
- OCFS_BH_PUT_DATA(ext_bh);
- brelse(ext_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_get_leaf_extent */
-
-/*
- * ocfs_find_contiguous_space_from_bitmap()
- *
- * This function looks for free space in the volume based on the bitmap.
- * It looks for contiguous space only and if it finds the space available
- * it returns a cluster bitmap offset. Each bit in Cluster bitmap represents
- * memory equal to cluster size (specified during format).
- *
- * TODO: The Bitmap stuff needs to be changed for handling more than 32 bits...
- * Although we can go upto 4k(clustersize) * 8 * 4M(max 32 bits for now...)
- *
- * Returns 0 on success, < 0 on error.
- *
- * Pass in 'lock_bh' only if you've already taken the vol_alloc
- * semaphore, and you've done the acquire_lock on the bitmap.
- */
-int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, struct buffer_head *lock_bh)
-{
- int status = 0, tmpstat, startbh, numblocks;
- __u32 bitoffset = 0, ClusterCount = 0;
- __u64 ByteCount = 0;
- __u32 LargeAlloc = 0;
- static __u32 LargeAllocOffset = 0;
- static __u32 SmallAllocOffset = 0;
- bool bLockAcquired = false;
- ocfs_lock_res *pLockResource = NULL;
- struct buffer_head *bh = NULL;
- ocfs_bitmap_lock *bm_lock = NULL;
- __u32 bitmapblocks; /* we only care about the valid blocks */
- bool local_lock = true;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (osb);
-
- if (lock_bh) {
- local_lock = false;
- bh = lock_bh;
- }
-
- if (local_lock) {
- ocfs_down_sem (&(osb->vol_alloc_lock), true);
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, 0,
- &pLockResource, &bh, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- bLockAcquired = true;
- }
- bm_lock = (ocfs_bitmap_lock *)OCFS_BH_GET_DATA(bh);
-
- ByteCount = file_size;
-
- /* Round off the byte count to next clustersize (bytes per cluster) */
- ByteCount += (ByteCount % (osb->vol_layout.cluster_size)) ?
- (osb->vol_layout.cluster_size -
- (ByteCount % (osb->vol_layout.cluster_size))) : 0;
-
- if (ByteCount == 0) {
- LOG_ERROR_STR ("DISK_FULL?: Bytecount==0");
- status = 0;
- goto leave;
- }
-
- ClusterCount = (__u32)
- ((__u64) ByteCount / (__u64) osb->vol_layout.cluster_size);
-
- if (sysfile ? (ClusterCount > osb->vol_layout.num_clusters) :
- (ClusterCount > (osb->vol_layout.num_clusters -
- ((8 * ONE_MEGA_BYTE) / osb->vol_layout.cluster_size)))){
- LOG_ERROR_STR ("Disk Full");
- status = -ENOSPC;
- goto leave;
- }
-
- /* This function will check for clear bits in the Bitmap for
- * consecutive */
- /* clear bits equal to ClusterCount */
-
- /* If we create a chunk that is larger than 5% of the
- * disksize, then start */
- /* allocation at 5%, so that small files stay in the beginning
- * as much as possible */
-
- if (ClusterCount > (osb->vol_layout.num_clusters / 20)) {
- LargeAlloc = 1;
- LargeAllocOffset = (osb->vol_layout.num_clusters / 20);
- }
-
- bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits,
- OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
-
- /* Ok, somewhat lame, but we submit the whole bitmap for reading here*/
- if (ocfs_read_bhs(osb, osb->vol_layout.bitmap_off,
- bitmapblocks * osb->sect_size,
- osb->cluster_bitmap.chunk, 0, NULL)) {
- LOG_ERROR_STATUS(-EIO);
- goto leave;
- }
-
- bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
- ClusterCount,
- LargeAlloc ? LargeAllocOffset :
- SmallAllocOffset, sysfile ? 0 :
- ((8 * ONE_MEGA_BYTE) /
- osb->vol_layout.cluster_size));
-
- /* if fails we should try again from the beginning of the disk. */
- /* in the end we pass # of bits we want to keep for system
- * file extention only. */
- /* Right now if we run out of diskspace, we still have 8mb
- * free for a systemfile */
-
- if (bitoffset == -1 && LargeAlloc) {
- LOG_TRACE_STR("Running low on diskspace.");
- osb->cluster_bitmap.failed++;
- bitoffset = ocfs_find_clear_bits (osb, &osb->cluster_bitmap,
- ClusterCount, 0,
- sysfile ? 0 :
- ((8 * ONE_MEGA_BYTE) /
- osb->vol_layout.cluster_size));
- }
-
- /* It returns -1 on failure, otherwise bitoffset points at the */
- /* location inb bitmap from where there are ClusterCount no of bits */
- /* are free. */
-
- if (bitoffset == -1) {
- if (sysfile)
- LOG_ERROR_ARGS ("Cannot allocate %u contiguous clusters for system file\n",
- ClusterCount);
- status = -ENOSPC;
- goto leave;
- }
-
- LOG_TRACE_ARGS ("byte offset=%u\n", bitoffset);
-
- ocfs_set_bits (&osb->cluster_bitmap, bitoffset, ClusterCount);
-
- /* Ok, write out the bitmap now. We optimize only by writing
- * out the bitmap blocks which have changed, and not all of
- * them like before. */
- startbh = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset);
- numblocks = OCFS_GLOBAL_OFF_TO_CHUNK(bitoffset + ClusterCount) - startbh + 1;
-
- LOG_TRACE_ARGS("bitoffset = %u, ClusterCount = %u, startbh = %u, numblocks = %u\n", bitoffset, ClusterCount, startbh, numblocks);
-
- status = ocfs_write_bhs(osb, &osb->cluster_bitmap.chunk[startbh],
- numblocks, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* write the bitmap size info to the lock sector */
- /* TODO: optimize by making this part of ocfs_release_lock
- * for now, it will be back-to-back writes to same sector */
- bm_lock->used_bits = ocfs_count_bits(&osb->cluster_bitmap);
- OCFS_BH_PUT_DATA(bh);
- bm_lock = NULL;
-
- status = ocfs_write_bh (osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- *cluster_off = bitoffset;
- *cluster_count = ClusterCount;
- status = 0;
-
-leave:
- if (bm_lock != NULL)
- OCFS_BH_PUT_DATA(bh);
-
- if (local_lock) {
- ocfs_up_sem (&(osb->vol_alloc_lock));
-
- if (bLockAcquired) {
- tmpstat = ocfs_release_lock(osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, pLockResource, bh,
- NULL);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- if (bh != NULL)
- brelse(bh);
- ocfs_put_lockres (pLockResource);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_find_contiguous_space_from_bitmap */
-
-
-/*
- * ocfs_alloc_node_block()
- *
- */
-int ocfs_alloc_node_block (ocfs_super * osb, __u64 FileSize, __u64 * DiskOffset, __u64 * file_off, __u32 NodeNum, __u32 Type, ocfs_journal_handle *handle)
-{
- int status = 0;
- int tmpstat = 0;
- __u64 fileSize = 0;
- __u64 offset = 0;
- __u64 lockId = 0;
- __u64 numBytes = 0;
- __u64 allocSize = 0;
- __u64 prevFileSize = 0;
- __u64 extent;
- __u64 newFileSize;
- __u64 bitMapSize;
- ocfs_alloc_bm bitmap;
- __u32 numBits = 0;
- __u32 foundBit = -1;
- __u32 blockSize = 0;
- bool bLockAcquired = false;
- ocfs_lock_res *pLockResource = NULL;
- __u32 fileId = 0;
- __u32 extendFileId = 0;
- struct buffer_head *bh = NULL;
- ocfs_file_entry *fe = NULL;
- bool needs_uninit = false;
- bool delay_lockrel = false;
-
- LOG_ENTRY_ARGS("(FileSize = (%u.%u), Type=%d)\n", HILO(FileSize),Type);
-
- ocfs_down_sem (&(osb->dir_alloc_lock), true);
- ocfs_down_sem (&(osb->file_alloc_lock), true);
- ocfs_down_sem (&(osb->vol_alloc_lock), true);
-
- if (Type == DISK_ALLOC_DIR_NODE) {
- fileId = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
- blockSize = (__u32) osb->vol_layout.dir_node_size;
- extendFileId = OCFS_FILE_DIR_ALLOC + NodeNum;
- } else if (Type == DISK_ALLOC_EXTENT_NODE) {
- fileId = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
- extendFileId = OCFS_FILE_FILE_ALLOC + NodeNum;
- blockSize = (__u32) osb->vol_layout.file_node_size;
- }
-
- /* Allocate a block of size blocksize from the relevant file/bitmap */
-
- OCFS_ASSERT (blockSize);
-
- lockId = (fileId * OCFS_SECTOR_SIZE) + osb->vol_layout.root_int_off;
-
- /* Get a lock on the file */
- status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, &pLockResource, &bh, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- bLockAcquired = true;
-
-
- numBytes = OCFS_ALIGN ((FileSize), blockSize);
- numBits = (__u32) (numBytes / blockSize);
-
- /* Read in the bitmap file for the dir alloc and look for the
- * required space, if found */
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
- fileSize = fe->file_size;
- allocSize = fe->alloc_size;
- OCFS_BH_PUT_DATA(bh);
-
- prevFileSize = fileSize;
-
- if ((fileSize != 0) && (allocSize != 0)) {
- /* Round this off to dirnodesize */
- ocfs_initialize_bitmap (&bitmap, (__u32) fileSize * 8, (__u32) allocSize * 8);
- needs_uninit = true;
-
- status = ocfs_read_system_file (osb, fileId, bitmap.chunk,
- allocSize, offset);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-
- /* Find the requisite number of bits... */
-
- /* This function will check for clear bits in the Bitmap for */
- /* consective clear bits equal to ClusterCount */
- foundBit = ocfs_find_clear_bits (osb, &bitmap,
- (__u32) numBits, 0, 0);
- }
-
- /* It returns -1 on failure , otherwise ByteOffset points at the */
- /* location in bitmap from where there are ClusterCount no of bits */
- /* are free. */
-
- if (foundBit == -1) {
- /* if not found add more allocation to the file and try again. */
-
- /* Lets get a 1MB chunks every time or clustersize which ever */
- /* is greater or the number of bit asked */
- extent = ((1 * ONE_MEGA_BYTE) > osb->vol_layout.cluster_size) ?
- (1 * ONE_MEGA_BYTE) :
- osb->vol_layout.cluster_size;
- extent = (extent > (numBits * blockSize)) ? extent :
- (numBits * blockSize);
-
- extent = OCFS_ALIGN (extent, ONE_MEGA_BYTE);
-
- status = ocfs_get_system_file_size (osb, (extendFileId),
- &newFileSize, &allocSize);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* This is for OUI optimzation to allocate more disk
- * space for directory allocations */
-
- if (allocSize > 0)
- extent *= 2;
-
- status = ocfs_extend_system_file (osb, (extendFileId),
- newFileSize + extent, NULL, handle);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- newFileSize += extent;
- bitMapSize = newFileSize / (blockSize * 8);
-
- /* Does this need the buffer_head? if so, we need to
- * do a put_data first! */
- /* Calculate the new bitmap size */
-
- status = ocfs_extend_system_file (osb, fileId, bitMapSize, bh, handle);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
- /* we wrote it back out in ocfs_extend_system_file so
- * we can trust the sizes here */
- fileSize = fe->file_size;
- allocSize = fe->alloc_size;
- OCFS_BH_PUT_DATA(bh);
-
- if (needs_uninit)
- ocfs_reinitialize_bitmap(&bitmap, fileSize * 8,
- allocSize * 8);
- else
- ocfs_initialize_bitmap(&bitmap, fileSize * 8,
- allocSize * 8);
- needs_uninit = true;
-
- status = ocfs_read_system_file (osb, fileId, bitmap.chunk,
- allocSize, offset);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- foundBit = prevFileSize * 8;
- /* only delay lock release if we have a handle,
- * otherwise the extend wasn't journalled. */
- if (handle)
- delay_lockrel = true;
- }
-
- LOG_TRACE_ARGS ("byte offset=%d\n", foundBit);
-
- ocfs_set_bits (&bitmap, (__u32) foundBit, (__u32) numBits);
-
- /* Write the bitmap file back */
- status = ocfs_write_system_file (osb, fileId, bitmap.chunk,
- allocSize, offset);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- LOG_TRACE_ARGS ("offset=%u.%u, type=%x, blksz=%u, foundbit=%u, fileid=%u\n",
- foundBit * blockSize, Type, blockSize, foundBit, extendFileId);
- *DiskOffset = ocfs_file_to_disk_off (osb, (extendFileId),
- (foundBit * blockSize));
- if (*DiskOffset == 0) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto leave;
- }
-
- *file_off = (__u64) ((__u64) foundBit * (__u64) blockSize);
- /* this can just fall through */
- if (*file_off == 0) {
- LOG_TRACE_ARGS ("offset=%u.%u, type=%x, blksz=%u, foundbit=%u\n",
- HILO (*file_off), Type, blockSize, foundBit);
- }
-
-leave:
-
- ocfs_up_sem (&(osb->vol_alloc_lock));
- ocfs_up_sem (&(osb->file_alloc_lock));
- ocfs_up_sem (&(osb->dir_alloc_lock));
-
- if (needs_uninit)
- ocfs_uninitialize_bitmap(&bitmap);
-
- if (bLockAcquired && delay_lockrel) {
- ocfs_journal_add_lock(handle, lockId,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- pLockResource, bh);
- tmpstat = 0;
- } else if (bLockAcquired) {
- tmpstat =
- ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, pLockResource, bh, NULL);
-
- ocfs_put_lockres (pLockResource);
- }
-
- if (tmpstat < 0)
- status = tmpstat;
- if (bh != NULL)
- brelse(bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_alloc_node_block */
-
-/*
- * ocfs_free_directory_block()
- *
- */
-int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe,
- ocfs_bitmap_free_head *free_head, struct inode *inode)
-{
- int status = 0;
- struct buffer_head *dir_hdr_bh = NULL;
- ocfs_dir_node *dirnode = NULL;
- __u32 size;
- __u64 currentDirNode;
-
- LOG_ENTRY ();
-
- currentDirNode = fe->extents[0].disk_off;
-
- size = OCFS_SECTOR_SIZE;
-
- status = ocfs_read_bh(osb, currentDirNode, &dir_hdr_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- dirnode = (ocfs_dir_node *) OCFS_BH_GET_DATA(dir_hdr_bh);
-
- while ((dirnode->node_disk_off != INVALID_NODE_POINTER) &&
- (IS_VALID_DIR_NODE (dirnode))) {
-
- status = ocfs_add_to_bitmap_free_head(osb, free_head, 1,
- dirnode->alloc_file_off,
- dirnode->alloc_node,
- DISK_ALLOC_DIR_NODE);
-
- /* LOG_FREE_BITMAP */
- currentDirNode = dirnode->next_node_ptr;
- OCFS_BH_PUT_DATA(dir_hdr_bh);
- dir_hdr_bh = NULL;
- dirnode = NULL;
- if (currentDirNode != INVALID_NODE_POINTER) {
- status = ocfs_read_bh(osb, currentDirNode, &dir_hdr_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- dirnode = (ocfs_dir_node *) OCFS_BH_GET_DATA(dir_hdr_bh);
- continue;
- } else {
- break;
- }
- }
-
-leave:
- if (dir_hdr_bh) {
- if (dirnode)
- OCFS_BH_PUT_DATA(dir_hdr_bh);
- brelse(dir_hdr_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_free_directory_block */
-
-/*
- * ocfs_free_file_extents()
- *
- */
-int ocfs_free_file_extents (ocfs_super * osb, struct buffer_head *fe_bh,
- ocfs_bitmap_free_head *free_head)
-{
- int status = 0;
- __u32 i;
- __u32 numBitsAllocated = 0, bitmapOffset = 0;
- ocfs_extent_group *extent = NULL;
- struct buffer_head *extent_bh = NULL;
- ocfs_file_entry *fe = NULL;
- struct inode *inode = NULL;
-
- LOG_ENTRY ();
-
- inode = ocfs_get_inode_from_bh(osb, fe_bh);
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
-
- if (fe->local_ext) {
- for (i = 0; i < fe->next_free_ext; i++) {
- numBitsAllocated = (__u32) (fe->extents[i].num_bytes /
- (osb->vol_layout.
- cluster_size));
-
- bitmapOffset =
- (__u32) ((fe->extents[i].disk_off -
- osb->vol_layout.data_start_off) /
- (osb->vol_layout.cluster_size));
-
- ocfs_add_to_bitmap_free_head(osb, free_head,
- numBitsAllocated, bitmapOffset,
- -1, DISK_ALLOC_VOLUME);
- }
- } else {
- for (i = 0; i < fe->next_free_ext; i++) {
- status = ocfs_read_bh(osb, fe->extents[i].disk_off,
- &extent_bh, OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
- if ((fe->granularity && (!IS_VALID_EXTENT_HEADER(extent))) || !IS_VALID_EXTENT_DATA(extent)) {
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- OCFS_BH_PUT_DATA(extent_bh);
- extent = NULL;
- status = ocfs_kill_this_tree(osb, extent_bh, free_head, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- brelse(extent_bh);
- extent_bh = NULL;
- }
- }
-
-leave:
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
- if (inode)
- iput(inode);
-
- OCFS_BH_PUT_DATA(fe_bh);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_free_file_extents */
-
-/* Some constants and functions that control how we allocate and use
- * local alloc bitmaps. These are intended to be easily
- * tunable. Possibly even remove them once we've found a good mix. */
-
-/* The largest cluster size where we even consider using local alloc. */
-#define OCFS_LOCAL_ALLOC_MAX_CSIZE (128 * 1024)
-/* The largest allocation to use the local bitmap for. */
-#define OCFS_LOCAL_ALLOC_MAX_ALLOC (2 * 1024 * 1024)
-
-/*
- * ocfs_local_alloc_window_bits
- *
- * Determine how large our local alloc window should be, in bits. This
- * is entirely changeable -- just replace this function. Right now as
- * a *testing* default, we have a function that takes cluster size
- * into account in the following manner:
- *
- * 4k -> 1024 bits, 8k -> 512 bits, 16k -> 256 bits,
- * 32/64/128k -> 64 bits
- */
-static inline int ocfs_local_alloc_window_bits(ocfs_super *osb)
-{
- int numbits;
-
- switch (osb->vol_layout.cluster_size) {
- case (4*1024):
- numbits = 1024;
- break;
-
- case (8*1024):
- numbits = 512;
- break;
-
- case (16*1024):
- numbits = 256;
- break;
-
- default:
- numbits = 64;
- break;
- }
- return(numbits);
-} /* ocfs_local_alloc_window_bits */
-
-/*
- * ocfs_alloc_count_bits
- */
-static __u32 ocfs_alloc_count_bits(ocfs_local_alloc *alloc)
-{
- int i;
- __u8 tmp;
- __u8 *buffer;
- __u32 count = 0;
-
- LOG_ENTRY();
-
- buffer = &(alloc->bitmap[0]);
- for (i = 0; i < 256; i++) {
- memcpy(&tmp, buffer, 1);
- count+= BITCOUNT(tmp);
- buffer++;
- }
-
- LOG_EXIT_ULONG (count);
- return(count);
-} /* ocfs_alloc_count_bits */
-
-/*
- * ocfs_clear_local_alloc
- */
-static void ocfs_clear_local_alloc(ocfs_local_alloc *alloc)
-{
- int i;
- LOG_ENTRY();
-
- alloc->alloc_size = 0;
- alloc->num_used = 0;
- alloc->bitmap_start = 0;
- for(i = 0; i < 256; i++)
- alloc->bitmap[i] = 0;
-
- LOG_EXIT();
- return;
-} /* ocfs_clear_local_alloc */
-
-/*
- * ocfs_sync_local_to_main
- *
- * sync the local alloc to main bitmap.
- *
- * 'osb' and 'f' are always assumed to be valid (though they don't
- * have to be allocated)
- *
- * local_alloc_bh is optional. If not passed, we use the one off osb.
- *
- * bm_lock_bh should be passed in if you've already locked the main
- * bitmap, otherwise we'll do our own locking. */
-static int ocfs_sync_local_to_main(ocfs_super *osb,
- ocfs_bitmap_free_head **f,
- struct buffer_head *local_alloc_bh,
- struct buffer_head *bm_lock_bh)
-{
- int status = 0, tmpstat;
- ocfs_lock_res *bm_lock_res = NULL;
- __u32 bitmapblocks;
- struct buffer_head *bh = NULL;
- int bit_off, left;
- ocfs_local_alloc *alloc = NULL;
- bool local_lock = true;
-
- LOG_ENTRY();
-
- if (!local_alloc_bh)
- local_alloc_bh = osb->local_alloc_bh;
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(local_alloc_bh);
- if (alloc->alloc_size == 0) {
- OCFS_BH_PUT_DATA(local_alloc_bh);
- LOG_TRACE_STR("nothing to sync!");
- goto bail;
- }
- OCFS_BH_PUT_DATA(local_alloc_bh);
-
- if (bm_lock_bh) {
- local_lock = false;
- bh = bm_lock_bh;
- }
-
- if (local_lock) {
- ocfs_down_sem (&(osb->vol_alloc_lock), true);
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, 0,
- &bm_lock_res, &bh, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- }
-
- bitmapblocks = (OCFS_ALIGN(osb->cluster_bitmap.validbits,
- OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
-
- status = ocfs_read_bhs(osb, osb->vol_layout.bitmap_off,
- bitmapblocks * osb->sect_size,
- osb->cluster_bitmap.chunk, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- if (!(*f)) {
- *f = alloc_bitmap_free_head();
- if (*f == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto bail;
- }
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(local_alloc_bh);
-
- LOG_TRACE_ARGS("alloc->alloc_size = %u, COUNT = %u, num_used = %u\n",
- alloc->alloc_size, ocfs_alloc_count_bits(alloc),
- alloc->num_used);
- /* any unset bits in local alloc need to be unset in bitmap. */
- bit_off = 0;
- left = alloc->alloc_size;
- while ((bit_off = find_next_zero_bit(alloc->bitmap, left, bit_off))
- != -1) {
- if (bit_off >= left) {
- /*LOG_TRACE_ARGS("bit_off (%d) >= left\n", bit_off);*/
- break;
- }
- /* LOG_TRACE_ARGS("Clearing bit %u in main bitmap\n", bit_off);*/
- status = ocfs_add_to_bitmap_free_head(osb,
- *f, 1,
- bit_off + alloc->bitmap_start,
- -1, DISK_ALLOC_VOLUME);
- if (status < 0) {
- free_bitmap_free_head(*f);
- *f = NULL;
- }
- bit_off++;
- }
-
- OCFS_BH_PUT_DATA(local_alloc_bh);
-
-bail:
- if (local_lock) {
- ocfs_up_sem (&(osb->vol_alloc_lock));
-
- if (bm_lock_res) {
- tmpstat = ocfs_release_lock (osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, bm_lock_res, bh, NULL);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_put_lockres (bm_lock_res);
- }
- if (bh != NULL)
- brelse(bh);
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_sync_local_to_main */
-
-/*
- * ocfs_alloc_new_window
- *
- * pass it the bitmap lock in lock_bh if you have it.
- */
-static int ocfs_alloc_new_window(ocfs_super *osb, struct buffer_head *lock_bh)
-{
- int status = 0;
- __u64 alloc_bytes, cluster_off, cluster_count;
- __u32 csize = osb->vol_layout.cluster_size;
- ocfs_local_alloc *alloc = NULL;
-
- LOG_ENTRY();
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
- if (alloc->alloc_size != 0)
- LOG_TRACE_STR("asking me to alloc a new window over a"
- " non-empty one");
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
-
- /* we try to use find_contig_space_from_bitmap here for now. */
- alloc_bytes = ocfs_local_alloc_window_bits(osb) * csize;
- LOG_TRACE_ARGS("Allocating %u.%u bytes (%u clusters) for a "
- "new window.\n", HILO(alloc_bytes),
- ocfs_local_alloc_window_bits(osb));
-
- status = ocfs_find_contiguous_space_from_bitmap(osb, alloc_bytes,
- &cluster_off,
- &cluster_count, false,
- lock_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
-
- alloc->bitmap_start = cluster_off;
- alloc->alloc_size = cluster_count;
- /* just in case... In the future when we find space ourselves,
- * we don't have to get all contiguous -- but we'll have to
- * set all previously used bits in bitmap and update
- * num_used before setting the bits in the main bitmap. */
- alloc->num_used = 0;
- memset(alloc->bitmap, 0, 256);
-
- LOG_TRACE_STR("New window allocated:");
- LOG_TRACE_ARGS("window bitmap_start = %u\n", alloc->bitmap_start);
- LOG_TRACE_ARGS("window alloc_size = %u\n", alloc->alloc_size);
-
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
-bail:
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_alloc_new_window */
-
-/*
- * ocfs_local_find_clear_bits
- */
-static int ocfs_local_find_clear_bits(ocfs_super *osb, ocfs_local_alloc *alloc,
- __u32 numbits)
-{
- int numfound, bitoff, left, startoff, lastzero;
- __u8 *bitmap = NULL;
-
- LOG_ENTRY_ARGS("(numbits wanted = %u)\n", numbits);
-
- bitmap = alloc->bitmap;
-
- numfound = bitoff = startoff = 0;
- lastzero = -1;
- left = alloc->alloc_size;
- while ((bitoff = find_next_zero_bit(bitmap, left, startoff)) != -1) {
- if (bitoff == left) {
- /* LOG_TRACE_ARGS("bitoff (%d) == left", bitoff); */
- break;
- }
- /* LOG_TRACE_ARGS("Found a zero: bitoff = %d, startoff = %d, "
- "numfound = %d\n", bitoff, startoff, numfound);*/
-
- /* Ok, we found a zero bit... is it contig. or do we
- * start over?*/
- if (bitoff == startoff) {
- /* we found a zero */
- numfound++;
- startoff++;
- } else {
- /* got a zero after some ones */
- numfound = 1;
- startoff = bitoff+1;
- }
- /* we got everything we needed */
- if (numfound == numbits) {
- /* LOG_TRACE_STR("Found it all!"); */
- break;
- }
- }
-
- LOG_TRACE_ARGS("Exiting loop, bitoff = %d, numfound = %d\n", bitoff,
- numfound);
-
- if (numfound == numbits)
- bitoff = startoff - numfound;
- else
- bitoff = -1;
-
- LOG_EXIT_STATUS(bitoff);
- return(bitoff);
-} /* ocfs_local_find_clear_bits */
-
-/*
- * ocfs_find_space_from_local
- *
- * We're somewhat sensitive to aborts here. If we're moving our
- * window, or shutting down due to error, we skip our own journal
- * handling and send the buffer straight to jbd. This ensures that if
- * we abort_trans during one of those operations, it still gets
- * written out. This way, the code above us can always process our
- * bitmap free head, and our latest window will always hit disk.
- */
-static int ocfs_find_space_from_local(ocfs_super *osb, __u32 bitswanted,
- __u64 * bitoff, __u64 * bitcount,
- ocfs_journal_handle *handle)
-{
- ocfs_local_alloc *alloc = NULL;
- int status = 0, tmpstat;
- int startoff, tmpoff;
- __u32 tmpwanted;
- bool dontdirty = false;
- /* main bitmap variables. */
- struct buffer_head *main_bm_bh = NULL;
- ocfs_lock_res *bm_lock_res = NULL;
-
- LOG_ENTRY_ARGS("(bitswanted = %u)\n", bitswanted);
-
- if (!osb->have_local_alloc)
- BUG();
-
- if (bitswanted > ocfs_local_alloc_window_bits(osb)) {
- LOG_TRACE_STR("Asking for more than my max window size!\n");
- status = -ENOSPC;
- goto bail;
- }
-
- status = ocfs_journal_access(handle, osb->local_alloc_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(osb->local_alloc_bh);
-tryagain:
- /* If we need to initialize a new window, do so now. */
- if (alloc->alloc_size == 0) {
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
- alloc = NULL;
- LOG_TRACE_STR("Allocating a new window...");
-
- status = ocfs_alloc_new_window(osb, main_bm_bh);
- if (status < 0) {
- if (status == -ENOSPC) {
- printk("ocfs: disabling local alloc "
- "bitmap for this mount.\n");
- /* at this point, we shouldn't have
- * anything allocated for the local
- * alloc, so shutting it down won't
- * wind up free'ing anything... */
- ocfs_shutdown_local_alloc(osb, NULL, true);
- goto bail;
- }
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- alloc = (ocfs_local_alloc *)
- OCFS_BH_GET_DATA(osb->local_alloc_bh);
- }
-
- /* Alright, try to satisfy the request. */
- startoff = ocfs_local_find_clear_bits(osb, alloc, bitswanted);
- if (startoff == -1) {
- /* we couldn't get enough bits from the local
- * alloc. Lets sync what we've got to the main bitmap,
- * clear the local out and try again. */
- LOG_TRACE_STR("Could not find enough contiguous bits in local "
- "alloc bitmap, trying to move my window.");
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
- alloc = NULL;
-
- /* lock bitmap here */
- ocfs_down_sem (&(osb->vol_alloc_lock), true);
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, 0,
- &bm_lock_res, &main_bm_bh, NULL);
- if (status < 0) {
- ocfs_up_sem (&(osb->vol_alloc_lock));
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- status = ocfs_sync_local_to_main(osb, &(osb->alloc_free_head),
- NULL, main_bm_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs_local_alloc *)
- OCFS_BH_GET_DATA(osb->local_alloc_bh);
-
- ocfs_clear_local_alloc(alloc);
-
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
- alloc = NULL;
-
- /* Ok, if we move our window, we have to make sure
- * that this transaction is a sync one, as we don't
- * want to crash after having free'd the main bitmap
- * bits and on replay have an old copy of the local
- * alloc put back! */
- ocfs_handle_set_sync(handle, true);
-
- /* skip our own abort handling. */
- status = journal_dirty_metadata(handle->k_handle,
- osb->local_alloc_bh);
- dontdirty = true;
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- alloc = (ocfs_local_alloc *)
- OCFS_BH_GET_DATA(osb->local_alloc_bh);
- goto tryagain;
- }
-
- LOG_TRACE_ARGS("Found %u bits, starting at local alloc offset %d\n",
- bitswanted, startoff);
-
- /* Ok, if we've got this far then the search suceeded and we
- * can mark the bitmap. */
- tmpoff = startoff;
- tmpwanted = bitswanted;
- while(tmpwanted--) {
- /* LOG_TRACE_ARGS("setting bit %d\n", tmpoff); */
- set_bit(tmpoff++, alloc->bitmap);
- }
- alloc->num_used += bitswanted;
-
- *bitoff = alloc->bitmap_start + startoff;
- *bitcount = bitswanted;
-
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
- alloc = NULL;
-
- if (!dontdirty) {
- status = ocfs_journal_dirty(handle, osb->local_alloc_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
-bail:
- /* if we locked the main bitmap, cleanup after ourselves. */
- if (main_bm_bh) {
- ocfs_up_sem (&(osb->vol_alloc_lock));
-
- tmpstat = ocfs_release_lock (osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, bm_lock_res, main_bm_bh, NULL);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_put_lockres (bm_lock_res);
- brelse(main_bm_bh);
- }
-
- if (alloc && osb->local_alloc_bh)
- OCFS_BH_PUT_DATA(osb->local_alloc_bh);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_find_space_from_local */
-
-
-/*
- * ocfs_find_space
- *
- * A drop-in replacement for
- * ocfs_find_contiguous_space_from_bitmap. We will in fact, call
- * ocfs_find_contiguous_space_from_bitmap if you don't give us a
- * journal handle, or if the local bitmap isn't loaded, or if the
- * allocation is simply to big to fit in the local one. otherwise,
- * we'll try to use our local alloc instead.
- *
- */
-int ocfs_find_space(ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count, bool sysfile, ocfs_journal_handle *handle)
-{
- int status = 0;
- __u32 bitswanted;
- __u32 csize = osb->vol_layout.cluster_size;
- bool use_global = true;
-
- LOG_ENTRY_ARGS("(file_size = (%u.%u), handle = 0x%x, sysfile = %s)\n",
- HILO(file_size), handle, sysfile ? "true" : "false");
-
- if (file_size == 0) {
- LOG_ERROR_STR ("asking for an allocation of zero bytes...");
- status = 0;
- goto bail;
- }
-
- /* need to calculate a couple of things for below... */
- bitswanted = (file_size + (csize-1)) / csize;
-
- /* Ok, now decide if we can use local alloc bitmap.
- * We *always* use global bitmap for clustersize > 128k,
- * file_size > 2mb, so force it under these conditions. */
- if ( (handle && osb->have_local_alloc)
- && (osb->vol_layout.cluster_size <= OCFS_LOCAL_ALLOC_MAX_CSIZE)
- && (file_size <= OCFS_LOCAL_ALLOC_MAX_ALLOC) )
- use_global = false;
-
- if (!use_global) {
- status = ocfs_find_space_from_local(osb, bitswanted,
- cluster_off, cluster_count,
- handle);
- /* If we've run out of space for our local alloc, lets
- * try the global one just in case... */
- if (status == -ENOSPC)
- use_global = true;
- else if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
-
- if (use_global)
- status = ocfs_find_contiguous_space_from_bitmap(osb, file_size,
- cluster_off,
- cluster_count,
- sysfile, NULL);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- LOG_TRACE_ARGS("Returning *cluster_off = %u.%u, *cluster_count"
- "= %u.%u\n", HILO(*cluster_off), HILO(*cluster_count));
-bail:
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_find_space */
-
-/*
- * ocfs_create_new_local_alloc
- *
- * significantly different enough from init_system_file that it
- * deserves it's own function
- */
-int ocfs_create_new_local_alloc(ocfs_super *osb, int node_num)
-{
- int status = 0;
- __u64 offset;
- struct buffer_head *alloc_bh = NULL;
- ocfs_local_alloc *alloc;
-
- LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
-
- offset = ((OCFS_VOL_BITMAP_FILE + node_num) * osb->sect_size) +
- osb->vol_layout.root_int_off;
-
- status = ocfs_read_bh(osb, offset, &alloc_bh, OCFS_BH_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(alloc_bh);
-
- memset(alloc, 0, sizeof(ocfs_local_alloc));
- strcpy (alloc->signature, OCFS_LOCAL_ALLOC_SIGNATURE);
- alloc->this_sector = offset;
- alloc->node_num = node_num;
-
- OCFS_BH_PUT_DATA(alloc_bh);
-
- status = ocfs_write_bh(osb, alloc_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-leave:
- if (alloc_bh)
- brelse(alloc_bh);
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_create_new_local_alloc */
-
-/*
- * ocfs_load_local_alloc
- */
-int ocfs_load_local_alloc(ocfs_super *osb)
-{
- int status = 0;
- ocfs_local_alloc *alloc = NULL;
- struct buffer_head *alloc_bh = NULL;
- __u64 offset;
- __u32 num_used;
-
- LOG_ENTRY();
-
- /* read the alloc off disk */
- offset = ((OCFS_VOL_BITMAP_FILE + osb->node_num) * osb->sect_size) +
- osb->vol_layout.root_int_off;
- status = ocfs_read_bh(osb, offset, &alloc_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(alloc_bh);
-
- /* do a little verification. */
- num_used = ocfs_alloc_count_bits(alloc);
-
- if (num_used != alloc->num_used) {
- LOG_TRACE_ARGS("num_used = %u, alloc->num_used = %u!\n",
- num_used, alloc->num_used);
- OCFS_BH_PUT_DATA(alloc_bh);
- status = -EFAIL;
- goto bail;
- }
-
- osb->local_alloc_bh = alloc_bh;
- osb->have_local_alloc = true;
-
- OCFS_BH_PUT_DATA(alloc_bh);
-bail:
- if (status < 0)
- if (alloc_bh)
- brelse(alloc_bh);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_load_local_alloc */
-
-/*
- * ocfs_shutdown_local_alloc
- *
- * return any unused bits to the bitmap and write out a clean
- * local_alloc.
- *
- * local_alloc_bh is optional. If not passed, we will simply use the
- * one off osb. If you do pass it however, be warned that it *will* be
- * returned brelse'd and NULL'd out.*/
-void ocfs_shutdown_local_alloc(ocfs_super *osb,
- struct buffer_head **local_alloc_bh, bool sync)
-{
- int status;
- ocfs_local_alloc *alloc = NULL;
- ocfs_bitmap_free_head *f = NULL;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY_ARGS("(local_alloc_bh = 0x%x, sync = %s\n)", local_alloc_bh,
- sync ? "true" : false);
-
- if (!osb->have_local_alloc)
- return;
-
- if (local_alloc_bh)
- bh = *local_alloc_bh;
- else
- bh = osb->local_alloc_bh;
-
- if (osb->alloc_free_head)
- LOG_TRACE_STR("Shutting down with a pending bitmap_free_head!");
- status = ocfs_sync_local_to_main(osb, &f, NULL, NULL);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- else if (f)
- ocfs_process_bitmap_free_head(osb, f);
-
- if (f) {
- free_bitmap_free_head(f);
- f = NULL;
- }
-
- alloc = (ocfs_local_alloc *) OCFS_BH_GET_DATA(bh);
- ocfs_clear_local_alloc(alloc);
- OCFS_BH_PUT_DATA(bh);
-
- if (sync) {
- status = ocfs_write_bh(osb, bh, OCFS_BH_IGNORE_JBD, NULL);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
-
- brelse(bh);
- /* this is special only if we're using the one off osb. */
- if (!local_alloc_bh) {
- osb->local_alloc_bh = NULL;
- osb->have_local_alloc = false;
- } else
- *local_alloc_bh = NULL;
-
- LOG_EXIT();
- return;
-} /* ocfs_shutdown_local_alloc */
-
-/*
- * ocfs_recover_local_alloc
- */
-int ocfs_recover_local_alloc(ocfs_super *osb, int node_num)
-{
- int status = 0;
- struct buffer_head *alloc_bh = NULL;
- __u64 offset;
-
- LOG_ENTRY_ARGS("(node_num = %d)\n", node_num);
-
- offset = ((OCFS_VOL_BITMAP_FILE + node_num) * osb->sect_size) +
- osb->vol_layout.root_int_off;
- status = ocfs_read_bh(osb, offset, &alloc_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- ocfs_shutdown_local_alloc(osb, &alloc_bh, true);
-
-bail:
- if (alloc_bh)
- brelse(alloc_bh);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_recover_local_alloc */
-
Deleted: trunk/bitmap.c
===================================================================
--- trunk/bitmap.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/bitmap.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,353 +0,0 @@
-/*
- * ocfsbitmap.c
- *
- * Bitmap infrastructure code
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#if defined(__KERNEL__)
-#include <ocfs.h>
-#else
-#include <asm/bitops.h>
-#include <dummy.h>
-#endif
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_PORT
-
-/*
- * ocfs_initialize_bitmap()
- *
- */
-void ocfs_initialize_bitmap (ocfs_alloc_bm * bitmap, __u32 validbits, __u32 allocbits)
-{
- __u32 tmp;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, %u)\n", bitmap, validbits, allocbits);
-
- bitmap->validbits = validbits;
- bitmap->allocbits = allocbits;
- bitmap->failed = 0;
- bitmap->ok_retries = 0;
-
- tmp = OCFS_ALIGN(allocbits, OCFS_BITS_IN_CHUNK);
- bitmap->numbh = (tmp / OCFS_BITS_IN_CHUNK);
- bitmap->chunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
- if (!bitmap->chunk)
- BUG();
-
- memset(bitmap->chunk, 0, (bitmap->numbh * sizeof(struct buffer_head *)));
-
- LOG_EXIT ();
- return;
-} /* ocfs_initialize_bitmap */
-
-void ocfs_uninitialize_bitmap(ocfs_alloc_bm *bitmap)
-{
- int i;
-
- LOG_ENTRY();
-
- for(i = 0; i < bitmap->numbh; i++)
- if (bitmap->chunk[i])
- brelse(bitmap->chunk[i]);
-
- ocfs_free(bitmap->chunk);
- bitmap->chunk = NULL;
- bitmap->numbh = 0;
- bitmap->validbits = 0;
- bitmap->allocbits = 0;
- bitmap->failed = 0;
- bitmap->ok_retries = 0;
-
- LOG_EXIT();
- return;
-}
-
-/* we only handle if the bitmap has grown, not shrunk. */
-void ocfs_reinitialize_bitmap(ocfs_alloc_bm *bitmap, __u32 validbits, __u32 allocbits)
-{
- __u32 tmp;
- __u32 newnumbh;
- struct buffer_head **newchunk;
-
- LOG_ENTRY();
-
- if (allocbits < bitmap->allocbits)
- BUG();
-
- /* most of the time the actual alloc'd size of the bitmap file
- * won't change and we don't have to update the buffer heads
- * or the number of bhs */
- if (allocbits == bitmap->allocbits)
- goto skipbhs;
-
- tmp = OCFS_ALIGN(allocbits, OCFS_BITS_IN_CHUNK);
- newnumbh = (tmp / OCFS_BITS_IN_CHUNK);
- newchunk = ocfs_malloc(bitmap->numbh * sizeof(struct buffer_head *));
-
- if (!newchunk)
- BUG();
-
- memset(newchunk, 0, (newnumbh * sizeof(struct buffer_head *)));
-
- memcpy(newchunk, bitmap->chunk, (bitmap->numbh * sizeof(struct buffer_head *)));
-
- ocfs_free(bitmap->chunk);
-
- bitmap->numbh = newnumbh;
- bitmap->chunk = newchunk;
- bitmap->allocbits = allocbits;
-skipbhs:
- bitmap->validbits = validbits;
-
- LOG_EXIT();
-}
-
-/*
- * ocfs_find_clear_bits()
- *
- * sysonly is passed # bits in bitmap that are rserved for system file space
- * in case we have a disk full.
- *
- */
-int ocfs_find_clear_bits (ocfs_super *osb, ocfs_alloc_bm * bitmap, __u32 numBits, __u32 offset, __u32 sysonly)
-{
- __u32 globalsize, globaloff, localstart, lastbh, size, bitoff, count;
- void *buffer;
- int c;
- struct buffer_head *currbh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %u, %u)\n", osb, bitmap, numBits,
- offset, sysonly);
-
- globalsize = bitmap->validbits - sysonly;
- bitoff = count = 0;
- lastbh = (OCFS_ALIGN(globalsize, OCFS_BITS_IN_CHUNK) /
- OCFS_BITS_IN_CHUNK) - 1;
-
- globaloff = offset;
- localstart = OCFS_GLOBAL_OFF_TO_LOCAL(globaloff);
-
- if (lastbh == 0)
- size = globalsize;
- else
- size = OCFS_BITS_IN_CHUNK;
-
- c = OCFS_GLOBAL_OFF_TO_CHUNK(localstart);
- currbh = bitmap->chunk[c];
-
- /*LOG_TRACE_ARGS("globalsize=%u, bitmap->validbits=%u, sysonly=%u\n",
- globalsize, bitmap->validbits, sysonly);*/
- /*LOG_TRACE_ARGS("before loop: c=%u, lastbh=%u, size=%u, "
- "localstart=%u\n", c, lastbh, size, localstart);*/
- buffer = OCFS_BH_GET_DATA(currbh);
-
- while ((bitoff = find_next_zero_bit(buffer, OCFS_BITS_IN_CHUNK,
- localstart)) != -1) {
- /*LOG_TRACE_ARGS("c=%u, globaloff=%u, bitoff=%u, "
- "localstart=%u\n", c, globaloff, bitoff,
- localstart);*/
- /* find_next_zero_bit returns:
- >= size passed in: if no zero bits in here.
- some number < size: at the next zero bit
- localstart: if the current one is a zero
- */
- if (bitoff >= size) {
- /* we've hit the end of our bh. */
- OCFS_BH_PUT_DATA(currbh);
- /*LOG_TRACE_ARGS("bitoff >= size (%u)\n", bitoff,c);*/
-
- /* if it's the last bh, then quit the loop */
- if (c == lastbh) {
- count = 0;
- LOG_TRACE_STR("Didn't find enough!");
- break;
- }
- /* otherwise, reset localstart and switch bhs
- * and continue */
- localstart = bitoff = 0;
- c++;
- currbh = bitmap->chunk[c];
- buffer = OCFS_BH_GET_DATA(currbh);
- if (c == lastbh)
- size = globalsize-(OCFS_BITS_IN_CHUNK*lastbh);
- continue;
- }
-
- if (bitoff == localstart) {
- /*LOG_TRACE_ARGS("bitoff == localstart (%u)\n",
- bitoff);*/
- /* cool, we have another zero! */
- count++;
- localstart++;
- globaloff++;
- } else {
- /*LOG_TRACE_ARGS("bitoff (%u) != localstart (%u)\n",
- bitoff, localstart);*/
- /* we had to skip over some ones */
- count = 1;
- globaloff = OCFS_CHUNK_TO_GLOBAL_OFF(c, bitoff) + 1;
- localstart = bitoff + 1;
- }
-
- if (count == numBits) {
- /* we've found everything we wanted. */
- LOG_TRACE_ARGS("Found it all! (count=%u)\n", count);
- OCFS_BH_PUT_DATA(currbh);
- buffer = NULL;
- break;
- }
- }
-
- if (count == numBits)
- bitoff = globaloff - count;
- else
- bitoff = -1;
-
- LOG_EXIT_LONG (bitoff);
- return bitoff;
-} /* ocfs_find_clear_bits */
-
-/*
- * ocfs_count_bits()
- *
- */
-int ocfs_count_bits (ocfs_alloc_bm * bitmap)
-{
- __u32 size, count = 0, i, j;
- struct buffer_head *currbh;
- unsigned char tmp;
- __u8 *buffer;
- __u32 validbh;
-
- LOG_ENTRY ();
-
- size = (bitmap->validbits >> 3);
- validbh = OCFS_ALIGN(bitmap->validbits, OCFS_BITS_IN_CHUNK) /
- OCFS_BITS_IN_CHUNK;
-
- for (i = 0; i < validbh; i++) {
- currbh = bitmap->chunk[i];
- buffer = OCFS_BH_GET_DATA(currbh);
- for (j = 0; j < (size % OCFS_BITMAP_CHUNK ?
- size % OCFS_BITMAP_CHUNK :
- OCFS_BITMAP_CHUNK); j++) {
- memcpy (&tmp, buffer, 1);
- count += BITCOUNT (tmp);
- buffer++;
- }
- OCFS_BH_PUT_DATA(currbh);
- }
-
- LOG_EXIT_ULONG (count);
- return count;
-} /* ocfs_count_bits */
-
-#ifdef __KERNEL__
-
-/* HEY LOOK! These two functions are IDENTICAL except for one line!
- * We'd never do that... no, never... */
-
-/*
- * ocfs_set_bits()
- *
- */
-void ocfs_set_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
-{
- struct buffer_head *currbh = NULL;
- char *buff;
- int i, local;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, %u)\n", bitmap, start, num);
-
- if ((start + num) > bitmap->validbits) {
- LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and " \
- "num = %u!\n", bitmap->validbits, start, num);
- goto bail;
- }
-
- i = OCFS_GLOBAL_OFF_TO_CHUNK(start);
- local = OCFS_GLOBAL_OFF_TO_LOCAL(start);
- currbh = bitmap->chunk[i];
-
- buff = OCFS_BH_GET_DATA(currbh);
-
- while (num--) {
- set_bit (local++, buff);
- if (local >= OCFS_BITS_IN_CHUNK && num != 0) {
- local = 0;
- OCFS_BH_PUT_DATA(currbh);
- i++;
- currbh = bitmap->chunk[i];
- buff = OCFS_BH_GET_DATA(currbh);
- }
- }
-
- OCFS_BH_PUT_DATA(currbh);
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_set_bits */
-
-/*
- * ocfs_clear_bits()
- *
- */
-void ocfs_clear_bits (ocfs_alloc_bm * bitmap, __u32 start, __u32 num)
-{
- struct buffer_head *currbh = NULL;
- char *buff;
- int i, local;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, %u)\n", bitmap, start, num);
-
- if ((start + num) > bitmap->validbits) {
- LOG_ERROR_ARGS("bitmap->validbits = %u but start = %u and " \
- "num = %u!\n", bitmap->validbits, start, num);
- goto bail;
- }
-
- i = OCFS_GLOBAL_OFF_TO_CHUNK(start);
- local = OCFS_GLOBAL_OFF_TO_LOCAL(start);
- currbh = bitmap->chunk[i];
-
- buff = OCFS_BH_GET_DATA(currbh);
-
- while (num--) {
- clear_bit (local++, buff);
- if (local >= OCFS_BITS_IN_CHUNK && num != 0) {
- local = 0;
- OCFS_BH_PUT_DATA(currbh);
- i++;
- currbh = bitmap->chunk[i];
- buff = OCFS_BH_GET_DATA(currbh);
- }
- }
-
- OCFS_BH_PUT_DATA(currbh);
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_clear_bits */
-
-#endif /* __KERNEL */
Deleted: trunk/dcache.c
===================================================================
--- trunk/dcache.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/dcache.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,153 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-/*
- * ocfs_dentry_revalidate()
- *
- */
-int ocfs_dentry_revalidate (struct dentry *dentry, int flags)
-{
- int tmpstat, ret = 0; /* if all else fails, just return false */
- ocfs_file_entry *fe = NULL;
- struct inode *inode;
- ocfs_inode *oin;
- ocfs_super *osb;
- __u64 off;
- ocfs_find_inode_args args;
- struct qstr q;
- struct buffer_head *fe_bh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %d, '%*s')\n", dentry, flags,
- dentry->d_name.len, dentry->d_name.name);
-
- if ((inode = dentry->d_inode) == NULL ||
- (osb = (ocfs_super *)(OCFS_GENERIC_SB_P(inode->i_sb))) == NULL)
- goto bail;
-
- if (osb->publ_map == (1 << osb->node_num)) {
- LOG_TRACE_STR ("Only node alive. revalidate=true.");
- ret = 1;
- goto bail;
- }
-
- /* check for oin */
- if (inode_data_is_oin (inode)) {
- ocfs_lock_res *res = NULL;
- ret = 1; /* with an oin we cannot fail revalidate */
- oin = GET_INODE_OIN(inode);
-
- if (ocfs_lookup_sector_node (osb, oin->file_disk_off, &res)==0) {
- /* if I hold cache lock, no revalidate needed */
- if (res->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK &&
- res->master_node_num == osb->node_num) {
- ocfs_put_lockres (res);
- goto bail;
- } else
- ocfs_put_lockres (res);
- }
- /* hit the disk */
- /* TODO: optimize */
- ocfs_down_sem (&(oin->main_res), true);
- oin->needs_verification = true;
- tmpstat = ocfs_verify_update_oin(osb, oin);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_up_sem (&(oin->main_res));
- goto bail;
- }
-
- /* no oin for this dentry, must hit the disk */
- /* TODO: optimize */
- if (S_ISDIR (inode->i_mode)) {
- __u64 parentOff;
- struct inode *parent = dentry->d_parent->d_inode;
-
- /* shouldn't be revalidating root dir, need offset to parent, and fe for this dir */
- if (osb->oin_root_dir->inode == inode ||
- !ocfs_linux_get_inode_offset (parent, &parentOff, NULL) ||
- !ocfs_linux_get_dir_entry_offset (osb, &off, parentOff, &(dentry->d_name), &fe_bh, NULL))
- goto bail;
- } else if (ocfs_linux_get_inode_offset (inode, &off, NULL)) {
- tmpstat= ocfs_read_bh(osb, off, &fe_bh, 0, inode);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS(tmpstat);
- goto bail;
- }
-
-// if (ocfs_force_get_file_entry (osb, &fe, off, true) < 0)
- // goto bail;
- } else {
- /* icky failure case :( */
- goto bail;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- /* we now have a file entry to call read_inode */
- q.name = fe->filename;
- q.len = strlen(fe->filename);
- if (fe->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION ||
- fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED ||
- fe->sync_flags & OCFS_SYNC_FLAG_DELETED ||
- ocfs_compare_qstr(&dentry->d_name, &q) != 0) {
- LOG_TRACE_STR("found the file entry, but it has been deleted or renamed!");
- ret = 0; /* it is now officially stale :) */
- } else {
-#ifdef LINUX_2_5
- ocfs_read_locked_inode (inode, fe);
-#else
- args.offset = fe->this_sector;
- args.fe_bh = fe_bh;
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
- ocfs_read_inode2 (inode, (void *) &args);
-#endif
- ret = 1;
- }
-
-bail:
- if (fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_dentry_revalidate */
-
-/*
- * ocfs_empty()
- *
- */
-int ocfs_empty (struct dentry *dentry)
-{
- struct list_head *list;
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, '%*s')\n", dentry,
- dentry->d_name.len, dentry->d_name.name);
-
- spin_lock (&dcache_lock);
- list = dentry->d_subdirs.next;
-
- while (list != &dentry->d_subdirs) {
- struct dentry *de = list_entry (list, struct dentry, d_child);
-
- if (de->d_inode && !d_unhashed (de)) {
- spin_unlock (&dcache_lock);
- ret = 0;
- goto bail;
- }
- list = list->next;
- }
- spin_unlock (&dcache_lock);
- ret = 1;
-
- bail:
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_empty */
-
-
Deleted: trunk/dir.c
===================================================================
--- trunk/dir.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/dir.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1374 +0,0 @@
-#include <ocfs.h>
-
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-static int ocfs_insert_dir_node (ocfs_super * osb, struct buffer_head *bhs[], ocfs_file_entry * InsertEntry, struct buffer_head *lockbh, __s32 * IndexOffset, struct buffer_head **insert_bh, ocfs_journal_handle * handle, struct inode *dir_inode, struct inode *file_inode);
-static bool ocfs_search_dir_node (ocfs_super * osb, struct buffer_head *bhs[],
- struct qstr * SearchName,
- struct buffer_head ** found_fe_bh,
- ocfs_file * OFile, struct inode *dir_inode);
-static bool ocfs_find_index (ocfs_super * osb, struct buffer_head *bhs[],
- struct qstr * FileName, int *Index);
-#if 0
-static void ocfs_print_dir_node (ocfs_super * osb, ocfs_dir_node * DirNode);
-static void ocfs_print_file_entry (ocfs_file_entry * fe);
-#endif
-
-/*
- * ocfs_readdir()
- *
- */
-int ocfs_readdir (struct file *filp, void *dirent, filldir_t filldir)
-{
- int pos;
- struct super_block *sb;
- ocfs_super *osb;
- ocfs_inode *oin;
- ocfs_file *ofile;
- struct buffer_head *entry_bh = NULL;
- ocfs_file_entry *entry = NULL;
- __u64 rootOff;
- int ret = 0;
- struct inode *inode = filp->f_dentry->d_inode;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", filp, dirent,
- filp->f_dentry->d_name.len, filp->f_dentry->d_name.name);
-
- pos = filp->f_pos;
- sb = inode->i_sb;
- if (!(OCFS_GENERIC_SB_P(sb))) {
- LOG_TRACE_STR ("Invalid OSB");
- goto bail;
- }
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
-
- if (!ocfs_linux_get_inode_offset (inode, &rootOff, &oin)) {
- LOG_TRACE_STR ("Inode has no OIN");
- goto bail;
- }
-
- if (!S_ISDIR (inode->i_mode)) {
- LOG_TRACE_STR ("Not a dir");
- ret = -ENOTDIR;
- goto bail;
- }
-
- switch (pos) {
- case 0:
- {
- if (filldir (dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
- break;
- pos++;
- filp->f_pos++;
- break;
- }
- case 1:
- {
- if (filldir (dirent, "..", 2, 1,
- filp->f_dentry->d_parent->d_inode->i_ino,
- DT_DIR) < 0)
- break;
- pos++;
- filp->f_pos++;
- break;
- }
- /* case 2: */
- default:
- {
- if (pos == 2) {
- if (filp->private_data)
- ocfs_release_ofile(((ocfs_file *) filp->private_data));
- filp->private_data = ocfs_allocate_ofile(OCFS_ATTRIB_DIRECTORY);
- if (filp->private_data == NULL) {
- LOG_TRACE_STR ("Failed to allocate OFile");
- ret = -ENOMEM;
- goto bail;
- }
- }
-
- ofile = (ocfs_file *) filp->private_data;
- while (1) {
- int r;
- /* TODO: find out if we need locking around this ofile */
- if (ofile->filldir.ino != 0) {
- r=filldir (dirent, ofile->filldir.fname, strlen (ofile->filldir.fname),
- ofile->filldir.pos, ofile->filldir.ino, DT_UNKNOWN);
- ofile->filldir.ino = 0;
- if (r < 0)
- LOG_ERROR_STR("filldir failed");
- } else {
- if (ocfs_find_files_on_disk (osb, rootOff, NULL, &entry_bh, ofile, inode) < 0)
- break;
- entry = (ocfs_file_entry *) OCFS_BH_GET_DATA(entry_bh);
- r=filldir (dirent, entry->filename, strlen (entry->filename), filp->f_pos,
- LO (entry->this_sector), DT_UNKNOWN);
- if (r < 0) {
- memcpy(ofile->filldir.fname, entry->filename, OCFS_MAX_FILENAME_LENGTH);
- ofile->filldir.pos = filp->f_pos;
- ofile->filldir.ino = LO (entry->this_sector);
- }
- OCFS_BH_PUT_DATA(entry_bh);
- brelse(entry_bh);
- entry_bh = NULL; entry = NULL;
- if (r < 0)
- goto bail;
- }
- pos++;
- filp->f_pos++;
- }
-
- break;
- }
- }
-
-bail:
- if (entry_bh) {
- if (entry)
- OCFS_BH_PUT_DATA(entry_bh);
- brelse(entry_bh);
- }
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_readdir */
-
-/* ocfs_find_files_on_disk()
- *
- */
-int ocfs_find_files_on_disk (ocfs_super * osb, __u64 parent_off, struct qstr * file_name, struct buffer_head ** fe_bh, ocfs_file * ofile, struct inode *inode)
-{
- int status = -ENOENT;
- __u64 thisDirNode;
- int tmpstat;
- ocfs_lock_res *lockres = NULL;
- bool temp_bhs = false;
- bool lock_acq = false;
- struct buffer_head *bh = NULL;
- struct buffer_head **bhs = NULL;
- int bufsz, nbhs, i;
-
-
- /* TODO: change this to take a buffer head instead of fe */
-
- LOG_ENTRY_ARGS ("(osb=%p, parent=%u.%u, fname=%p, fe_bh=%p, ofile=%p)\n", osb, parent_off, file_name, fe_bh, ofile);
-
- nbhs = osb->vol_layout.dir_node_size >> 9;
- bufsz = nbhs * (sizeof(struct buffer_head *));
-
- thisDirNode = parent_off;
- if (ofile == NULL) {
- temp_bhs = true;
- bhs = ocfs_malloc (bufsz);
- if (bhs == NULL) {
- temp_bhs = false;
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto leave;
- }
- memset(bhs, 0, bufsz);
- } else {
- if (ofile->curr_dir_off > 0)
- thisDirNode = ofile->curr_dir_off;
- bhs = ofile->curr_dir_buf;
- }
- OCFS_ASSERT(bhs);
-
- /* Get a shared lock on the directory... */
- status = ocfs_acquire_lock (osb, parent_off, OCFS_DLM_SHARED_LOCK, FLAG_DIR,
- &lockres, &bh, inode);
- if (status < 0) {
- /* Volume should be disabled in this case */
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- lock_acq = true;
-
- if (bhs[0]==NULL || bhs[0]->b_blocknr != (thisDirNode >> 9)) {
- for (i=0; i<nbhs; i++) {
- if (bhs[i]) {
- brelse(bhs[i]);
- bhs[i]=NULL;
- }
- }
- status = ocfs_read_bhs (osb, thisDirNode, osb->vol_layout.dir_node_size, bhs, OCFS_BH_CACHED, inode);
- if (status < 0) {
- /* Volume should be disabled in this case */
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
- status = 0;
- /* if file_name is null here, it means that we want to walk the */
- /* directory for all files if it is not null, it means we want */
- /* a particular file */
- if (!ocfs_search_dir_node (osb, bhs, file_name, fe_bh, ofile, inode))
- status = -ENOENT;
-
-leave:
-
- if (lock_acq)
- {
- tmpstat = ocfs_release_lock (osb, parent_off, OCFS_DLM_SHARED_LOCK,
- FLAG_DIR, lockres, bh, inode);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (tmpstat);
- /* Volume should be disabled in this case */
- }
- }
-
- if (bh != NULL)
- brelse(bh);
-
- ocfs_put_lockres (lockres);
-
- /* if we won't be brelsing/freeing on file */
- /* close do all of the cleanup here */
- if (temp_bhs) {
- for (i=0; i<nbhs; i++)
- if (bhs[i])
- brelse(bhs[i]);
- ocfs_safefree(bhs);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_find_files_on_disk */
-
-/* ocfs_initialize_dir_node()
- *
- */
-void ocfs_initialize_dir_node (ocfs_super * osb, ocfs_dir_node * dir_node, __u64 bitmap_off, __u64 file_off, __u32 node)
-{
- LOG_ENTRY ();
-
- memset (dir_node, 0, sizeof (ocfs_dir_node));
- strcpy (dir_node->signature, OCFS_DIR_NODE_SIGNATURE);
-
- dir_node->num_ents = (__u8) osb->max_dir_node_ent;
- dir_node->node_disk_off = bitmap_off;
- dir_node->alloc_file_off = file_off;
- dir_node->alloc_node = node;
-
- DISK_LOCK_CURRENT_MASTER (dir_node) = OCFS_INVALID_NODE_NUM;
-
- dir_node->free_node_ptr = INVALID_NODE_POINTER;
- dir_node->next_node_ptr = INVALID_NODE_POINTER;
- dir_node->indx_node_ptr = INVALID_NODE_POINTER;
- dir_node->next_del_ent_node = INVALID_NODE_POINTER;
- dir_node->head_del_ent_node = INVALID_NODE_POINTER;
-
- dir_node->first_del = INVALID_DIR_NODE_INDEX;
- dir_node->index_dirty = 0;
-
- LOG_EXIT ();
- return;
-} /* ocfs_initialize_dir_node */
-
-#if 0
-/*
- * ocfs_write_force_dir_node()
- *
- */
-int ocfs_write_force_dir_node (ocfs_super * osb, struct buffer_head *bhs[], __s32 idx)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- /* Write the file entry at idx, if given */
- if (idx != -1) {
- status = ocfs_write_bh (osb, bhs[idx+1], 0);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
- /* Write the first sector last */
- status = ocfs_write_bh (osb, bhs[0], 0);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_force_dir_node */
-#endif
-
-/*
- * ocfs_write_dir_node()
- *
- */
-int ocfs_write_dir_node (ocfs_super * osb, struct buffer_head *bhs[], __s32 idx, struct inode *dir_inode, struct inode *file_inode)
-{
- int status = 0;
- __u64 offset;
- ocfs_dir_node *DirNode = NULL;
- ocfs_file_entry *fe = NULL;
- bool sync_hdr_write = false, sync_fe_write = false;
- bool cached_hdr_write = false, cached_fe_write = false;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
-
- offset = DirNode->node_disk_off + ((idx + 1) * 512);
-
- if ((DISK_LOCK_CURRENT_MASTER (DirNode) == osb->node_num) &&
- (DISK_LOCK_FILE_LOCK (DirNode) == OCFS_DLM_ENABLE_CACHE_LOCK)) {
- cached_hdr_write = true;
- } else
- sync_hdr_write = true;
-
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (idx != -1) {
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bhs[idx+1]);
-
- if(!IS_VALID_FILE_ENTRY(fe)) {
- OCFS_BH_PUT_DATA(bhs[idx+1]);
- status = -EIO; // ???
- goto bail;
- }
-
- if ((DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num) &&
- (DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK)) {
- cached_fe_write = true;
- if (!cached_hdr_write)
- sync_fe_write = true;
- } else {
- ocfs_down_sem(&(osb->map_lock), true);
- ocfs_remove_extent_map_entry(osb, &osb->metadata_map, offset, 512);
- ocfs_remove_extent_map_entry(osb, &osb->trans_map, offset, 512);
- ocfs_up_sem(&(osb->map_lock));
- sync_fe_write = true;
- sync_hdr_write = true;
- }
-
- OCFS_BH_PUT_DATA(bhs[idx+1]);
- }
-
- /* Write the file entry at idx, if given */
- if (cached_fe_write) {
- status = ocfs_write_bh (osb, bhs[idx+1], OCFS_BH_CACHED, file_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
- if (sync_fe_write) {
- status = ocfs_write_bh (osb, bhs[idx+1], 0, file_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
- /* Write the first sector last */
- if (cached_hdr_write) {
- status = ocfs_write_bh (osb, bhs[0], OCFS_BH_CACHED, dir_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
- if (sync_hdr_write) {
- status = ocfs_write_bh (osb, bhs[0], 0, dir_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
- //IF_TRACE (ocfs_print_dir_node (osb, DirNode));
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_dir_node */
-
-
-/*
- * ocfs_search_dir_node()
- *
- */
-static bool ocfs_search_dir_node (ocfs_super * osb, struct buffer_head *bhs[], struct qstr * SearchName, struct buffer_head ** found_fe_bh, ocfs_file * OFile, struct inode *dir_inode)
-{
- __u32 start;
- __u32 i;
- ocfs_file_entry *fe;
- int status;
- bool bRet = false;
- ocfs_dir_node * DirNode = NULL, *tmp;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *) ocfs_malloc(512);
- if (DirNode == NULL) {
- LOG_ERROR_STR("Out of memory");
- bRet = false;
- goto bail;
- }
-
- tmp = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- memcpy(DirNode, tmp, 512);
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (OFile != NULL)
- start = OFile->curr_byte_off;
- else
- start = 0;
-
-
- if (!IS_VALID_DIR_NODE (DirNode)) {
- bRet = false;
- goto bail;
- }
-
- while (1) {
- /* Iterate thru this dirnode and find a matching entry */
- for (i = start; i < DirNode->num_ent_used; i++) {
- bool found = true;
-
- if (SearchName != NULL) {
- found = ocfs_find_index (osb, bhs, SearchName, (int *) &i);
- }
-
- if (found) {
- fe = FILEENT_GETBH(DirNode, bhs, i);
- if (fe == NULL) {
- // fe is locked by this kernel thread
- continue;
- }
-
- if (fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED ||
- !(fe->sync_flags & OCFS_SYNC_FLAG_VALID)) {
- FILEENT_PUTBH(DirNode, bhs, i);
- continue;
- }
-
- LOG_TRACE_ARGS ("Returning entry: %u, name: %s\n", i, fe->filename);
- FILEENT_PUTBH(DirNode, bhs, i);
- *found_fe_bh = bhs[DirNode->index[i]+1];
- /* we get_bh this guy one more time
- * because the caller needs his own
- * reference as this is still also
- * part of the directory data. */
- get_bh(*found_fe_bh);
-
- if (OFile != NULL) {
- OFile->curr_dir_off = DirNode->node_disk_off;
- OFile->curr_byte_off = i + 1;
- }
- bRet = true;
- goto bail;
- } else
- break;
- }
- if (DirNode->next_node_ptr != -1) {
- __u64 next = DirNode->next_node_ptr;
-
- /* dump what we've got */
- for (i=0; i<256; i++) {
- if (bhs[i]) {
- brelse(bhs[i]);
- bhs[i] = NULL;
- }
- }
- status = ocfs_read_bhs (osb, next, osb->vol_layout.dir_node_size, bhs, OCFS_BH_CACHED, dir_inode);
- if (status < 0) {
- LOG_ERROR_STR("failed to read directory");
- bRet = false;
- goto bail;
- }
-
- tmp = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- memcpy(DirNode, tmp, 512);
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (!IS_VALID_DIR_NODE (DirNode)) {
- bRet = false;
- goto bail;
- }
- start = 0;
- continue;
- } else {
- /* We are done... */
- break;
- }
- }
-
- if (OFile != NULL) {
- OFile->curr_dir_off = DirNode->node_disk_off;
- OFile->curr_byte_off = i + 1;
- }
-
- bail:
- if (DirNode)
- ocfs_safefree(DirNode);
-
- LOG_EXIT_ULONG (bRet);
- return bRet;
-} /* ocfs_search_dir_node */
-
-
-/*
- * ocfs_find_index()
- *
- */
-static bool ocfs_find_index (ocfs_super * osb, struct buffer_head *bhs[], struct qstr * FileName, int *Index)
-{
- int lowBnd, upBnd;
- ocfs_file_entry *fe;
- int res = -1, index = 0, start = 0;
- int ret = false;
- struct qstr q;
- ocfs_dir_node * DirNode = NULL;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- if (!IS_VALID_DIR_NODE (DirNode) || FileName==NULL) {
- ret = false;
- goto bail;
- }
-
- if (*Index > 0)
- start = *Index;
-
- if (DirNode->index_dirty) {
- for (index = start; index < DirNode->num_ent_used; index++) {
- fe = FILEENT_GETBH(DirNode, bhs, index);
- if (fe == NULL) {
- // fe is locked by this kernel thread
- continue;
- }
-
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- OCFS_BH_PUT_DATA(bhs[index+1]);
- continue;
- }
- q.name = fe->filename;
- q.len = strlen(fe->filename);
- res = ocfs_compare_qstr(&q, FileName);
- FILEENT_PUTBH(DirNode, bhs, index);
-
- if (!res) {
- *Index = index;
- ret = true;
- goto bail;
- }
- }
- *Index = index;
- ret = false;
- goto bail;
- }
-
- for (lowBnd = start, upBnd = (DirNode->num_ent_used - start); upBnd; upBnd >>= 1) {
- index = lowBnd + (upBnd >> 1);
- fe = FILEENT_GETBH(DirNode, bhs, index);
- if (fe == NULL) {
- // fe is locked by this kernel thread
- continue;
- }
-
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
-
- FILEENT_PUTBH(DirNode, bhs, index);
-
- for (index = lowBnd; index < (lowBnd + upBnd); index++) {
- fe = FILEENT_GETBH(DirNode, bhs, index);
- if (fe == NULL) {
- // fe is locked by this kernel thread
- continue;
- }
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- FILEENT_PUTBH(DirNode, bhs, index);
- continue;
- }
-
- q.name = fe->filename;
- q.len = strlen(fe->filename);
- res = ocfs_compare_qstr(&q, FileName);
- FILEENT_PUTBH(DirNode, bhs, index);
-
- if (!res) {
- *Index = index;
- ret = true;
- goto bail;
- }
- if (res < 0) {
- *Index = index;
- ret = false;
- goto bail;
- }
- }
- *Index = lowBnd + upBnd - 1;
- ret = false;
- goto bail;
- }
-
- q.name = fe->filename;
- q.len = strlen(fe->filename);
- res = ocfs_compare_qstr(&q, FileName);
- FILEENT_PUTBH(DirNode, bhs, index);
-
- if (!res) {
- *Index = index;
- ret = true;
- goto bail;
- }
-
- if (res > 0) {
- lowBnd = index + 1;
- --upBnd;
- }
- }
-
- *Index = index;
-
-bail:
- if (DirNode)
- OCFS_BH_PUT_DATA(bhs[0]);
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_find_index */
-
-/*
- * ocfs_reindex_dir_node()
- *
- */
-int ocfs_reindex_dir_node (ocfs_super * osb, __u64 DirNodeOffset, struct buffer_head *bhs[], ocfs_journal_handle *handle, struct inode *dir_inode)
-{
- int status = 0;
- ocfs_dir_node *dir = NULL;
- ocfs_file_entry *target;
- ocfs_file_entry *fe;
- __u32 i;
- __u8 offset = 0;
- int nbhs, bufsz;
- struct buffer_head **arr = NULL;
-
- LOG_ENTRY ();
-
- nbhs = osb->vol_layout.dir_node_size >> 9;
- bufsz = nbhs * (sizeof(struct buffer_head *));
-
- if (bhs == NULL) {
- arr = ocfs_malloc (bufsz);
- if (arr == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- status = ocfs_read_bhs (osb, DirNodeOffset,
- osb->vol_layout.dir_node_size, arr,
- OCFS_BH_CACHED, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else
- arr = bhs;
-
- dir = (ocfs_dir_node *)OCFS_BH_GET_DATA(arr[0]);
- if (!IS_VALID_DIR_NODE (dir)) {
- OCFS_BH_PUT_DATA(arr[0]);
- LOG_ERROR_STATUS(status = -EINVAL);
- goto leave;
- }
-
- if (dir->index_dirty) {
- offset = dir->bad_off;
-
- target = (ocfs_file_entry *)OCFS_BH_GET_DATA(arr[offset+1]);
-
- for (i = 0; i < dir->num_ent_used; i++) {
- /* don't need to check ourselves */
- if (dir->index[i] == offset)
- continue;
-
- fe = FILEENT_GETBH(dir, arr, i);
- if (fe == NULL) {
- // buffer is locked, like the rename case
- continue;
- }
-
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- FILEENT_PUTBH(dir, arr, i);
- continue;
- }
-
- /* find the first file entry that is alphabetically */
- /* less than the target file entry */
- if (strcmp (fe->filename, target->filename) < 0) {
- FILEENT_PUTBH(dir, arr, i);
- break;
- }
- FILEENT_PUTBH(dir, arr, i);
- }
-
- OCFS_BH_PUT_DATA(arr[offset+1]);
-
- if (i < dir->num_ent_used - 1) {
- memmove (&dir->index[i+1], &dir->index[i],
- dir->num_ent_used - i);
- dir->index[i] = offset;
- }
-
- dir->index_dirty = 0;
- OCFS_BH_PUT_DATA(arr[0]);
-
- status = ocfs_write_dir_node (osb, arr, -1, dir_inode, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else
- OCFS_BH_PUT_DATA(arr[0]);
-
- leave:
- if (bhs == NULL)
- ocfs_safefree (arr);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_reindex_dir_node */
-
-/*
- * ocfs_insert_dir_node()
- *
- */
-static int ocfs_insert_dir_node (ocfs_super * osb, struct buffer_head *bhs[], ocfs_file_entry * InsertEntry, struct buffer_head *lockbh, __s32 * IndexOffset, struct buffer_head **insert_bh, ocfs_journal_handle * handle, struct inode *dir_inode, struct inode *file_inode)
-{
- int status = 0;
- ocfs_file_entry *fe;
- int res = 0;
- int index = -1;
- ocfs_file_entry *lastEntry;
- __u8 freeOffset;
- struct qstr q;
- ocfs_dir_node * DirNode = NULL;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
-
- if (!IS_VALID_DIR_NODE (DirNode)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- OCFS_BH_PUT_DATA(bhs[0]);
- goto bail;
- }
-
- if (DirNode->index_dirty) {
- __u64 off = DirNode->node_disk_off;
-
- OCFS_BH_PUT_DATA(bhs[0]);
- status = ocfs_reindex_dir_node (osb, off, bhs, handle, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- }
-
- /* Should status be updated here? */
- if (DirNode->num_ent_used >= osb->max_dir_node_ent) {
- OCFS_BH_PUT_DATA(bhs[0]);
- status = -ENOSPC;
- LOG_TRACE_STR("DirNode->num_ent_used >= osb->max_dir_node_ent");
- goto bail;
- }
-
- /* find a place to add the new file entry. */
- if (DirNode->num_ent_used) {
- /* make sure we're not already in this dirnode. */
- q.name = InsertEntry->filename;
- q.len = strlen(InsertEntry->filename);
- OCFS_BH_PUT_DATA(bhs[0]);
- if (ocfs_find_index (osb, bhs, &q, &index)) {
- /* Already inserted... */
- status = -EEXIST;
- goto bail;
- }
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
-
- if (index < DirNode->num_ent_used) {
- fe = FILEENT_GETBH(DirNode, bhs, index);
- if (fe == NULL) {
- // fe is locked by this kernel thread
- index = 0;
- } else {
- res = strcmp (fe->filename, InsertEntry->filename);
- FILEENT_PUTBH(DirNode, bhs, index);
- if (res > 0) {
- /* We are greater than the entry in question we
- * should be less than the one next to it */
- index++;
- }
- }
- }
- } else {
- index = 0;
- }
-
- if (index < DirNode->num_ent_used) {
- /* shimmy everything over, we're putting
- * the new fe in the middle somewhere */
- memmove (&DirNode->index[index + 1],
- &DirNode->index[index],
- DirNode->num_ent_used - index);
- }
-
- if (DirNode->num_ent_used) {
- if (DirNode->num_del) {
- /* Insert at first deleted & change first deleted */
- freeOffset = DirNode->first_del;
- DirNode->num_del--;
- if (DirNode->num_del) {
- lastEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bhs[freeOffset+1]);
- DirNode->first_del = lastEntry->next_del;
- OCFS_BH_PUT_DATA(bhs[freeOffset+1]);
- }
- } else {
- /* Insert at end and change the index */
- freeOffset = DirNode->num_ent_used;
- }
- } else {
- freeOffset = 0;
- }
-
-
- status = ocfs_journal_access(handle, bhs[freeOffset+1],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- /* we know which entry we're using so return it. */
- *IndexOffset = freeOffset;
- if (insert_bh) {
- /* note that if you asked for insert_bh, we did an
- * additional get_bh */
- get_bh(bhs[freeOffset+1]);
- *insert_bh = bhs[freeOffset+1];
- }
-
- /* Put the entry at the end */
- lastEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bhs[freeOffset+1]);
- InsertEntry->dir_node_ptr = DirNode->node_disk_off;
- memcpy (lastEntry, InsertEntry, osb->sect_size);
- OCFS_SET_FLAG (lastEntry->sync_flags, OCFS_SYNC_FLAG_VALID);
- lastEntry->this_sector = InsertEntry->this_sector =
- DirNode->node_disk_off + ((freeOffset + 1) * OCFS_SECTOR_SIZE);
- OCFS_BH_PUT_DATA(bhs[freeOffset+1]);
-
- status = ocfs_journal_dirty(handle, bhs[freeOffset+1]);
-
- DirNode->index[index] = freeOffset;
- DirNode->num_ent_used++;
- OCFS_BH_PUT_DATA(bhs[0]);
-
- /* in case we fail, we want to make sure we don't return a bh. */
- if ((status < 0) && insert_bh) {
- if (*insert_bh)
- brelse(*insert_bh);
- *insert_bh = NULL;
- }
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_insert_dir_node */
-
-/*
- * there are 3 buffer heads of interest in ocfs_del_file_entry:
- * febh: the actual file entry to delete (EntryToDel)
- * lockbh: the ocfs_dir_node locked for this delete (LockNode)
- * dirbh: the ocfs_dir_node that owns EntryToDel, if NULL
- * then PDirNode is the same as LockNode, otherwise
- * dirbh is the bh for PDirNode
- */
-
-/*
- * ocfs_remove_file()
- * only removes the file entry, not the extents or dirnodes.
- */
-int ocfs_remove_file (ocfs_super * osb, struct buffer_head *febh, struct buffer_head *lockbh, ocfs_journal_handle *handle, struct inode *dir_inode, struct inode *file_inode)
-{
- int status = 0;
- __u32 offset;
- int index = 0;
- ocfs_file_entry * EntryToDel = NULL;
- ocfs_dir_node * LockNode = NULL;
- ocfs_dir_node *PDirNode = NULL;
- struct buffer_head *dirbh = NULL;
- struct buffer_head **dirbhs = NULL;
- __u64 lock_off, head_del, parent_off;
- bool journal_lockbh = false;
- const int numbhs = 256;
- const int length = numbhs * sizeof(struct buffer_head *);
-
- LOG_ENTRY ();
-
- /* alloc a whole dirnode of bhs even tho I will only use 2 :( */
- dirbhs = (struct buffer_head **) ocfs_malloc (length);
- if (dirbhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(dirbhs, 0, length);
-
- EntryToDel = (ocfs_file_entry *) OCFS_BH_GET_DATA(febh);
-
- /* briefly grab LockNode and get useful bits of info */
- LockNode = (ocfs_dir_node *) OCFS_BH_GET_DATA(lockbh);
- lock_off = LockNode->node_disk_off;
- head_del = LockNode->head_del_ent_node;
- OCFS_BH_PUT_DATA(lockbh);
- LockNode = NULL;
-
- status= ocfs_journal_access(handle, lockbh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* if fe comes from lower down in the dir chain, get the ocfs_dir_node
- * for that chain. otherwise, use the lockbh (toplevel) */
- if (EntryToDel->dir_node_ptr == lock_off) {
- journal_lockbh = false;
- dirbhs[0] = lockbh;
- } else {
- journal_lockbh = true;
- status = ocfs_read_bh(osb, EntryToDel->dir_node_ptr,
- &dirbh, OCFS_BH_CACHED, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- dirbhs[0] = dirbh;
-
- status= ocfs_journal_access(handle, dirbh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
- PDirNode = (ocfs_dir_node *) OCFS_BH_GET_DATA(dirbhs[0]);
- parent_off = PDirNode->node_disk_off;
- offset= ((EntryToDel->this_sector - parent_off) >> 9) - 1;
- for (index = 0; index < PDirNode->num_ent_used; index++)
- if (PDirNode->index[index] == offset)
- break;
-
- if (index == PDirNode->num_ent_used) {
- LOG_TRACE_STR("index == PDirNode->num_ent_used");
- goto leave;
- }
-
- if (febh->b_blocknr != (EntryToDel->this_sector >> 9)) {
- LOG_TRACE_STR("febh->b_blocknr != (EntryToDel->this_sector >> 9)");
- goto leave;
- }
-
- dirbhs[offset+1] = febh;
-
- memmove (&PDirNode->index[index], &PDirNode->index[index + 1],
- PDirNode->num_ent_used - (index + 1));
-
- PDirNode->num_ent_used--;
- if (PDirNode->num_ent_used == 0) {
- PDirNode->num_del = 0;
- } else {
- /* Insert this dir node as one containing a deleted
- * entry if the count on the root dir node for deleted
- * entries is 0 */
- if (PDirNode->num_del != 0) {
- PDirNode->num_del++;
- EntryToDel->sync_flags = OCFS_SYNC_FLAG_DELETED;
- EntryToDel->next_del = PDirNode->first_del;
- PDirNode->first_del = offset;
- } else {
- PDirNode->num_del++;
- EntryToDel->sync_flags = OCFS_SYNC_FLAG_DELETED;
- EntryToDel->next_del = INVALID_DIR_NODE_INDEX;
- PDirNode->first_del = offset;
- }
- }
-
- OCFS_BH_PUT_DATA(febh);
- OCFS_BH_PUT_DATA(dirbhs[0]);
- EntryToDel = NULL;
- PDirNode = NULL;
-
- LockNode = (ocfs_dir_node *) OCFS_BH_GET_DATA(lockbh);
- if (LockNode->head_del_ent_node == INVALID_NODE_POINTER) {
- if (lock_off != parent_off)
- journal_lockbh = true;
- LockNode->head_del_ent_node = parent_off;
- }
- OCFS_BH_PUT_DATA(lockbh);
- LockNode = NULL;
-
- status = ocfs_journal_dirty(handle, dirbhs[0]);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- if (journal_lockbh) {
- status = ocfs_journal_dirty(handle, lockbh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
-leave:
-
- if (EntryToDel)
- OCFS_BH_PUT_DATA(febh);
- if (PDirNode)
- OCFS_BH_PUT_DATA(dirbhs[0]);
- if (dirbh)
- brelse(dirbh);
-
- ocfs_safefree(dirbhs);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_remove_file */
-
-
-
-/*
- * ocfs_insert_file()
- *
- */
-int ocfs_insert_file (ocfs_super * osb, ocfs_file_entry * InsertEntry, struct buffer_head *lock_bh, struct buffer_head **insert_bh, ocfs_journal_handle * handle, struct inode *dir_inode, struct inode *file_inode)
-{
- int status = 0;
- __u64 bitmapOffset = 0;
- __s32 indexOffset = -1;
- ocfs_dir_node *pNewDirNode = NULL;
- ocfs_dir_node *DirNode = NULL;
- ocfs_dir_node *LockNode = NULL;
- __u64 dir_off;
- bool parent_is_lock_node, dir_cache_lock;
- struct buffer_head **bhs = NULL;
- const int numbhs = 256;
- const int length = numbhs * sizeof(struct buffer_head *);
- int i = 0;
- bool dirtyall = false;
- void *buf;
- __u64 locknode_off, dir_next_node, new_head_del = 0;
- __u64 locknode_head_del;
- __u8 dir_num_ent_used;
-
- LOG_ENTRY ();
-
- /* NOTE:
- * Since the LockNode and the DirNode may point to the same
- * buffer, it is very important to never do a GET_DATA on both
- * at the same time. That is why we only briefly kmap these,
- * work on them, and unmap. Also, we may do a getblk on this
- * buffer more than once, but the bh refcount should be ok
- * since we brelse it here, then again when the
- * ocfs_release_lock happens. */
-
- /* alloc bhs */
- bhs = (struct buffer_head **)ocfs_malloc(length);
- if (bhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(bhs, 0, length);
-
- if (insert_bh != NULL)
- *insert_bh = NULL;
-
- /* deal with a few fields on the file entry to be inserted */
- if (!IS_VALID_FILE_ENTRY(InsertEntry)) {
- LOG_ERROR_STR ("Invalid file entry");
- status = -EFAIL;
- goto leave;
- }
- OcfsQuerySystemTime (&DISK_LOCK_LAST_WRITE (InsertEntry));
- DISK_LOCK_LAST_READ (InsertEntry) = DISK_LOCK_LAST_WRITE (InsertEntry);
- DISK_LOCK_WRITER_NODE (InsertEntry) = osb->node_num;
- DISK_LOCK_READER_NODE (InsertEntry) = osb->node_num;
-
- /* route the new file entry to the proper dir_off */
- LockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(lock_bh);
- locknode_off = LockNode->node_disk_off;
- locknode_head_del = LockNode->head_del_ent_node;
-
- LOG_TRACE_ARGS("ocfs_insert_file: head_del=%u.%u, free_node=%u.%u, locknode=%u.%u\n",
- HILO(LockNode->head_del_ent_node), HILO(LockNode->free_node_ptr),
- HILO(locknode_off));
-
- if (locknode_head_del != INVALID_NODE_POINTER)
- dir_off = locknode_head_del;
- else if (LockNode->free_node_ptr != INVALID_NODE_POINTER)
- dir_off = LockNode->free_node_ptr;
- else
- dir_off = locknode_off;
-
- LOG_TRACE_ARGS("ocfs_insert_file: dir_off selected was %u.%u\n", HILO(dir_off));
-
- parent_is_lock_node = (dir_off == locknode_off);
- OCFS_BH_PUT_DATA(lock_bh);
- LockNode = NULL;
-
- /* get the bhs for dir_off */
- status = ocfs_read_bhs (osb, dir_off, osb->vol_layout.dir_node_size,
- bhs, OCFS_BH_CACHED, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* see if it fits at dir_off */
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- dir_num_ent_used = DirNode->num_ent_used;
- dir_next_node = DirNode->next_node_ptr;
- dir_cache_lock = ((DISK_LOCK_FILE_LOCK(DirNode) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (DISK_LOCK_CURRENT_MASTER(DirNode) == osb->node_num));
- OCFS_BH_PUT_DATA(bhs[0]);
- DirNode = NULL;
-
- if (dir_off != locknode_head_del || dir_num_ent_used < osb->max_dir_node_ent) {
- LOG_TRACE_ARGS("ocfs_insert_file: going to got_dirnode, numentused=%d\n",
- dir_num_ent_used);
- goto got_dirnode;
- }
-
- /* we read the head_del_ent_node or the free_node_ptr, but */
- /* hit the old BUG. there are no free slots at dir_off. */
- /* need to search. */
-
- /* dump the bhs already found */
- for (i=0; i<256; i++) {
- brelse(bhs[i]);
- bhs[i] = NULL;
- }
-
- /* start from locknode, travel along next_node_ptr */
- dir_off = locknode_off;
- while (1) {
- LOG_TRACE_ARGS("ocfs_insert_file: now checking %u.%u\n", dir_off);
- status = ocfs_read_bhs (osb, dir_off, osb->vol_layout.dir_node_size,
- bhs, OCFS_BH_CACHED, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- dir_num_ent_used = DirNode->num_ent_used;
- dir_next_node = DirNode->next_node_ptr;
- OCFS_BH_PUT_DATA(bhs[0]);
- DirNode = NULL;
-
- if (dir_num_ent_used < osb->max_dir_node_ent) {
- LOG_TRACE_ARGS("ocfs_insert_file: num_ent_used for %u.%u is good (%d)\n", dir_off,
- dir_num_ent_used);
- new_head_del = dir_off;
- break;
- }
- LOG_TRACE_ARGS("ocfs_insert_file: next_node pointer for %u.%u is %u.%u\n", dir_off, dir_next_node);
- dir_off = dir_next_node;
- if (dir_off == INVALID_NODE_POINTER) {
- new_head_del = INVALID_NODE_POINTER;
- break;
- }
- for (i=0; i<256; i++) {
- brelse(bhs[i]);
- bhs[i] = NULL;
- }
- }
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- dir_num_ent_used = DirNode->num_ent_used;
- dir_next_node = DirNode->next_node_ptr;
- dir_cache_lock = ((DISK_LOCK_FILE_LOCK(DirNode) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (DISK_LOCK_CURRENT_MASTER(DirNode) == osb->node_num));
- parent_is_lock_node = (DirNode->node_disk_off == locknode_off);
- OCFS_BH_PUT_DATA(bhs[0]);
- DirNode = NULL;
-
-got_dirnode:
- /* it's legal to do this twice on the same buffer, so
- * don't worry about whether they're the same. */
- status = ocfs_journal_access(handle, bhs[0],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (!status)
- status = ocfs_journal_access(handle, lock_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- if (new_head_del != 0) {
- LockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(lock_bh);
- LockNode->head_del_ent_node = new_head_del;
- OCFS_BH_PUT_DATA(lock_bh);
- LockNode = NULL;
- }
-
- /* If we have a list of dir nodes go to the last dirnode */
- /* and insert in that. */
- /* We should not find this entry already inserted */
- if (dir_num_ent_used < osb->max_dir_node_ent) {
- LOG_TRACE_ARGS("ocfs_insert_file: CASE 1\n");
- status = ocfs_insert_dir_node (osb, bhs, InsertEntry, lock_bh,
- &indexOffset, insert_bh, handle, dir_inode, file_inode);
- if (status < 0) {
- /* Should we not remove the head from the
- * current transaction before leaving? */
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else {
- /* ran out of room, file entry will not be inserted */
- /* into DirNode but instead into pNewDirNode */
- struct buffer_head **newbhs = NULL;
- __u64 new_disk_off;
-
- LOG_TRACE_ARGS("ocfs_insert_file: CASE 2\n");
- newbhs = (struct buffer_head **)ocfs_malloc(length);
- if (newbhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(newbhs, 0, length);
-
- if (dir_next_node != INVALID_NODE_POINTER) {
- /* already allocated a new block */
- LOG_TRACE_ARGS("ocfs_insert_file: CASE 2A\n");
- status = ocfs_read_bhs(osb, dir_next_node,
- osb->vol_layout.dir_node_size,
- newbhs, OCFS_BH_COND_CACHED,
- dir_inode);
- if (status < 0) {
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- status = ocfs_journal_access(handle, newbhs[0],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- for (i=0; i<numbhs; i++)
- brelse(newbhs[i]);
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else {
- /* Allocate a new dir node */
- __u64 fileOffset = 0;
- LOG_TRACE_ARGS("ocfs_insert_file: CASE 2B\n");
-
- status = ocfs_alloc_node_block(osb,
- osb->vol_layout.dir_node_size,
- &bitmapOffset, &fileOffset,
- osb->node_num,
- DISK_ALLOC_DIR_NODE, handle);
- if (status < 0) {
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- status = ocfs_read_bhs(osb, bitmapOffset,
- osb->vol_layout.dir_node_size,
- newbhs, OCFS_BH_COND_CACHED, dir_inode);
- if (status < 0) {
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- dirtyall = true;
- /* clear all 128k, all garbage currently */
- for (i=0; i<numbhs; i++) {
- status = ocfs_journal_access(handle, newbhs[i],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- for (i=0; i<numbhs; i++)
- brelse(newbhs[i]);
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- buf = OCFS_BH_GET_DATA(newbhs[i]);
- memset(buf, 0, 512);
- OCFS_BH_PUT_DATA(newbhs[i]);
- }
- pNewDirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(newbhs[0]);
- ocfs_initialize_dir_node (osb, pNewDirNode,
- bitmapOffset, fileOffset,
- osb->node_num);
- OCFS_BH_PUT_DATA(newbhs[0]);
- pNewDirNode = NULL;
- }
-
- pNewDirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(newbhs[0]);
- new_disk_off = pNewDirNode->node_disk_off;
- if (dir_cache_lock) {
- DISK_LOCK_CURRENT_MASTER (pNewDirNode) = osb->node_num;
- DISK_LOCK_FILE_LOCK (pNewDirNode) = OCFS_DLM_ENABLE_CACHE_LOCK;
- }
- OCFS_BH_PUT_DATA(newbhs[0]);
- pNewDirNode = NULL;
-
- status = ocfs_insert_dir_node (osb, newbhs, InsertEntry,
- lock_bh, &indexOffset,
- insert_bh, handle, dir_inode,
- file_inode);
-
- if (status >= 0) {
- LockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(lock_bh);
- LockNode->free_node_ptr = new_disk_off;
- OCFS_BH_PUT_DATA(lock_bh);
- LockNode = NULL;
-
- /* Setup the pointer to this new directory block */
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(bhs[0]);
- DirNode->next_node_ptr = new_disk_off;
- OCFS_BH_PUT_DATA(bhs[0]);
- DirNode = NULL;
-
- status = ocfs_journal_dirty(handle, newbhs[0]);
- if (dirtyall)
- for(i=1;i<numbhs;i++)
- status = ocfs_journal_dirty(handle,
- newbhs[i]);
- }
-
- for (i = 0; i < numbhs; i++)
- if (newbhs[i])
- brelse(newbhs[i]);
-
- ocfs_safefree(newbhs);
-
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- indexOffset = -1;
- }
-
- status = ocfs_journal_dirty(handle, bhs[0]);
- if (!status)
- status = ocfs_journal_dirty(handle, lock_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-leave:
- if (bhs) {
- for (i=0; i<numbhs; i++)
- brelse(bhs[i]);
- ocfs_safefree(bhs);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_insert_file */
Deleted: trunk/divdi3.c
===================================================================
--- trunk/divdi3.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/divdi3.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,592 +0,0 @@
-/* Ripped from gcc-2.95.1/gcc/libgcc2.c */
-
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* As a special exception, if you link this library with other files,
- some of which are compiled with GCC, to produce an executable,
- this library does not by itself cause the resulting executable
- to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
-
-typedef unsigned int UQItype __attribute__ ((mode (QI)));
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef unsigned int UDItype __attribute__ ((mode (DI)));
-
-typedef int word_type __attribute__ ((mode (__word__)));
-
-/* Make sure that we don't accidentally use any normal C language built-in
- type names in the first part of this file. Instead we want to use *only*
- the type names defined above. The following macro definitions insure
- that if we *do* accidentally use some normal C language built-in type name,
- we will get a syntax error. */
-
-#define char bogus_type
-#define short bogus_type
-#define int bogus_type
-#define long bogus_type
-#define unsigned bogus_type
-#define float bogus_type
-#define double bogus_type
-
-/* DIstructs are pairs of SItype values in the order determined by
- little/big ENDIAN. */
-
-#ifdef __i386__
- struct DIstruct {SItype low, high;};
-#endif
-#ifdef __powerpc__
- struct DIstruct {SItype high, low;};
-#endif
-#ifdef __s390__
- struct DIstruct {SItype high, low;};
-#endif
-
-
-/* We need this union to unpack/pack DImode values, since we don't have
- any arithmetic yet. Incoming DImode parameters are stored into the
- `ll' field, and the unpacked result is read from the struct `s'. */
-
-typedef union
-{
- struct DIstruct s;
- DItype ll;
-} DIunion;
-
-
-/* From gcc-2.95.1/gcc/longlong.h */
-
-#ifndef SI_TYPE_SIZE
-#define SI_TYPE_SIZE 32
-#endif
-
-#define __BITS4 (SI_TYPE_SIZE / 4)
-#define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
-
-#ifdef __i386__
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subl %5,%1\n\tsbbl %3,%0" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "0" ((USItype) (ah)), \
- "g" ((USItype) (bh)), \
- "1" ((USItype) (al)), \
- "g" ((USItype) (bl)))
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("mull %3" \
- : "=a" ((USItype) (w0)), \
- "=d" ((USItype) (w1)) \
- : "%0" ((USItype) (u)), \
- "rm" ((USItype) (v)))
-#define udiv_qrnnd(q, r, n1, n0, d) \
- __asm__ ("divl %4" \
- : "=a" ((USItype) (q)), \
- "=d" ((USItype) (r)) \
- : "0" ((USItype) (n0)), \
- "1" ((USItype) (n1)), \
- "rm" ((USItype) (d)))
-#define count_leading_zeros(count, x) \
- do { \
- USItype __cbtmp; \
- __asm__ ("bsrl %1,%0" \
- : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
- (count) = __cbtmp ^ 31; \
- } while (0)
-#endif /* __i386__ */
-
-#ifdef __powerpc__
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- do { \
- if (__builtin_constant_p (ah) && (ah) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (bh)), \
- "rI" ((USItype) (al)), \
- "r" ((USItype) (bl))); \
- else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (bh)), \
- "rI" ((USItype) (al)), \
- "r" ((USItype) (bl))); \
- else if (__builtin_constant_p (bh) && (bh) == 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (ah)), \
- "rI" ((USItype) (al)), \
- "r" ((USItype) (bl))); \
- else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
- __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (ah)), \
- "rI" ((USItype) (al)), \
- "r" ((USItype) (bl))); \
- else \
- __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (ah)), \
- "r" ((USItype) (bh)), \
- "rI" ((USItype) (al)), \
- "r" ((USItype) (bl))); \
- } while (0)
-#define count_leading_zeros(count, x) \
- __asm__ ("{cntlz|cntlzw} %0,%1" \
- : "=r" ((USItype) (count)) \
- : "r" ((USItype) (x)))
-#define umul_ppmm(ph, pl, m0, m1) \
- do { \
- USItype __m0 = (m0), __m1 = (m1); \
- __asm__ ("mulhwu %0,%1,%2" \
- : "=r" ((USItype) ph) \
- : "%r" (__m0), \
- "r" (__m1)); \
- (pl) = __m0 * __m1; \
- } while (0)
-#endif /* __powerpc__ */
-
-#ifdef __s390__
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) ({ \
- USItype __sh = (ah); \
- USItype __sl = (al); \
- __asm__ (" slr %1,%3\n" \
- " brc 3,0f\n" \
- " ahi %0,-1\n" \
- "0: slr %0,%2" \
- : "+&d" (__sh), "+d" (__sl) \
- : "d" (bh), "d" (bl) : "cc" ); \
- (sh) = __sh; \
- (sl) = __sl; \
-})
-#define umul_ppmm(wh, wl, u, v) ({ \
- USItype __wh = (u); \
- USItype __wl = (v); \
- __asm__ (" ltr 1,%0\n" \
- " mr 0,%1\n" \
- " jnm 0f\n" \
- " alr 0,%1\n" \
- "0: ltr %1,%1\n" \
- " jnm 1f\n" \
- " alr 0,%0\n" \
- "1: lr %0,0\n" \
- " lr %1,1\n" \
- : "+d" (__wh), "+d" (__wl) \
- : : "0", "1", "cc" ); \
- (wh) = __wh; \
- (wl) = __wl; \
-})
-static const UQItype __clz_tab[] =
-{
- 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-};
-#define count_leading_zeros(count, x) \
- do { \
- USItype __xr = (x); \
- USItype __a; \
- \
- if (SI_TYPE_SIZE <= 32) \
- { \
- __a = __xr < ((USItype)1<<2*__BITS4) \
- ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
- : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
- } \
- else \
- { \
- for (__a = SI_TYPE_SIZE - 8; __a > 0; __a -= 8) \
- if (((__xr >> __a) & 0xff) != 0) \
- break; \
- } \
- \
- (count) = SI_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
- } while (0)
-#endif
-
-/* If this machine has no inline assembler, use C macros. */
-
-/* Define this unconditionally, so it can be used for debugging. */
-#define __udiv_qrnnd_c(q, r, n1, n0, d) \
- do { \
- USItype __d1, __d0, __q1, __q0; \
- USItype __r1, __r0, __m; \
- __d1 = __ll_highpart (d); \
- __d0 = __ll_lowpart (d); \
- \
- __r1 = (n1) % __d1; \
- __q1 = (n1) / __d1; \
- __m = (USItype) __q1 * __d0; \
- __r1 = __r1 * __ll_B | __ll_highpart (n0); \
- if (__r1 < __m) \
- { \
- __q1--, __r1 += (d); \
- if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
- if (__r1 < __m) \
- __q1--, __r1 += (d); \
- } \
- __r1 -= __m; \
- \
- __r0 = __r1 % __d1; \
- __q0 = __r1 / __d1; \
- __m = (USItype) __q0 * __d0; \
- __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
- if (__r0 < __m) \
- { \
- __q0--, __r0 += (d); \
- if (__r0 >= (d)) \
- if (__r0 < __m) \
- __q0--, __r0 += (d); \
- } \
- __r0 -= __m; \
- \
- (q) = (USItype) __q1 * __ll_B | __q0; \
- (r) = __r0; \
- } while (0)
-
-/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */
-#if !defined (udiv_qrnnd)
-#define UDIV_NEEDS_NORMALIZATION 1
-#define udiv_qrnnd __udiv_qrnnd_c
-#endif
-
-/* End of gcc-2.95.1/gcc/longlong.h */
-
-
-DItype __divdi3 (DItype u, DItype v);
-DItype __moddi3 (DItype u, DItype v);
-UDItype __umoddi3 (UDItype u, UDItype v);
-UDItype __udivdi3 (UDItype n, UDItype d);
-
-
-static inline
-DItype
-__negdi2 (DItype u)
-{
- DIunion w;
- DIunion uu;
-
- uu.ll = u;
-
- w.s.low = -uu.s.low;
- w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
-
- return w.ll;
-}
-
-
-static inline
-UDItype
-__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
-{
- DIunion ww;
- DIunion nn, dd;
- DIunion rr;
- USItype d0, d1, n0, n1, n2;
- USItype q0, q1;
- USItype b, bm;
-
- nn.ll = n;
- dd.ll = d;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
-#if !UDIV_NEEDS_NORMALIZATION
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- udiv_qrnnd (q1, n1, 0, n1, d0);
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-
-#else /* UDIV_NEEDS_NORMALIZATION */
-
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- count_leading_zeros (bm, d0);
-
- if (bm != 0)
- {
- /* Normalize, i.e. make the most significant bit of the
- denominator set. */
-
- d0 = d0 << bm;
- n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
- n0 = n0 << bm;
- }
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0 >> bm. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- count_leading_zeros (bm, d0);
-
- if (bm == 0)
- {
- /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- leading quotient digit q1 = 1).
-
- This special case is necessary, not an optimization.
- (Shifts counts of SI_TYPE_SIZE are undefined.) */
-
- n1 -= d0;
- q1 = 1;
- }
- else
- {
- /* Normalize. */
-
- b = SI_TYPE_SIZE - bm;
-
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q1, n1, n2, n1, d0);
- }
-
- /* n1 != d0... */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0 >> bm. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0 >> bm;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-#endif /* UDIV_NEEDS_NORMALIZATION */
-
- else
- {
- if (d1 > n1)
- {
- /* 00 = nn / DD */
-
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- /* 0q = NN / dd */
-
- count_leading_zeros (bm, d1);
- if (bm == 0)
- {
- /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an optimization. */
-
- /* The condition on the next line takes advantage of that
- n1 >= d1 (true due to program flow). */
- if (n1 > d1 || n0 >= d0)
- {
- q0 = 1;
- sub_ddmmss (n1, n0, n1, n0, d1, d0);
- }
- else
- q0 = 0;
-
- q1 = 0;
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- USItype m1, m0;
- /* Normalize. */
-
- b = SI_TYPE_SIZE - bm;
-
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q0, n1, n2, n1, d1);
- umul_ppmm (m1, m0, q0, d0);
-
- if (m1 > n1 || (m1 == n1 && m0 > n0))
- {
- q0--;
- sub_ddmmss (m1, m0, m1, m0, d1, d0);
- }
-
- q1 = 0;
-
- /* Remainder in (n1n0 - m1m0) >> bm. */
- if (rp != 0)
- {
- sub_ddmmss (n1, n0, n1, n0, m1, m0);
- rr.s.low = (n1 << b) | (n0 >> bm);
- rr.s.high = n1 >> bm;
- *rp = rr.ll;
- }
- }
- }
- }
-
- ww.s.low = q0;
- ww.s.high = q1;
- return ww.ll;
-}
-
-
-DItype
-__divdi3 (DItype u, DItype v)
-{
- word_type c = 0;
- DIunion uu, vv;
- DItype w;
-
- uu.ll = u;
- vv.ll = v;
-
- if (uu.s.high < 0)
- c = ~c,
- uu.ll = __negdi2 (uu.ll);
- if (vv.s.high < 0)
- c = ~c,
- vv.ll = __negdi2 (vv.ll);
-
- w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
- if (c)
- w = __negdi2 (w);
-
- return w;
-}
-
-
-DItype
-__moddi3 (DItype u, DItype v)
-{
- word_type c = 0;
- DIunion uu, vv;
- DItype w;
-
- uu.ll = u;
- vv.ll = v;
-
- if (uu.s.high < 0)
- c = ~c,
- uu.ll = __negdi2 (uu.ll);
- if (vv.s.high < 0)
- vv.ll = __negdi2 (vv.ll);
-
- (void) __udivmoddi4 (uu.ll, vv.ll, &w);
- if (c)
- w = __negdi2 (w);
-
- return w;
-}
-
-
-UDItype
-__umoddi3 (UDItype u, UDItype v)
-{
- UDItype w;
-
- (void) __udivmoddi4 (u, v, &w);
-
- return w;
-}
-
-
-UDItype
-__udivdi3 (UDItype n, UDItype d)
-{
- return __udivmoddi4 (n, d, (UDItype *) 0);
-}
-
-
Deleted: trunk/dlm.c
===================================================================
--- trunk/dlm.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/dlm.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,2100 +0,0 @@
-/*
- * ocfsgendlm.c
- *
- * Distributed lock manager. Requests and processes lock votes.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-extern __u32 comm_voting;
-
-#define WAIT_FOR_VOTE_INCREMENT 200
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_DLM
-
-static int ocfs_insert_cache_link (ocfs_super * osb, ocfs_lock_res * lockres);
-static int ocfs_update_lock_state (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, bool *disk_vote, struct inode *inode);
-static int ocfs_send_dlm_request_msg (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, __u64 vote_map);
-static int ocfs_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u64 * lock_seq_num, struct inode *inode);
-static int ocfs_wait_for_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u32 time_to_wait, __u64 lock_seq_num, ocfs_lock_res * lockres);
-static int ocfs_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u64 vote_map);
-static int ocfs_wait_for_lock_release (ocfs_super * osb, __u64 offset, __u32 time_to_wait, ocfs_lock_res * lockres, __u32 lock_type, struct inode *inode);
-static int ocfs_get_vote_on_disk (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 * got_vote_map, __u64 vote_map, __u64 lock_seq_num, __u64 * oin_open_map);
-static int ocfs_break_cache_lock (ocfs_super * osb, ocfs_lock_res * lockres, struct inode *inode);
-static int ocfs_disk_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u64 * lock_seq_num);
-int ocfs_make_lock_master (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, bool *disk_vote, struct inode *inode);
-int ocfs_update_disk_lock (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, struct buffer_head **bh, struct inode *inode);
-static int ocfs_update_master_on_open (ocfs_super * osb, ocfs_lock_res * lockres, struct inode *inode);
-int ocfs_disk_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, struct inode *inode);
-
-/*
- * ocfs_insert_cache_link()
- *
- */
-static int ocfs_insert_cache_link (ocfs_super * osb, ocfs_lock_res * lockres)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- lockres->in_cache_list = true;
-
- list_add_tail (&(lockres->cache_list), &(osb->cache_lock_list));
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_insert_cache_link */
-
-/*
- * ocfs_update_lock_state()
- *
- */
-static int ocfs_update_lock_state (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, bool *disk_vote, struct inode *inode)
-{
- __u32 votemap;
- int status = 0;
- int tmpstat;
- __u64 lockseqno = 0;
- unsigned long jif;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u)\n", osb, lockres, flags);
-
- ocfs_acquire_lockres (lockres);
- votemap = (1 << lockres->master_node_num);
-
- if (comm_voting && !*disk_vote) {
- LOG_TRACE_STR ("Network vote");
- jif = jiffies;
- status = ocfs_send_dlm_request_msg (osb, lockres->sector_num,
- lockres->lock_type, flags, lockres, votemap);
- if (status >= 0) {
- status = lockres->vote_status;
- if (status >= 0)
- goto vote_success;
- else
- goto finito;
- } else if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- }
- else
- LOG_ERROR_STATUS (status);
- lockres->vote_state = 0;
- }
-
- LOG_TRACE_STR ("Disk vote");
- *disk_vote = true;
- jif = jiffies;
- status = ocfs_request_vote (osb, lockres->sector_num,
- lockres->lock_type, flags, votemap, &lockseqno, inode);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- goto finito;
- }
-
- status = ocfs_wait_for_vote (osb, lockres->sector_num,
- lockres->lock_type, flags, votemap, 5000,
- lockseqno, lockres);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- goto finito;
- }
-
-vote_success:
- jif = jiffies - jif;
- LOG_TRACE_ARGS ("Lock time:%u\n", jif);
-
- if (flags & FLAG_CHANGE_MASTER)
- lockres->master_node_num = osb->node_num;
-finito:
- if (*disk_vote) {
- tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
- lockres->lock_type, votemap);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- ocfs_release_lockres (lockres);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_update_lock_state */
-
-/*
- * ocfs_disk_request_vote()
- *
- */
-static int ocfs_disk_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u64 * lock_seq_num)
-{
- int status = 0;
- __u64 offset = 0;
- __u64 pub_off;
- __u32 size = 0;
- __u32 numnodes = 0;
- __u32 i;
- ocfs_publish *pubsect = NULL;
- __u64 largestseqno = 0;
- __u64 pubmap = 0;
- __u8 *p;
- __u32 wait;
- bool publish_flag = false;
- struct buffer_head **bhs = NULL;
-
- LOG_ENTRY_ARGS ("(osb=0x%08x, id=%u.%u, ty=%u, fl=%u, vm=0x%08x)\n",
- osb, HILO (lock_id), lock_type, flags, LO (vote_map));
-
- LOG_TRACE_ARGS ("osb=0x%08x, id=%u.%u, ty=%u, fl=%u, vm=0x%08x\n",
- osb, HILO (lock_id), lock_type, flags, LO (vote_map));
-
- pubmap = osb->publ_map;
- offset = osb->vol_layout.publ_sect_off;
- numnodes = OCFS_MAXIMUM_NODES;
- size = (numnodes * osb->sect_size);
-
- /* take lock to prevent overwrites by vote_reset and nm thread */
- down_with_flag (&(osb->publish_lock), publish_flag);
-
- /* Read the Publish Sector of all nodes */
- bhs = (struct buffer_head **)ocfs_malloc(numnodes * sizeof(struct buffer_head *));
- if (bhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- memset(bhs, 0, numnodes * sizeof(struct buffer_head *));
- status = ocfs_read_bhs (osb, offset, size, bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- for (i = 0; i < numnodes; i++) {
- p = OCFS_BH_GET_DATA(bhs[i]);
- pubsect = (ocfs_publish *) p;
- if (pubsect->time == (__u64) 0 || pubsect->publ_seq_num <= largestseqno) {
- OCFS_BH_PUT_DATA(bhs[i]);
- continue;
- }
- largestseqno = pubsect->publ_seq_num;
- if (pubsect->dirty) {
- OCFS_BH_PUT_DATA(bhs[i]);
- if (!IS_NODE_ALIVE (pubmap, i, numnodes) ||
- TEST_NODE_IN_RECOVERY(osb, i)) {
- LOG_TRACE_STR("Node is in recovery, trying"
- " again.");
- } else {
- up_with_flag (&(osb->publish_lock),
- publish_flag);
- get_random_bytes(&wait, sizeof(wait));
- wait %= 200;
- wait += OCFS_NM_HEARTBEAT_TIME;
- LOG_TRACE_ARGS ("wait: %d\n", wait);
- ocfs_sleep (wait);
- }
- status = -EAGAIN;
- goto finally;
- }
-
- OCFS_BH_PUT_DATA(bhs[i]);
- }
-
- /* Increment the largest sequence number by one & */
- /* write it in its own Publish Sector and set the Dirty Bit */
- p = OCFS_BH_GET_DATA(bhs[osb->node_num]);
- pubsect = (ocfs_publish *)p;
- largestseqno++;
- LOG_TRACE_ARGS ("largestseqno : %u.%u\n", HILO (largestseqno));
- osb->publish_dirty = true;
- pubsect->publ_seq_num = largestseqno;
- pubsect->dirty = true;
- pubsect->vote = FLAG_VOTE_NODE;
- pubsect->vote_map = vote_map;
- pubsect->vote_type = flags;
- pubsect->dir_ent = lock_id;
-
- OCFS_BH_PUT_DATA(bhs[osb->node_num]);
- pub_off = osb->vol_layout.publ_sect_off + (osb->node_num * osb->sect_size);
-
- status = ocfs_write_bh (osb, bhs[osb->node_num], 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- ocfs_sleep(2);
-
- atomic_set (&osb->node_req_vote, 1);
-
- *lock_seq_num = largestseqno;
-
-finally:
- up_with_flag (&(osb->publish_lock), publish_flag);
-
- if (bhs != NULL) {
- for (i = 0; i < numnodes; i++)
- brelse(bhs[i]);
- ocfs_safefree(bhs);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_disk_request_vote */
-
-/*
- * ocfs_wait_for_disk_lock_release()
- *
- * @osb: ocfs super block for the volume
- * @offset:
- * @time_to_wait:
- * @lock_type: lowest level to which a lock must deprecate for us to break out.
- *
- * Returns 0 of success, < 0 if error.
- */
-int ocfs_wait_for_disk_lock_release (ocfs_super * osb, __u64 offset, __u32 time_to_wait, __u32 lock_type)
-{
- int status = -ETIMEDOUT;
- int tmpstat = -ETIMEDOUT;
- __u32 timewaited = 0;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY ();
-
- /* Create a sepearate thread which should set the event of the */
- /* resource after N retries. */
-
- while (time_to_wait > timewaited) {
- bh = NULL;
- fe = NULL;
-
- tmpstat = ocfs_read_bh (osb, offset, &bh, 0, NULL);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (status = tmpstat);
- goto finally;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- /* This will always be zero when the first Node comes up after reboot */
- /* (for volume lock) */
- if ((DISK_LOCK_CURRENT_MASTER (fe) == OCFS_INVALID_NODE_NUM) ||
- (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
- goto got_it;
- }
-
- if (!IS_NODE_ALIVE (osb->publ_map,
- DISK_LOCK_CURRENT_MASTER (fe),
- OCFS_MAXIMUM_NODES)) {
-// LOG_TRACE_ARGS ("old_ocfs_recover_vol(%u)\n",
-// DISK_LOCK_CURRENT_MASTER (fe));
-// old_ocfs_recover_vol(osb, DISK_LOCK_CURRENT_MASTER(fe));
-
- /* Reset the lock as not owned and return success?? */
- /* This needs to be under some sort of cluster wide lock */
- DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
- goto got_it;
- }
-
- /* If we are here in the code it means the local node is not the master */
- if (DISK_LOCK_FILE_LOCK (fe) <= lock_type)
- goto got_it;
-
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
- timewaited += WAIT_FOR_VOTE_INCREMENT;
- continue;
-got_it:
- status = 0;
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- break;
- }
-
-finally:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_wait_for_disk_lock_release */
-
-/*
- * ocfs_wait_for_lock_release()
- *
- */
-static int ocfs_wait_for_lock_release (ocfs_super * osb, __u64 offset, __u32 time_to_wait, ocfs_lock_res * lockres, __u32 lock_type, struct inode *inode)
-{
- int status = -ETIMEDOUT;
- int tmpstat = -ETIMEDOUT;
- __u32 timewaited = 0;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u, 0x%08x, %u)\n", osb,
- HI (offset), LO (offset), time_to_wait,
- lockres, lock_type);
-
- while (time_to_wait > timewaited) {
- bh = NULL;
- fe = NULL;
-
- tmpstat = ocfs_read_bh (osb, offset, &bh, 0, inode);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (status = tmpstat);
- goto finally;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if ((DISK_LOCK_CURRENT_MASTER (fe) == OCFS_INVALID_NODE_NUM) ||
- (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
- goto got_it;
- }
-
- if (!IS_NODE_ALIVE (osb->publ_map, DISK_LOCK_CURRENT_MASTER(fe),
- OCFS_MAXIMUM_NODES)) {
-// LOG_ERROR_ARGS ("old_ocfs_recover_vol(%u)",
-// DISK_LOCK_CURRENT_MASTER (fe));
-// old_ocfs_recover_vol(osb, DISK_LOCK_CURRENT_MASTER(fe));
-
- /* Reset the lock as not owned and return success?? */
- /* This needs to be under some sort of cluster wide lock, */
- DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
- goto got_it;
- }
-
- /* The local node is not the master */
- if (DISK_LOCK_FILE_LOCK (fe) >= OCFS_DLM_ENABLE_CACHE_LOCK) {
- int tmpstat;
-
- lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
- lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
- status = ocfs_break_cache_lock (osb, lockres, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- tmpstat = ocfs_read_bh (osb, offset, &bh, 0, inode);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (tmpstat);
- status = tmpstat;
- goto finally;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
- }
-
- if (DISK_LOCK_FILE_LOCK (fe) <= lock_type)
- goto got_it;
-
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
- timewaited += WAIT_FOR_VOTE_INCREMENT;
- continue;
-got_it:
- status = 0;
- break;
- }
-
-finally:
- if (lockres && status >= 0) {
- ocfs_acquire_lockres (lockres);
- if (fe) {
- lockres->lock_type = DISK_LOCK_FILE_LOCK (fe);
- lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
- lockres->oin_openmap = DISK_LOCK_OIN_MAP (fe);
- lockres->last_lock_upd = DISK_LOCK_LAST_WRITE (fe);
- } else
- LOG_ERROR_STR("fe was null!");
- ocfs_release_lockres (lockres);
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_wait_for_lock_release */
-
-
-void ocfs_process_one_vote_reply(ocfs_super *osb, ocfs_vote_reply_ctxt *ctxt, __u32 node_num)
-{
- int status;
- int reply_status;
- int open_handle = 0;
- __u64 mask = 0;
-
- if (ctxt->reply_method == DISK_VOTE) {
- reply_status = ctxt->u.vote->vote[osb->node_num];
- open_handle = ctxt->u.vote->open_handle;
- } else {
- reply_status = ctxt->u.reply->status;
- open_handle = ctxt->u.reply->h.open_handle;
- }
-
- status = 0;
- mask = 1 << node_num;
- switch (reply_status) {
- case FLAG_VOTE_NODE:
- *(ctxt->got_vote_map) |= mask;
- if (ctxt->flags & (FLAG_FILE_EXTEND|FLAG_FILE_UPDATE) &&
- open_handle)
- *(ctxt->open_map) |= mask;
- break;
- case FLAG_VOTE_OIN_ALREADY_INUSE:
- *(ctxt->got_vote_map) |= mask;
- status = -EFAIL;
- if (ctxt->flags & FLAG_FILE_DELETE)
- status = -EBUSY;
- break;
- case FLAG_VOTE_OIN_UPDATED:
- status = 0;
- *(ctxt->got_vote_map) |= mask;
- break;
- case FLAG_VOTE_UPDATE_RETRY:
- status = -EAGAIN;
- break;
- case FLAG_VOTE_FILE_DEL:
- status = -ENOENT;
- break;
- }
- *(ctxt->status) = status;
-}
-
-/*
- * ocfs_get_vote_on_disk()
- *
- */
-static int ocfs_get_vote_on_disk (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 * got_vote_map, __u64 vote_map, __u64 lock_seq_num, __u64 * oin_open_map)
-{
- int status = 0;
- __u32 length = 0;
- __u32 i;
- __u32 numnodes;
- ocfs_vote *vote;
- __u8 *p;
- struct buffer_head **bhs = NULL;
-
- LOG_ENTRY_ARGS ("(lockid=%u.%u, locktype=%u, votemap=0x%08x)\n",
- HILO (lock_id), lock_type, LO (vote_map));
-
- numnodes = OCFS_MAXIMUM_NODES;
-
- /* Read the vote sectors of all the nodes */
- length = numnodes * osb->sect_size;
- bhs = (struct buffer_head **)ocfs_malloc(numnodes * sizeof(struct buffer_head *));
- if (bhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
- memset(bhs, 0, numnodes * sizeof(struct buffer_head *));
- status = ocfs_read_bhs (osb, osb->vol_layout.vote_sect_off, length, bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- for (i = 0; i < numnodes; i++) {
- bool node_alive = (IS_NODE_ALIVE (osb->publ_map, i, numnodes));
- bool node_in_map = (IS_NODE_ALIVE (vote_map, i, numnodes));
-
- status = 0;
- p = OCFS_BH_GET_DATA(bhs[i]);
- vote = (ocfs_vote *) p;
-
- /* A node we were asking to vote is dead */
- if (!node_alive) {
- if (node_in_map) {
- if (flags & FLAG_FILE_UPDATE_OIN)
- (*got_vote_map) |= 1 << i;
- else
- status = -EAGAIN;
- }
- } else if (node_in_map && vote->vote_seq_num == lock_seq_num &&
- vote->dir_ent == lock_id) {
- ocfs_vote_reply_ctxt ctxt;
- ctxt.reply_method = DISK_VOTE;
- ctxt.got_vote_map = got_vote_map;
- ctxt.open_map = oin_open_map;
- ctxt.status = &status;
- ctxt.flags = flags;
- ctxt.u.vote = vote;
- ocfs_process_one_vote_reply(osb, &ctxt, i);
- }
-
- OCFS_BH_PUT_DATA(bhs[i]);
- if (status < 0)
- break;
- }
-
-finally:
- if (bhs != NULL) {
- for (i=0; i < numnodes; i++)
- brelse(bhs[i]);
- ocfs_safefree(bhs);
- }
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_get_vote_on_disk */
-
-/*
- * ocfs_disk_reset_voting()
- *
- */
-int ocfs_disk_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type)
-{
- int status = 0;
- ocfs_publish *pubsect = NULL;
- __u64 offset = 0;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u)\n", osb, HI (lock_id),
- LO (lock_id), lock_type);
-
- LOG_TRACE_ARGS ("0x%08x, %u.%u, %u\n", osb, HI (lock_id),
- LO (lock_id), lock_type);
-
- /* take lock to prevent publish overwrites by vote_req and nm thread */
- down (&(osb->publish_lock));
-
- /* Read node's publish sector */
- offset = osb->vol_layout.publ_sect_off + (osb->node_num * osb->sect_size);
-
- status = ocfs_read_bh (osb, offset, &bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- pubsect = (ocfs_publish *)OCFS_BH_GET_DATA(bh);
-
- pubsect->dirty = false;
- pubsect->vote = 0;
- pubsect->vote_type = 0;
- pubsect->vote_map = 0;
- pubsect->dir_ent = 0;
-
- /* Write it back */
- OCFS_BH_PUT_DATA(bh);
- status = ocfs_write_bh (osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
-
- osb->publish_dirty = false;
-
- atomic_set (&osb->node_req_vote, 0);
-
- finally:
- if (bh != NULL)
- brelse(bh);
- up (&(osb->publish_lock));
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_disk_reset_voting */
-
-/*
- * ocfs_wait_for_vote()
- *
- */
-static int ocfs_wait_for_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u32 time_to_wait, __u64 lock_seq_num, ocfs_lock_res * lockres)
-{
- int status = -EAGAIN;
- __u32 timewaited = 0;
- __u64 gotvotemap = 0;
- __u64 fileopenmap = 0;
-
- LOG_ENTRY_ARGS ("(osb=0x%08x, id=%u.%u, ty=%u, fl=%u, vm=0x%08x, "
- "sq:%u.%u)\n", osb, HILO (lock_id), lock_type, flags,
- LO (vote_map), HILO (lock_seq_num));
-
- LOG_TRACE_ARGS ("osb=0x%08x, id=%u.%u, ty=%u, fl=%u, vm=0x%08x, "
- "sq=%u.%u\n", osb, HILO (lock_id), lock_type, flags,
- LO (vote_map), HILO (lock_seq_num));
-
- while (time_to_wait > timewaited) {
- ocfs_sleep (WAIT_FOR_VOTE_INCREMENT);
-
- if (!atomic_read (&osb->node_req_vote)) {
- LOG_TRACE_ARGS ("wait EAGAIN\n");
- status = -EAGAIN;
- goto bail;
- }
-
- gotvotemap |= (1 << osb->node_num);
-
- status = ocfs_get_vote_on_disk (osb, lock_id, lock_type, flags,
- &gotvotemap, vote_map, lock_seq_num, &fileopenmap);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (!(gotvotemap & (1 << osb->node_num))) {
- status = -EAGAIN;
- goto bail;
- }
-
- vote_map |= (1 << osb->node_num);
- if (vote_map == gotvotemap) {
- if ((flags & FLAG_FILE_EXTEND) || (flags & FLAG_FILE_UPDATE))
- lockres->oin_openmap = fileopenmap;
- status = 0;
- goto bail;
- }
-
- timewaited += WAIT_FOR_VOTE_INCREMENT;
- }
-
- if (timewaited >= time_to_wait)
- status = -EAGAIN;
-
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_wait_for_vote */
-
-/*
- * ocfs_reset_voting()
- *
- */
-static int ocfs_reset_voting (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u64 vote_map)
-{
- int status;
-
- LOG_ENTRY ();
-
- status = ocfs_disk_reset_voting (osb, lock_id, lock_type);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_reset_voting */
-
-/*
- * ocfs_request_vote()
- *
- */
-static int ocfs_request_vote (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, __u64 vote_map, __u64 * lock_seq_num, struct inode *inode)
-{
- int status;
-
- LOG_ENTRY ();
-
- status = ocfs_disk_request_vote (osb, lock_id, lock_type, flags,
- vote_map, lock_seq_num);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_request_vote */
-
-
-
-/*
- * ocfs_init_dlm_msg()
- *
- */
-void ocfs_init_dlm_msg (ocfs_super * osb, ocfs_dlm_msg * dlm_msg, __u32 msg_len)
-{
- LOG_ENTRY ();
-
- dlm_msg->magic = OCFS_DLM_MSG_MAGIC;
- dlm_msg->msg_len = msg_len;
-
- memcpy (dlm_msg->vol_id, osb->vol_layout.vol_id, MAX_VOL_ID_LENGTH);
-
- dlm_msg->src_node = osb->node_num;
-
- LOG_EXIT ();
- return;
-} /* ocfs_init_dlm_msg */
-
-/*
- * ocfs_send_dlm_request_msg()
- *
- */
-static int ocfs_send_dlm_request_msg (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, __u64 vote_map)
-{
- int status = 0;
- ocfs_dlm_msg *dlm_msg = NULL;
- __u32 msg_len;
- ocfs_dlm_msg_hdr *req;
-
- LOG_ENTRY_ARGS ("(osb=0x%08x, id=%u.%u, ty=%u, fl=%u, vm=0x%08x)\n",
- osb, HILO (lock_id), lock_type, flags, LO(vote_map));
-
- msg_len = sizeof (ocfs_dlm_msg) - 1 + sizeof (ocfs_dlm_req_master);
-
- dlm_msg = ocfs_malloc (msg_len);
- if (dlm_msg == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- ocfs_acquire_lockres (lockres);
- lockres->vote_state = LOCK_STATE_IN_VOTING;
- lockres->req_vote_map = vote_map;
- lockres->got_vote_map = 0;
- lockres->tmp_openmap = 0;
- spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
- OcfsGlobalCtxt.comm_seq_num++;
- lockres->last_upd_seq_num = OcfsGlobalCtxt.comm_seq_num;
- spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
- ocfs_release_lockres (lockres);
-
- ocfs_init_dlm_msg (osb, dlm_msg, msg_len);
-
- dlm_msg->msg_type = OCFS_VOTE_REQUEST;
-
- req = (ocfs_dlm_msg_hdr *) dlm_msg->msg_buf;
- req->lock_id = lock_id;
- req->flags = flags;
- req->lock_seq_num = lockres->last_upd_seq_num;
-
- ocfs_send_bcast (osb, vote_map, dlm_msg);
- status = ocfs_wait (lockres->voted_event,
- atomic_read (&lockres->voted_event_woken), 1000);
- atomic_set (&lockres->voted_event_woken, 0);
-
- finally:
- ocfs_safefree (dlm_msg);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_send_dlm_request_msg */
-
-/*
- * ocfs_make_lock_master()
- *
- */
-int ocfs_make_lock_master (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, bool *disk_vote, struct inode *inode)
-{
- __u64 vote_map = 0;
- __u64 lockseqnum = 0;
- int status = 0;
- int tmpstat;
- unsigned long jif;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY ();
-
- ocfs_acquire_lockres (lockres);
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- vote_map = osb->publ_map;
- if (((flags & FLAG_FILE_DELETE) || (flags & FLAG_FILE_RENAME)) &&
- (!(flags & FLAG_DIR)) &&
- (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
- vote_map = DISK_LOCK_OIN_MAP (fe);
- vote_map &= osb->publ_map; /* remove all dead nodes */
- }
- vote_map &= ~(1 << osb->node_num);
- OCFS_BH_PUT_DATA(bh);
-
- if (vote_map == 0) {
- /* As this is the only node alive, make it master of the lock */
- if (lockres->lock_type <= lock_type)
- lockres->lock_type = (__u8) lock_type;
- lockres->master_node_num = osb->node_num;
-
- status = ocfs_update_disk_lock (osb, lockres,
- DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK, &bh, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- goto bail;
- }
-
-
- if (comm_voting && !*disk_vote) {
- LOG_TRACE_STR ("Network vote");
- jif = jiffies;
- status = ocfs_send_dlm_request_msg (osb, lock_id, lock_type,
- flags, lockres, vote_map);
- if (status >= 0) {
- status = lockres->vote_status;
- if (status >= 0)
- goto vote_success;
- else
- goto bail;
- } else if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- }
- else
- LOG_ERROR_STATUS (status);
- lockres->vote_state = 0;
- }
-
- LOG_TRACE_STR ("Disk vote");
- *disk_vote = true;
- jif = jiffies;
- status = ocfs_request_vote (osb, lock_id, lock_type, flags, vote_map,
- &lockseqnum, inode);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- status = ocfs_wait_for_vote (osb, lock_id, lock_type, flags, vote_map,
- 5000, lockseqnum, lockres);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-vote_success:
- jif = jiffies - jif;
- LOG_TRACE_ARGS ("Lock time: %u\n", jif);
-
- /* Make this node the master of this lock */
- if (lockres->lock_type <= lock_type)
- lockres->lock_type = (__u8) lock_type;
-
- lockres->master_node_num = osb->node_num;
-
- /* Write that we now are the master to the disk */
- status = ocfs_update_disk_lock (osb, lockres,
- DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK | DLOCK_FLAG_OPEN_MAP, &bh, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-bail:
-
- if (*disk_vote) {
- tmpstat = ocfs_reset_voting (osb, lock_id, lock_type, vote_map);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- ocfs_release_lockres (lockres);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_make_lock_master */
-
-/*
- * ocfs_acquire_lockres_ex()
- *
- * @lockres: lockres to acquire
- * @timeout: timeout in ms, 0 == no timeout
- */
-int ocfs_acquire_lockres_ex (ocfs_lock_res * lockres, __u32 timeout)
-{
- int mypid;
- unsigned long jif = 0;
- int status = 0;
- int cnt = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, %d)\n", lockres, timeout);
-
- mypid = ocfs_getpid ();
-
- if (timeout)
- jif = jiffies + (timeout * HZ / 1000);
-
- while (1) {
- spin_lock (&lockres->lock_mutex);
-
- if (lockres->in_use) {
- if (lockres->thread_id != mypid) {
- spin_unlock (&lockres->lock_mutex);
- if (jif && jif < jiffies) {
- LOG_TRACE_ARGS ("lockpid=%d, newpid=%d,"
- " timedout\n",
- lockres->thread_id, mypid);
- status = -ETIMEDOUT;
- goto bail;
- }
-
- if (++cnt == 10) {
- LOG_TRACE_ARGS ("lockpid=%d, newpid=%d\n",
- lockres->thread_id, mypid);
- cnt = 0;
- }
- ocfs_sleep (OCFS_NM_HEARTBEAT_TIME / 10);
- }
- else {
- lockres->in_use++;
- spin_unlock (&lockres->lock_mutex);
- break;
- }
- } else {
- lockres->in_use = 1;
- lockres->thread_id = mypid;
- spin_unlock (&lockres->lock_mutex);
- break;
- }
- }
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_acquire_lockres_ex */
-
-/*
- * ocfs_release_lockres()
- *
- */
-void ocfs_release_lockres (ocfs_lock_res * lockres)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", lockres);
-
- spin_lock (&lockres->lock_mutex);
- if (lockres->in_use == 0) {
- LOG_ERROR_ARGS("Releasing lockres with inuse 0: 0x%08x\n", lockres);
- BUG();
- } else {
- if (lockres->thread_id != current->pid)
- LOG_ERROR_ARGS("PID %d is trying to release lockres held by PID %d\n",
- current->pid, lockres->thread_id);
- lockres->in_use--;
- if (lockres->in_use == 0) {
- lockres->thread_id = 0;
- }
- }
- spin_unlock (&lockres->lock_mutex);
-
- LOG_EXIT ();
- return;
-} /* ocfs_release_lockres */
-
-/*
- * ocfs_update_disk_lock()
- *
- */
-int ocfs_update_disk_lock (ocfs_super * osb, ocfs_lock_res * lockres, __u32 flags, struct buffer_head **bh, struct inode *inode)
-{
- int status = 0;
- __u64 offset = 0;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY ();
-
- offset = lockres->sector_num;
- status = ocfs_read_bh (osb, offset, bh, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(*bh);
-
- if (flags & DLOCK_FLAG_MASTER)
- DISK_LOCK_CURRENT_MASTER (fe) = lockres->master_node_num;
-
- if (flags & DLOCK_FLAG_LOCK)
- DISK_LOCK_FILE_LOCK (fe) = lockres->lock_type;
-
- if (flags & DLOCK_FLAG_OPEN_MAP)
- DISK_LOCK_OIN_MAP (fe) = lockres->oin_openmap;
-
- if (flags & DLOCK_FLAG_SEQ_NUM)
- DISK_LOCK_SEQNUM (fe) = lockres->last_upd_seq_num;
-
- OCFS_BH_PUT_DATA(*bh);
-
- status = ocfs_write_bh (osb, *bh, 0, inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
-finally:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_update_disk_lock */
-
-/*
- * ocfs_update_master_on_open()
- *
- */
-int ocfs_update_master_on_open (ocfs_super * osb, ocfs_lock_res * lockres, struct inode *inode)
-{
- int status = -EAGAIN;
- bool disk_vote = false;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY ();
-
- while (status == -EAGAIN) {
- if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
- OCFS_MAXIMUM_NODES)) {
- LOG_TRACE_ARGS ("Master (%u) dead, lockid %u.%u\n",
- lockres->master_node_num,
- HI (lockres->sector_num), LO (lockres->sector_num));
- status = 0;
- goto bail;
- }
-
- ocfs_acquire_lockres (lockres);
-
- if (lockres->master_node_num == osb->node_num) {
- LOG_TRACE_ARGS ("Added node to map 0x%08x, lockid %u.%u\n",
- LO (lockres->oin_openmap), HI (lockres->sector_num),
- LO (lockres->sector_num));
-
- lockres->oin_openmap |= (1 << osb->node_num);
- status = ocfs_update_disk_lock (osb, lockres,
- DLOCK_FLAG_OPEN_MAP, &bh, inode);
- if (bh)
- brelse(bh);
-
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- ocfs_release_lockres (lockres);
- } else {
- status = ocfs_update_lock_state (osb, lockres,
- FLAG_ADD_OIN_MAP, &disk_vote, inode);
- if (status < 0) {
- if (status != -EAGAIN)
- LOG_ERROR_STATUS (status);
- ocfs_release_lockres (lockres);
- if (status == -EAGAIN) {
- ocfs_sleep (500);
- if (ocfs_task_interruptible (osb)) {
- LOG_TRACE_ARGS("interrupted... lockid=%u.%u\n",
- HILO(lockres->sector_num));
- status = -EINTR;
- goto bail;
- }
- continue;
- }
-
- goto bail;
- }
- ocfs_release_lockres (lockres);
- }
- }
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_update_master_on_open */
-
-/*
- * ocfs_init_lockres()
- *
- */
-void ocfs_init_lockres (ocfs_super * osb, ocfs_lock_res * lockres, __u64 lock_id)
-{
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u.%u)\n", osb, lockres,
- HI (lock_id), LO (lock_id));
-
- lockres->signature = 0x55AA;
- lockres->lock_type = OCFS_DLM_NO_LOCK;
- lockres->master_node_num = OCFS_INVALID_NODE_NUM;
- lockres->last_upd_seq_num = 0;
- lockres->oin_openmap = 0;
- lockres->sector_num = lock_id;
- lockres->in_use = 0;
- lockres->oin = NULL;
- lockres->lock_state = 0;
- lockres->vote_state = 0;
- lockres->in_cache_list = false;
- lockres->cache_lock_held = false;
-
- spin_lock_init (&lockres->lock_mutex);
- init_waitqueue_head (&lockres->voted_event);
- atomic_set (&lockres->voted_event_woken, 0);
- atomic_set (&lockres->lr_ref_cnt, 0);
- atomic_set (&lockres->lr_share_cnt, 0);
-
- /* For read/write caching */
- lockres->last_read_time = 0;
- lockres->last_write_time = 0;
- lockres->writer_node_num = OCFS_INVALID_NODE_NUM;
- lockres->reader_node_num = OCFS_INVALID_NODE_NUM;
-
- lockres->lock_holders = 0;
- LOG_TRACE_ARGS("lockres->lock_holders = %u\n", lockres->lock_holders);
-
- LOG_EXIT ();
- return;
-} /* ocfs_init_lockres */
-
-/*
- * ocfs_create_update_lock()
- *
- */
-int ocfs_create_update_lock (ocfs_super * osb, ocfs_inode * oin, __u64 lock_id, __u32 flags, bool new_file, struct inode *inode)
-{
- int status = 0;
- ocfs_lock_res *lockres = NULL;
- ocfs_lock_res *tmp_lockres = NULL;
- bool is_dir = false;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u.%u, %u)\n", osb, oin,
- HI (lock_id), LO (lock_id), flags);
-
- is_dir = (flags & OCFS_OIN_DIRECTORY) ? true : false;
-
- /* Check the lock state on the disk / in our resource map */
- status = ocfs_lookup_sector_node (osb, lock_id, &lockres);
- if (status >= 0) {
- if (lockres->signature != 0x55AA) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- ocfs_acquire_lockres (lockres);
- if (lockres->oin) {
- if (lockres->oin->obj_id.type != OCFS_TYPE_OIN) {
- ocfs_release_lockres (lockres);
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- } else {
- ocfs_put_lockres (lockres->oin->lock_res);
- lockres->oin->lock_res = NULL;
- }
- }
- lockres->oin = oin;
- oin->oin_flags |= flags;
- ocfs_get_lockres (lockres);
- oin->lock_res = lockres;
- ocfs_release_lockres (lockres);
-
- status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
- (is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK), inode);
- if (status < 0) {
- if (status != -EINTR) {
- LOG_ERROR_STR ("Lock owner is alive and taking too much time");
- LOG_ERROR_STATUS(status);
- }
- goto bail;
- }
- } else {
- /* Create a resource and insert in the hash */
- lockres = ocfs_allocate_lockres();
- if (lockres == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- ocfs_init_lockres (osb, lockres, lock_id);
-
- ocfs_get_lockres (lockres);
-
- status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
- (is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK), inode);
- if (status < 0) {
- if (status != -EINTR) {
- LOG_ERROR_STR ("Lock owner is alive and taking too much time");
- LOG_ERROR_STATUS(status);
- }
- goto bail;
- }
-
- status = ocfs_insert_sector_node (osb, lockres, &tmp_lockres);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* Check if another process added a lockres after our lookup */
- if (tmp_lockres) {
- /* If so, put the recently allocated lockres */
- ocfs_put_lockres (lockres);
- lockres = tmp_lockres;
- status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
- (is_dir ? OCFS_DLM_EXCLUSIVE_LOCK : OCFS_DLM_NO_LOCK), inode);
- if (status < 0) {
- if (status != -EINTR) {
- LOG_ERROR_STR ("Lock owner is alive and taking too much time");
- LOG_ERROR_STATUS(status);
- }
- goto bail;
- }
- } else {
- if (flags & OCFS_OIN_CACHE_UPDATE) {
- status = ocfs_insert_cache_link (osb, lockres);
- if (status < 0) {
- LOG_ERROR_STR ("Lock up volume");
- goto bail;
- }
- }
- }
- }
-
- ocfs_acquire_lockres (lockres);
-
- lockres->oin = oin;
- oin->oin_flags |= flags;
- if (oin->lock_res != lockres) {
- ocfs_put_lockres (oin->lock_res);
- oin->lock_res = lockres;
- ocfs_get_lockres (lockres);
- }
-
- LOG_TRACE_ARGS ("MasterNode=%d, ThisNode=%d\n",
- lockres->master_node_num, osb->node_num);
-
- if (!is_dir && !new_file &&
- (lockres->master_node_num != OCFS_INVALID_NODE_NUM) &&
- ((!IS_NODE_ALIVE (lockres->oin_openmap, osb->node_num, OCFS_MAXIMUM_NODES)) ||
- (lockres->lock_state & FLAG_ALWAYS_UPDATE_OPEN))) {
- /* Send a message to master so that he can send the oin update to */
- /* this node also. If u are the master then update File_entry */
- /* and set the bit that this node has a open */
- status = ocfs_update_master_on_open (osb, lockres, inode);
- if (status < 0) {
- ocfs_release_lockres (lockres);
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- }
- if (new_file)
- lockres->oin_openmap |= (1 << osb->node_num);
-
- ocfs_release_lockres (lockres);
-
- bail:
- ocfs_put_lockres(lockres);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_update_lock */
-
-/*
- * ocfs_acquire_lock()
- *
- */
-int
-ocfs_acquire_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
- __u32 flags, ocfs_lock_res ** lr, struct buffer_head **bh, struct inode *inode)
-{
- int status = -EFAIL;
- ocfs_file_entry *disklock = NULL;
- __u32 updated = 0;
- ocfs_lock_res *lockres = NULL;
- int k = 0;
- struct buffer_head *tmpbh = NULL, **b = NULL;
- int lockflags = (lock_id >= osb->vol_layout.bitmap_off ? OCFS_BH_CACHED : 0);
- /* TODO: 40 bytes of "bool" sitting on the stack for now. move */
- /* mutually exclusive flags into an enum and switch on them */
- bool disk_vote = false;
- bool become_master = false, keep_exclusive = false, wait_for_release = false;
- bool local_lock = false, fast_path = false, wait_on_recovery = false;
- bool get_x = false, master_request = false, truncate_extend = false;
- bool have_cache_already = false;
-
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u, %u, 0x%08x, 0x%08x)\n", osb,
- HI (lock_id), LO (lock_id), lock_type, flags, lr, bh);
-
- if (bh != NULL)
- b = bh;
- else
- b = &tmpbh;
-
- flags |= FLAG_ACQUIRE_LOCK;
-
- status = ocfs_find_update_res (osb, lock_id, lr, b, &updated, 0, inode);
- if (lr)
- lockres = *lr;
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* NO_LOCK */
- if (lock_type == OCFS_DLM_NO_LOCK)
- goto bail;
-
- /* SHARED */
- if (lock_type == OCFS_DLM_SHARED_LOCK) {
- if (!(flags & FLAG_DIR))
- goto bail;
- ocfs_acquire_lockres (lockres);
- if (lockres->lock_type == OCFS_DLM_NO_LOCK)
- lockres->lock_type = OCFS_DLM_SHARED_LOCK;
- else if ((lockres->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (lockres->master_node_num != osb->node_num))
- status = ocfs_break_cache_lock (osb, lockres, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- ocfs_release_lockres (lockres);
- goto bail;
- }
- lockres->lock_holders++;
- LOG_TRACE_ARGS("lockres->lock_holders = %u\n",
- lockres->lock_holders);
- atomic_inc (&(lockres->lr_share_cnt));
- ocfs_release_lockres (lockres);
- goto bail;
- }
-
- /* EXCLUSIVE or CACHE */
- status = 0;
- ocfs_get_lockres (lockres);
-
-again:
- ocfs_acquire_lockres (lockres);
-
- k++;
- LOG_TRACE_ARGS("attempting to get lock, pass: %d\n", k);
-
- if (lockres->master_node_num == osb->node_num)
- updated = true;
-
- if (!updated) {
- status = ocfs_read_bh (osb, lock_id, b, 0, inode);
- if (status < 0) {
- ocfs_release_lockres (lockres);
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- disklock = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
-
- // This code is added to avoid the case when fileentry is not yet updated
- // but the lockresource is updated by NMthread and needsflush is set to FALSE.
- if (lockres->master_node_num != osb->node_num &&
- DISK_LOCK_CURRENT_MASTER (disklock) == osb->node_num) {
- OCFS_BH_PUT_DATA(*b);
- ocfs_release_lockres (lockres);
- ocfs_sleep (1000);
- goto again;
- }
-
- if (lockres->master_node_num != osb->node_num ||
- lockres->master_node_num != DISK_LOCK_CURRENT_MASTER (disklock)) {
- lockres->master_node_num = DISK_LOCK_CURRENT_MASTER (disklock);
- lockres->lock_type = DISK_LOCK_FILE_LOCK (disklock);
- lockres->oin_openmap = DISK_LOCK_OIN_MAP (disklock);
- }
- updated = true;
- OCFS_BH_PUT_DATA(*b);
- }
-
- /* master node is an invalid node */
- if (unlikely(lockres->master_node_num >= OCFS_MAXIMUM_NODES &&
- lockres->master_node_num != OCFS_INVALID_NODE_NUM)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- ocfs_release_lockres (lockres);
- goto finally;
- }
-
- master_request = false;
- fast_path = false;
- truncate_extend = (flags & (FLAG_FILE_EXTEND | FLAG_FILE_TRUNCATE));
- local_lock = (lockres->master_node_num == osb->node_num);
- wait_on_recovery = TEST_NODE_IN_RECOVERY(osb, lockres->master_node_num);
- become_master = (osb->node_num != lockres->master_node_num)
- && (wait_on_recovery ||
- lockres->master_node_num == OCFS_INVALID_NODE_NUM ||
- !IS_NODE_ALIVE(osb->publ_map, lockres->master_node_num,
- OCFS_MAXIMUM_NODES));
-
- wait_for_release = (lockres->lock_type > OCFS_DLM_SHARED_LOCK);
- wait_for_release = false;
- get_x = (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)
- && !become_master && (local_lock || !wait_for_release));
- if (local_lock && !(get_x || truncate_extend))
- fast_path = true;
- if (local_lock && truncate_extend) {
-#ifdef VERBOSE_LOCKING_TRACE
- printk("local_lock but an extend or truncate request! will do a master_request.\n");
-#endif
- become_master = true;
- }
- if (!(fast_path || become_master || get_x || wait_for_release))
- master_request = true;
-
- /* possible locking paths: */
- /* fast_path, become_master, get_x, */
- /* wait_for_release, master_request */
-
-#ifdef VERBOSE_LOCKING_TRACE
- printk("acquire_lock: lock path is %s\n",
- fast_path ? "fast_path" :
- (become_master ? "become_master" :
- (get_x ? "get_x" :
- (wait_for_release ? "wait_for_release" :
- (master_request ? "master_request" : "invalid")))));
-#endif
-
- /* master node is this node */
- if (fast_path) {
- /* specifically keep an exclusive if we already have one on */
- /* this node even if we are asking for a cache lock */
- disklock = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
- keep_exclusive = (DISK_LOCK_FILE_LOCK (disklock) == OCFS_DLM_EXCLUSIVE_LOCK);
- OCFS_BH_PUT_DATA(*b);
- goto got_lock;
- }
-
- /* there is no master, or master needs recovery */
- /* or a delete or rename request */
- if (become_master || get_x) {
- if (wait_on_recovery && !(flags & FLAG_FILE_RECOVERY)) {
- int waitcnt = 0;
- LOG_TRACE_ARGS("Waiting on node %u to be recovered\n",
- lockres->master_node_num);
- while (1) {
- LOG_TRACE_ARGS("waitcnt = %d\n", waitcnt);
- if (!TEST_NODE_IN_RECOVERY(osb, lockres->master_node_num))
- break;
- ocfs_sleep(500);
- }
- }
-
- status = ocfs_make_lock_master (osb, lock_id, lock_type,
- flags, lockres, *b, &disk_vote, inode);
-
- if (status < 0) {
- ocfs_release_lockres (lockres);
- if (status == -EAGAIN) {
- ocfs_sleep (500);
- if (ocfs_task_interruptible (osb)) {
- LOG_TRACE_ARGS("interrupted... lockid=%u.%u\n", HILO(lock_id));
- status = -EINTR;
- goto finally;
- }
-
- updated = false;
- goto again;
- }
- goto finally;
- }
-
- /* make lock master succeeded */
- /* so why, if get_x and the make lock master do the same thing,
- * does the make lock master path need to rewrite the stuff to disk
- * but the get_x path doesn't ???? */
- if (get_x)
- goto skip_lock_write;
- keep_exclusive = false;
- goto got_lock;
- }
-
- /* there is a valid, live master and it's not this node */
- /* if the lock is acquired already by the master wait */
- /* for release, else change master */
- if (wait_for_release) {
- ocfs_release_lockres(lockres);
- status = ocfs_wait_for_lock_release (osb, lock_id, 30000, lockres,
- ((flags & FLAG_DIR) ? OCFS_DLM_SHARED_LOCK : OCFS_DLM_NO_LOCK), inode);
- if (status == 0 || status == -ETIMEDOUT) {
- /* lock released or waited too long, back to top */
- if (status == -ETIMEDOUT) {
- LOG_TRACE_ARGS("lock %u.%u, level %d, not being freed by node %u\n",
- HILO(lock_id), lockres->lock_type, lockres->master_node_num);
- }
- updated = false;
- goto again;
- }
- if (status != -EINTR) {
- LOG_ERROR_STR ("Lock owner is alive and taking too much time");
- LOG_ERROR_STATUS(status);
- }
- goto finally;
- }
-
- OCFS_ASSERT(master_request);
-
- if (master_request) {
- status = ocfs_update_lock_state (osb, lockres, flags | FLAG_CHANGE_MASTER,
- &disk_vote, inode);
- if (status < 0) {
- ocfs_release_lockres (lockres);
- if (status == -EAGAIN) {
- ocfs_sleep (500);
- if (ocfs_task_interruptible (osb)) {
- LOG_TRACE_ARGS("interrupted... lockid=%u.%u\n",
- HILO(lockres->sector_num));
- status = -EINTR;
- goto finally;
- }
- updated = false;
- goto again;
- }
- goto finally;
- }
- // successfully got vote to change master
- status = ocfs_read_bh (osb, lock_id, b, lockflags, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- keep_exclusive = false;
- }
-
-got_lock:
-
- disklock = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
- have_cache_already = (DISK_LOCK_CURRENT_MASTER (disklock) == osb->node_num &&
- DISK_LOCK_FILE_LOCK (disklock) == OCFS_DLM_ENABLE_CACHE_LOCK);
- DISK_LOCK_CURRENT_MASTER (disklock) = osb->node_num;
-
- if (!keep_exclusive) {
- DISK_LOCK_FILE_LOCK (disklock) = lock_type;
- OCFS_BH_PUT_DATA(*b);
-
- if (have_cache_already)
- LOG_TRACE_STR("have cachelock already... skip the write");
- else if (lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) {
- status = ocfs_write_bh (osb, *b, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- } else
- OCFS_BH_PUT_DATA(*b);
-
- status = ocfs_write_bh (osb, *b, lockflags, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- } else {
- /* We got the lock */
- disklock = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
- lockres->lock_type = lock_type;
- lockres->master_node_num = osb->node_num;
- lockres->oin_openmap = DISK_LOCK_OIN_MAP (disklock);
- OCFS_BH_PUT_DATA(*b);
- status = 0;
- }
-
-skip_lock_write:
- lockres->lock_holders++;
- LOG_TRACE_ARGS("lockres->lock_holders = %u\n", lockres->lock_holders);
- ocfs_release_lockres (lockres);
-
-finally:
- ocfs_put_lockres (lockres);
-
-bail:
- if (tmpbh)
- brelse(tmpbh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_acquire_lock */
-
-/*
- * ocfs_disk_release_lock()
- *
- */
-int ocfs_disk_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, struct inode *inode)
-{
- __u32 votemap = 0;
- __u32 tempmap = 0;
- __u32 i;
- int status = 0;
- int tmpstat;
- __u64 lockseqno;
- bool cachelock = false;
- bool disk_vote = false;
- unsigned long jif;
- bool disk_reset = true;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *tmpbh = NULL, **b = NULL;
- __u64 oin_node_map;
- __u32 curr_master;
- int lockflags = (lock_id >= osb->vol_layout.bitmap_off ? OCFS_BH_CACHED : 0);
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u, %u, 0x%08x)\n", osb, HI (lock_id),
- LO (lock_id), lock_type, flags, lockres);
-
- if (bh != NULL)
- b = &bh;
- else
- b = &tmpbh;
-
- if (bh == NULL) {
- status = ocfs_read_bh (osb, lock_id, b, lockflags, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
- oin_node_map = DISK_LOCK_OIN_MAP (fe);
- curr_master = DISK_LOCK_CURRENT_MASTER (fe);
- OCFS_BH_PUT_DATA(*b);
-
- if (!IS_VALID_NODE_NUM (curr_master)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto finito;
- }
-
- if (curr_master != osb->node_num) {
- LOG_ERROR_ARGS ("Current master is NOT this NODE (%d)", curr_master);
- status = 0;
- goto finito;
- }
-
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- if (((1 << i) & oin_node_map) &&
- IS_NODE_ALIVE (osb->publ_map, i, OCFS_MAXIMUM_NODES)) {
- votemap |= (1 << i);
- }
- }
-
- /* Send an update to all nodes alive, can be optimized later TODO */
- if ((flags & FLAG_FILE_RENAME) || (flags & FLAG_FILE_DELETE))
- votemap = (__u32) (osb->publ_map);
-
- /* TODO: figure out how to properly handle inode updates w/no oin */
- votemap = (__u32) (osb->publ_map); // temporary hack, forces broadcast
-
- /* remove current node from the votemap */
- tempmap = (1 << osb->node_num);
- votemap &= (~tempmap);
- jif = jiffies;
-
- if (votemap == 0)
- goto finally;
-
- if (!(flags & FLAG_FILE_UPDATE_OIN) && !(flags & FLAG_FILE_DELETE))
- goto finally;
-
-#if 0
- if (comm_voting) {
- LOG_TRACE_STR ("Network vote");
- status = ocfs_send_dlm_request_msg (osb, lock_id, lock_type,
- flags, lockres, votemap);
- if (status >= 0)
- goto finally;
- if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- lockres->vote_state = 0;
- }
- }
-
- LOG_TRACE_STR ("Disk vote");
- disk_vote = true;
- jif = jiffies;
-#endif
- status = -EAGAIN;
- while (status == -EAGAIN) {
- if (comm_voting && !disk_vote) {
- LOG_TRACE_STR ("Network vote");
- status = ocfs_send_dlm_request_msg (osb, lock_id, lock_type,
- flags, lockres, votemap);
- if (status >= 0) {
- status = lockres->vote_status;
- if (status >= 0) {
- goto finally;
- } else if (status == -EAGAIN) {
- goto loop;
- } else {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
- } else if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- }
- lockres->vote_state = 0;
- }
-
- LOG_TRACE_STR ("Disk vote");
- disk_vote = true;
- jif = jiffies;
-
- disk_reset = false;
- status = ocfs_request_vote (osb, lock_id, lock_type, flags, votemap, &lockseqno, inode);
-
- if (status >= 0) {
- status = ocfs_wait_for_vote (osb, lock_id, lock_type, FLAG_FILE_UPDATE_OIN,
- votemap, 5000, lockseqno, lockres);
- } else
- LOG_ERROR_STR("ocfs_request_vote failed");
-
- if (status < 0 && status != -EAGAIN) {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
-
- tmpstat = ocfs_reset_voting (osb, lock_id, lock_type, oin_node_map);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (status = tmpstat);
- goto finito;
- }
-
- disk_reset = true;
-
- if (status != -EAGAIN)
- break;
-
-loop:
- LOG_TRACE_ARGS ("id=%u.%u\n", HILO(lock_id));
- ocfs_sleep (500);
- }
-
-finally:
- jif = jiffies - jif;
- LOG_TRACE_ARGS ("Lock time: %u\n", jif);
-
- if (disk_vote && !disk_reset) {
- tmpstat = ocfs_reset_voting (osb, lock_id, lock_type, oin_node_map);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
-
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(*b);
-
- if (flags & FLAG_FILE_RELEASE_MASTER)
- DISK_LOCK_CURRENT_MASTER (fe) = OCFS_INVALID_NODE_NUM;
-
- if ((DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
- lockres->lock_state = OCFS_DLM_ENABLE_CACHE_LOCK;
- cachelock = true;
- }
- else
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
-
- OCFS_BH_PUT_DATA(*b);
-
- /* Reset the lock on the disk */
- if (!cachelock) {
- tmpstat = ocfs_write_bh (osb, *b, lockflags, inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
-
-finito:
- if (tmpbh)
- brelse(tmpbh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_disk_release_lock */
-
-/*
- * ocfs_release_lock()
- *
- */
-int ocfs_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, ocfs_lock_res * lockres, struct buffer_head *bh, struct inode *inode)
-{
- int status = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, %u, %u, 0x%08x)\n", osb, HI (lock_id),
- LO (lock_id), lock_type, flags, lockres);
-
- flags |= FLAG_RELEASE_LOCK;
-
- ocfs_acquire_lockres (lockres);
-
- if (lock_type == OCFS_DLM_SHARED_LOCK) {
- if (atomic_dec_and_test (&lockres->lr_share_cnt)) {
- if (lockres->lock_type == OCFS_DLM_SHARED_LOCK)
- lockres->lock_type = OCFS_DLM_NO_LOCK;
- }
- status = 0;
- goto finally;
- }
- /*
- * Change flags based on which kind of lock we are releasing
- * For directory we need special handling of oin updates when the release
- * is for XBcast
- * For file we need to update oin's
- * For Shared we need to update the lock state locally only
- */
-
- if ((lockres->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (lockres->master_node_num == osb->node_num) &&
- !(flags & FLAG_FILE_DELETE)) {
- status = 0;
- goto finally;
- }
-
- lockres->lock_type = OCFS_DLM_NO_LOCK;
- if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RELEASE_MASTER))
- lockres->master_node_num = OCFS_INVALID_NODE_NUM;
-
- status = ocfs_disk_release_lock (osb, lock_id, lock_type, flags,
- lockres, bh, inode);
- if (status < 0) {
- /* Disable the vol */
- LOG_ERROR_STATUS (status);
- }
-
-finally:
- lockres->lock_holders--;
- LOG_TRACE_ARGS("lockres->lock_holders = %u\n", lockres->lock_holders);
- ocfs_release_lockres (lockres);
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_release_lock */
-
-/*
- * ocfs_init_dlm()
- *
- */
-int ocfs_init_dlm (void)
-{
- LOG_ENTRY ();
-
- OcfsIpcCtxt.init = false;
- OcfsIpcCtxt.re_init = false;
-
- LOG_EXIT_STATUS (0);
- return 0;
-} /* ocfs_init_dlm */
-
-/*
- * ocfs_create_log_extent_map()
- *
- */
-int ocfs_create_log_extent_map (ocfs_super * osb, __u64 diskOffset, __u64 ByteCount)
-{
- int status = 0;
- __u32 i;
- __u64 remainingLength;
- __u32 length, byte_cnt;
- __u32 num_runs = 0;
- __s64 to_find = 0, found_foff = 0, found_doff = 0;
-
- LOG_ENTRY ();
-
- to_find = diskOffset;
- remainingLength = ByteCount;
-
- ocfs_down_sem (&(osb->map_lock), true);
-
- num_runs = osb->metadata_map.count;
-
- for (i = 0; i < num_runs; i++) {
- if (!ocfs_get_next_extent_map_entry
- (osb, &osb->metadata_map, i, &found_foff,
- &found_doff, &length))
- continue;
-
- if (found_doff >= (to_find + remainingLength))
- break;
-
- if (to_find >= (found_doff + length)) {
- /* This meta data run is before the relevant stf */
- continue;
- }
-
- if (to_find < found_doff) {
- if (to_find + remainingLength > found_doff) {
- /* We have a data run and a metadata run */
- remainingLength -= found_doff - to_find;
- to_find = found_doff;
- byte_cnt = remainingLength<length?remainingLength:length;
- osb->log_file_size += byte_cnt;
- ocfs_add_extent_map_entry (osb, &osb->trans_map,
- found_doff, found_doff, byte_cnt);
- remainingLength -= byte_cnt;
- to_find += byte_cnt;
- if (remainingLength > 0)
- continue;
- else
- break;
- }
- } else { /* if ((to_find >= found_doff)) */
- if (to_find + remainingLength <= found_doff + length) {
- /* It is only metadata */
- osb->log_file_size += remainingLength;
- ocfs_add_extent_map_entry (osb, &osb->trans_map,
- to_find, to_find, remainingLength);
- remainingLength -= remainingLength;
- to_find += remainingLength;
- break;
- } else {
- /* Meta data and as yet unknown data */
- byte_cnt = length - (to_find - found_doff);
- osb->log_file_size += byte_cnt;
- ocfs_add_extent_map_entry (osb, &osb->trans_map,
- to_find, to_find, byte_cnt);
- remainingLength -= byte_cnt;
- to_find += byte_cnt;
- continue;
- }
- }
- }
-
- ocfs_up_sem (&(osb->map_lock));
-
- /* Create new extent map from real runs */
-
-
- if (osb->log_file_size >= OCFS_TRANS_FLUSH_LIMIT) {
- osb->needs_flush = true;
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_log_extent_map */
-
-/*
- * ocfs_break_cache_lock()
- *
- */
-static int ocfs_break_cache_lock (ocfs_super * osb, ocfs_lock_res * lockres, struct inode *inode)
-{
- int status;
- int tmpstat;
- __u32 votemap;
- __u64 lockseqno = 0;
- bool retry = false;
- bool disk_vote = false;
- unsigned long jif;
- bool disk_reset = true;
-
- LOG_ENTRY ();
-
- ocfs_acquire_lockres (lockres);
-
- /* Ask the node with cache to flush and revert to write thru on this file */
- votemap = (1 << lockres->master_node_num);
-
- jif = jiffies;
-
-#if 0
- if (comm_voting) {
- LOG_TRACE_STR ("Network vote");
- status = ocfs_send_dlm_request_msg (osb, lockres->sector_num,
- lockres->lock_type,
- FLAG_FILE_RELEASE_CACHE,
- lockres, votemap);
- if (status >= 0) {
- lockres->lock_type = OCFS_DLM_NO_LOCK;
- goto finally;
- }
- if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- lockres->vote_state = 0;
- }
- }
-
- LOG_TRACE_STR ("Disk vote");
- disk_vote = true;
- jif = jiffies;
-#endif
- status = -EAGAIN;
- while (status == -EAGAIN) {
- if (!IS_NODE_ALIVE (osb->publ_map, lockres->master_node_num,
- OCFS_MAXIMUM_NODES)) {
- LOG_TRACE_ARGS ("Master (%u) is dead, lockid %u.%u\n",
- lockres->master_node_num, lockres->sector_num);
- /* TODO recovery needs to be done here .....and then become master */
- status = 0;
- goto finally;
- }
-
- if (comm_voting && !disk_vote) {
- LOG_TRACE_STR ("Network vote");
- jif = jiffies;
- status = ocfs_send_dlm_request_msg (osb, lockres->sector_num,
- lockres->lock_type, FLAG_FILE_RELEASE_CACHE,
- lockres, votemap);
- if (status >= 0) {
- status = lockres->vote_status;
- if (status >= 0) {
- lockres->lock_type = OCFS_DLM_NO_LOCK;
- } else if (status == -EAGAIN) {
- goto loop;
- } else {
- LOG_ERROR_STATUS (status);
- }
- goto finally;
- } else if (status == -ETIMEDOUT) {
- LOG_TRACE_STR ("Network voting timed out");
- }
- lockres->vote_state = 0;
- }
-
- LOG_TRACE_STR ("Disk vote");
- disk_vote = true;
- jif = jiffies;
-
- disk_reset = false;
- status = ocfs_request_vote (osb, lockres->sector_num,
- lockres->lock_type,
- FLAG_FILE_RELEASE_CACHE, votemap,
- &lockseqno, inode);
- if (status < 0) {
- if (status == -EAGAIN) {
- retry = true;
- goto reset;
- }
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- status = ocfs_wait_for_vote (osb, lockres->sector_num,
- lockres->lock_type,
- FLAG_FILE_RELEASE_CACHE, votemap,
- 15000, lockseqno, lockres);
- if (status < 0) {
- if (status == -EAGAIN) {
- retry = true;
- goto reset;
- }
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
-reset:
- tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
- lockres->lock_type, votemap);
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (status = tmpstat);
- goto finally;
- }
-
- disk_reset = true;
-
- if (status != -EAGAIN)
- break;
-
-loop:
- LOG_TRACE_ARGS ("id=%u.%u\n", HILO(lockres->sector_num));
- ocfs_sleep (500);
- if (ocfs_task_interruptible (osb)) {
- LOG_TRACE_ARGS("interrupted.... lockid=%u.%u\n",
- HILO(lockres->sector_num));
- status = -EINTR;
- goto finito;
- }
- }
-
- lockres->lock_type = (__u8) OCFS_DLM_NO_LOCK;
-
- LOG_TRACE_STR ("okie dokie... ocfs_break_cache_lock done\n");
-
-finally:
- jif = jiffies - jif;
- LOG_TRACE_ARGS ("Lock time: %u\n", jif);
-
- if (disk_vote && !disk_reset) {
- tmpstat = ocfs_reset_voting (osb, lockres->sector_num,
- lockres->lock_type, votemap);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
-finito:
- ocfs_release_lockres (lockres);
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_break_cache_lock */
Deleted: trunk/extmap.c
===================================================================
--- trunk/extmap.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/extmap.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,672 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-/* Crazy wacky extent map stuff */
-/* works ok in userland debugocfs stuff too */
-
-static bool ocfs_extent_map_add (ocfs_extent_map * map, __s64 virtual, __s64 physical, __s64 sectors);
-static void ocfs_extent_map_remove (ocfs_extent_map * map, __s64 virtual, __s64 sectors);
-static bool ocfs_extent_map_lookup (ocfs_extent_map *map, __s64 virtual, __s64 *physical, __s64 *sectors, __u32 *index);
-static bool ocfs_extent_map_next_entry (ocfs_extent_map *map, __u32 index, __s64 *virtual, __s64 *physical, __s64 *sectors);
-
-/*
- * ocfs_extent_map_init()
- *
- */
-void ocfs_extent_map_init (ocfs_extent_map * map)
-{
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
- spin_lock_init(&(map->lock));
- map->count = 0;
- map->initialized = true;
- INIT_LIST_HEAD(&map->head);
-
- LOG_EXIT ();
- return;
-} /* ocfs_extent_map_init */
-
-
-/*
- * ocfs_extent_map_destroy()
- *
- */
-void ocfs_extent_map_destroy (ocfs_extent_map * map)
-{
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
- if (map->initialized) {
- spin_lock(&(map->lock));
- if (map->initialized) {
- struct list_head *tmp, *tmp2;
- ocfs_extent *ext;
- list_for_each_safe(tmp, tmp2, &map->head) {
- ext = list_entry (tmp, ocfs_extent, list);
- list_del(&ext->list);
- ocfs_free_extent_entry(ext);
- map->count--;
- }
- if (map->count!=0) {
- LOG_ERROR_ARGS("count too high by %d!",
- map->count);
- map->count = 0;
- }
- map->initialized = false;
- }
- spin_unlock(&(map->lock));
- }
-
- LOG_EXIT ();
- return;
-} /* ocfs_extent_map_destroy */
-
-
-/*
- * get_overlap_type()
- *
- */
-static int get_overlap_type (__u64 new, __u64 newend, __u64 exist, __u64 existend)
-{
- OCFS_ASSERT (newend > new);
- OCFS_ASSERT (existend > exist);
-
- if (new < exist) {
- if (newend < exist)
- return LEFT_NO_OVERLAP;
- else if (newend == exist)
- return LEFT_ADJACENT;
- else if (newend >= existend) /* && newend > exist */
- return FULLY_CONTAINING;
- else /* newend < existend && newend > exist */
- return LEFT_OVERLAP;
- } else if (new > exist) {
- if (new > existend)
- return RIGHT_NO_OVERLAP;
- else if (new == existend)
- return RIGHT_ADJACENT;
- else if (newend > existend) /* && new < existend */
- return RIGHT_OVERLAP;
- else /* newend <= existend && new < existend */
- return FULLY_CONTAINED;
- } else if (newend > existend) /* && new == exist */
- return FULLY_CONTAINING;
- else /* newend <= existend && new == exist */
- return FULLY_CONTAINED;
-} /* get_overlap_type */
-
-/*
- * ocfs_coalesce_extent_map_entry()
- *
- * Must call this with spinlock already held!
- */
-static bool ocfs_coalesce_extent_map_entry (ocfs_extent_map * map, __s64 virtual, __s64 physical, __s64 sectors)
-{
- struct list_head *iter, *tmpiter;
- ocfs_extent *tmp, *victim;
- int voverlap, loverlap;
- bool ret = false;
-
- LOG_ENTRY ();
-
- if (!map->initialized) {
- LOG_ERROR_STR ("ExtentMap is not initialized");
- goto bail;
- }
-
- /* attempt to coalesce this into an existing entry */
-
- /*
- * NOTE: if we are successful in coalescing this entry with an entry from somewhere
- * in the list, we still need to check the rest of the list in case this entry
- * ends up filling one or more holes
- * |---- this ----|
- * |-- found --| |-- another entry --|
- * |---| <--- yet another entry
- */
-
- victim = NULL;
- list_for_each_safe(iter, tmpiter, &map->head) {
- bool assimilate = false;
-
- tmp = list_entry (iter, ocfs_extent, list);
- voverlap =
- get_overlap_type (virtual, virtual + sectors,
- tmp->virtual,
- tmp->virtual + tmp->sectors);
- loverlap =
- get_overlap_type (physical, physical + sectors,
- tmp->physical,
- tmp->physical + tmp->sectors);
-
- /* first off, if the virtual range and real range don't */
- /* overlap in the same way it definitely can't be coalesced */
- if (voverlap != loverlap)
- continue;
-
- switch (voverlap) {
- case LEFT_NO_OVERLAP: /* keep looking */
- break;
-
- case FULLY_CONTAINED: /* already fully accounted for, done */
- ret = true;
- goto bail;
- break;
-
- case RIGHT_NO_OVERLAP: /* DONE! */
- break;
-
- case LEFT_ADJACENT: /* add new left part to found entry */
- assimilate = true;
- sectors += tmp->sectors;
- ret = true;
- break;
-
- case LEFT_OVERLAP: /* new physical/virtual ==> old end */
- /* must be same distance from edge */
- if ((tmp->virtual - virtual) == (tmp->physical - physical)) {
- assimilate = true;
- sectors = tmp->sectors + (tmp->virtual - virtual);
- ret = true;
- }
- break;
-
- case FULLY_CONTAINING: /* completely take over this entry */
- assimilate = true;
- ret = true;
- break;
-
- case RIGHT_OVERLAP: /* old physical/virtual ==> new end */
- /* must be same distance from edge */
- if ((virtual - tmp->virtual) == (physical - tmp->physical)) {
- assimilate = true;
- sectors += virtual - tmp->virtual;
- virtual = tmp->virtual;
- physical = tmp->physical;
-//KASEY??? tmp->sectors = 0; /* mark for deletion */
- ret = true;
- }
- break;
-
- case RIGHT_ADJACENT: /* add new right part to found entry */
- assimilate = true;
- virtual = tmp->virtual;
- physical = tmp->physical;
- sectors += tmp->sectors;
- ret = true;
- break;
-
- }
-
- if (assimilate) {
- if (victim==NULL) {
- victim = tmp;
- } else {
- list_del(&tmp->list);
- ocfs_free_extent_entry(tmp);
- map->count--;
- }
- }
- } /* list_for_each_safe */
-
- if (victim) {
- victim->virtual = virtual;
- victim->physical = physical;
- victim->sectors = sectors;
- }
-
- bail:
-
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_coalesce_extent_map_entry */
-
-/*
- * ocfs_extent_map_add()
- *
- */
-static bool ocfs_extent_map_add (ocfs_extent_map * map, __s64 virtual, __s64 physical, __s64 sectors)
-{
- ocfs_extent *ext, *tmp;
- bool ret = false;
- struct list_head *iter, *tmpiter;
- bool added;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
-
- if (!map->initialized) {
- LOG_ERROR_STATUS (-EFAIL);
- goto bail;
- }
- spin_lock(&(map->lock));
-
- if (ocfs_coalesce_extent_map_entry (map, virtual, physical, sectors)) {
- LOG_TRACE_STR ("Successfully coalesced map entry");
- ret = true;
- goto release_spinlock;
- }
-
- ext = ocfs_allocate_extent_entry();
- if (ext==NULL) {
- LOG_ERROR_STR ("failed to allocate extent entry");
- goto release_spinlock;
- }
- ext->virtual = virtual;
- ext->physical = physical;
- ext->sectors = sectors;
-
- added=false;
- list_for_each_safe(iter, tmpiter, &map->head) {
- tmp = list_entry (iter, ocfs_extent, list);
- if (ext->virtual < tmp->virtual) {
- list_add_tail(&ext->list, iter);
- added=true;
- break;
- }
- }
- if (!added)
- list_add_tail(&ext->list, &map->head);
-
- map->count++;
- ret = true;
-
-release_spinlock:
- spin_unlock(&(map->lock));
-
-bail:
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_extent_map_add */
-
-/* ocfs_extent_map_remove()
- *
- */
-static void ocfs_extent_map_remove (ocfs_extent_map * map, __s64 virtual, __s64 sectors)
-{
- struct list_head *iter, *tmpiter;
- ocfs_extent *tmp;
- int voverlap;
- __s64 lo, sec;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
-
- if (!map->initialized)
- goto bail;
-
- spin_lock(&(map->lock));
- list_for_each_safe(iter, tmpiter, &map->head) {
- tmp = list_entry (iter, ocfs_extent, list);
- lo = tmp->virtual;
- sec = tmp->sectors;
- voverlap = get_overlap_type (virtual, virtual+sectors, lo, lo+sec);
- /* for now, don't allow splitting of entries */
- if (voverlap!=FULLY_CONTAINED)
- continue;
- if (virtual == lo && sectors == sec) {
- list_del(&tmp->list);
- ocfs_free_extent_entry(tmp);
- map->count--;
- break;
- }
- }
- spin_unlock(&(map->lock));
-bail:
-
- LOG_EXIT ();
- return;
-} /* ocfs_extent_map_remove */
-
-/*
- * ocfs_extent_map_lookup()
- *
- */
-static bool ocfs_extent_map_lookup (ocfs_extent_map *map, __s64 virtual, __s64 *physical, __s64 *sectors, __u32 *index)
-{
- struct list_head *iter, *tmpiter;
- ocfs_extent *tmp;
- bool ret = false;
- __s64 hi, lo, delta;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
-
- if (!map->initialized) {
- LOG_ERROR_STR ("BUG! Uninitialized ExtentMap!");
- goto bail;
- }
-
- spin_lock(&(map->lock));
- list_for_each_safe(iter, tmpiter, &map->head) {
- tmp = list_entry (iter, ocfs_extent, list);
- lo = tmp->virtual;
- hi = lo + tmp->sectors;
- delta = virtual - lo;
- if (virtual >= lo && virtual < hi) {
- *physical = tmp->physical + delta;
- *sectors = tmp->sectors - delta;
- ret = true;
- break;
- }
- (*index)++;
- }
- spin_unlock(&(map->lock));
-
-bail:
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_extent_map_lookup */
-
-/*
- * ocfs_extent_map_next_entry()
- *
- */
-static bool ocfs_extent_map_next_entry (ocfs_extent_map *map, __u32 index, __s64 *virtual, __s64 *physical, __s64 *sectors)
-{
- struct list_head *iter, *tmpiter;
- ocfs_extent *tmp;
- bool ret = false;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (map != NULL);
-
- if (!map->initialized) {
- LOG_ERROR_STR ("BUG! Uninitialized ExtentMap!");
- goto bail;
- }
-
- spin_lock(&(map->lock));
- if (index >= map->count)
- goto release_spinlock;
-
- list_for_each_safe(iter, tmpiter, &map->head) {
- tmp = list_entry (iter, ocfs_extent, list);
- if (index) {
- index--;
- continue;
- }
- *virtual = tmp->virtual;
- *physical = tmp->physical;
- *sectors = tmp->sectors;
- ret = true;
- break;
- }
-
-
-release_spinlock:
- spin_unlock(&(map->lock));
-bail:
-
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_extent_map_next_entry */
-
-
-/*
- * ocfs_delete_all_extent_maps()
- *
- */
-void ocfs_delete_all_extent_maps (ocfs_inode * oin)
-{
- __u32 RunsInExtentMap = 0, ExtentMapIndex, ByteCount = 0;
- __s64 Vbo;
- __s64 Lbo;
-
- LOG_ENTRY ();
-
- RunsInExtentMap = oin->map.count;
-
- for (ExtentMapIndex = 0; ExtentMapIndex < RunsInExtentMap;
- ExtentMapIndex++) {
- if (ocfs_get_next_extent_map_entry
- (oin->osb, &oin->map, ExtentMapIndex, &Vbo, &Lbo,
- &ByteCount)) {
- ocfs_remove_extent_map_entry (oin->osb, &oin->map, Vbo,
- ByteCount);
- }
- }
-
- LOG_EXIT ();
- return;
-} /* ocfs_delete_all_extent_maps */
-
-
-
-/*
- * ocfs_remove_extent_map_entry()
- *
- * Remove an entry from the extent map
- */
-void ocfs_remove_extent_map_entry (ocfs_super * osb, ocfs_extent_map * Map, __s64 Vbo, __u32 ByteCount)
-{
- LOG_ENTRY ();
-
- if ((ByteCount) && (ByteCount != 0xFFFFFFFF)) {
- ByteCount--;
- ByteCount >>= OCFS_LOG_SECTOR_SIZE;
- ByteCount++;
- }
-
- Vbo >>= OCFS_LOG_SECTOR_SIZE;
-
- ocfs_extent_map_remove ((ocfs_extent_map *) Map, (__s64) Vbo,
- (__s64) ByteCount);
-
- LOG_EXIT ();
- return;
-} /* ocfs_remove_extent_map_entry */
-
-/*
- * ocfs_get_next_extent_map_entry()
- *
- * This routine looks up the existing mapping of VBO to LBO for a file.
- * The information it queries is either stored in the extent map field
- * of the oin or is stored in the allocation file and needs to be
- * retrieved, decoded and updated in the extent map.
- *
- */
-bool ocfs_get_next_extent_map_entry (ocfs_super * osb, ocfs_extent_map * Map, __u32 RunIndex, __s64 * Vbo, __s64 * Lbo, __u32 * SectorCount)
-{
- bool Results;
- __s64 LiSectorCount;
-
- LOG_ENTRY ();
-
- Results = ocfs_extent_map_next_entry (Map, RunIndex, Vbo, Lbo,
- &LiSectorCount);
-
- (*Vbo) <<= OCFS_LOG_SECTOR_SIZE;
- (*Lbo) <<= OCFS_LOG_SECTOR_SIZE;
-
- if (LiSectorCount > 0x00000000ffffffffLL) {
- /* overflow */
- Results = false;
- *SectorCount = 0xffffffffUL;
- } else {
- *SectorCount = (LO(LiSectorCount)) << OCFS_LOG_SECTOR_SIZE;
- }
-
- LOG_EXIT_ULONG (Results);
- return Results;
-} /* ocfs_get_next_extent_map_entry */
-
-/*
- * ocfs_lookup_extent_map_entry()
- *
- * search for an VBO in the extent map passed on.
- *
- * Returns true if entry available in the extent map, false otherwise.
- */
-bool ocfs_lookup_extent_map_entry (ocfs_super * osb, ocfs_extent_map * Map, __s64 Vbo, __s64 * Lbo, __u64 * SectorCount, __u32 * Index)
-{
- bool ret;
- __s64 LiLbo = 0;
- __s64 LiSectorCount = 0;
- __u64 remainder = 0;
-
- LOG_ENTRY ();
-
- /* Sector Align the vbo */
- remainder = Vbo & OCFS_MOD_SECTOR_SIZE;
-
- ret = ocfs_extent_map_lookup (Map, (Vbo >> OCFS_LOG_SECTOR_SIZE), &LiLbo,
- &LiSectorCount, Index);
- if ((__u32) LiLbo != -1) {
- *Lbo = (((__s64) LiLbo) << (__s64) OCFS_LOG_SECTOR_SIZE);
- if (ret) {
- *Lbo += remainder;
- }
- } else {
- ret = false;
- *Lbo = 0;
- }
-
- *SectorCount = LiSectorCount;
- if (*SectorCount) {
- *SectorCount <<= (__s64) OCFS_LOG_SECTOR_SIZE;
- if (*SectorCount == 0) {
- *SectorCount = (__u32) - 1;
- }
-
- if (ret) {
- *SectorCount -= remainder;
- }
- }
-
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_lookup_extent_map_entry */
-
-
-/* ocfs_update_extent_map()
- *
- */
-int ocfs_update_extent_map (ocfs_super * osb, ocfs_extent_map * Map, void *Buffer, __s64 * localVbo, __u64 * remainingLength, ocfs_ext_flag Flag)
-{
- int status = -EFAIL;
- ocfs_file_entry *FileEntry;
- ocfs_extent_group *OcfsExtent;
- __s64 tempVbo;
- __s64 tempLbo;
- __u64 tempSize;
- bool Ret;
- int j;
-
- LOG_ENTRY ();
-
- if (Flag == LOCAL_EXT) {
- FileEntry = (ocfs_file_entry *) Buffer;
-
- OCFS_ASSERT (FileEntry->local_ext);
-
- for (j = 0; j < FileEntry->next_free_ext; j++) {
- tempVbo = FileEntry->extents[j].file_off;
- tempLbo = FileEntry->extents[j].disk_off;
- tempSize = FileEntry->extents[j].num_bytes;
-
- /* Add the Extent to extent map list */
- Ret =
- ocfs_add_extent_map_entry (osb, Map, tempVbo, tempLbo,
- tempSize);
- if (!Ret) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
- }
- status = 0;
- } else {
- __u64 localLength = 0;
-
- OcfsExtent = (ocfs_extent_group *) Buffer;
-
- for (j = 0; j < OcfsExtent->next_free_ext; j++) {
- if ((__s64) (OcfsExtent->extents[j].file_off +
- OcfsExtent->extents[j].num_bytes) >
- (*localVbo)) {
- tempVbo = OcfsExtent->extents[j].file_off;
- tempLbo = OcfsExtent->extents[j].disk_off;
- tempSize = OcfsExtent->extents[j].num_bytes;
-
- /* Add the Extent to extent map list */
- Ret =
- ocfs_add_extent_map_entry (osb, Map, tempVbo,
- tempLbo,
- (__u32) tempSize);
- if (!Ret) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- localLength =
- (tempSize - ((*localVbo) - tempVbo));
-
- /* Since we have read the disk we should add some */
- /* more Entries to the extent map list */
- if (localLength >= (*remainingLength)) {
- (*remainingLength) = 0;
- status = 0;
- goto bail;
- } else {
- (*remainingLength) -= localLength;
- (*localVbo) += localLength;
- }
- }
- }
-
- if ((OcfsExtent->next_free_ext != OCFS_MAX_DATA_EXTENTS) &&
- (*remainingLength)) {
- LOG_ERROR_ARGS ("next_free_extent=%d, rem_len=%u.%u",
- OcfsExtent->next_free_ext, HILO(*remainingLength));
- } else
- status = 0;
- }
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_update_extent_map */
-
-/*
- * ocfs_add_extent_map_entry()
- *
- * adds an entry to an extent map
- *
- * Returns true on success, false otherwise.
- */
-bool ocfs_add_extent_map_entry (ocfs_super * osb, ocfs_extent_map * Map, __s64 Vbo, __s64 Lbo, __u64 ByteCount)
-{
- bool ret;
-
- LOG_ENTRY ();
-
- /* Convert the Bytes in to number of Sectors */
- if (ByteCount) {
- /* Round up sectors */
- ByteCount--;
- ByteCount >>= OCFS_LOG_SECTOR_SIZE;
- ByteCount++;
- }
-
- /* Make the ByteOffsets in to Sector numbers. */
- /* In case of 512 byte sectors the OcfsLogOf gives back a value of 9. */
- /* And by doing a right shift of 9 bits we are actually dividing */
- /* the value by 512. */
- Vbo >>= OCFS_LOG_SECTOR_SIZE;
- Lbo >>= OCFS_LOG_SECTOR_SIZE;
-
- ret = ocfs_extent_map_add (Map, ((__s64) Vbo), ((__s64) Lbo), ((__s64) ByteCount));
- if (!ret)
- LOG_ERROR_ARGS ("fileoff=%u.%u, diskoff=%u.%u, len=%u.%u",
- HILO (Vbo), HILO (Lbo), HILO (ByteCount));
-
-
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_add_extent_map_entry */
Deleted: trunk/file.c
===================================================================
--- trunk/file.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/file.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1411 +0,0 @@
-#include <ocfs.h>
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, struct iattr *attr, struct inode *inode);
-static int ocfs_truncate_file (ocfs_super * osb, __u64 file_off, __u64 file_size, ocfs_inode * oin, struct inode *inode);
-
-#define OCFS_FE_SET_ATTRIBUTES(fe, attr) \
-do { \
- if (attr->ia_valid & ATTR_SIZE) \
- fe->file_size = attr->ia_size; \
- if (attr->ia_valid & ATTR_UID) \
- fe->uid = attr->ia_uid; \
- if (attr->ia_valid & ATTR_GID) \
- fe->gid = attr->ia_gid; \
- if (attr->ia_valid & ATTR_MODE) \
- fe->prot_bits = attr->ia_mode & 0007777; \
- if (attr->ia_valid & ATTR_CTIME) \
- fe->create_time = attr->ia_ctime; \
- if (attr->ia_valid & ATTR_MTIME) \
- fe->modify_time = attr->ia_mtime; \
-} while (0)
-
-/*
- * ocfs_file_open()
- *
- */
-int ocfs_file_open (struct inode *inode, struct file *file)
-{
- struct dentry *dentry = file->f_dentry;
- struct inode *parent = dentry->d_parent->d_inode;
- ocfs_file *ofile = NULL;
- int ret =0, err = 0, status = 0;
- int mode = file->f_flags;
- ocfs_super *osb = NULL;
- ocfs_inode *ParentOin = NULL;
- ocfs_inode *oin = NULL;
- bool bAcquiredOIN = false;
- bool bClearInUse = false;
- bool new_oin = false;
- struct buffer_head *fe_bh = NULL;
- __u64 parent_off;
- ocfs_sem *oin_sem = NULL;
-
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", inode, file,
- file->f_dentry->d_name.len, file->f_dentry->d_name.name);
- atomic_inc (&parent->i_count);
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(parent->i_sb);
-
- if (!ocfs_linux_get_inode_offset (parent, &parent_off, &ParentOin)) {
- LOG_ERROR_STATUS (status = -ENOENT);
- goto leave;
- }
-
- if (osb->osb_flags & OCFS_OSB_FLAGS_SHUTDOWN) {
- LOG_ERROR_STR ("Volume has been shutdown");
- status = -EACCES;
- goto leave;
- }
-
- /* kch - for an open request we are already given the
- * inode, and therefore we are given the oin too */
- down(&inode->i_sem);
- oin = NULL;
- if (inode_data_is_oin (inode))
- oin = GET_INODE_OIN(inode);
- status = -EFAIL;
- if (oin != NULL) {
- if (!(oin->oin_flags & OCFS_OIN_IN_TEARDOWN) &&
- !(oin->oin_flags & OCFS_OIN_DELETE_ON_CLOSE)) {
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_IN_USE);
- status = 0;
- }
- if (status < 0) {
- if (oin->oin_flags & OCFS_OIN_IN_TEARDOWN)
- LOG_ERROR_ARGS ("oin (%p) in teardown", oin);
- else
- LOG_ERROR_ARGS ("oin (%p) deleted", oin);
- }
- } else {
- /* now it IS possible to have an inode but no OIN attached yet
- * must be loaded now to open file */
- status = -ENOENT;
- }
- up(&inode->i_sem);
-
- if (status < 0) {
- if (status != -ENOENT && status != -EINTR) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* Look on the disk now ... */
- status = ocfs_find_files_on_disk (osb, parent_off, &(dentry->d_name),
- &fe_bh, NULL, parent);
- if (status >= 0) {
- oin = NULL;
- ocfs_down_sem (&(osb->osb_res), true);
- status = ocfs_create_oin_from_entry (osb, fe_bh, &oin, parent_off, inode);
- new_oin = true;
- ocfs_up_sem (&(osb->osb_res));
- }
- }
-
- if (status < 0) { /* not found on disk or in mem */
- if (status != -EINTR) {
- LOG_ERROR_STR ("Open request made for nonexistent file!");
- status = -ENOENT;
- }
- goto leave;
- }
-
- bClearInUse = true;
-
- /* check if another process doing an open */
- /* concurrently has just set the oin */
- down(&inode->i_sem);
- if (new_oin) {
- if (inode_data_is_oin (inode)) {
- // delete the oin we just made
- oin->inode = NULL;
- oin->lock_res = NULL;
- ocfs_release_oin(oin, true);
- // and use the correct one
- oin = GET_INODE_OIN(inode);
- } else {
- oin->inode = inode;
- SET_INODE_OIN (inode, oin);
- }
- }
-
- /* we should now have a single oin regardless */
- /* of how many concurrent openers at this point */
- /* so take the oin->main_res so we won't need the i_sem */
- up(&inode->i_sem);
-
- oin_sem = &(oin->main_res);
- if (!bAcquiredOIN) {
- ocfs_down_sem (oin_sem, true);
- bAcquiredOIN = true;
- }
-
- if (oin->oin_flags & OCFS_OIN_DELETE_ON_CLOSE) {
- LOG_TRACE_STR ("oin has DELETE_ON_CLOSE set, returning DELETE_PENDING");
- status = -ENOENT;
- goto leave;
- }
-
- /* only call ocfs_verify_update_oin if there's a good inode */
- if (oin->inode == inode && OIN_NEEDS_VERIFICATION(oin)) {
- status = ocfs_verify_update_oin (osb, oin);
- if (status < 0) {
- /* disable VOLUME TODO */
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
- if (oin->open_hndl_cnt > 0) {
- /* The OIN is currently in use by some thread. */
- /* We must check whether the requested access/share access */
- /* conflicts with the existing open operations. */
-
- LOG_TRACE_ARGS ("oin->open_hndl_cnt > 0! : %u\n", oin->open_hndl_cnt);
- if (!(mode & O_DIRECT)) {
- if ((oin->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO) && !(mode & O_RDONLY)) {
- status = -EACCES;
- LOG_TRACE_STR("file is already open O_DIRECT, "
- "cannot open non O_DIRECT");
- goto leave;
- }
- OCFS_CLEAR_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- } else if (mode & O_DIRECT) {
- if (!(oin->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO)) {
- status = -EACCES;
- LOG_TRACE_STR("file is already open non " \
- "O_DIRECT, cannot open " \
- "O_DIRECT");
- goto leave;
- }
- OCFS_SET_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- }
- status = 0;
- } else {
- ocfs_extent_map_destroy (&oin->map);
- ocfs_extent_map_init (&oin->map);
- if (mode & O_DIRECT)
- OCFS_SET_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- else {
- OCFS_CLEAR_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
- if (inode->i_data.nrpages)
- ocfs_truncate_inode_pages(inode, 0);
- }
- }
-
- ofile = ocfs_allocate_ofile (OCFS_ATTRIB_REG);
- if (ofile == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- oin->open_hndl_cnt++;
- ofile->oin = oin;
-
- /* We should clear the in use now as we are safe from the case */
- /* where the voting thread can vote and we have an open in */
- /* progress */
- OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_OIN_IN_USE);
- if (ParentOin)
- OCFS_CLEAR_FLAG (ParentOin->oin_flags, OCFS_OIN_IN_USE);
-
- if (bAcquiredOIN) {
- ocfs_up_sem (oin_sem);
- bAcquiredOIN = false;
- }
-
- status = 0;
-
-leave:
- if (bClearInUse) {
- if (!bAcquiredOIN && oin_sem) {
- ocfs_down_sem (oin_sem, true);
- bAcquiredOIN = true;
- }
-
- OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_OIN_IN_USE);
-
- if (bAcquiredOIN && oin_sem) {
- ocfs_up_sem (oin_sem);
- bAcquiredOIN = false;
- }
- }
-
- if (bAcquiredOIN && oin_sem) {
- ocfs_up_sem (oin_sem);
- bAcquiredOIN = false;
- }
-
- if (fe_bh)
- brelse(fe_bh);
-
- if (status < 0) {
- if (status != -ENOENT && status != -ENOMEM &&
- status != -EACCES && status != -EINTR) {
- LOG_ERROR_STATUS (status);
- ret = -EACCES;
- } else
- ret = status;
- atomic_dec (&parent->i_count);
- } else {
- file->private_data = (void *) ofile;
- ret = 0;
- }
-
- LOG_TRACE_ARGS
- ("exiting file_open: file=%p dentry=%p inode=%p oin=%p kiovec=%d\n",
- file, file->f_dentry, file->f_dentry->d_inode,
- GET_INODE_OIN(file->f_dentry->d_inode), err);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_file_open */
-
-/*
- * ocfs_file_release()
- *
- */
-int ocfs_file_release (struct inode *inode, struct file *file)
-{
- //int nbhs = KIO_MAX_SECTORS;
- ocfs_file *ofile = NULL;
- ocfs_super * osb;
- ocfs_inode *oin;
- struct dentry *dentry;
- struct inode *parent;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", inode, file,
- file->f_dentry->d_name.len, file->f_dentry->d_name.name);
-
- dentry = file->f_dentry;
-
- if (file->private_data)
- ofile = (ocfs_file *) file->private_data;
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(inode->i_sb);
-
- /* dir */
- if (S_ISDIR (inode->i_mode)) {
- /* fix all this - need a real open/close for directories */
- if (ofile) {
- if (ofile->curr_dir_buf) {
- const int nbhs = osb->vol_layout.dir_node_size >> 9;
- struct buffer_head **bhs;
- int i;
-
- bhs = (struct buffer_head **)ofile->curr_dir_buf;
- for (i=0; i<nbhs; i++) {
- if (bhs[i]) {
- brelse(bhs[i]);
- bhs[i]=NULL;
- }
- }
- ocfs_safefree (ofile->curr_dir_buf);
- ofile->curr_dir_buf = NULL;
- }
- // hmm
- // if (ofile->f_iobuf)
- // free_kiovec_sz(1, &ofile->f_iobuf, &nbhs);
- ocfs_release_ofile (ofile);
- }
- goto bail;
- }
-
- /* file */
- oin = NULL;
-
- if (ofile == NULL) {
- if (inode_data_is_oin(inode))
- oin = GET_INODE_OIN(inode);
- } else {
- oin = ofile->oin;
- ocfs_release_ofile (ofile);
- }
- if (oin == NULL)
- goto do_parent_dec;
-
- ocfs_down_sem (&(oin->main_res), true);
- oin->open_hndl_cnt--;
-
- if (oin->oin_flags & OCFS_OIN_ROOT_DIRECTORY) {
- ocfs_up_sem (&(oin->main_res));
- goto do_parent_dec;
- }
-
- LOG_TRACE_ARGS ("openhandles: %d / osbfiles: %d / refcount: %d\n",
- oin->open_hndl_cnt, osb->file_open_cnt,
- atomic_read(&dentry->d_count));
-
- /* FIXME: in all the other places I run thru all the dentries */
- /* for the inode, but here I just check this one becuz I'm lz */
- /* no hard links yet so who cares */
- if (!atomic_read(&dentry->d_count)) {
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
- if (inode->i_data.nrpages)
- ocfs_truncate_inode_pages(inode, 0);
-
- if (oin->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO) {
- OCFS_CLEAR_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- }
- if (oin->oin_flags & OCFS_OIN_NEEDS_DELETION ||
- oin->oin_flags & OCFS_OIN_IN_USE) {
- ocfs_up_sem (&(oin->main_res));
- goto do_parent_dec;
- }
-
- ocfs_up_sem (&(oin->main_res));
- ocfs_release_oin (oin, true);
- } else {
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
- if (inode->i_data.nrpages)
- ocfs_truncate_inode_pages(inode, 0);
-
- ocfs_up_sem (&(oin->main_res));
- ocfs_release_cached_oin (osb, oin);
- }
-
-do_parent_dec:
- if (dentry && dentry->d_parent &&
- dentry->d_parent->d_inode) {
- parent = dentry->d_parent->d_inode;
- if (parent)
- atomic_dec (&parent->i_count);
- }
-
-bail:
- LOG_EXIT_LONG (0);
- return 0;
-} /* ocfs_file_release */
-
-/*
- * ocfs_flush()
- *
- */
-int ocfs_flush (struct file *file)
-{
- int err = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, '%*s')\n", file,
- file->f_dentry->d_name.len, file->f_dentry->d_name.name);
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(file->f_dentry->d_inode);
-#endif
- err = fsync_inode_buffers(file->f_dentry->d_inode);
- LOG_EXIT_STATUS (err);
- return (err < 0) ? -EIO : 0;
-} /* ocfs_flush */
-
-/*
- * ocfs_sync_file()
- *
- */
-int ocfs_sync_file (struct file *file, struct dentry *dentry, int datasync)
-{
- int err = 0;
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, '%*s')\n", file, dentry, datasync,
- dentry->d_name.len, dentry->d_name.name);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(file->f_dentry->d_inode);
-#endif
- err = fsync_inode_buffers(dentry->d_inode);
- LOG_EXIT_STATUS (err);
- return (err < 0) ? -EIO : 0;
-} /* ocfs_sync_file */
-
-/* ocfs_change_file_attrib()
- *
- */
-static int ocfs_change_file_attrib (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, struct iattr *attr, struct inode *inode)
-{
- int status = 0;
- int tmpstat;
- ocfs_file_entry *fileEntry = NULL;
- __u64 dirOffset = 0;
- __u32 size;
- bool bAcquiredLock = false;
- ocfs_lock_res *pLockResource = NULL;
- __u64 changeSeqNum = 0;
- __u64 lockId = 0;
- __u32 lockFlags = 0;
- bool bCacheLock = false;
- struct buffer_head *bh = NULL;
- ocfs_journal_handle *handle = NULL;
- int flags = 0;
-
- LOG_ENTRY ();
-
- changeSeqNum = osb->curr_trans_id;
-
- status = ocfs_read_bh (osb, *file_off, &bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if (!IS_VALID_FILE_ENTRY(fileEntry)) {
- LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO (*file_off));
- OCFS_BH_PUT_DATA(bh);
- status = -EFAIL;
- goto leave;
- }
-
- /* Acquire the Lock using TCP/IP and disk based locking */
- if ((DISK_LOCK_FILE_LOCK (fileEntry) == OCFS_DLM_ENABLE_CACHE_LOCK) &&
- (DISK_LOCK_CURRENT_MASTER (fileEntry) == osb->node_num)) {
- bCacheLock = true;
- }
-
- /* now we always take an UPDATE lock */
- lockId = fileEntry->this_sector;
- lockFlags = FLAG_FILE_UPDATE;
- OCFS_BH_PUT_DATA(bh);
-
- /* Start a transaction - need a minimal amount of block credits (1) */
- handle = ocfs_start_trans(osb, 1);
- if (handle == NULL) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- /* we want this transaction to return quickly. */
- ocfs_handle_set_checkpoint(handle, false);
-#ifdef ALLOW_NO_HANDLE_SYNCING
- ocfs_handle_set_sync(handle, false);
-#endif
-
- status = ocfs_acquire_lock (osb, lockId,
- bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK : OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, &pLockResource, &bh, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- bAcquiredLock = true;
-
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if (bCacheLock) {
- DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_CURRENT_MASTER (fileEntry) = osb->node_num;
- }
-
- fileEntry->modify_time = CURRENT_TIME;
-
- DISK_LOCK_SEQNUM (fileEntry) = changeSeqNum;
- OCFS_FE_SET_ATTRIBUTES(fileEntry, attr);
-
- /* Set the valid bit here */
- SET_VALID_BIT (fileEntry->sync_flags);
- fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
-
- dirOffset = fileEntry->this_sector;
- size = (__u32) OCFS_SECTOR_ALIGN (sizeof (ocfs_file_entry));
-
- flags = OCFS_FE_CACHE_FLAGS(osb, fileEntry);
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-leave:
- lockFlags |= FLAG_FILE_UPDATE_OIN;
-
- if (handle) {
- if (status < 0) {
- ocfs_abort_trans(handle);
- } else {
- ocfs_journal_add_lock(handle, lockId,
- OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, pLockResource, bh);
- bAcquiredLock = false;
- status = ocfs_commit_trans(handle);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
- }
- if (bAcquiredLock) {
- tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, pLockResource, bh, inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_put_lockres (pLockResource);
- }
-
- if (bh != NULL)
- brelse(bh);
-
- if (status < 0)
- if (status != -ENOSPC && status != -EINTR)
- LOG_ERROR_STATUS (status);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_change_file_attrib */
-
-/*
- * ocfs_file_write()
- * Linux 2.5 TODO: Remove all O_DIRECT conditionals here, they are no longer
- * needed.
- */
-ssize_t ocfs_file_write (struct file *filp, const char *buf, size_t count, loff_t * ppos)
-{
- int ret = 0;
- int saAcquired = false, writingAtEOF = false;
- ocfs_inode *oin = NULL;
- ocfs_super *osb = NULL;
- struct inode *inode = filp->f_dentry->d_inode;
- int status;
- __u64 newsize;
- ocfs_lock_res *lockres = NULL;
- struct super_block *sb = inode->i_sb;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, '%*s')\n", filp, buf, count,
- filp->f_dentry->d_name.len, filp->f_dentry->d_name.name);
-
- /* happy write of zero bytes */
- if (count == 0) {
- ret = 0;
- goto bail;
- }
-
- if (!inode || !inode_data_is_oin (inode)) {
- LOG_TRACE_STR ("bad inode or inode has no oin");
- ret = -EIO;
- goto bail;
- }
- oin = GET_INODE_OIN(inode);
- osb = (ocfs_super *) oin->osb;
-
- lockres = oin->lock_res;
- if (lockres == NULL) {
- ret = -EIO;
- goto bail;
- }
-
- ocfs_get_lockres (lockres);
-
- if ((lockres->master_node_num != osb->node_num) ||
- (lockres->lock_state != OCFS_DLM_ENABLE_CACHE_LOCK)) {
- oin->cache_enabled = false;
- } else {
- oin->cache_enabled = true;
- }
-
- if (osb->osb_flags & OCFS_OSB_FLAGS_SHUTDOWN) {
- LOG_TRACE_STR ("Volume has already started shutdown");
- ret = -EIO;
- goto bail;
- }
-
- if (filp->f_flags & O_DIRECT) {
- /* anything special for o_direct? */
- LOG_TRACE_STR ("O_DIRECT");
- } else {
- /* FIXME: is the down_sem supposed to be here?! */
- LOG_TRACE_ARGS ("non O_DIRECT write, fileopencount=%d\n",
- oin->open_hndl_cnt);
- if (oin->open_hndl_cnt > 1) {
- if (oin->oin_flags & OCFS_OIN_OPEN_FOR_WRITE) {
- LOG_TRACE_STR
- ("uh oh! someone else is doing non O_DIRECT writes!\n");
- ret = -EIO;
- goto bail;
- } else {
- LOG_TRACE_STR
- ("there are other readers, but you're the first writer\n");
- saAcquired = true;
- OCFS_SET_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_WRITE);
- }
- }
- }
-
- if (OIN_NEEDS_VERIFICATION (oin)) {
- LOG_TRACE_STR ("OIN_NEEDS_VERIFICATION");
- ocfs_down_sem (&(oin->main_res), true);
- status = ocfs_verify_update_oin (osb, oin);
- ocfs_up_sem (&(oin->main_res));
- if (status < 0) {
- LOG_TRACE_STR ("ocfs_verify_update_oin failed");
- LOG_TRACE_STR ("TODO: disable volume");
- ret = -EIO;
- goto bail;
- }
- }
-
-
- if (filp->f_flags & O_APPEND)
- newsize = count + inode->i_size;
- else
- newsize = count + *ppos;
-
- if (newsize > inode->i_size) {
- writingAtEOF = true;
- LOG_TRACE_STR ("Writing at EOF");
- }
-
- LOG_TRACE_ARGS ("ppos=%u.%u newsize=%u.%u cursize=%u.%u\n",
- HI (*ppos), LO (*ppos), HI (newsize), LO (newsize),
- HI (inode->i_size), LO (inode->i_size));
-
- if (newsize > oin->alloc_size) {
- LOG_TRACE_ARGS
- ("Will need more allocation: have=%u.%u, need=%u.%u\n",
- HI (oin->alloc_size), LO (oin->alloc_size), HI (newsize),
- LO (newsize));
-
-
- status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode, NULL);
- if (status < 0) {
- if (status != -EINTR && status != -ENOSPC) {
- LOG_ERROR_STATUS (status);
- LOG_ERROR_ARGS ("Failed to extend file from %u.%u to %u.%u",
- HILO (*ppos), HILO (newsize));
- ret = -ENOSPC;
- } else
- ret = status;
- goto bail;
- }
- }
-
- if (filp->f_flags & O_DIRECT)
- ret = ocfs_rw_direct (WRITE, filp, (char *) buf, count, ppos);
- else
- ret = generic_file_write (filp, buf, count, ppos);
-
- if (writingAtEOF && ret >= 0) {
- LOG_TRACE_STR
- ("Generic_file_write ok, asking for OIN update now");
- inode->i_size = newsize;
- inode->i_blocks = (newsize + sb->s_blocksize) >> sb->s_blocksize_bits;
- }
-
-bail:
- if (saAcquired) {
- OCFS_CLEAR_FLAG(oin->oin_flags, OCFS_OIN_OPEN_FOR_WRITE);
- }
-
-#if 0
- if (inode && oin && !oin->cache_enabled && !(filp->f_flags & O_DIRECT)) {
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
- }
-#endif
-
- ocfs_put_lockres (lockres);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_file_write */
-
-/*
- * ocfs_file_read()
- * Linux 2.5 TODO: Remove all O_DIRECT conditionals here, they are no longer
- * needed.
- */
-ssize_t ocfs_file_read (struct file *filp, char *buf, size_t count, loff_t * ppos)
-{
- int ret = 0;
- ocfs_inode *oin = NULL;
- ocfs_super *osb = NULL;
- struct inode *inode = filp->f_dentry->d_inode;
- int status;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, '%*s')\n", filp, buf, count,
- filp->f_dentry->d_name.len, filp->f_dentry->d_name.name);
-
-
- if (!inode || !inode_data_is_oin (inode)) {
- LOG_ERROR_STR ("Bad inode or inode has no oin");
- ret = -EINVAL;
- goto bail;
- }
- oin = GET_INODE_OIN(inode);
- osb = (ocfs_super *) oin->osb;
-
- if (filp->f_flags & O_DIRECT) {
- /* anything special for o_direct? */
- LOG_TRACE_STR ("O_DIRECT");
- }
-
- if (OIN_NEEDS_VERIFICATION (oin)) {
- ocfs_down_sem (&(oin->main_res), true);
- status = ocfs_verify_update_oin (osb, oin);
- ocfs_up_sem (&(oin->main_res));
- if (status < 0) {
- LOG_TRACE_STR ("ocfs_verify_update_oin failed");
- LOG_TRACE_STR ("TODO: disable volume");
- ret = -EIO;
- goto bail;
- }
- }
-
- if (filp->f_flags & O_DIRECT)
- ret = ocfs_rw_direct (READ, filp, buf, count, ppos);
- else
- ret = generic_file_read (filp, buf, count, ppos);
-
- if (ret == -EINVAL)
- LOG_TRACE_STR ("Generic_file_read returned -EINVAL");
-
-bail:
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_file_read */
-
-/*
- * ocfs_truncate_file()
- *
- */
-static int ocfs_truncate_file (ocfs_super * osb, __u64 file_off, __u64 file_size, ocfs_inode * oin, struct inode *inode)
-{
- int status = 0, tmpstat;
- ocfs_file_entry *fe = NULL;
- __u64 lockId = 0;
- __u32 lockFlags = 0;
- bool bFileLockAcquired = false;
- bool bAcquiredLock = false;
- ocfs_lock_res *pLockResource = NULL;
- __u64 changeSeqNum = 0;
- bool bCacheLock = false;
- __u64 new_alloc_size;
- __u32 csize = osb->vol_layout.cluster_size;
- struct buffer_head *bh = NULL;
- int flags = 0;
- ocfs_bitmap_free_head *free_head = NULL;
- ocfs_journal_handle *handle = NULL;
-
- LOG_ENTRY ();
-
- changeSeqNum = osb->curr_trans_id;
-
- new_alloc_size = OCFS_ALIGN(file_size, csize);
-
- status = ocfs_read_bh (osb, file_off, &bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* start a journal transaction */
- handle = ocfs_start_trans(osb, OCFS_FILE_TRUNCATE_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
- if (!IS_VALID_FILE_ENTRY(fe)) {
- LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO (file_off));
- status = -EFAIL;
- OCFS_BH_PUT_DATA(bh);
- goto leave;
- }
-
- /* we keep our bitmap updates in this structure and process
- * them later. */
- free_head = alloc_bitmap_free_head();
- if (free_head == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- lockId = fe->this_sector;
- lockFlags = FLAG_FILE_TRUNCATE;
- bFileLockAcquired = true;
-
- if ((DISK_LOCK_FILE_LOCK (fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
- && (DISK_LOCK_CURRENT_MASTER (fe) == osb->node_num)) {
- bCacheLock = true;
- }
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_acquire_lock (osb, lockId,
- bCacheLock ? OCFS_DLM_ENABLE_CACHE_LOCK : OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, &pLockResource, &bh, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- bAcquiredLock = true;
-
- /* add this fe to the journal transaction */
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- /* the file entry might have changed underneath us (while
- * waiting on the lock). make sure the size is still a valid
- * one. This really ought to check for other things too, like
- * a valid bit, etc. */
- if (file_size > fe->file_size) {
- LOG_TRACE_ARGS("asked to truncate file with size (%u.%u) "
- "to size (%u.%u)!\n", HILO(fe->file_size),
- HILO(file_size));
- OCFS_BH_PUT_DATA(bh);
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- fe->file_size = file_size;
- fe->alloc_size = new_alloc_size;
-
- status = ocfs_free_extents_for_truncate (osb, fe, handle, free_head, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (bCacheLock) {
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
- }
-
- DISK_LOCK_SEQNUM (fe) = changeSeqNum;
- SET_VALID_BIT (fe->sync_flags);
- fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
- OcfsQuerySystemTime (&fe->modify_time);
-
- flags = OCFS_FE_CACHE_FLAGS(osb, fe);
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (oin) {
- /* if we updated correctly then we can update the OIN */
- ocfs_down_sem (&(oin->main_res), true);
- oin->alloc_size = new_alloc_size;
- ocfs_up_sem (&(oin->main_res));
- }
-
-leave:
- if (handle && (status == 0)) {
- status = ocfs_commit_trans(handle);
- if ((status == 0) && free_head)
- ocfs_process_bitmap_free_head(osb, free_head);
- } else if (handle)
- ocfs_abort_trans(handle);
-
- if (free_head)
- free_bitmap_free_head(free_head);
-
- if (bAcquiredLock) {
- if (bFileLockAcquired)
- lockFlags |= FLAG_FILE_UPDATE_OIN;
-
- tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, pLockResource, bh, inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
-
- if (bh != NULL)
- brelse(bh);
-
- ocfs_put_lockres (pLockResource);
-
- if (status < 0)
- if (status != -ENOSPC && status != -EINTR)
- LOG_ERROR_STATUS (status);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_truncate_file */
-
-
-/* ocfs_extend_file()
- *
- */
-int ocfs_extend_file (ocfs_super * osb, __u64 parent_off, ocfs_inode * oin, __u64 file_size, __u64 * file_off, ocfs_journal_handle *passed_handle, struct inode *inode, struct iattr *attr)
-{
- int status = 0;
- int tmpstat;
- ocfs_file_entry *fileEntry = NULL;
- __u64 tempOffset = 0;
- __u64 allocSize = 0;
- __u32 size;
- __u64 bitmapOffset = 0;
- __u64 numClustersAlloc = 0;
- __u64 lockId = 0;
- __u32 lockFlags = 0;
- bool bFileLockAcquired = false;
- bool bAcquiredLock = false;
- ocfs_lock_res *pLockResource = NULL;
- __u64 changeSeqNum = 0;
- __u64 actualDiskOffset = 0;
- __u64 actualLength = 0;
- bool bCacheLock = false;
- struct buffer_head *bh = NULL;
- int flags = 0;
- ocfs_journal_handle *handle = NULL;
-
- LOG_ENTRY ();
-
- changeSeqNum = osb->curr_trans_id;
-
- if (file_size == 0)
- goto leave;
-
- status = ocfs_read_bh (osb, *file_off, &bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if (!IS_VALID_FILE_ENTRY(fileEntry)) {
- printk("fe->signature=%8s\n", fileEntry->signature);
- printk("fe->filename=%8s\n", fileEntry->filename);
- LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO (*file_off));
- status = -EFAIL;
- OCFS_BH_PUT_DATA(bh);
- goto leave;
- }
-
- if (passed_handle == NULL) {
- /* cannot call start_trans with a locked buffer head. */
- OCFS_BH_PUT_DATA(bh);
-
- handle = ocfs_start_trans(osb, OCFS_FILE_EXTEND_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto leave;
- }
-
- /* we don't want to checkpoint extends. */
- ocfs_handle_set_checkpoint(handle, false);
-#ifdef ALLOW_NO_HANDLE_SYNCING
- ocfs_handle_set_sync(handle, false);
-#endif
- /* Grab a lock on the entry found if we have more than
- * 1 extents and also make this node the master*/
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- /* now we always take an EXTEND lock */
- lockId = fileEntry->this_sector;
- lockFlags = FLAG_FILE_EXTEND;
- bFileLockAcquired = true;
-
- if ((DISK_LOCK_FILE_LOCK (fileEntry) == OCFS_DLM_ENABLE_CACHE_LOCK) && (DISK_LOCK_CURRENT_MASTER (fileEntry) == osb->node_num)) {
- bCacheLock = true;
- }
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- bh = NULL;
-
- status = ocfs_acquire_lock (osb, lockId, bCacheLock ?
- OCFS_DLM_ENABLE_CACHE_LOCK :
- OCFS_DLM_EXCLUSIVE_LOCK, lockFlags,
- &pLockResource, &bh, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- bAcquiredLock = true;
- } else {
- OCFS_BH_PUT_DATA(bh);
- fileEntry = NULL;
- handle = passed_handle;
- }
-
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if (bCacheLock) {
- DISK_LOCK_FILE_LOCK (fileEntry) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_CURRENT_MASTER (fileEntry) = osb->node_num;
- }
-
- if (file_size > (__s64) fileEntry->alloc_size) {
- allocSize = file_size - fileEntry->alloc_size;
-
- /* TODO: We can add something here so that after 2-3 allocations, */
- /* we give a lot more disk space to the file than the allocSize so */
- /* in order to try to use the Extents of File Entry only and ofcourse */
- /* the file will have more contigous disk space. */
- {
- __u64 tempSize = fileEntry->alloc_size;
-
- if (tempSize > ONE_MEGA_BYTE)
- tempSize = ONE_MEGA_BYTE;
- allocSize += (tempSize * 2);
- if (allocSize < fileEntry->alloc_size / 100) {
- allocSize = fileEntry->alloc_size / 100;
- allocSize = OCFS_ALIGN(allocSize, (10*ONE_MEGA_BYTE));
- }
-
- }
-
- status = ocfs_find_space(osb, allocSize, &bitmapOffset,
- &numClustersAlloc, false, handle);
- if (status < 0) {
- OCFS_BH_PUT_DATA(bh);
- if (status != -ENOSPC && status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- actualDiskOffset =
- (bitmapOffset * osb->vol_layout.cluster_size) +
- osb->vol_layout.data_start_off;
- actualLength =
- (__u64) (numClustersAlloc * osb->vol_layout.cluster_size);
-
- OCFS_BH_PUT_DATA(bh);
- fileEntry = NULL;
-
- /* note: ok if oin is null here, not used in
- * ocfs_allocate_extent */
- status = ocfs_allocate_extent (osb, oin, bh, handle,
- actualDiskOffset, actualLength, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- fileEntry = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- /* update the total allocation size here */
- fileEntry->alloc_size += actualLength;
-
- if (oin) {
- ocfs_down_sem (&(oin->main_res), true);
- oin->alloc_size = fileEntry->alloc_size;
- ocfs_up_sem (&(oin->main_res));
- }
-
- /* no need to do OCFS_SECTOR_ALIGN once the allocation size is correct. */
- DISK_LOCK_SEQNUM (fileEntry) = changeSeqNum;
- }
-
- /* Update tha file size and add the new one to old one. */
- fileEntry->file_size = file_size;
- LOG_TRACE_ARGS("fileEntry->alloc_size = %u.%u\n", HILO(fileEntry->alloc_size));
-
- if (attr)
- OCFS_FE_SET_ATTRIBUTES(fileEntry, attr);
- /* Set the Valid bit and reset the change bit here... TODO */
- SET_VALID_BIT (fileEntry->sync_flags);
- fileEntry->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
- fileEntry->modify_time = OCFS_CURRENT_TIME;
-
- tempOffset = fileEntry->this_sector;
- size = (__u32) OCFS_ALIGN (sizeof (ocfs_file_entry), osb->sect_size);
-
- flags = OCFS_FE_CACHE_FLAGS(osb, fileEntry);
-
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_journal_dirty(handle, bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* Update all open oins */
-
- /* Our local update is done, if somebody had asked for a bdcast lock */
- /* He shd set the state */
-
-leave:
- if (passed_handle == NULL) {
- if (handle) {
- ocfs_bitmap_free_head *f = osb->alloc_free_head;
- osb->alloc_free_head = NULL;
-
- if (status < 0) {
- ocfs_abort_trans(handle);
- } else {
- if (bFileLockAcquired)
- lockFlags |= FLAG_FILE_UPDATE_OIN;
-
- ocfs_journal_add_lock(handle, lockId,
- OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, pLockResource,
- bh);
- bAcquiredLock = false;
- status = ocfs_commit_trans(handle);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
-
- if (f) {
- ocfs_process_bitmap_free_head(osb, f);
- free_bitmap_free_head(f);
- }
- }
- }
-
- if (bAcquiredLock) {
- if (bFileLockAcquired)
- lockFlags |= FLAG_FILE_UPDATE_OIN;
-
- tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, pLockResource, bh, inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_put_lockres (pLockResource);
- }
-
- if (bh != NULL)
- LOG_TRACE_ARGS("bh->b_count = %d\n",
- atomic_read(&(bh->b_count)));
- if (bh != NULL)
- brelse(bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_extend_file */
-
-/*
- * ocfs_setattr()
- *
- */
-int ocfs_setattr (struct dentry *dentry, struct iattr *attr)
-{
- struct inode *parentInode;
- struct inode *inode = dentry->d_inode;
- int error = 0;
- __u64 newsize;
- int status;
- ocfs_inode *oin = NULL;
- ocfs_super *osb = NULL;
- __u64 parentOff, fileOff;
- struct super_block *sb = inode->i_sb;
- bool extended = false;
-
- LOG_ENTRY_ARGS ("(0x%08x, '%*s')\n", dentry,
- dentry->d_name.len, dentry->d_name.name);
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(inode->i_sb);
-
- if (!dentry->d_parent || !dentry->d_parent->d_inode) {
- LOG_ERROR_STR ("bad inode or root inode");
- goto bail2;
- }
- if (dentry == inode->i_sb->s_root) {
- LOG_ERROR_STR("changes to root inode not allowed");
- goto bail2;
- }
-
- parentInode = dentry->d_parent->d_inode;
- atomic_inc (&parentInode->i_count);
- newsize = attr->ia_size;
-
- if (attr->ia_valid & ATTR_MODE)
- LOG_TRACE_ARGS ("mode change: %d\n", attr->ia_mode);
- if (attr->ia_valid & ATTR_UID)
- LOG_TRACE_ARGS ("uid change: %d\n", attr->ia_uid);
- if (attr->ia_valid & ATTR_GID)
- LOG_TRACE_ARGS ("gid change: %d\n", attr->ia_gid);
- if (attr->ia_valid & ATTR_SIZE)
- LOG_TRACE_STR ("size change...");
- if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME))
- LOG_TRACE_STR ("time change...");
-
- if (!(attr->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_CTIME |
- ATTR_SIZE | ATTR_GID | ATTR_UID | ATTR_MODE))) {
- LOG_TRACE_STR
- ("can only change mode, uid, gid, size and time. exiting!");
- goto bail;
- }
-
- error = inode_change_ok (inode, attr);
- if (error)
- goto bail;
-
- /* get the file and parent offsets, and the file oin if present */
- if (!ocfs_linux_get_inode_offset (inode, &fileOff, &oin) ||
- !ocfs_linux_get_inode_offset (parentInode, &parentOff, NULL)) {
- LOG_ERROR_STR ("error getting inode offset");
- goto bail;
- }
-
- if (attr->ia_valid & ATTR_SIZE) {
- if (oin != NULL) {
- ocfs_down_sem (&(oin->main_res), true);
- if (OIN_NEEDS_VERIFICATION (oin)) {
- LOG_TRACE_STR ("OIN_NEEDS_VERIFICATION");
- status = ocfs_verify_update_oin (osb, oin);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- LOG_TRACE_STR ("TODO: disable volume");
- ocfs_up_sem (&(oin->main_res));
- error = -EIO;
- goto bail;
- }
- }
- ocfs_up_sem (&(oin->main_res));
- }
-
- if (inode->i_size > newsize)
- status = ocfs_truncate_file(osb, fileOff, newsize,
- oin, inode);
- else {
- status = ocfs_extend_file(osb, parentOff, oin, newsize,
- &fileOff, NULL, inode, attr);
- extended = true;
- }
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- error = -ENOSPC;
- goto bail;
- }
-
- if (oin != NULL) {
- ocfs_down_sem (&(oin->main_res), true);
- if (inode->i_size > newsize) {
- ocfs_delete_all_extent_maps(oin);
- }
- inode->i_size = newsize;
- inode->i_blocks = (newsize + sb->s_blocksize) >> sb->s_blocksize_bits;
- ocfs_up_sem (&(oin->main_res));
- }
- }
-
- /* if directory, put FILE_ENTRY ptr into fileOff */
- if (S_ISDIR (inode->i_mode))
- ocfs_linux_get_dir_entry_offset(osb, &fileOff, parentOff,
- &(dentry->d_name), NULL,
- parentInode);
-
- status = -EFAIL;
- if ((fileOff != -1) && !extended) {
- status = ocfs_change_file_attrib(osb, parentOff, NULL, newsize,
- &fileOff, attr, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- error = -EIO;
- goto bail;
- }
- }
- inode_setattr (inode, attr);
-
-bail:
- atomic_dec (&parentInode->i_count);
-bail2:
- LOG_EXIT_LONG (error);
- return error;
-} /* ocfs_setattr */
-
-#ifdef LINUX_2_5
-/*
- * ocfs_getattr() (Linux 2.5 version)
- *
- */
-int ocfs_getattr (struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
- struct inode *inode;
- struct super_block *sb;
- ocfs_super *osb;
- int err = -1;
-
- LOG_ENTRY();
-
- if (!dentry || !stat)
- goto bail;
-
- inode = dentry->d_inode;
- if (!inode)
- goto bail;
- sb = dentry->d_inode->i_sb;
- osb = ((ocfs_super *) sb->s_fs_info);
-
- stat->dev = inode->i_sb->s_dev;
- stat->ino = inode->i_ino;
- stat->mode = inode->i_mode;
- stat->nlink = inode->i_nlink;
- stat->uid = inode->i_uid;
- stat->gid = inode->i_gid;
- stat->rdev = kdev_t_to_nr(inode->i_rdev);
- stat->atime = inode->i_atime;
- stat->mtime = inode->i_mtime;
- stat->ctime = inode->i_ctime;
- stat->size = inode->i_size;
- stat->blocks = inode->i_blocks;
-
- /* We set the blksize from the cluster size for performance */
- stat->blksize = (__u32) osb->vol_layout.cluster_size;
-
- err = 0;
-bail:
- LOG_EXIT_LONG (err);
- return err;
-} /* ocfs_getattr */
-
-#else
-/*
- * ocfs_getattr()
- *
- */
-int ocfs_getattr (struct dentry *dentry, struct iattr *attr)
-{
- ocfs_inode *oin;
- struct inode *inode;
- struct super_block *sb = dentry->d_inode->i_sb;
- int status;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", dentry, attr,
- dentry->d_name.len, dentry->d_name.name);
-
- inode = dentry->d_inode;
- if (inode == NULL || !inode_data_is_oin (inode))
- goto bail;
- oin = GET_INODE_OIN(inode);
- if (oin == ((ocfs_super *)(OCFS_GENERIC_SB_P(sb)))->oin_root_dir)
- goto bail;
- if (oin != NULL) {
- ocfs_down_sem (&(oin->main_res), true);
- status = ocfs_verify_update_oin (oin->osb, oin);
- ocfs_up_sem (&(oin->main_res));
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
-bail:
- LOG_EXIT_LONG (0);
- return 0;
-} /* ocfs_getattr */
-#endif
-
Deleted: trunk/hash.c
===================================================================
--- trunk/hash.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/hash.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,623 +0,0 @@
-/*
- * ocfshash.c
- *
- * Allows for creation and destruction of a hash table which one
- * can use to read, write and delete data.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_HASH
-
-
-/*
- * ocfs_insert_sector_node()
- *
- */
-int ocfs_insert_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res, ocfs_lock_res ** found_lock_res)
-{
- int status = 0;
- __u32 tmp;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", osb, lock_res);
-
- if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
- LOG_TRACE_STATUS (status = -EFAIL);
- goto bail;
- }
-
- if (lock_res->signature != 0x55AA) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- if (!ocfs_hash_add (&(osb->root_sect_node), &(lock_res->sector_num),
- sizeof (__u64), lock_res, sizeof (ocfs_lock_res *),
- (void **)found_lock_res, &tmp)) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto bail;
- }
-
- if (*found_lock_res) {
- ocfs_get_lockres (*found_lock_res);
- LOG_TRACE_ARGS ("isn: fres=0x%08x, ref=%d, lid=%u.%u\n",
- *found_lock_res,
- atomic_read (&((*found_lock_res)->lr_ref_cnt)),
- HILO((*found_lock_res)->sector_num));
- }
- else {
- ocfs_get_lockres (lock_res);
- LOG_TRACE_ARGS ("isn: lres=0x%08x, ref=%d, lid=%u.%u\n", lock_res,
- atomic_read (&lock_res->lr_ref_cnt),
- HILO(lock_res->sector_num));
- }
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_insert_sector_node */
-
-/*
- * ocfs_lookup_sector_node()
- *
- */
-int ocfs_lookup_sector_node (ocfs_super * osb, __u64 lock_id, ocfs_lock_res ** lock_res)
-{
- int status = 0;
- __u32 len = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, 0x%08x)\n", osb, HI (lock_id),
- LO (lock_id), lock_res);
-
- if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
- status = -EFAIL;
- LOG_TRACE_STATUS(status);
- goto bail;
- }
-
- if (ocfs_hash_get (&(osb->root_sect_node), &(lock_id), sizeof (__u64),
- (void **) lock_res, &len)) {
- if (len != sizeof (ocfs_lock_res *)) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- if ((*lock_res)->signature != 0x55AA) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- ocfs_get_lockres (*lock_res);
- LOG_TRACE_ARGS ("lsn: lid=%u.%u, lres=0x%08x, ref=%d\n",
- HILO(lock_id), *lock_res,
- atomic_read (&((*lock_res)->lr_ref_cnt)));
- } else
- status = -ENOENT;
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_lookup_sector_node */
-
-/*
- * ocfs_remove_sector_node()
- *
- */
-void ocfs_remove_sector_node (ocfs_super * osb, ocfs_lock_res * lock_res)
-{
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", osb, lock_res);
-
- if (HASHTABLE_DESTROYED (&(osb->root_sect_node))) {
- LOG_TRACE_STATUS (-EFAIL);
- goto bail;
- }
-
- if (lock_res->signature != 0x55AA) {
- LOG_ERROR_STATUS (-EFAIL);
- goto bail;
- }
-
- LOG_TRACE_ARGS ("rsn: lres=0x%08x, ref=%d, lid=%u.%u\n", lock_res,
- atomic_read (&lock_res->lr_ref_cnt),
- HILO(lock_res->sector_num));
-
- ocfs_hash_del (&(osb->root_sect_node), &(lock_res->sector_num),
- sizeof (__u64));
-
- ocfs_put_lockres (lock_res);
-
- bail:
- LOG_EXIT ();
- return ;
-} /* ocfs_remove_sector_node */
-
-
-/*
- * ocfs_hash_create()
- *
- */
-int ocfs_hash_create (HASHTABLE *ht, __u32 noofbits)
-{
- int ret = 0;
- __u32 size = 0;
-
- LOG_ENTRY ();
-
- if (noofbits > 32 || noofbits < 1) {
- LOG_ERROR_STR ("Error in noofbits");
- goto bail;
- }
-
- ht->size = hashsize (noofbits);
- ht->mask = hashmask (noofbits);
- ht->inithash = 0x10325476;
- ht->entries = 0;
- ht->newbuckets = 0;
- ht->reusedbuckets = 0;
- ht->freelist = NULL;
- ht->lastfree = NULL;
-
- ocfs_init_sem (&(ht->hashlock));
-
- size = ht->size * sizeof (HASHBUCKET);
- ht->buckets = (HASHBUCKET *) ocfs_malloc (size);
- if (!ht->buckets) {
- LOG_ERROR_ARGS ("unable to allocate %u bytes of memory", size);
- goto bail;
- }
-
- memset (ht->buckets, 0, (ht->size * sizeof (HASHBUCKET)));
- ret = 1;
-
- bail:
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_hash_create */
-
-/*
- * ocfs_hash_destroy()
- *
- * @ht: ptr to the hash table
- * @freefn: if not null, uses function to free bucket->val
- *
- */
-void ocfs_hash_destroy (HASHTABLE *ht, void (*freefn) (const void *p))
-{
- HASHBUCKET *bucket;
- HASHBUCKET *nxtbucket;
- __u32 slot;
-
- LOG_ENTRY ();
-
- if (!ht || !ht->buckets)
- goto bail;
-
- if (ht->buckets) {
- for (slot = 0; slot < ht->size; slot++) {
- if (freefn) {
- bucket = &(ht->buckets[slot]);
- if (bucket->key && bucket->val)
- freefn (bucket->val);
- }
-
- bucket = ht->buckets[slot].next;
- while (bucket) {
- if (freefn && bucket->key && bucket->val)
- freefn (bucket->val);
- nxtbucket = bucket->next;
- ocfs_safefree (bucket);
- bucket = nxtbucket;
- }
- }
- }
-
- bucket = ht->freelist;
- while (bucket) {
- nxtbucket = bucket->next;
- ocfs_safefree (bucket);
- bucket = nxtbucket;
- }
-
- ocfs_safefree (ht->buckets);
- ht->buckets = NULL;
-
- bail:
- LOG_EXIT ();
- return;
-} /* ocfs_hash_destroy */
-
-/*
- * ocfs_hash_add()
- *
- * @ht: ptr to the hash table
- * @key: key
- * @keylen: length of key
- * @val: value
- * @vallen: length of value
- *
- */
-int ocfs_hash_add (HASHTABLE * ht, void *key, __u32 keylen, void *val, __u32 vallen, void **found, __u32 *foundlen)
-{
- HASHBUCKET *bucket;
- HASHBUCKET *prvbucket = NULL;
- HASHBUCKET *lastbucket;
- __u32 slot;
- int ret = 1;
- int lockacqrd = false;
-
- LOG_ENTRY ();
-
- if (!ht || !ht->buckets) {
- ret = 0;
- goto bail;
- }
-
- *found = NULL;
- *foundlen = 0;
-
- slot = hash (key, keylen, ht->inithash) & ht->mask;
- bucket = &(ht->buckets[slot]);
-
- /* Acquire Lock */
- ocfs_down_sem (&(ht->hashlock), true);
- lockacqrd = true;
-
- while (bucket) {
- if (bucket->key) {
- if (!memcmp (bucket->key, key, keylen)) {
- /* return warning & val if key already exists */
- LOG_TRACE_STR ("Duplicate key");
- *found = bucket->val;
- *foundlen = bucket->vallen;
- ret = 2;
- goto bail;
- }
- } else {
- /* Fill the empty bucket */
- bucket->key = key;
- bucket->keylen = keylen;
- bucket->val = val;
- bucket->vallen = vallen;
-
- /* Increment the number of entries */
- ht->entries++;
- ret = 1;
- goto bail;
- }
- prvbucket = bucket;
- bucket = bucket->next;
- }
-
- /* Save the last bucket for this slot */
- lastbucket = prvbucket;
-
- /* Check if any bucket in freelist ... */
- if (ht->freelist) {
- /* ... if so, attach it to the end of the slot list ... */
- lastbucket->next = bucket = ht->freelist;
-
- /* ... and detach it from the freelist */
- if (ht->lastfree == ht->freelist)
- ht->freelist = ht->lastfree = NULL;
- else
- ht->freelist = ht->freelist->next;
-
- /* Fill the empty bucket */
- bucket->key = key;
- bucket->keylen = keylen;
- bucket->val = val;
- bucket->vallen = vallen;
- bucket->next = NULL;
- ht->reusedbuckets++;
-
- /* Increment the number of entries */
- ht->entries++;
- ret = 1;
- goto bail;
- }
-
- /* Create a new bucket and add to the end of list */
- if ((bucket = (HASHBUCKET *) ocfs_malloc (sizeof (HASHBUCKET))) == NULL) {
- LOG_ERROR_ARGS ("unable to allocate %u bytes of memory",
- sizeof (HASHBUCKET));
- ret = 0;
- goto bail;
- }
-
- bucket->key = key;
- bucket->keylen = keylen;
- bucket->val = val;
- bucket->vallen = vallen;
- bucket->next = NULL;
- lastbucket->next = bucket;
- ht->newbuckets++;
-
- /* Increment the number of entries */
- ht->entries++;
-
- bail:
- /* Release Lock */
- if (lockacqrd)
- ocfs_up_sem (&(ht->hashlock));
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_hash_add */
-
-/*
- * ocfs_hash_del()
- *
- * @ht: ptr to hash table
- * @key: key to be deleted
- * @keylen: length of key
- *
- */
-int ocfs_hash_del (HASHTABLE * ht, void *key, __u32 keylen)
-{
- HASHBUCKET *bucket;
- HASHBUCKET *prvbucket = NULL;
- __u32 slot;
- int ret = 0;
- int lockacqrd = false;
-
- LOG_ENTRY ();
-
- if (!ht || !ht->buckets)
- goto bail;
-
- slot = hash (key, keylen, ht->inithash) & ht->mask;
- bucket = &(ht->buckets[slot]);
-
- /* Acquire Lock */
- ocfs_down_sem (&(ht->hashlock), true);
- lockacqrd = true;
-
- while (bucket) {
- if (bucket->key) {
- if (!memcmp (bucket->key, key, keylen)) {
- /* Found it */
- if (!prvbucket) {
- /* If first bucket, clear it */
- bucket->key = NULL;
- } else {
- /* If not first bucket, detach the bucket from list ... */
- prvbucket->next = bucket->next;
-
- /* ... clear it ... */
- bucket->key = NULL;
- bucket->next = NULL;
-
- /* ... and attach to the end of the free list */
- if (ht->lastfree) {
- ht->lastfree->next = bucket;
- ht->lastfree = bucket;
- } else {
- ht->lastfree = ht->freelist =
- bucket;
- }
- }
- /* Decrement the number of entries and exit */
- ht->entries--;
- ret = 1;
- goto bail;
- }
- }
- prvbucket = bucket;
- bucket = bucket->next;
- }
-
- bail:
- /* Release Lock */
- if (lockacqrd)
- ocfs_up_sem (&(ht->hashlock));
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_hash_del */
-
-/*
- * ocfs_hash_get()
- *
- */
-int ocfs_hash_get (HASHTABLE * ht, void *key, __u32 keylen, void **val, __u32 * vallen)
-{
- HASHBUCKET *bucket;
- __u32 slot;
- int ret = 0;
- int lockacqrd = false;
-
- LOG_ENTRY ();
-
- if (!ht || !ht->buckets)
- goto bail;
-
- slot = hash (key, keylen, ht->inithash) & ht->mask;
- bucket = &(ht->buckets[slot]);
-
- /* Acquire Lock */
- ocfs_down_sem (&(ht->hashlock), true);
- lockacqrd = true;
-
- while (bucket) {
- if (bucket->key) {
- if (!memcmp (bucket->key, key, keylen)) {
- /* found it */
- *val = bucket->val;
- *vallen = bucket->vallen;
- ret = 1;
- goto bail;
- }
- }
- bucket = bucket->next;
- }
-
- bail:
- /* Release Lock */
- if (lockacqrd)
- ocfs_up_sem (&(ht->hashlock));
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_hash_get */
-
-/*
- * ocfs_hash_stat()
- *
- */
-void ocfs_hash_stat (HASHTABLE * ht, char *data, __u32 datalen)
-{
- HASHBUCKET *bucket;
- __u32 slot;
- __u32 i;
- char *p;
- __u32 len = 0;
- __u32 stats[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- int lockacqrd = false;
-
- LOG_ENTRY ();
-
- if (!ht || !ht->buckets)
- goto bail;
-
- if (!data || !datalen)
- goto bail;
-
- /* Acquire Lock */
- ocfs_down_sem (&(ht->hashlock), true);
- lockacqrd = true;
-
- for (slot = 0; slot < ht->size; ++slot) {
- bucket = &(ht->buckets[slot]);
- i = 0;
-
- while (bucket) {
- if (bucket->key)
- ++i;
- bucket = bucket->next;
- }
-
- if (i < 9)
- stats[i]++;
- else
- stats[9]++;
- }
-
- for (i = 0, p = data; i < 10; ++i, p += len)
- len = sprintf (p, "%2u: %u\n", i, stats[i]);
-
- sprintf (p, "New: %u, Reused: %u\n", ht->newbuckets, ht->reusedbuckets);
-
- data[datalen - 1] = '\0';
-
- bail:
- /* Release Lock */
- if (lockacqrd)
- ocfs_up_sem (&(ht->hashlock));
-
- LOG_EXIT ();
- return;
-} /* ocfs_hash_stat */
-
-/*
- * --------------------------------------------------------------------
- * hash() -- hash a variable-length key into a 32-bit value
- * k : the key (the unaligned variable-length array of bytes)
- * len : the length of the key, counting by bytes
- * initval : can be any 4-byte value
- *
- * Returns a 32-bit value. Every bit of the key affects every bit of
- * the return value. Every 1-bit and 2-bit delta achieves avalanche.
- * About 6*len+35 instructions.
- *
- * The best hash table sizes are powers of 2. There is no need to do
- * mod a prime (mod is sooo slow!). If you need less than 32 bits,
- * use a bitmask. For example, if you need only 10 bits, do
- * h = (h & hashmask(10));
- * In which case, the hash table should have hashsize(10) elements.
- *
- * If you are hashing n strings (__u8 **)k, do it like this:
- * for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
- *
- * By Bob Jenkins, 1996. bob_jenkins at burtleburtle.net. You may use this
- * code any way you wish, private, educational, or commercial. It's free.
- *
- * See http://burtleburtle.net/bob/hash/evahash.html
- * Use for hash table lookup, or anything where one collision in 2^^32 is
- * acceptable. Do NOT use for cryptographic purposes.
- * --------------------------------------------------------------------
- */
-__u32 hash (register __u8 *k, register __u32 length, register __u32 initval)
-{
- register __u32 a, b, c, len;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = initval; /* the previous hash value */
-
- /*---------------------------------------- handle most of the key */
- while (len >= 12) {
- a += (k[0] + ((__u32) k[1] << 8) + ((__u32) k[2] << 16) +
- ((__u32) k[3] << 24));
- b += (k[4] + ((__u32) k[5] << 8) + ((__u32) k[6] << 16) +
- ((__u32) k[7] << 24));
- c += (k[8] + ((__u32) k[9] << 8) + ((__u32) k[10] << 16) +
- ((__u32) k[11] << 24));
- mix (a, b, c);
- k += 12;
- len -= 12;
- }
-
- /*------------------------------------- handle the last 11 bytes */
- c += length;
- switch (len) { /* all the case statements fall through */
- case 11:
- c += ((__u32) k[10] << 24);
- case 10:
- c += ((__u32) k[9] << 16);
- case 9:
- c += ((__u32) k[8] << 8);
- /* the first byte of c is reserved for the length */
- case 8:
- b += ((__u32) k[7] << 24);
- case 7:
- b += ((__u32) k[6] << 16);
- case 6:
- b += ((__u32) k[5] << 8);
- case 5:
- b += k[4];
- case 4:
- a += ((__u32) k[3] << 24);
- case 3:
- a += ((__u32) k[2] << 16);
- case 2:
- a += ((__u32) k[1] << 8);
- case 1:
- a += k[0];
- /* case 0: nothing left to add */
- }
- mix (a, b, c);
- /*-------------------------------------------- report the result */
- return c;
-} /* hash */
Deleted: trunk/heartbeat.c
===================================================================
--- trunk/heartbeat.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/heartbeat.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,244 +0,0 @@
-/*
- * ocfsheartbeat.c
- *
- * Keeps track of alive nodes in the cluster.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#if !defined(USERSPACE_TOOL)
-#include <ocfs.h>
-#endif
-
-#if defined(USERSPACE_TOOL)
-#include <format.h>
-#endif
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_HEARTBEAT
-
-#if !defined(USERSPACE_TOOL)
-/*
- * ocfs_nm_heart_beat()
- *
- * @osb: ocfs super block for the volume
- * @flag: type of heart beat
- * @read_publish: if the publish sector needs to be re-read
- *
- * Updates the timestamp in the nodes publish sector.
- * NOTE: must be called while holding publish_lock!
- *
- * Returns 0 if success, < 0 if error.
- */
-int ocfs_nm_heart_beat (ocfs_super * osb, __u32 flag, bool read_publish)
-{
- int status = 0;
- ocfs_publish *publish = NULL;
- int publish_idx = OCFS_VOLCFG_NEWCFG_SECTORS + osb->node_num;
- struct buffer_head **pub_bh = &osb->cfg_bhs[publish_idx];
- __u64 node_publ_off = osb->vol_layout.publ_sect_off + (osb->node_num * osb->sect_size);
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, %s)\n", osb, flag,
- read_publish ? "true" : "false");
-
- if (flag & HEARTBEAT_METHOD_DISK) {
- if (pub_bh == NULL && !read_publish)
- BUG();
-
- if (read_publish) {
- status = ocfs_read_bh(osb, node_publ_off, pub_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(*pub_bh);
- if ((publish->dirty) && (!osb->publish_dirty)) {
- LOG_TRACE_STR(("NMThread reads the bit as dirty"));
- publish->dirty = false;
- }
- /* Write the current time in local node's publish sector */
- OcfsQuerySystemTime (&publish->time);
- publish->hbm[osb->node_num] = osb->hbm;
- spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
- publish->comm_seq_num = OcfsGlobalCtxt.comm_seq_num;
- spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
- OCFS_BH_PUT_DATA(*pub_bh);
-
- status = ocfs_write_bh(osb, *pub_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- if (flag & HEARTBEAT_METHOD_IPC) {
- /* Plug this in later... */
- }
-
-finally:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_nm_heart_beat */
-#endif /* !defined(USERPSPACE_TOOL) */
-
-
-/*
- * ocfs_update_publish_map()
- *
- * @osb: ocfs super block for the volume
- * @buffer: publish sectors read in the last round
- * @first_time: if true, the buffer needs to be initialized
- *
- * Reads the publish sectors and compares the timestamp of each node
- * to the one it read in the last round. As long as the timestamp keeps
- * changing, the node is marked alive. Conversely, if the timestamp does
- * not change over time, the node is marked dead. The function marks all
- * the live nodes in the publishmap.
- *
- */
-void ocfs_update_publish_map (ocfs_super * osb, struct buffer_head *bhs[], bool first_time)
-{
- ocfs_publish *publish;
- ocfs_vol_node_map *node_map;
- __u64 curr_time = 0;
- __u32 i;
- __u32 num_nodes;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u)\n", osb, bhs, first_time);
-
- num_nodes = OCFS_MAXIMUM_NODES;
- node_map = &(osb->vol_node_map);
-#if !defined(USERSPACE_TOOL)
- OcfsQuerySystemTime (&curr_time);
-#endif
-
- /* First time thru, update buffer with timestamps for all nodes */
- if (first_time) {
-#if !defined(USERSPACE_TOOL)
- /* Read the last comm_seq_num */
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(bhs[osb->node_num]);
- spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
- OcfsGlobalCtxt.comm_seq_num = publish->comm_seq_num + 10;
- spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
- OCFS_BH_PUT_DATA(bhs[osb->node_num]);
-#endif
- /* Refresh local buffers */
- for (i = 0; i < num_nodes; i++) {
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(bhs[i]);
- node_map->time[i] = publish->time;
- node_map->scan_rate[i] = publish->hbm[i];
- node_map->scan_time[i] = curr_time;
- if (publish->mounted && i != osb->node_num) {
- printk("ocfs: Adding %s (node %d) to "
- "clustered device (%u,%u)\n",
- osb->node_cfg_info[i]->node_name, i,
- MAJOR(osb->sb->s_dev),
- MINOR(osb->sb->s_dev));
- node_map->miss_cnt[i] = 0;
- node_map->time[i] = publish->time;
- UPDATE_PUBLISH_MAP(osb->publ_map, i,
- OCFS_PUBLISH_SET,
- num_nodes);
- }
- OCFS_BH_PUT_DATA(bhs[i]);
- }
- goto bail; /* exit */
- }
-
- for (i = 0; i < num_nodes; i++) {
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(bhs[i]);
-
- /* Loop if slot is unused */
- if (publish->time == (__u64) 0) {
- OCFS_BH_PUT_DATA(bhs[i]);
- continue;
- }
-
- /* Check if the node is hung or not by comparing the disk */
- /* and memory timestamp values */
- if (node_map->time[i] == publish->time) {
- if (IS_NODE_ALIVE(osb->publ_map, i, num_nodes)) {
- if (atomic_read (&(node_map->dismount[i]))) {
- node_map->miss_cnt[i] = MISS_COUNT_VALUE;
- atomic_set (&(node_map->dismount[i]), 0);
- UPDATE_PUBLISH_MAP (osb->publ_map, i,
- OCFS_PUBLISH_CLEAR,
- num_nodes);
- } else
- (node_map->miss_cnt[i])++;
- if (node_map->miss_cnt[i] > MISS_COUNT_VALUE) {
-#if !defined(USERSPACE_TOOL)
- printk ("ocfs: Removing %s (node %d) "
- "from clustered device (%u,%u)\n",
- osb->node_cfg_info[i]->node_name, i,
- MAJOR(osb->sb->s_dev),
- MINOR(osb->sb->s_dev));
-#endif
-
- SET_NODE_IN_RECOVERY(osb, i);
- UPDATE_PUBLISH_MAP (osb->publ_map, i,
- OCFS_PUBLISH_CLEAR, num_nodes);
-
- /* Ok, we'd better recover him now...*/
- ocfs_recovery_thread(osb, i);
- }
- }
- } else {
-#if !defined(USERSPACE_TOOL)
- if (!IS_NODE_ALIVE(osb->publ_map, i, num_nodes) && osb->node_num != i)
- printk ("ocfs: Adding %s (node %d) to clustered device (%u,%u)\n",
- osb->node_cfg_info[i]->node_name, i,
- MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
-#endif
- node_map->miss_cnt[i] = 0;
- node_map->time[i] = publish->time;
- UPDATE_PUBLISH_MAP (osb->publ_map, i, OCFS_PUBLISH_SET,
- num_nodes);
-
-#if !defined(USERSPACE_TOOL)
- /* Update the multiple the other node wants us to beat */
- if ((publish->hbm[osb->node_num] != DISK_HBEAT_INVALID)
- && (osb->hbm > publish->hbm[osb->node_num])) {
- /* Go to the lowest multiplier any of the nodes */
- /* alive want us to heartbeat with. */
- osb->hbm = publish->hbm[osb->node_num];
-
- if (osb->hbm == 0)
- osb->hbm = DISK_HBEAT_NO_COMM;
-
- if (OcfsGlobalCtxt.hbm > osb->hbm)
- OcfsGlobalCtxt.hbm = osb->hbm;
-
- if (OcfsGlobalCtxt.hbm == 0)
- OcfsGlobalCtxt.hbm = DISK_HBEAT_NO_COMM;
- }
-#endif
- }
- node_map->scan_time[i] = curr_time;
- OCFS_BH_PUT_DATA(bhs[i]);
- }
-
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_update_publish_map */
Deleted: trunk/inode.c
===================================================================
--- trunk/inode.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/inode.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1635 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-
-static int ocfs_readpage (struct file *file, struct page *page);
-static int ocfs_writepage (struct page *page);
-static int ocfs_prepare_write (struct file *file, struct page *page, unsigned from, unsigned to);
-static int ocfs_commit_write (struct file *file, struct page *page, unsigned from, unsigned to);
-static int ocfs_get_block (struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create);
-static int ocfs_get_block2 (struct inode *inode, long iblock, long *oblock, int len);
-static int ocfs_extend_allocation(ocfs_super *osb, ocfs_inode *oin, __u64 newsize, bool unlock, struct inode *inode);
-static int ocfs_symlink_get_block (struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create);
-static int ocfs_bmap(struct address_space *mapping, long block);
-
-
-#ifdef LINUX_2_5
-static int ocfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs);
-#elif LINUX_VERSION_CODE >= LinuxVersionCode(2,4,10)
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,20) || defined(SUSE)
-static int ocfs_direct_IO (int rw, struct file *filp, struct kiobuf *iobuf, unsigned long blocknr, int blocksize);
-#else
-static int ocfs_direct_IO (int rw, struct inode *inode, struct kiobuf *iobuf, unsigned long blocknr, int blocksize);
-#endif
-#endif /* version >= 2.4.10 */
-
-
-static struct address_space_operations ocfs_aops = {
- .readpage = ocfs_readpage,
- .writepage = ocfs_writepage,
- .prepare_write = ocfs_prepare_write,
- .bmap = ocfs_bmap,
- .commit_write = ocfs_commit_write,
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,10)
-/*
-* we are only adding this here as a dummy basically, just need open with O_DIRECT
-* to succeed, we still call ocfs_rw_direct()
-*/
- .direct_IO = ocfs_direct_IO
-#endif
-};
-
-static struct file_operations ocfs_fops = {
- .read = ocfs_file_read,
- .write = ocfs_file_write,
- .mmap = generic_file_mmap,
- .fsync = ocfs_sync_file,
- .flush = ocfs_flush,
- .release = ocfs_file_release,
- .open = ocfs_file_open,
- .ioctl = ocfs_ioctl,
-#ifdef AIO_ENABLED
- .kvec_read = ocfs_kvec_read,
- .kvec_write = ocfs_kvec_write,
- .aio_read = generic_file_aio_read,
- .aio_write = generic_file_aio_write,
-#endif
-};
-
-static struct file_operations ocfs_dops = {
- .read = generic_read_dir,
- .readdir = ocfs_readdir,
- .fsync = ocfs_sync_file,
- .release = ocfs_file_release,
- .ioctl = ocfs_ioctl
-};
-
-static struct inode_operations ocfs_dir_iops = {
- .create = ocfs_create,
- .lookup = ocfs_lookup,
- .link = ocfs_link,
- .unlink = ocfs_unlink,
- .rmdir = ocfs_unlink,
- .symlink = ocfs_symlink,
- .mkdir = ocfs_mkdir,
- .mknod = ocfs_mknod,
- .rename = ocfs_rename,
- .setattr = ocfs_setattr,
- .getattr = ocfs_getattr,
-};
-
-static struct inode_operations ocfs_file_iops = {
- .setattr = ocfs_setattr,
- .getattr = ocfs_getattr,
-};
-
-struct inode_operations ocfs_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: ocfs_follow_link
-};
-
-
-/*
- * here's how inodes get read from disk:
- * iget4 -> find_inode -> OCFS_FIND_INODE
- * found? : return the in-memory inode
- * not found? : get_new_inode -> OCFS_READ_INODE2
- */
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
-
-#define REPOPULATE_INODE 1
-
-/*
- * ocfs_find_inode()
- *
- * This is the iget4 helper function
- */
-int ocfs_find_inode (struct inode *inode, unsigned long ino, void *opaque)
-{
- ocfs_find_inode_args *args = NULL;
- ocfs_inode *oin;
- int ret = 0;
- __u64 fileOff;
- mode_t mode;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, 0x%08x)\n", inode, ino, opaque);
-
- if (opaque == NULL || inode == NULL)
- goto bail;
- args = (ocfs_find_inode_args *) opaque;
-
- if (ino != inode->i_ino) {
- goto bail;
- }
-
- if (!ocfs_linux_get_inode_offset (inode, &fileOff, NULL)) {
- LOG_TRACE_STR ("error getting inode offset");
- goto bail;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(args->fe_bh);
- if (S_ISDIR (inode->i_mode)) {
- LOG_TRACE_STR ("find_inode -> S_ISDIR");
- if (fe->extents[0].disk_off != fileOff) {
- LOG_TRACE_ARGS
- ("DIR : inode number same but full offset does not match: %u.%u != %u.%u\n",
- fe->extents[0].disk_off, fileOff);
- goto bail;
- }
- } else if (args->offset != fileOff) {
- LOG_TRACE_ARGS
- ("FILE : inode number same but full offset does not match: %u.%u != %u.%u\n",
- args->offset, fileOff);
- goto bail;
- }
-
-#ifdef REPOPULATE_INODE
- /* not sure if this is appropriate, but we have the most
- * current file entry so why not use it? */
- mode = fe->prot_bits;
-
- switch (fe->attribs) {
- case OCFS_ATTRIB_DIRECTORY:
- mode |= S_IFDIR;
- break;
- case OCFS_ATTRIB_CHAR:
- mode |= S_IFCHR;
- inode->i_rdev = MKDEV (fe->dev_major, fe->dev_minor);
- break;
- case OCFS_ATTRIB_BLOCK:
- mode |= S_IFBLK;
- inode->i_rdev = MKDEV (fe->dev_major, fe->dev_minor);
- break;
- case OCFS_ATTRIB_FIFO:
- mode |= S_IFIFO;
- break;
- case OCFS_ATTRIB_SYMLINK:
- mode |= S_IFLNK;
- break;
- case OCFS_ATTRIB_SOCKET:
- mode |= S_IFSOCK;
- break;
- case OCFS_ATTRIB_REG:
- default:
- mode |= S_IFREG;
- break;
- }
- oin = NULL; /* set it back to our current OIN if we have one */
- if (inode_data_is_oin (inode))
- oin = ((ocfs_inode *)inode->u.generic_ip);
- ocfs_populate_inode (inode, fe, mode, oin);
-#endif /* REPOPULATE_INODE */
-
- ret = 1;
-bail:
- if (fe)
- OCFS_BH_PUT_DATA(args->fe_bh);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_find_inode */
-#endif /* LINUX_VERSION_CODE < LinuxVersionCode(2,5,0) */
-
-
-/*
- * ocfs_populate_inode()
- *
- */
-void ocfs_populate_inode (struct inode *inode, ocfs_file_entry *fe, umode_t mode, void *genptr)
-{
- struct super_block *sb;
- ocfs_super *osb;
- __u64 offset;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, size:%u)\n", inode, mode, fe->file_size);
-
- sb = inode->i_sb;
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
- offset = S_ISDIR (mode) ? fe->extents[0].disk_off : fe->this_sector;
-
- OCFS_SET_INODE_DEV(sb, inode);
- inode->i_mode = mode;
- inode->i_uid = fe->uid;
- inode->i_gid = fe->gid;
- inode->i_blksize = (__u32) osb->vol_layout.cluster_size; // sb->s_blocksize;
- inode->i_blocks = (fe->file_size + sb->s_blocksize) >> sb->s_blocksize_bits;
- inode->i_mapping->a_ops = &ocfs_aops;
- inode->i_attr_flags |= ATTR_FLAG_NOATIME;
- inode->i_flags |= S_NOATIME;
- OCFS_SET_INODE_TIME(inode, i_atime, fe->modify_time);
- OCFS_SET_INODE_TIME(inode, i_mtime, fe->modify_time);
- OCFS_SET_INODE_TIME(inode, i_ctime, fe->create_time);
- if (genptr)
- SET_INODE_OIN (inode, genptr);
- else
- SET_INODE_OFFSET (inode, offset);
-
- switch (inode->i_mode & S_IFMT) {
- case S_IFREG:
- atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
- inode->i_fop = &ocfs_fops;
- inode->i_op = &ocfs_file_iops;
- inode->i_size = fe->file_size;
- break;
- case S_IFDIR:
- atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
- inode->i_op = &ocfs_dir_iops;
- inode->i_fop = &ocfs_dops;
- inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
- break;
- case S_IFLNK:
- atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
- inode->i_op = &ocfs_symlink_inode_operations;
- //inode->i_fop = &ocfs_fops;
- inode->i_size = fe->file_size;
- break;
- default:
-#ifdef LINUX_2_5
- init_special_inode (inode, mode, inode->i_rdev.value);
-#else
- init_special_inode (inode, mode, inode->i_rdev);
-#endif
- break;
- }
-
- LOG_EXIT ();
- return;
-} /* ocfs_populate_inode */
-
-#ifdef LINUX_2_5
-/*
- * ocfs_read_locked_inode()
- *
- * by this point, i_sb, i_dev, i_ino are filled in
- *
- */
-static void ocfs_read_locked_inode (struct inode *inode,
- ocfs_file_entry *entry)
-{
- struct super_block *sb;
- ocfs_super *osb;
- ocfs_inode *newoin;
- umode_t mode;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", inode, entry);
-
- if (inode == NULL || inode->i_sb == NULL) {
- LOG_ERROR_STR ("bad inode");
- goto bail;
- }
- sb = inode->i_sb;
- osb = ((ocfs_super *)(sb->s_fs_info));
- LOG_TRACE_ARGS("osb = %x\n", osb);
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
- LOG_TRACE_ARGS("Populating root inode (i_ino = %lu)\n", inode->i_ino);
- inode->i_mode = S_IFDIR | osb->vol_layout.prot_bits;
- inode->i_blksize = 512; /* TODO: fix */
- inode->i_blkbits = 9;
- inode->i_blocks = 0;
- inode->i_mapping->a_ops = &ocfs_aops;
- inode->i_atime = OCFS_CURRENT_TIME;
- inode->i_mtime = OCFS_CURRENT_TIME;
- inode->i_ctime = OCFS_CURRENT_TIME;
- inode->i_attr_flags |= ATTR_FLAG_NOATIME;
- inode->i_flags |= S_NOATIME;
- inode->i_op = &ocfs_dir_iops;
- inode->i_fop = &ocfs_dops;
- inode->i_uid = osb->vol_layout.uid;
- inode->i_gid = osb->vol_layout.gid;
- SET_INODE_OIN (inode, osb->oin_root_dir);
- goto bail;
- }
-
- LOG_TRACE_ARGS("Populating non-root inode (i_ino = %lu)\n", inode->i_ino);
-
- if (entry == NULL) {
- make_bad_inode (inode);
- goto bail;
- }
-
- newoin = NULL;
-
- mode = entry->prot_bits;
-
- switch (entry->attribs) {
- case OCFS_ATTRIB_DIRECTORY:
- mode |= S_IFDIR;
- break;
- case OCFS_ATTRIB_CHAR:
- inode->i_rdev = mk_kdev (entry->dev_major, entry->dev_minor);
- mode |= S_IFCHR;
- break;
- case OCFS_ATTRIB_BLOCK:
- inode->i_rdev = mk_kdev (entry->dev_major, entry->dev_minor);
- mode |= S_IFBLK;
- break;
- case OCFS_ATTRIB_FIFO:
- mode |= S_IFIFO;
- break;
- case OCFS_ATTRIB_SYMLINK:
- mode |= S_IFLNK;
- break;
- case OCFS_ATTRIB_SOCKET:
- mode |= S_IFSOCK;
- break;
- case OCFS_ATTRIB_REG:
- default:
- mode |= S_IFREG;
- break;
- }
- ocfs_populate_inode (inode, entry, mode, newoin);
-
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_read_locked_inode */
-
-#else
-
-/*
- * ocfs_read_inode2()
- *
- * by this point, i_sb, i_dev, i_ino are filled in
- *
- */
-void ocfs_read_inode2 (struct inode *inode, void *opaque)
-{
- struct super_block *sb;
- ocfs_find_inode_args *args = NULL;
- ocfs_super *osb;
- ocfs_inode *newoin;
- umode_t mode;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", inode, opaque);
-
- if (inode == NULL || inode->i_sb == NULL) {
- LOG_ERROR_STR ("bad inode");
- goto bail;
- }
- sb = inode->i_sb;
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
- inode->i_mode = S_IFDIR | osb->vol_layout.prot_bits;
- inode->i_blksize = (__u32) osb->vol_layout.cluster_size;
- inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
- inode->i_blocks = OCFS_DEFAULT_DIR_NODE_SIZE;
- inode->i_mapping->a_ops = &ocfs_aops;
- inode->i_atime = OCFS_CURRENT_TIME;
- inode->i_attr_flags |= ATTR_FLAG_NOATIME;
- inode->i_flags |= S_NOATIME;
- inode->i_mtime = OCFS_CURRENT_TIME;
- inode->i_ctime = OCFS_CURRENT_TIME;
- inode->i_attr_flags |= ATTR_FLAG_NOATIME;
- inode->i_flags |= S_NOATIME;
- inode->i_op = &ocfs_dir_iops;
- inode->i_fop = &ocfs_dops;
- inode->i_uid = osb->vol_layout.uid;
- inode->i_gid = osb->vol_layout.gid;
- SET_INODE_OIN (inode, osb->oin_root_dir);
- goto bail;
- }
-
- if (opaque == NULL) {
- make_bad_inode (inode);
- goto bail;
- }
-
- args = (ocfs_find_inode_args *) opaque;
- newoin = NULL;
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(args->fe_bh);
-
- mode = fe->prot_bits;
-
- switch (fe->attribs) {
- case OCFS_ATTRIB_DIRECTORY:
- mode |= S_IFDIR;
- break;
- case OCFS_ATTRIB_CHAR:
- inode->i_rdev = MKDEV (fe->dev_major, fe->dev_minor);
- mode |= S_IFCHR;
- break;
- case OCFS_ATTRIB_BLOCK:
- inode->i_rdev = MKDEV (fe->dev_major, fe->dev_minor);
- mode |= S_IFBLK;
- break;
- case OCFS_ATTRIB_FIFO:
- mode |= S_IFIFO;
- break;
- case OCFS_ATTRIB_SYMLINK:
- mode |= S_IFLNK;
- break;
- case OCFS_ATTRIB_SOCKET:
- mode |= S_IFSOCK;
- break;
- case OCFS_ATTRIB_REG:
- default:
- mode |= S_IFREG;
- break;
- }
- ocfs_populate_inode (inode, fe, mode, newoin);
-
-bail:
- if (fe)
- OCFS_BH_PUT_DATA(args->fe_bh);
- LOG_EXIT ();
- return;
-} /* ocfs_read_inode2 */
-
-/*
- * ocfs_read_inode()
- * Only used in Linux 2.4
- */
-void ocfs_read_inode (struct inode *inode)
-{
- make_bad_inode (inode);
-} /* ocfs_read_inode() */
-#endif
-
-#ifdef LINUX_2_5
-/*
- * here's how inodes get read from disk:
- * iget5_locked -> find_actor -> OCFS_FIND_ACTOR
- * found? : return the in-memory inode
- * not found? : get_new_inode -> OCFS_INIT_LOCKED_INODE
- */
-
-/*
- * ocfs_find_actor()
- *
- * This is the iget5_locked helper function. It used to be ocfs_find_inode()
- */
-int ocfs_find_actor (struct inode *inode, void *opaque)
-{
- ocfs_find_inode_args *args;
- int ret = 0;
- __u64 fileOff;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u, 0x%08x)\n", inode, inode->i_ino, opaque);
-
- /* Special Case: opaque == NULL, means we're looking for
- the root inode. We only get called like this from
- ocfs_fill_super, and therefore that inode should not exist
- yet. */
- if (opaque == NULL)
- goto bail;
- if (inode == NULL)
- goto bail;
- args = (ocfs_find_inode_args *) opaque;
-
- if (!ocfs_linux_get_inode_offset (inode, &fileOff, NULL)) {
- LOG_TRACE_STR ("could not get inode offset");
- goto bail;
- }
-
- if (S_ISDIR (inode->i_mode)) {
- LOG_TRACE_STR ("find_actor -> S_ISDIR\n");
- fe = OCFS_BH_GET_DATA(args->fe_bh);
- if (fe->extents[0].disk_off != fileOff) {
- LOG_TRACE_ARGS
- ("DIR : inode number same but full offset does not match: %u.%u != %u.%u\n",
- fe->extents[0].disk_off, fileOff);
- goto bail;
- }
- } else if (args->offset != fileOff) {
- LOG_TRACE_ARGS
- ("FILE : inode number same but full offset does not match: %u.%u != %u.%u\n",
- args->offset, fileOff);
- goto bail;
- }
-
- ret = 1;
- bail:
- if (fe)
- OCFS_BH_PUT_DATA(args->fe_bh);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_find_actor */
-
-
-/*
- * initialize the new inode, but don't do anything that would cause
- * us to sleep.
- * return 0 on success, 1 on failure
- */
-int ocfs_init_locked_inode(struct inode * inode, void * opaque) {
- int ret = 1;
- LOG_ENTRY_ARGS("inode = %x, opaque = %x\n", inode, opaque);
-
- /* We might be called from ocfs_fill_super in which case, opaque
- * will be null (but we'll be looking for the root inode
- * anyway... */
- if (opaque == NULL) {
- inode->i_ino = OCFS_ROOT_INODE_NUMBER;
- }
-
- ret = 0;
-//bail:
- LOG_EXIT_STATUS(ret);
- return(ret);
-}
-
-/*
- * ocfs_iget()
- *
- * expects sb and args to be already filled out.
- * specifically, need fe->extents[0].disk_off, args->offset
- * if we're called from ocfs_fill_super, args == NULL
- */
-struct inode * ocfs_iget(struct super_block *sb, ocfs_find_inode_args *args)
-{
- struct inode *inode = NULL;
- __u64 off;
- ocfs_file_entry *fe = NULL;
-
- LOG_ENTRY();
-
- if (!sb)
- goto bail;
-
- /* if args == NULL, we want the root inode */
- if (!args) {
- LOG_TRACE_STR("looking for root inode");
- inode = iget5_locked(sb, OCFS_ROOT_INODE_NUMBER, ocfs_find_actor, ocfs_init_locked_inode, NULL);
- } else {
- LOG_TRACE_STR("looking for non-root inode");
- off = args->offset;
- /* Need to verify that ocfs_find_inode does the right thing,
- * and need to actually write ocfs_init_inode */
- inode = iget5_locked(sb, LO (off), ocfs_find_actor,
- ocfs_init_locked_inode, args);
- }
-
- if (!inode)
- goto bail;
-
- /* inode was *not* in the inode cache */
- if (inode->i_state & I_NEW) {
- LOG_TRACE_STR("Inode was not in inode cache, reading it.");
- if (args)
- fe = OCFS_BH_GET_DATA(args->fe_bh);
- ocfs_read_locked_inode(inode, fe);
- if (args)
- OCFS_BH_PUT_DATA(fe_bh);
- unlock_new_inode(inode);
- }
-
-bail:
- LOG_EXIT_PTR(inode);
- return(inode);
-}
-
-#endif /* LINUX_2_5 stuff */
-
-
-/*
- * ocfs_put_inode()
- *
- */
-void ocfs_put_inode (struct inode *inode)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", inode);
- LOG_TRACE_ARGS ("put_inode: count=%d\n", inode->i_count);
- if (inode_data_is_oin(inode) && (atomic_read (&inode->i_count) == 1) ) {
- ocfs_inode *oin;
- oin = GET_INODE_OIN(inode);
- ocfs_extent_map_destroy (&oin->map);
- ocfs_extent_map_init (&oin->map);
- //dump_inode_clean_queue_buffers(inode);
- }
- LOG_EXIT ();
- return;
-} /* ocfs_put_inode */
-
-
-void ocfs_sync_blockdev(struct super_block *sb)
-{
-#ifdef LINUX_2_5
- sync_blockdev (sb->s_bdev);
-#else
- fsync_no_super (sb->s_dev);
-#endif
-}
-
-/*
- * ocfs_clear_inode()
- *
- */
-void ocfs_clear_inode (struct inode *inode)
-{
- LOG_ENTRY();
-
- if (inode) {
- if (inode_data_is_oin (inode)) {
- ocfs_inode *oin;
- ocfs_super *osb;
-
- LOG_TRACE_STR ("inode with oin : clear inode");
-
- oin = GET_INODE_OIN(inode);
- osb = (ocfs_super *) oin->osb;
- if (oin == osb->oin_root_dir) {
- LOG_TRACE_STR
- ("this is the root inode, doing cleanup now!");
- ocfs_sync_blockdev(inode->i_sb);
- LOG_TRACE_STR ("syncing past root inode");
- LOG_TRACE_STR ("calling dismount");
- ocfs_dismount_volume (inode->i_sb);
- goto bail;
- }
-
- ocfs_extent_map_destroy (&oin->map);
- ocfs_extent_map_init (&oin->map);
-
- ocfs_release_cached_oin (osb, oin);
- ocfs_release_oin (oin, true);
- oin = NULL;
- LOG_TRACE_STR ("yeah! done with deallocs!");
- } else {
- __u64 fileOff;
- ocfs_lock_res *lockres = NULL;
- ocfs_super *osb;
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(inode->i_sb);
-
- if (ocfs_linux_get_inode_offset (inode, &fileOff, NULL)) {
- if (!ocfs_lookup_sector_node (osb, fileOff, &lockres)) {
- if (lockres) {
- if (lockres->oin) {
- ocfs_put_lockres (lockres->oin->lock_res);
- lockres->oin->lock_res = NULL;
- lockres->oin = NULL;
- }
- ocfs_remove_sector_node (osb, lockres);
- ocfs_put_lockres(lockres);
- } else
- LOG_TRACE_STR ("lockres in hash is null");
- } else {
- LOG_TRACE_STR
- ("hashtable has already been destroyed. skipping.");
- }
- } else {
- LOG_TRACE_STR ("Could not find offset");
- }
- }
- }
- bail:
- LOG_EXIT ();
- return;
-} /* ocfs_clear_inode */
-
-
-/*
- * ocfs_prepare_write()
- *
- */
-static int ocfs_prepare_write (struct file *file, struct page *page, unsigned from, unsigned to)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %u)\n", file, page, from, to);
-
- ret = block_prepare_write (page, from, to, ocfs_get_block);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_prepare_write */
-
-/*
- * ocfs_commit_write()
- *
- */
-static int ocfs_commit_write (struct file *file, struct page *page, unsigned from, unsigned to)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %u)\n", file, page, from, to);
-
- ret = generic_commit_write (file, page, from, to);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_commit_write */
-
-
-/*
- * ocfs_block_symlink()
- *
- */
-int ocfs_block_symlink (struct inode *inode, const char *symname, int len)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page = grab_cache_page (mapping, 0);
- int err = -ENOMEM;
- char *kaddr;
-
- if (!page)
- goto fail;
- err = mapping->a_ops->prepare_write (NULL, page, 0, len - 1);
- if (err)
- goto fail_map;
- kaddr = page_address (page);
- memset (kaddr, 0, PAGE_CACHE_SIZE);
- memcpy (kaddr, symname, len - 1);
- mapping->a_ops->commit_write (NULL, page, 0, len - 1);
- err = mapping->a_ops->readpage (NULL, page);
-#ifdef LINUX_2_5
- wait_on_page_locked (page);
-#else
- wait_on_page (page);
-#endif
- page_cache_release (page);
- if (err < 0)
- goto fail;
- mark_inode_dirty (inode);
- return 0;
-
-fail_map:
-#ifdef LINUX_2_5
- unlock_page (page);
-#else
- UnlockPage (page);
-#endif
- page_cache_release (page);
-fail:
- return err;
-} /* ocfs_block_symlink */
-
-
-/*
- * ocfs_extend_allocation()
- *
- */
-static inline int ocfs_extend_allocation(ocfs_super *osb, ocfs_inode *oin, __u64 newsize, bool unlock, struct inode *inode)
-{
- int status = 0;
-
- if (newsize > oin->alloc_size) {
- LOG_TRACE_ARGS ("Extend: have=%u.%u, need=%u.%u\n",
- HILO (oin->alloc_size), HILO (newsize));
-
- if (unlock)
- ocfs_up_sem (&(oin->main_res));
-
- status = ocfs_extend_file (osb, oin->parent_dirnode_off, oin, newsize, &oin->file_disk_off, NULL, inode, NULL);
-
- if (unlock)
- ocfs_down_sem (&(oin->main_res), true);
- }
-
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- LOG_TRACE_ARGS ("Failed to extend file to %u.%u\n", HILO (newsize));
- status = -ENOSPC;
- }
-
- return status;
-} /* ocfs_extend_allocation */
-
-/*
- * ocfs_symlink_get_block()
- *
- */
-static int ocfs_symlink_get_block (struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
-{
- int err = -EIO;
- ocfs_super *osb;
- int status;
- ocfs_file_entry *fe = NULL;
- __u64 entryOffset;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %d, 0x%08x, %d)\n", inode, iblock, bh_result,
- create);
-
- if (!inode) {
- LOG_ERROR_STR ("bad inode");
- goto bail;
- }
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(inode->i_sb);
-
- if ((iblock << 9) > PATH_MAX + 1) {
- LOG_ERROR_ARGS ("file offset > PATH_MAX: %u.%u", iblock << 9);
- goto bail;
- }
-
- if (!ocfs_linux_get_inode_offset (inode, &entryOffset, NULL)) {
- LOG_ERROR_STR ("could not get inode offset!");
- goto bail;
- }
-
- status = ocfs_read_bh (osb, entryOffset, &bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_ARGS ("Invalid fe at offset %u.%u", HILO(entryOffset));
- goto bail;
- }
-
- if ((iblock << 9) >= (__s64)fe->alloc_size) {
- OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_ARGS ("file offset is outside the allocated size: %u.%u",
- HILO(iblock << 9));
- goto bail;
- }
-
- map_bh(bh_result, inode->i_sb, (fe->extents[0].disk_off >> 9) + iblock);
- OCFS_BH_PUT_DATA(bh);
-
- if (create)
- bh_result->b_state |= (1UL << BH_New);
- err = 0;
-
-bail:
- if (bh)
- brelse(bh);
-
- LOG_EXIT_LONG (err);
- return err;
-} /* ocfs_symlink_get_block */
-
-/*
- * ocfs_get_block()
- *
- */
-static int ocfs_get_block (struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
-{
- int err = -EIO;
- ocfs_inode *oin = NULL;
- ocfs_super *osb = NULL;
- __s64 vbo = 0;
- __s64 lbo = 0;
- __u32 len;
- bool oin_locked = false;
-
- LOG_ENTRY_ARGS ("(0x%08x, %d, 0x%08x, %d)\n", inode, iblock, bh_result,
- create);
-
- if (S_ISLNK (inode->i_mode)) {
- err = ocfs_symlink_get_block (inode, iblock, bh_result, create);
- goto bail;
- }
-
- if (!inode || !inode_data_is_oin (inode)) {
- LOG_ERROR_STR ("bad inode or inode has no oin");
- goto bail;
- }
-
- oin = GET_INODE_OIN(inode);
-
- if (!oin) {
- LOG_ERROR_STR("oin is NULL!");
- err = -EIO;
- goto bail;
- }
-
- osb = (ocfs_super *) oin->osb;
- vbo = (__s64) iblock << inode->i_sb->s_blocksize_bits;
-
- if (!oin->journal_inode && vbo >= oin->alloc_size) {
- LOG_TRACE_STR("Extending allocation");
- err = ocfs_extend_allocation(osb, oin, vbo+512, false, inode);
- if (err < 0) {
- LOG_ERROR_STATUS (err);
- goto bail;
- }
- }
-
- if (!(oin->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO)) {
- ocfs_down_sem (&(oin->main_res), true);
- oin_locked = true;
- }
-
- len = 1;
- err = ocfs_lookup_file_allocation(osb, oin, vbo, &lbo, len, NULL,
- (oin->journal_inode) ? NULL : inode);
- if (err < 0) {
- LOG_ERROR_ARGS ("vbo=%u.%u lbo=%u.%u len=%u", HILO(vbo),
- HILO(lbo), len);
- goto bail;
- }
-
- if (create) {
- LOG_TRACE_ARGS ("CREATE: offset: %u -> block#: %d\n", iblock,
- lbo >> inode->i_sb->s_blocksize_bits);
- bh_result->b_state |= (1UL << BH_New);
- }
-
- map_bh(bh_result, inode->i_sb, lbo >> inode->i_sb->s_blocksize_bits);
-
- if (create)
- bh_result->b_state |= (1UL << BH_New);
-
- err = 0;
-
- if (bh_result->b_blocknr == 0) {
- err = -EIO;
- LOG_ERROR_ARGS ("vbo=%u.%u lbo=%u.%u len=%u, fe=0x%08x",
- HILO(vbo), HILO(lbo), len, oin->file_disk_off);
- }
-
-bail:
- if (err < 0)
- err = -EIO;
-
- if (oin_locked && !(oin->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO)) {
- ocfs_up_sem (&(oin->main_res));
- }
-
- LOG_EXIT_LONG (err);
- return err;
-} /* ocfs_get_block */
-
-static int ocfs_bmap(struct address_space *mapping, long block)
-{
- int disk_block = 0;
- ocfs_super *osb =(ocfs_super *) OCFS_GENERIC_SB_P(mapping->host->i_sb);
- __s64 vbo = 0;
- __s64 lbo = 0;
- __u32 len;
- int err = 0;
- struct inode *inode = mapping->host;
- ocfs_inode *oin = NULL;
-
- LOG_ENTRY_ARGS("(block = %lu)\n", block);
-
- if (!inode || !inode_data_is_oin (inode)) {
- LOG_ERROR_STR ("bmap: bad inode or inode has no oin");
- err = -EINVAL;
- LOG_ERROR_STATUS(err);
- goto bail;
- }
-
- oin = GET_INODE_OIN(inode);
-
- if (!(oin->journal_inode)) {
- LOG_ERROR_STR("bmap is only for journal inodes!");
- err = -EINVAL;
- LOG_ERROR_STATUS(err);
- goto bail;
- }
-
- /* To understand this block, see ocfs_journal_create */
- if (osb->journal.state == OCFS_JOURNAL_CREATE) {
- if (osb->journal.bmaps >= OCFS_JOURNAL_CREATE_MAX_BMAPS) {
- LOG_TRACE_ARGS("%d iterations in journal_create, "
- "yielding\n",
- OCFS_JOURNAL_CREATE_MAX_BMAPS);
- osb->journal.bmaps = 0;
-
- yield();
- } else {
- osb->journal.bmaps++;
- }
- }
-
- vbo = (__s64) block << inode->i_sb->s_blocksize_bits;
- len = 1;
- err = ocfs_lookup_file_allocation(osb, oin, vbo, &lbo, len,
- NULL, NULL);
- if (err < 0) {
- LOG_ERROR_ARGS ("vbo=%u.%u lbo=%u.%u len=%u", HILO(vbo),
- HILO(lbo), len);
- LOG_ERROR_STATUS(err);
- goto bail;
- }
-
- disk_block = lbo >> inode->i_sb->s_blocksize_bits;
-
-bail:
- LOG_EXIT_STATUS(err ? err : disk_block);
- return(err ? err : disk_block);
-}
-
-#ifndef LINUX_2_5
-/*
- * ocfs_get_block2()
- *
- */
-static int ocfs_get_block2 (struct inode *inode, long iblock, long *oblock, int len)
-{
- int err = -EIO;
- ocfs_inode *oin;
- ocfs_super *osb;
- __s64 vbo = 0;
- __s64 lbo = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, %d)\n", inode, iblock);
-
- if (!inode || !inode_data_is_oin (inode)) {
- LOG_ERROR_STR ("bad inode or inode has no oin");
- err = -1;
- goto bail;
- }
-
- oin = GET_INODE_OIN(inode);
- osb = (ocfs_super *) oin->osb;
-
- vbo = (__s64) iblock << inode->i_sb->s_blocksize_bits;
- len = 1;
- err = ocfs_lookup_file_allocation (osb, oin, vbo, &lbo, len, NULL, inode);
- if (err < 0) {
- LOG_ERROR_STATUS (err);
- err = -1;
- goto bail;
- }
-
- err = 0;
-
- *oblock = lbo >> inode->i_sb->s_blocksize_bits;
- if (*oblock == 0) {
- err = -EIO;
- LOG_ERROR_ARGS ("vbo=%u.%u lbo=%u.%u len=%u, fe=0x%08x",
- HILO(vbo), HILO(lbo), len, oin->file_disk_off);
- }
-
- bail:
- if (err < 0)
- err = -EIO;
- LOG_EXIT_LONG (err);
- return err;
-} /* ocfs_get_block2 */
-#endif
-
-/*
- * ocfs_readpage()
- *
- */
-static int ocfs_readpage (struct file *file, struct page *page)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u)\n", file, (page ? page->index : 0));
-
- ret = block_read_full_page (page, ocfs_get_block);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_readpage */
-
-/*
- * ocfs_writepage()
- *
- */
-#ifdef LINUX_2_5
-static int ocfs_writepage (struct page *page, struct writeback_control *wbc)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x)\n", page);
-
- ret = block_write_full_page (page, ocfs_get_block, wbc);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_writepage */
-#else
-static int ocfs_writepage (struct page *page)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x)\n", page);
-
- ret = block_write_full_page (page, ocfs_get_block);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_writepage */
-#endif
-
-
-#if LINUX_2_5
-/*
- * TODO: Make this into a generic get_blocks function.
- *
- * From do_direct_io in direct-io.c:
- * "So what we do is to permit the ->get_blocks function to populate
- * bh.b_size with the size of IO which is permitted at this offset and
- * this i_blkbits."
- *
- * This function is called directly from get_more_blocks in direct-io.c.
- *
- * We should probably have this data in the oin for the inode.
- * Otherwise, we might want to look at ocfs_rw_direct,
- * ocfs_lookup_file_allocation and ocfs_get_block
- *
- * called like this: dio->get_blocks(dio->inode, fs_startblk,
- * fs_count, map_bh, dio->rw == WRITE);
- */
-int ocfs_direct_IO_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks, struct buffer_head *bh_result, int create)
-{
- int ret = -1;
- int status;
- ocfs_super *osb = NULL;
- ocfs_inode *oin = NULL;
- __s64 vbo; /* file offset */
- __s64 lbo; /* logical (disk) offset */
- __s64 vbo_max; /* file offset, max_blocks from iblock */
- int set_new = 0; /* flag */
- u32 new_size; /* In sectors, the size of the contiguous block */
- unsigned char blocksize_bits;
-
- if (!inode || !bh_result) {
- LOG_ERROR_STR("ocfs_direct_IO_get_blocks: inode or bh_result is null");
- return -EIO;
- }
- if (!inode_data_is_oin(inode)) {
- LOG_ERROR_STR("ocfs_direct_IO_get_blocks: inode has no oin\n");
- return -EIO;
- }
-
- oin = GET_INODE_OIN(inode);
- osb = (ocfs_super *) inode->i_sb->s_fs_info;
- blocksize_bits = inode->i_sb->s_blocksize_bits;
- /* make sure we're up to date... */
- if (OIN_NEEDS_VERIFICATION (oin)) {
- LOG_TRACE_STR ("ocfs_direct_IO_get_blocks: verify oin.");
- status = ocfs_verify_update_oin (osb, oin);
- if (status < 0) {
- LOG_TRACE_STR ("ocfs_verify_update_oin failed");
- ret = -EIO;
- goto bail;
- }
- }
-
- /* This function won't even be called if the request isn't all
- * nicely aligned and of the right size, so there's no need
- * for us to check any of that. */
-
- vbo = (__s64) iblock << blocksize_bits;
- vbo_max = vbo + ((__s64) max_blocks << blocksize_bits);
-
- /* NOTE: create flag is set when we ?may? have to allocate some
- blocks for the file. */
- if (create && vbo_max > oin->alloc_size) {
- /* WARNING: How much do we really want to extend the file?
- is 'false' the right argument there? */
- status = ocfs_extend_allocation(osb, oin, vbo_max, false);
- if (status < 0) {
- LOG_ERROR_STR("ocfs_direct_IO_get_blocks: failed to extend the file!");
- goto bail;
- }
- set_new = 1;
- }
-
- /* This figure out the size of the next contiguous block, and
- * our logical offset */
- /* TODO: Try our damndest to give sizes in multiples of PAGE_SIZE */
- status = ocfs_lookup_file_allocation(osb, oin, vbo, &lbo, max_blocks, &new_size);
-
- /* Do whatever we need to the buffer_head */
- if (set_new) {
- set_buffer_new(bh_result);
- /* Do we really want to set bh_result->b_blocknr here too? */
- bh_result->b_blocknr = lbo >> blocksize_bits;
- } else {
- clear_buffer_new(bh_result);
- /* is the last argument here correct? */
- map_bh(bh_result, inode->i_sb, lbo >> blocksize_bits);
- }
-
- /* make sure we don't map more than max_blocks blocks here as
- that's all the kernel will handle at this point. */
- if (new_size > max_blocks)
- new_size = max_blocks;
- bh_result->b_size = new_size << blocksize_bits;
-
- ret = 0;
-bail:
- return ret;
-}
-
-/*
- * ocfs_direct_IO()
- * used to be:
- * static int ocfs_direct_IO (int rw,
- * struct inode *inode,
- * struct kiobuf *iobuf, unsigned long blocknr, int blocksize)
- *
- * now:
- static int ocfs_direct_IO(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t offset,
- unsigned long nr_segs)
- * int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
- * loff_t offset, unsigned long nr_segs);
- */
-static int ocfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t offset, unsigned long nr_segs)
-{
- struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_dentry->d_inode->i_mapping->host;
- int ret;
-
- LOG_ENTRY ();
-
- /* blockdev_direct_IO checks alignment for us, using */
- ret = blockdev_direct_IO (rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, ocfs_direct_IO_get_blocks);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_direct_IO */
-
-#elif LINUX_VERSION_CODE >= LinuxVersionCode(2,4,10)
-/*
- * ocfs_direct_IO()
- *
- * we are not using this function anymore, in fact
- * we should never get here any more
- * so let's just BUG(), hint from sct at redhat.com
- */
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,20) || defined(SUSE)
-static int ocfs_direct_IO (int rw, struct file *filp, struct kiobuf *iobuf, unsigned long blocknr, int blocksize)
-{
- BUG();
- return 0;
-} /* ocfs_direct_IO */
-#else
-static int ocfs_direct_IO (int rw, struct inode *inode, struct kiobuf *iobuf, unsigned long blocknr, int blocksize)
-{
- BUG();
- return 0;
-} /* ocfs_direct_IO */
-#endif
-#endif /* version >= 2.4.10 */
-
-#if defined(SUSE) && LINUX_VERSION_CODE < LinuxVersionCode(2,4,20)
-#define OCFS_KIO_BLOCKS(_iobuf) ((_iobuf)->kio_blocks)
-#else
-#define OCFS_KIO_BLOCKS(_iobuf) ((_iobuf)->blocks)
-#endif
-
-
-/*
- * ocfs_rw_direct()
- *
- */
-ssize_t ocfs_rw_direct (int rw, struct file *filp, char *buf, size_t size, loff_t * offp)
-{
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- struct kiobuf *iobuf;
-#else
- struct kiobuf *iobuf = filp->f_iobuf;
- int new_iobuf = 0;
-#endif
- int err = 0;
- unsigned long blocknr, blocks, myiosize;
- size_t transferred;
- int iosize, clustersize;
- int i;
- struct inode *inode = filp->f_dentry->d_inode;
- int max_sectors;
- int nbhs;
- int sector_size, sector_bits, sector_mask;
- int ret = 0;
- bool large_io = false;
- bool inuse = false;
- unsigned long blocks_end_cluster = 0;
- loff_t saved_off;
- size_t saved_size;
- unsigned long firstlogic;
- long firstphys;
- long nextphys;
- unsigned long nextlogic = 0;
- unsigned long totalioblocks = 0;
-
- saved_off = *offp;
- saved_size = size;
-
- /* warning not all devices have 512 byte sectors */
- sector_size = 512;
- sector_bits = SECTOR_BITS;
- sector_mask = 511;
- /* max sectors is 1024 in 2.4.9
- * max data is 512kb
- */
-
- err = -EINVAL;
- if (size == 0) {
- printk("direct write of 0 byte\n");
- return 0;
- }
-
- if (rw == READ) {
- if (inode->i_size < *offp) /* read past end of file */
- return 0;
- if (size > (inode->i_size - *offp))
- size = inode->i_size - *offp;
- }
-
- /* make sure we are aligned to either 4kb or 512 byte IO */
-#ifndef LARGEIOS
- if ((*offp & 511) || (size & 511))
- /* if not, then fail, we need either to do dio */
- return err;
-
- max_sectors = KIO_MAX_SECTORS;
- large_io = false;
-#endif
-#ifdef LARGEIOS
- if ((*offp & 4095) || (size & 4095)) {
- /* if it's not 4kb, then 512 */
- if ((*offp & 511) || (size & 511))
- /* if not, then fail, we need either to do dio */
- return err;
- max_sectors = KIO_MAX_SECTORS; /* for 2.4.9 - 1024 */
- } /* ok we 're 4kb aligned, lets see if the buffer is */
- else {
- if (!((unsigned long) buf & 4095)) {
- /* yippie we are .. we can do 4kb size io's */
- large_io = true;
- /* for 2.4.9 */
- max_sectors = KIO_MAX_SECTORS / 8;
- } else {
- max_sectors = KIO_MAX_SECTORS;
- large_io = false;
- }
-
- }
-#endif
- /* find out how far we are to the end of our cluster */
-
- err = 0;
- if (size)
- err = -ENXIO;
-
- /* Split the IO into KIO_MAX_SECTORS chunks, mapping and */
- /* unmapping the single kiobuf as we go to perform each chunk of IO. */
-
- transferred = 0;
- blocknr = *offp >> SECTOR_BITS;
- clustersize = inode->i_blksize >> 9;
- myiosize = size >> 9;
- blocks_end_cluster = clustersize - (blocknr % clustersize);
- firstlogic = blocknr;
- totalioblocks = 0;
-
- ret = ocfs_get_block2 (inode, blocknr, &firstphys, 512);
- if (ret == -1) {
- err = 0;
- goto out;
- }
- while (myiosize > 0) {
- if (blocks_end_cluster + 1 > myiosize) {
- totalioblocks += myiosize;
- myiosize = 0;
- goto doio;
- } else {
- totalioblocks += blocks_end_cluster;
- myiosize -= blocks_end_cluster;
- nextlogic = firstlogic + blocks_end_cluster;
- }
-again:
- ret = ocfs_get_block2 (inode, nextlogic, &nextphys, 512);
- if (ret == -1) {
- err = 0;
- goto out;
- }
- if (nextphys == (firstphys + totalioblocks)) {
- // merge ok
- blocks_end_cluster = clustersize - (nextlogic % clustersize);
- if (blocks_end_cluster + 1 > myiosize) {
- totalioblocks += myiosize;
- myiosize = 0;
- } else {
- totalioblocks += blocks_end_cluster;
- myiosize -= blocks_end_cluster;
- nextlogic = nextlogic + blocks_end_cluster;
- goto again;
- }
- }
-doio:
- size = totalioblocks << 9;
- if (large_io)
- nbhs = (size >> 12);
- else
- nbhs = (size >> SECTOR_BITS);
- if (nbhs > max_sectors)
- nbhs = max_sectors;
-
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- err = alloc_kiovec_sz (1, &iobuf, &nbhs);
-#else
- if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
- /*
- * A parallel read/write is using the preallocated iobuf
- * so just run slow and allocate a new one.
- */
- err = alloc_kiovec_sz (1, &iobuf, &nbhs);
- if (err)
- goto out;
- new_iobuf = 1;
- }
-
-#endif
- inuse = true;
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- if (err)
- goto out;
-#endif
- totalioblocks = 0;
- while (size > 0) {
- if (large_io) {
- blocks = size >> 12;
- if (blocks > max_sectors)
- blocks = max_sectors;
- iosize = blocks << 12;
- } else {
- blocks = size >> SECTOR_BITS;
- if (blocks > max_sectors)
- blocks = max_sectors;
- iosize = blocks << SECTOR_BITS;
- }
- if (!blocks)
- break;
- err = map_user_kiobuf (rw, iobuf, (unsigned long) buf, iosize);
- if (err)
- break;
- /* get the blocknr depending on io size for all blocks */
- /* since we are awlays within the extent we only need to get the first block */
- OCFS_KIO_BLOCKS(iobuf)[0] = firstphys + totalioblocks;
-
- if (large_io) {
- blocknr+=8;
- OCFS_KIO_BLOCKS(iobuf)[0] = OCFS_KIO_BLOCKS(iobuf)[0] / 8;
- } else {
- blocknr++;
- }
-
- for (i = 1; i < blocks; i++) {
- if (large_io) {
- blocknr+=8;
- } else {
- blocknr++;
- }
- OCFS_KIO_BLOCKS(iobuf)[i] = OCFS_KIO_BLOCKS(iobuf)[0] + i;
- }
- err = brw_kiovec (rw, 1, &iobuf, inode->i_dev, OCFS_KIO_BLOCKS(iobuf),
- large_io ? 4096 : 512);
-#ifdef SUSE
- if (rw == READ && err > 0)
- mark_dirty_kiobuf(iobuf, err);
-#endif
- if (err >= 0) {
- transferred += err;
- size -= err;
- buf += err;
- if (large_io) {
- totalioblocks += (blocks * 8);
- } else {
- totalioblocks += blocks;
- }
- } else {
- printk(
- "ocfs_rw_direct : brw_kiovec() %d\n",
- err);
- break;
- }
- unmap_kiobuf (iobuf);
- if (err != iosize)
- break;
- }
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- free_kiovec_sz(1, &iobuf, &nbhs);
-#else
- if (!new_iobuf)
- clear_bit(0, &filp->f_iobuf_lock);
- else
- free_kiovec_sz(1, &iobuf, &nbhs);
-#endif
- inuse = false;
- totalioblocks = 0;
- firstlogic = nextlogic;
- firstphys = nextphys;
- }
- if (transferred) {
- *offp += transferred;
- err = transferred;
- }
-
-out:
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- if (inuse)
- free_kiovec_sz (1, &iobuf, &nbhs);
-#else
- if (inuse) {
- if (!new_iobuf)
- clear_bit(0, &filp->f_iobuf_lock);
- else
- free_kiovec_sz(1, &iobuf, &nbhs);
- }
-#endif
- return err;
-} /* ocfs_rw_direct */
-
-
-
-#ifdef AIO_ENABLED
-static int ocfs_kvec_rw(struct file *filp, int rw, kvec_cb_t cb, size_t size, loff_t pos);
-
-int ocfs_kvec_read(struct file *file, kvec_cb_t cb, size_t size, loff_t pos)
-{
- return ocfs_kvec_rw(file, READ, cb, size, pos);
-}
-
-int ocfs_kvec_write(struct file *file, kvec_cb_t cb, size_t size, loff_t pos)
-{
- return ocfs_kvec_rw(file, WRITE, cb, size, pos);
-}
-
-int ocfs_kvec_rw(struct file *filp, int rw, kvec_cb_t cb, size_t size, loff_t pos)
-{
- int err = 0;
- int sector_bits = SECTOR_BITS;
- int max_sectors = 25000;
- struct inode *inode = filp->f_dentry->d_inode;
- unsigned long blocknr, blocks, iosize,myiosize;
- long firstphys;
- int clustersize;
- unsigned long blocks_end_cluster = 0;
-
- int ret;
- unsigned long firstlogic;
- long nextphys;
- unsigned long nextlogic = 0;
- unsigned long totalioblocks = 0;
-
- if (!size || (pos == inode->i_size)) {
- cb.fn(cb.data, cb.vec, err);
- return err;
- }
-
- err = -ENXIO;
- if (pos >= inode->i_size) {
- return err;
- }
-
- err = -EINVAL;
- if ((pos < 0) || (pos & 511) || (size & 511)) {
- return err;
- }
-
- blocknr = pos >> SECTOR_BITS;
-
- blocks = size >> SECTOR_BITS;;
- if (blocks > max_sectors)
- blocks = max_sectors;
- if (!blocks) {
- err = -ENXIO;
- return err;;
- }
-
- iosize = blocks << SECTOR_BITS;
- clustersize = inode->i_blksize >> 9;
- blocks_end_cluster = clustersize - (blocknr % clustersize);
- myiosize = size >> 9;
- firstlogic = blocknr;
- totalioblocks = 0;
-
- err = ocfs_get_block2(inode, blocknr, &firstphys, 512);
- if ( err == -1 ) {
- err = 0;
- return err;
- }
- if (blocks_end_cluster + 1 > myiosize) {
- totalioblocks += myiosize;
- myiosize = 0;
- goto doio;
- } else {
- totalioblocks += blocks_end_cluster;
- myiosize -= blocks_end_cluster;
- nextlogic = firstlogic + blocks_end_cluster;
- }
-again:
- ret = ocfs_get_block2 (inode, nextlogic, &nextphys, 512);
- if (ret == -1) {
- err = 0;
- return err;
- }
- if (nextphys == (firstphys + totalioblocks)) {
- blocks_end_cluster = clustersize - (nextlogic % clustersize);
- if (blocks_end_cluster + 1 > myiosize) {
- totalioblocks += myiosize;
- myiosize = 0;
- } else {
- totalioblocks += blocks_end_cluster;
- myiosize -= blocks_end_cluster;
- nextlogic = nextlogic + blocks_end_cluster;
- goto again;
- }
- }
-doio:
- blocks = totalioblocks;
- err = brw_kvec_async(rw, cb, inode->i_dev, blocks, firstphys, sector_bits);
- return err;
-
-}
-
-#endif
Deleted: trunk/ioctl.c
===================================================================
--- trunk/ioctl.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/ioctl.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,69 +0,0 @@
-/*
- * ocfsioctl.c
- *
- * ocfs' ioctl interface
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_IOCTL
-
-/*
- * ocfs_ioctl()
- *
- * To be fixed.
- */
-int ocfs_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
-{
- struct ocfs_ioc data;
- extern char *ocfs_version;
- int ret = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %u, %lu)\n", inode, filp, cmd, arg);
-
- if (_IOC_TYPE (cmd) != OCFS_IOC_MAGIC) {
- ret = -ENOTTY;
- goto exit_ioctl;
- }
-
- switch (cmd) {
- case OCFS_IOC_GETTYPE:
- strncpy (data.name, OCFS_NAME, sizeof (data.name) - 1);
- strncpy (data.version, ocfs_version,
- sizeof (data.version) - 1);
- strncpy (data.nodename, OcfsGlobalCtxt.node_name,
- sizeof (data.nodename) - 1);
- data.nodenum = 999; /* TODO */
- ret = copy_to_user ((struct ocfs_ioc *) arg, &data,
- sizeof (struct ocfs_ioc));
- break;
- default:
- ret = -ENOTTY;
- break;
- }
-
- exit_ioctl:
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_ioctl */
Deleted: trunk/journal.c
===================================================================
--- trunk/journal.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/journal.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1708 +0,0 @@
-/*
- * ocfsjournal.c
- *
- * Defines functions of journalling api
- *
- * Copyright (C) 2003 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Kurt Hackel, Sunil Mushran, Manish Singh, Wim Coekaerts,
- * Mark Fasheh
- */
-
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_JOURNAL
-
-static int ocfs_checkpoint_handle(ocfs_journal_handle *handle);
-static int ocfs_revoke_handle(ocfs_journal_handle *handle);
-static int ocfs_journal_toggle_mounted(ocfs_super *osb, int node_num, bool value);
-static bool ocfs_journal_get_mount_state(ocfs_super *osb, int node_num);
-static int ocfs_reset_publish (ocfs_super * osb, __u64 node_num);
-static int ocfs_journal_release_locks(ocfs_journal_handle *handle, int abort);
-static int ocfs_force_read_journal(ocfs_super *osb, __u64 size,
- ocfs_inode *oin);
-static int ocfs_recover_vol(struct _ocfs_super *osb, int node_num);
-static int __ocfs_recovery_thread(void *arg);
-#ifdef USE_JOURNAL_CREATE_REPLACEMENT
-static int ocfs_replacement_journal_create(journal_t *journal);
-#endif
-
-/* DO NOT EVER CALL THIS FUNCTION WITH A LOCKED BUFFER HEAD! */
-ocfs_journal_handle * ocfs_start_trans(ocfs_super *osb, int max_buffs)
-{
- ocfs_journal_handle * retval = NULL;
- journal_t * journal = osb->journal.k_journal;
-
- LOG_ENTRY_ARGS ("(max_buffs = %d)\n", max_buffs);
-
- if (!osb || !osb->journal.k_journal)
- BUG();
-
- /* for now, we only do one transaction at a time. Eventually
- * this and trans_in_progress need to be replaced. */
- ocfs_take_trans_lock(osb);
-
- retval = ocfs_malloc(sizeof(*retval));
- if (!retval) {
- LOG_ERROR_STR("Failed to allocate memory for journal handle!");
- goto done_free;
- }
- memset(retval, 0, sizeof(*retval));
-
- retval->buffs = ocfs_malloc(sizeof(struct buffer_head *) * max_buffs);
- if (!retval->buffs) {
- LOG_ERROR_STR("Failed to allocate memory for journal buffers!");
- goto done_free;
- }
- memset(retval->buffs, 0, sizeof(struct buffer_head *) * max_buffs);
-
- spin_lock_init(&(retval->list_lock));
- INIT_LIST_HEAD(&(retval->h_list));
- INIT_LIST_HEAD(&(retval->locks));
- retval->max_buffs = max_buffs;
- retval->num_buffs = 0;
- retval->num_locks = 0;
- retval->journal = &osb->journal;
- retval->osb = osb;
-
- /* actually start the transaction now */
- retval->k_handle = journal_start(journal, max_buffs);
- if (IS_ERR(retval->k_handle)) {
- LOG_ERROR_STR("journal_start() failed!");
- LOG_ERROR_STATUS(PTR_ERR(retval->k_handle));
- retval->k_handle = NULL;
- goto done_free;
- }
-
- atomic_inc(&(osb->journal.num_trans));
-
- down(&osb->journal.commit_sem);
- osb->journal.curr = retval;
- up(&osb->journal.commit_sem);
-
- /* default handle flags! */
- ocfs_handle_set_sync(retval, true);
- ocfs_handle_set_checkpoint(retval, true);
-
- LOG_EXIT_PTR(retval);
- return(retval);
-
-done_free:
- ocfs_release_trans_lock(osb);
-
- if (retval) {
- if (retval->buffs)
- ocfs_safefree(retval->buffs);
- ocfs_safefree(retval);
- }
- LOG_EXIT_PTR(NULL);
- return(NULL);
-} /* ocfs_start_trans */
-
-static int ocfs_checkpoint_handle(ocfs_journal_handle *handle)
-{
- int retval = 0;
- ocfs_super *osb = NULL;
-
- LOG_ENTRY();
-
- osb = handle->osb;
-
- if (!handle->num_buffs)
- goto done;
-
- retval = ocfs_write_bhs(osb, handle->buffs, handle->num_buffs,
- OCFS_BH_IGNORE_JBD, NULL);
- if (retval < 0)
- LOG_ERROR_STR("Error checkpointing handle.");
-
-done:
-
- LOG_EXIT_STATUS(retval);
- return(retval);
-}
-
-/* This function expects the journal handle to have already been
- * commited to disk (and it'd better have been checkpointed too!)
- *
- * Tells JBD to revoke these buffers from the on disk journal so if we
- * crash later, they won't be replayed.
- *
- * The call to journal_revoke does a brelse. It also winds up removing
- * the journal_head from the buffer, and therefore the JBD bit is no
- * longer set.
- */
-static int ocfs_revoke_handle(ocfs_journal_handle *handle)
-{
- int retval = 0;
- struct buffer_head *bh;
- handle_t *new_handle = NULL;
- ocfs_journal *journal;
- int i;
-
- LOG_ENTRY();
-
- journal = handle->journal;
-
- if (!handle->num_buffs)
- goto done;
-
- new_handle = journal_start(journal->k_journal, handle->num_buffs);
- if (IS_ERR(new_handle)) {
- retval = PTR_ERR(new_handle);
- new_handle = NULL;
- LOG_ERROR_STATUS(retval);
- LOG_ERROR_STR("Could not start revoke transaction!");
- goto done;
- }
-
- new_handle->h_sync = 1;
-
- for(i = 0; i < handle->num_buffs; i++) {
- bh = handle->buffs[i];
-
- retval = journal_revoke(new_handle, bh->b_blocknr, bh);
- if (retval < 0) {
- LOG_ERROR_STR("Could not revoke buffer!");
- goto done;
- }
- }
-
-done:
- if (new_handle)
- journal_stop(new_handle);
-
- LOG_EXIT_STATUS(retval);
- return(retval);
-}
-
-/* This does no locking of the handle, so make sure that the handle
- * isn't on journal->curr. If the handle is on journal->commited, then
- * you want to be holding the commit_sem before calling this. */
-static int ocfs_journal_release_locks(ocfs_journal_handle *handle, int abort)
-{
- ocfs_super *osb;
- ocfs_journal_lock *lock;
- int status = 0;
- int tmpstat;
- struct list_head *p, *n;
-
- LOG_ENTRY();
-
- osb = handle->osb;
-
- if (osb->journal.curr == handle)
- BUG();
-
- LOG_TRACE_ARGS("num_locks = %d\n", handle->num_locks);
-
- list_for_each_safe(p, n, &(handle->locks)) {
- lock = list_entry(p, ocfs_journal_lock, lock_list);
-
- tmpstat = ocfs_release_lock(osb, lock->id, lock->type,
- lock->flags, lock->res,
- (abort ? NULL : lock->bh), NULL);
- if (tmpstat < 0) {
- LOG_ERROR_ARGS("Could not release lock %u.%u\n",
- HILO(lock->id));
- LOG_ERROR_STATUS(tmpstat);
- status = tmpstat;
- }
- ocfs_put_lockres(lock->res);
- if (lock->bh != NULL)
- brelse(lock->bh);
-
- list_del(&(lock->lock_list));
- handle->num_locks--;
- ocfs_free(lock);
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-
-/* This for loop is for debug purposes. Basically we want to check the
- * BH_JBD bit on our buffers. If the handle was checkpointed, then
- * none of them should have that bit set after the revoke
- * stage. Otherwise, they *should* have it set. */
-#define CHECK_JBD_BUFFERS(buffs, num_buffs) \
-do { \
- int __i; \
- for(__i = 0; __i < num_buffs; __i++) { \
- LOG_TRACE_ARGS("Checking block %u\n", buffs[__i]->b_blocknr); \
- if (buffer_jbd(buffs[__i])) \
- LOG_TRACE_ARGS("block %u has jbd bit set!\n", \
- buffs[__i]->b_blocknr); \
- } \
-} while (0)
-
-/*
- Should this function also mark the buffers dirty (journal_dirty_*)
- or should we expect a higher layer to be doing that?
-*/
-int ocfs_commit_trans(ocfs_journal_handle * handle)
-{
- ocfs_super *osb;
- handle_t *kern_handle;
- transaction_t *kern_trans;
- int retval = 0, i;
- struct buffer_head *bh;
- bool revoked = false;
- bool checkpoint, sync;
- ocfs_journal *journal;
-
- LOG_ENTRY();
-
- if (!handle)
- BUG();
-
- osb = handle->osb;
- kern_handle = handle->k_handle;
- kern_trans = kern_handle->h_transaction;
- journal = &osb->journal;
- checkpoint = handle->flags & OCFS_HANDLE_CHECKPOINT;
- /* if you want to checkpoint, you MUST also sync. */
- if (checkpoint)
- ocfs_handle_set_sync(handle, true);
- sync = handle->flags & OCFS_HANDLE_SYNC;
-
- LOG_TRACE_ARGS("Commiting %d blocks, checkpoint = %s, sync = %s\n",
- handle->num_buffs, checkpoint ? "true" : "false",
- sync ? "true" : "false");
-
- if (sync)
- kern_handle->h_sync = 1;
- else
- kern_handle->h_sync = 0;
-
- /* actually stop the transaction. if we've set h_sync,
- * it'll have been commited when we return */
- retval = journal_stop(kern_handle);
- if (retval < 0) {
- LOG_ERROR_STATUS(retval);
- goto done;
- }
-
- /* for now we manually checkpoint and force out our revoke
- * records. In the future we'll try to queue up as many
- * buffer_heads as possible so that a single callback call
- * will checkpoint and revoke everything from that
- * transaction. */
- handle->k_handle = NULL; /* it's been free'd in journal_stop */
-
- if (checkpoint) {
- /* checkpoint from buffer_head list */
- retval = ocfs_checkpoint_handle(handle);
- if (retval < 0) {
- LOG_ERROR_STR("Could not checkpoint transaction!");
- goto done;
- }
-
- /* revoke from buffer_head list, commit revoke records */
- retval = ocfs_revoke_handle(handle);
- if (retval < 0) {
- LOG_ERROR_STR("Could not completely revoke "
- "transaction!");
- goto done;
- }
-
- revoked = true;
- } else {
-
- /* we'll want to get rid of the buffers now as
- * journal_flush does the other work for us, so leave
- * revoked to false. */
- }
-
-
-done:
- if (!revoked) {
- /* usually the journal_revoke in ocfs_revoke_handle
- * will brelse the buffers for us, but if we aren't
- * checkpointing this handle, or we've gotten here
- * because of error then we have to do it manually. */
- for(i = 0; i < handle->num_buffs; i++) {
- bh = handle->buffs[i];
- handle->buffs[i] = NULL;
- brelse(bh);
- }
- }
-
- down(&journal->commit_sem);
- journal->curr = NULL;
-
- if (checkpoint) {
- up(&journal->commit_sem);
- atomic_dec(&(osb->journal.num_trans));
-
- /* Release locks associated with this handle. */
- retval = ocfs_journal_release_locks(handle, 0);
- if (retval < 0)
- LOG_ERROR_STATUS(retval);
-
-
- } else {
- /* If we're not going to checkpoint the handle on
- * commit then we need to add it to our journals list
- * so it can be done later */
- list_add_tail(&(handle->h_list), &(journal->commited));
- osb->needs_flush = true;
- up(&journal->commit_sem);
- }
-
- /* we don't free the kernel handle because jbd has freed it. */
- if (handle->buffs) {
- ocfs_free(handle->buffs);
- handle->buffs = NULL;
- handle->num_buffs = 0;
- }
-
- /* This has to happen after we release the other locks. */
- ocfs_release_trans_lock(osb);
-
- if (checkpoint)
- ocfs_free(handle);
-
- LOG_EXIT_STATUS(retval);
-
- return(retval);
-}
-
-/*
- * ocfs_abort_trans
- */
-void ocfs_abort_trans(ocfs_journal_handle * handle)
-{
- struct buffer_head *bh;
- ocfs_super *osb = NULL;
- int i;
- int retval;
-
- LOG_ENTRY();
-
- osb = handle->osb;
-
- /* There is a potential bug here which we may have to
- * resolve. What if you do a get_write_access on a buffer,
- * modify it, but error out before you've passed it to
- * dirty_metadata? We currently have to way to get to these
- * (unless we start tracking them much like dirty buffers). In
- * the worst case, the buffer could potentially hang around
- * the system and be picked up by another call and used as
- * though it were clean, even though it contains aborted
- * data!*/
-
- /* take all our dirtied buffers and make sure they can't be
- * written to disk */
- for(i = 0; i < handle->num_buffs; i++) {
- bh = handle->buffs[i];
- lock_buffer(bh);
- /* this buffer has changed data which we want to
- * consider invalid -- mark the sequence number as
- * old. */
- bh->b_state &= ~STATE_BIT_MASK;
- /* clear the uptodate and dirty flags so this never
- * gets written to disk inadvertantly by someone
- * else. */
-#ifdef LINUX_2_5
- clear_buffer_uptodate(bh);
-#else
- mark_buffer_uptodate(bh, false);
-#endif
- clear_bit(BH_Dirty, &bh->b_state);
- unlock_buffer(bh);
- /* journal_forget will bforget the buffers for us too. */
- journal_forget(handle->k_handle, bh);
- }
-
- /* want to force our handle to disk in abort case. */
- handle->k_handle->h_sync = 1;
-
- retval = journal_stop(handle->k_handle);
- if (retval < 0) {
- LOG_ERROR_STR("Could not commit aborted transaction!");
- goto done;
- }
- handle->k_handle = NULL;
-
- atomic_dec(&(osb->journal.num_trans));
-done:
-
- down(&osb->journal.commit_sem);
- osb->journal.curr = NULL;
- up(&osb->journal.commit_sem);
-
- retval = ocfs_journal_release_locks(handle, 1);
- if (retval < 0)
- LOG_ERROR_STATUS(retval);
-
- /* This has to happen after we release the other locks. */
- ocfs_release_trans_lock(osb);
-
- if (handle->buffs)
- ocfs_free(handle->buffs);
- ocfs_free(handle);
-
- LOG_EXIT();
- return;
-} /* ocfs_abort_trans */
-
-int ocfs_journal_access(ocfs_journal_handle *handle, struct buffer_head *bh, int type)
-{
- int status = -1;
-
- LOG_ENTRY_ARGS("(bh->b_blocknr=%lu, type=%d (\"%s\"))\n", bh->b_blocknr,
- type, (type == OCFS_JOURNAL_ACCESS_CREATE) ?
- "OCFS_JOURNAL_ACCESS_CREATE" :
- "OCFS_JOURNAL_ACCESS_WRITE");
-
- switch (type) {
- case OCFS_JOURNAL_ACCESS_CREATE:
- status = journal_get_create_access(handle->k_handle, bh);
- break;
-
- case OCFS_JOURNAL_ACCESS_WRITE:
- status = journal_get_write_access(handle->k_handle, bh);
- break;
-
- default:
- status = -EINVAL;
- LOG_ERROR_STR("Uknown access type!");
- goto done;
- }
-
- if (status < 0) {
- LOG_ERROR_ARGS("Error getting %s access to buffer!\n",
- (type == OCFS_JOURNAL_ACCESS_CREATE ? "create" : "write"));
- goto done;
- }
-
- status = 0;
-done:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * We also have to add the buffer to our handles list.
- */
-int ocfs_journal_dirty(ocfs_journal_handle *handle, struct buffer_head *bh)
-{
- int status = -1;
- int i;
-
- LOG_ENTRY_ARGS("(bh->b_blocknr=%lu)\n", bh->b_blocknr);
-
- if (handle->num_buffs >= handle->max_buffs) {
- LOG_ERROR_STR("Cannot add buffer to full transaction!");
- goto done;
- }
-
- /* First, make sure we aren't already in the list. If we've
- * already been added, then that's OK as JBD knows how to
- * handle this so just jump ahead.
- */
- for(i = 0; i < handle->num_buffs; i++) {
- if (handle->buffs[i] == bh) {
- LOG_TRACE_ARGS("block (%lu) already added to dirty " \
- "list!\n", bh->b_blocknr);
- goto call_jbd;
- }
- }
-
- i = handle->num_buffs;
- /* Increase the ref count on this buffer. We
- * do this because we still want to keep them
- * around after commit so that we can
- * checkpoint them and then "revoke" the whole
- * transaction. */
- get_bh(bh);
- handle->buffs[i] = bh;
- handle->num_buffs++;
- LOG_TRACE_ARGS("Dirtied buffer at position %d\n", i);
-
-call_jbd:
- status = journal_dirty_metadata(handle->k_handle, bh);
- if (status < 0) {
- LOG_ERROR_ARGS("Could not dirty metadata buffer. "
- "(bh->b_blocknr=%lu)\n", bh->b_blocknr);
- LOG_TRACE_ARGS("Setting handle->buffs[%d] = NULL\n", i);
- brelse(bh);
- handle->buffs[i] = NULL;
- handle->num_buffs--;
- goto done;
- }
-
-
- status = 0;
-done:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-
-/* We are expecting to be run on the current running transaction, so
- * we use the spin_lock here. You really shouldn't be calling this on
- * other transactions anyway... */
-void ocfs_journal_add_lock(ocfs_journal_handle *handle, __u64 id, __u32 type,
- __u32 flags, struct _ocfs_lock_res *res,
- struct buffer_head *bh)
-{
- ocfs_journal_lock *lock;
-
- LOG_ENTRY_ARGS("(id=%u.%u, type=%u, flags=%u, res=0x%08x, "
- "bh=0x%08x)\n", HILO(id), type, flags, res, bh);
-
- lock = ocfs_malloc(sizeof(ocfs_journal_lock));
- if (lock == NULL) {
- LOG_ERROR_STR("Out of memory -- cannot add lock to release.");
- LOG_ERROR_STATUS(-ENOMEM);
-
- BUG();
- }
-
- lock->id = id;
- lock->type = type;
- lock->flags = flags;
- lock->res = res;
- lock->bh = bh;
-
- spin_lock(&handle->list_lock);
- list_add_tail(&(lock->lock_list), &(handle->locks));
- handle->num_locks++;
- spin_unlock(&handle->list_lock);
-
- if (bh)
- get_bh(bh);
-
- LOG_EXIT();
- return;
-}
-
-/*
- * ocfs_journal_update_config()
- * yes, this is just like ocfs_refresh_node_config.
- */
-int ocfs_journal_update_config (ocfs_super * osb, int new_version)
-{
- ocfs_node_config_info *node;
- ocfs_disk_node_config_info *disk;
- __u64 offset;
- __u8 *buffer = NULL;
- int status = 0;
-
- LOG_ENTRY();
-
- buffer = ocfs_malloc (osb->sect_size);
- if (buffer == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- memset ((void *) buffer, 0, osb->sect_size);
- disk = (ocfs_disk_node_config_info *) buffer;
- disk->journal_version = new_version;
-
- /* populate the nodecfg info in disk from global context */
- ocfs_volcfg_gblctxt_to_disknode (disk);
-
- /* populate the nodecfg info in mem from global context */
- node = osb->node_cfg_info[osb->node_num];
- ocfs_volcfg_gblctxt_to_node (node);
- node->journal_version = new_version;
-
- /* Update the nodecfg on disk with the new info */
- offset = osb->vol_layout.new_cfg_off;
- status = ocfs_config_with_disk_lock (osb, offset, (__u8 *) disk,
- osb->node_num, OCFS_VOLCFG_UPD);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-bail:
- ocfs_safefree(buffer);
- LOG_EXIT_STATUS(status);
- return status;
-} /* ocfs_journal_update_config */
-
-/*
- * Ok, what used to be our "cleanup log" becomes our journal.
- * TODO: Concatenate the cleanup and recover logs to make a larger journal.
- */
-int ocfs_journal_init(ocfs_super *osb)
-{
- int status = -1;
- struct inode *inode = NULL; /* the journal inode */
- journal_t * k_journal = NULL;
- ocfs_find_inode_args args;
- ocfs_file_entry *fe = NULL;
- ocfs_lock_res *lock_res = NULL;
- __u32 cleanup_file_id = 0;
- __u64 lock_id = 0;
- ocfs_inode * oin = NULL;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY();
-
- if (!osb)
- BUG();
-
- /* initialize our journal structure */
- memset(&osb->journal, 0, sizeof(ocfs_journal));
-
- INIT_LIST_HEAD(&(osb->journal.commited));
- init_MUTEX(&(osb->journal.commit_sem));
-
- /* get the cleanup file fe and lock */
- cleanup_file_id = (__u32) (JOURNAL_FILE_BASE_ID + osb->node_num);
- lock_id = ((JOURNAL_FILE_BASE_ID + osb->node_num) * osb->sect_size) +
- osb->vol_layout.root_int_off;
-
- /* TODO: Use another type of lock. */
- status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, &lock_res, &bh, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STR("Could not get lock on journal!");
- goto done;
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
-
- /* extend the system file if we need to - it should be exactly
- * eight megs. */
- if (fe->file_size != OCFS_JOURNAL_DEFAULT_SIZE) {
- OCFS_BH_PUT_DATA(bh);
- fe = NULL;
- status = ocfs_extend_system_file(osb, cleanup_file_id,
- OCFS_JOURNAL_DEFAULT_SIZE,
- bh, NULL);
- if (status < 0) {
- LOG_ERROR_STR("Could not extend journal file!");
- goto done;
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
- }
- LOG_TRACE_ARGS("fe->file_size = %u.%u\n", HI(fe->file_size),
- LO(fe->file_size));
- LOG_TRACE_ARGS("fe->alloc_size = %u.%u\n", HI(fe->alloc_size),
- LO(fe->alloc_size));
-
-
- /* Ok, look up the inode for our journal */
- args.offset = fe->this_sector;
- args.fe_bh = bh;
- LOG_TRACE_ARGS("fe->this_sector = %u.%u\n", HI(fe->this_sector),
- LO(fe->this_sector));
- OCFS_BH_PUT_DATA(bh);
- fe = NULL;
-#ifdef LINUX_2_5
- inode = ocfs_iget (sb, &args);
-#else
- inode =
- iget4 (osb->sb, LO (args.offset),
- (find_inode_t) ocfs_find_inode, (void *) (&args));
-#endif
- if (inode == NULL) {
- LOG_ERROR_STR("access error");
- status = -EACCES;
- goto done;
- }
- if (is_bad_inode (inode)) {
- LOG_ERROR_STR("access error (bad inode)");
- iput (inode);
- inode = NULL;
- status = -EACCES;
- goto done;
- }
- LOG_TRACE_ARGS("inode->i_size = %u\n", inode->i_size);
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
- status = ocfs_create_new_oin(&oin, fe->alloc_size, osb);
- status = ocfs_initialize_oin(oin, osb, 0, fe->this_sector, 0, false, NULL);
- oin->journal_inode = true;
- oin->open_hndl_cnt++;
- SET_INODE_OIN(inode, oin);
- LOG_TRACE_ARGS("oin->alloc_size = %u.%u\n", HI(oin->alloc_size),
- LO(oin->alloc_size));
-
- OCFS_BH_PUT_DATA(bh);
- fe = NULL;
-
- /* call the kernels journal init function now */
- k_journal = journal_init_inode(inode);
- if (k_journal == NULL) {
- LOG_ERROR_STR("Linux journal layer error");
- status = -1;
- goto done;
- }
-
- LOG_TRACE_STR("Returned from journal_init_inode");
- LOG_TRACE_ARGS("k_journal->j_maxlen = %u\n", k_journal->j_maxlen);
- lock_journal(k_journal);
- k_journal->j_commit_interval = OCFS_DEFAULT_COMMIT_INTERVAL;
- unlock_journal(k_journal);
-
- /* yay, pass the proper info back to our journal structure. */
- osb->journal.osb = osb;
- /* eventually this will be a value passed into us */
- osb->journal.node_num = osb->node_num;
- osb->journal.k_journal = k_journal;
- osb->journal.k_inode = inode;
- osb->journal.version = OCFS_JOURNAL_CURRENT_VERSION;
- osb->journal.lockbh = bh;
- osb->journal.lock_res = lock_res;
- osb->journal.lock_id = lock_id;
- atomic_set(&(osb->journal.num_trans), 0);
- osb->journal.state = OCFS_JOURNAL_LOADED;
- status = 0;
-done:
- if (status < 0) {
- ocfs_put_lockres (lock_res);
- if (bh != NULL) {
- if (fe)
- OCFS_BH_PUT_DATA(bh);
- brelse(bh);
- }
- if (oin)
- oin->open_hndl_cnt--;
- }
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- if the journal has been ocfs_malloc'd it needs to be freed after this call.
-*/
-void ocfs_journal_shutdown(ocfs_super *osb)
-{
- ocfs_journal * journal = NULL;
- int status = 0;
- ocfs_inode *oin;
- struct inode * inode = NULL;
- int num_running_trans = 0;
-
- LOG_ENTRY();
-
- if (!osb)
- BUG();
-
- journal = &osb->journal;
- inode = journal->k_inode;
-
- if (journal->state != OCFS_JOURNAL_LOADED) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto done;
- }
-
- /* need to inc inode use count as journal_destroy will iput. */
- atomic_inc(&inode->i_count);
-
- num_running_trans = atomic_read(&(osb->journal.num_trans));
- if (num_running_trans > 0)
- LOG_TRACE_ARGS("Shutting down journal: must wait on %d"
- " running transactions!\n", num_running_trans);
-
- down(&osb->trans_lock);
- /* Do a commit_cache here. It will flush our journal, *and*
- * release any locks that are still held The
- * OCFS_JOURNAL_IN_SHUTDOWN will signal to commit_cache to not
- * drop the trans_lock (which we want to hold until we
- * completely destroy the journal. */
- journal->state = OCFS_JOURNAL_IN_SHUTDOWN;
-
- status = ocfs_commit_cache(osb, false);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- /* Shutdown the kernel journal system */
- journal_destroy(journal->k_journal);
-
- /* release the oin here. Isn't this racy? */
- if (inode_data_is_oin(inode)) {
- oin = GET_INODE_OIN(inode);
- inode->i_flags &= ~S_OCFS_OIN_VALID;
- oin->open_hndl_cnt--;
- ocfs_release_oin(oin, true);
- }
-
- /* unlock our journal */
- status = ocfs_release_lock (osb, journal->lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, journal->lock_res,
- journal->lockbh, NULL);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- brelse (journal->lockbh);
- journal->lockbh = NULL;
- ocfs_put_lockres (journal->lock_res);
-
- journal->state = OCFS_JOURNAL_FREE;
-
- up (&osb->trans_lock);
-done:
- if (inode)
- iput(inode);
- LOG_EXIT();
- return;
-}
-
-/*
- * journal is formatted and loaded - so no need to call journal_load.
- * obviously, you MUST call this *after* ocfs_journal_init
- */
-int ocfs_journal_create(ocfs_journal *journal)
-{
- int status = 0;
- ocfs_super * osb = NULL;
- struct super_block *sb = NULL;
-
- LOG_ENTRY();
-
- if (!journal)
- BUG();
-
- osb = journal->osb;
- sb = osb->sb;
-
- /* The call to journal create will NOT result in our process
- * going to sleep after the 1st bmap. On *really* slow, single
- * CPU machines this can monopolize the CPU and prevent the
- * heartbeat thread from timestamping our publish
- * sector. Other nodes might think we're dead, and then try to
- * recover us which could cause Very Bad Things. The
- * (hackiferous) solution is to set our state, and in
- * ocfs_bmap, call "yield" every 1000 times to give the
- * heartbeat a chance. */
- journal->state = OCFS_JOURNAL_CREATE;
- journal->bmaps = 0;
-
-#ifdef USE_JOURNAL_CREATE_REPLACEMENT
- status = ocfs_replacement_journal_create(journal->k_journal);
-#else
- status = journal_create(journal->k_journal);
-#endif
- if (status < 0) {
- LOG_ERROR_STR("Failed to create new journal!");
- goto done;
- }
-
- journal->state = OCFS_JOURNAL_LOADED;
- journal->bmaps = 0;
-
-done:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-int ocfs_journal_load(ocfs_journal *journal)
-{
- int status = 0;
- int olderr = 0;
- ocfs_super *osb;
-
- LOG_ENTRY();
-
- if (!journal)
- BUG();
-
- osb = journal->osb;
-
- status = journal_load(journal->k_journal);
- if (status < 0) {
- LOG_ERROR_STR("Failed to load journal!");
- goto done;
- }
-
- olderr = journal_errno(journal->k_journal);
- if (olderr) {
- printk("ocfs: last journal left error code %d\n", olderr);
- journal_ack_err(journal->k_journal);
- journal_clear_err(journal->k_journal);
- }
-
-done:
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/* true if mounted, false otherwise */
-static bool ocfs_journal_get_mount_state(ocfs_super *osb, int node_num)
-{
- int status = 0;
- ocfs_publish *publish = NULL;
- struct buffer_head *publish_bh = NULL;
- __u64 offset = 0;
- bool retval = false;
- int flags = 0;
-
- LOG_ENTRY();
-
- /* read it in */
- offset = osb->vol_layout.publ_sect_off +
- (node_num * osb->sect_size);
- /* we may be called during mount in which case our publish
- * sector might be dirty. */
- if (node_num == osb->node_num)
- flags = OCFS_BH_CACHED;
- status = ocfs_read_bh(osb, offset, &publish_bh, flags, NULL);
- if (status < 0) {
- brelse(publish_bh);
- LOG_ERROR_STR("Could not read publish sector, mounted value"
- " may be incorrect!");
- LOG_ERROR_STATUS (status);
- goto done;
- }
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(publish_bh);
-
- retval = publish->mounted;
-
- OCFS_BH_PUT_DATA(publish_bh);
- brelse(publish_bh);
-done:
- LOG_EXIT_STATUS(retval);
- return(retval);
-}
-
-static int ocfs_journal_toggle_mounted(ocfs_super *osb, int node_num, bool value)
-{
- int status = 0;
- ocfs_publish *publish = NULL;
- struct buffer_head * publish_bh = NULL;
- __u64 offset = 0;
-
- LOG_ENTRY_ARGS("(node_num=%d, value=%d)\n", node_num, value);
-
- /* take a lock on the publish sector */
- down (&(osb->publish_lock));
-
- /* read it in */
- offset = osb->vol_layout.publ_sect_off +
- (node_num * osb->sect_size);
- status = ocfs_read_bh(osb, offset, &publish_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto done;
- }
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(publish_bh);
-
- /* change it */
- publish->mounted = value;
- OCFS_BH_PUT_DATA(publish_bh);
-
- /* write it back out */
- status = ocfs_write_bh(osb, publish_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto done;
- }
-
-done:
- /* unlock it */
- up (&(osb->publish_lock));
-
- if (publish_bh)
- brelse(publish_bh);
-
- LOG_EXIT_STATUS(status);
-
- return(status);
-}
-
-/* set the 'mounted' bit in the publish sector */
-int ocfs_journal_set_mounted(ocfs_super *osb, int node_num)
-{
- int retval;
-
- LOG_ENTRY_ARGS("(node_num=%d)\n", node_num);
-
- retval = ocfs_journal_toggle_mounted(osb, node_num, true);
-
- LOG_EXIT_STATUS(retval);
-
- return(retval);
-}
-
-/* unset the 'mounted' bit in the publish sector */
-int ocfs_journal_set_unmounted(ocfs_super *osb, int node_num)
-{
- int retval;
-
- LOG_ENTRY_ARGS("(node_num=%d)\n", node_num);
-
- retval = ocfs_journal_toggle_mounted(osb, node_num, false);
-
- LOG_EXIT_STATUS(retval);
-
- return(retval);
-}
-
-/* 'full' flag tells us whether we clear out all blocks or if we just
- * mark the journal clean */
-int ocfs_journal_wipe(ocfs_journal *journal, int full)
-{
- int status;
-
- LOG_ENTRY();
-
- if (!journal)
- BUG();
-
- status = journal_wipe(journal->k_journal, full);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * JBD Might read a cached version of another nodes journal file. We
- * don't want this as this file changes often and we get no
- * notification on those changes. The only way to be sure that we've
- * got the most up to date version of those blocks then is to force
- * read them off disk. Just searching through the buffer cache won't
- * work as there may be pages backing this file which are still marked
- * up to date. We know things can't change on this file underneath us
- * as we have the lock by now :)
- *
- * size should be file_size, NOT alloc_size
- */
-static int ocfs_force_read_journal(ocfs_super *osb, __u64 size,
- ocfs_inode *oin)
-{
- int status = 0;
- int i, run;
- __u32 totalblks, alloc_size, numblks, numbytes, numruns;
- __s64 vbo = 0;
- __s64 lbo = 0;
- ocfs_extent_map *map = NULL;
- struct buffer_head **bhs = NULL;
-
- LOG_ENTRY();
-
- totalblks = size / osb->sect_size;
-
- /* Ok, allocate the maximum number of blocks we'll possibly
- * need. This is heavy, but it doesn't happen often. If need
- * be, we can change things to allocate a little memory at a
- * time. ocfs_journal_init should insure that our journals are
- * always *exactly* eight megs large, so running out of memory
- * should not be an issue here. */
- alloc_size = sizeof(struct buffer_head *) * totalblks;
- bhs = ocfs_malloc(alloc_size);
- if (bhs == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto bail;
- }
- memset(bhs, 0, alloc_size);
-
- LOG_TRACE_ARGS("Force reading %u blocks\n", totalblks);
-
- status = ocfs_lookup_file_allocation(osb, oin, vbo, &lbo, size, NULL,
- NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- map = &(oin->map);
- spin_lock(&(map->lock));
- numruns = map->count;
- spin_unlock(&(map->lock));
-
- LOG_TRACE_ARGS("%d runs in this file\n", numruns);
-
- for(run = 0; run < numruns; run++) {
- vbo = lbo = numbytes = 0;
- if (!ocfs_get_next_extent_map_entry(osb, map, run, &vbo, &lbo,
- &numbytes)) {
- LOG_ERROR_STR("Failure in "
- "ocfs_get_next_extent_map_entry");
- status = -EINVAL;
- goto bail;
- }
- LOG_TRACE_ARGS("(Run %d), lbo = %d.%d bytes, numbytes = %u "
- "bytes\n", run, HILO(lbo), numbytes);
-
- /* there are actually returned in bytes. need blocks. */
- numblks = numbytes / osb->sect_size;
-
- status = ocfs_read_bhs(osb, lbo, numbytes, bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- for(i = 0; i < numblks; i++) {
- brelse(bhs[i]);
- bhs[i] = NULL;
- }
- }
-
-bail:
- if (bhs) {
- for(i = 0; i < totalblks; i++)
- if (bhs[i])
- brelse(bhs[i]);
- ocfs_free(bhs);
- }
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-struct ocfs_recover_arg {
- ocfs_super *osb;
- int node_num;
-};
-
-static int __ocfs_recovery_thread(void *arg)
-{
- ocfs_super *osb = ((struct ocfs_recover_arg *) arg)->osb;
- int node_num = ((struct ocfs_recover_arg *) arg)->node_num;
- int status = 0;
-
- LOG_ENTRY_ARGS("(node_num=%d, osb->node_num = %d)\n", node_num,
- osb->node_num);
-
- daemonize();
- reparent_to_init();
-#ifdef HAVE_NPTL
- spin_lock_irq (¤t->sighand->siglock);
- sigfillset(¤t->blocked);
- recalc_sigpending();
- spin_unlock_irq (¤t->sighand->siglock);
-#else
- spin_lock_irq(¤t->sigmask_lock);
- sigfillset(¤t->blocked);
- recalc_sigpending(current);
- spin_unlock_irq(¤t->sigmask_lock);
-#endif
- sprintf(current->comm, "ocfs_recover");
-
- status = ocfs_recover_vol(osb, node_num);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- LOG_EXIT_STATUS(status);
-
- ocfs_free(arg);
- return status;
-}
-
-void ocfs_recovery_thread(ocfs_super *osb, int node_num)
-{
- struct ocfs_recover_arg *arg;
-
- LOG_ENTRY_ARGS("(node_num=%d, osb->node_num = %d)\n", node_num,
- osb->node_num);
-
- arg = ocfs_malloc(sizeof(struct ocfs_recover_arg));
- if (arg == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto done;
- }
-
- arg->osb = osb;
- arg->node_num = node_num;
-
- LOG_TRACE_STR("starting recovery thread...");
-
- kernel_thread(__ocfs_recovery_thread, (void *) arg,
- CLONE_VM | CLONE_FS | CLONE_FILES);
-
-done:
- LOG_EXIT();
- return;
-}
-
-/* TODO: We need to manually scan the config sectors at startup and
- * call this function on any that aren't clean... */
-static int ocfs_recover_vol(ocfs_super *osb, int node_num)
-{
- int status = -1;
- __u64 lock_id = 0;
- __u32 cleanup_file_id = 0;
- ocfs_lock_res *lock_res = NULL;
- ocfs_file_entry *fe = NULL;
- ocfs_inode *oin = NULL;
- struct inode *inode = NULL;
- journal_t *k_journal = NULL;
- ocfs_find_inode_args args;
- struct buffer_head *bh = NULL;
- ocfs_journal * journal = NULL;
- bool recovery_lock = false;
- struct buffer_head *config_bh = NULL;
- ocfs_disk_node_config_info *config = NULL;
-
- LOG_ENTRY_ARGS("(node_num=%d, osb->node_num = %d)\n", node_num,
- osb->node_num);
-
- if (!osb || !IS_VALID_NODE_NUM(node_num)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto done;
- }
-
- journal = &osb->journal;
-
- /* Grab the local recovery resource to ensure no other thread
- * comes in from this node for recovery */
- ocfs_down_sem (&(osb->recovery_lock), true);
- recovery_lock = true;
-
- /* get the cleanup file fe and lock */
- cleanup_file_id = (__u32) (JOURNAL_FILE_BASE_ID + node_num);
- lock_id = ((JOURNAL_FILE_BASE_ID + node_num) * osb->sect_size)
- + osb->vol_layout.root_int_off;
-
- /* Should not ever be called to recover ourselves -- in that
- * case we should've called ocfs_journal_load instead. */
- if (osb->node_num == node_num)
- BUG();
-
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_FILE_RECOVERY,
- &lock_res, &bh, NULL);
- if (status < 0) {
- LOG_TRACE_ARGS("status returned from acquire_lock=%d\n",
- status);
- if (status != -EINTR)
- LOG_ERROR_STR("Could not lock journal!");
- goto done;
- }
-
- /* check if that nodes publish sector has been reset (mounted
- * is set false) if so, we can unlock and quit. otherwise we
- * should recover. */
- if (!ocfs_journal_get_mount_state(osb, node_num)) {
- LOG_TRACE_ARGS("No recovery required for node %d\n", node_num);
- status = 0;
- goto clear_node;
- }
- printk("ocfs: Recovering node %d from device (%u,%u)\n", node_num,
- MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
-
- /* Absolutely need to make sure that the node is using the
- * correct journal version here! Otherwise VERY BAD THINGS
- * WILL HAPPEN. */
- status = ocfs_read_bh(osb,
- (osb->vol_layout.node_cfg_off + 1024 +
- node_num * osb->sect_size), &config_bh, 0,NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto done;
- }
-
- config = (ocfs_disk_node_config_info *) OCFS_BH_GET_DATA(config_bh);
- if (config->journal_version < OCFS_JOURNAL_CURRENT_VERSION) {
- OCFS_BH_PUT_DATA(config_bh);
- LOG_ERROR_ARGS("Cannot recover node %d, it has an old journal"\
- " configuration!\n", node_num);
- goto done;
- }
- OCFS_BH_PUT_DATA(config_bh);
-
- /* Ok, look up the inode for our journal */
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
- args.offset = fe->this_sector;
- args.fe_bh = bh;
- OCFS_BH_PUT_DATA(bh);
- fe = NULL;
-#ifdef LINUX_2_5
- inode = ocfs_iget (sb, &args);
-#else
- inode =
- iget4 (osb->sb, LO (args.offset),
- (find_inode_t) ocfs_find_inode, (void *) (&args));
-#endif
- if (inode == NULL) {
- LOG_ERROR_STR("access error");
- status = -EACCES;
- goto done;
- }
- if (is_bad_inode (inode)) {
- LOG_ERROR_STR("access error (bad inode)");
- iput (inode);
- inode = NULL;
- status = -EACCES;
- goto done;
- }
- LOG_TRACE_ARGS("inode->i_size = %u\n", inode->i_size);
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(bh);
- status = ocfs_create_new_oin(&oin, fe->alloc_size, osb);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto done;
- }
- status = ocfs_initialize_oin(oin, osb, 0, fe->this_sector, 0, false,
- NULL);
- oin->journal_inode = true;
- SET_INODE_OIN(inode, oin);
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_force_read_journal(osb, inode->i_size, oin);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto done;
- }
-
- /* init the journal, load it and possibly replay it */
- LOG_TRACE_STR("calling journal_init_inode");
- k_journal = journal_init_inode(inode);
- if (k_journal == NULL) {
- LOG_ERROR_STR("Linux journal layer error");
- status = -EIO;
- goto done;
- }
-
- status = journal_load(k_journal);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- atomic_inc(&inode->i_count);
- journal_destroy(k_journal);
- goto done;
- }
-
- /* wipe the journal */
- LOG_TRACE_STR("flushing the journal.");
- journal_lock_updates(k_journal);
- status = journal_flush(k_journal);
- journal_unlock_updates(k_journal);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- atomic_inc(&inode->i_count);
-
- /* shutdown the journal */
- journal_destroy(k_journal);
-
- /* recover his local alloc file, AFTER recovering his journal... */
- status = ocfs_recover_local_alloc(osb, node_num);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto done;
- }
-
- /* clear the publish sector (mark it unmounted and clean) */
- status = ocfs_reset_publish(osb, node_num);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- status = 0;
-
-clear_node:
- CLEAR_NODE_IN_RECOVERY(osb, node_num);
- ocfs_recover_oin_locks(osb, node_num);
-done:
- /* close the journal file */
- if (inode)
- inode->i_flags &= ~S_OCFS_OIN_VALID;
-
- if (oin)
- ocfs_release_oin(oin, true);
-
- if (inode)
- iput(inode);
-
- if (recovery_lock)
- ocfs_up_sem (&(osb->recovery_lock));
-
- /* drop the lock on this nodes journal */
- if (lock_res)
- status = ocfs_release_lock(osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_FILE_RECOVERY,
- lock_res, bh, NULL);
- if (bh)
- brelse(bh);
-
- if (config_bh)
- brelse(config_bh);
-
- if (lock_res)
- ocfs_put_lockres (lock_res);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-/*
- * ocfs_reset_publish()
- *
- *
- * called by: old_ocfs_recover_vol()
- *
- * NOTE: This function is very similar to ocfs_disk_reset_voting().
- * This function should replace the other one.
- *
- * NOTE: This function is unused. I keep it here because it may be
- * useful in the future. --Mark (Sept. 22, 2003)
- */
-static int ocfs_reset_publish (ocfs_super * osb, __u64 node_num)
-{
- int status = 0;
- ocfs_publish *publish = NULL;
- struct buffer_head *publish_bh = NULL;
- __u64 node_publ_off;
-
- LOG_ENTRY_ARGS("(0x%08x, %u.%u)\n", osb, HI (node_num), LO (node_num));
-
- /* take a lock on the publish sector */
- down (&(osb->publish_lock));
-
- /* Read the publish sector */
- node_publ_off = osb->vol_layout.publ_sect_off +
- (node_num * osb->sect_size);
- status = ocfs_read_bh(osb, node_publ_off, &publish_bh,
- OCFS_BH_COND_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(publish_bh);
-
- publish->dirty = false;
- publish->vote = 0;
- publish->vote_type = 0;
- publish->mounted = false;
-
- OCFS_BH_PUT_DATA(publish_bh);
-
- /* Write the publish sector */
- status = ocfs_write_bh(osb, publish_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
-finally:
- /* unlock it */
- up (&(osb->publish_lock));
-
- if (publish_bh)
- brelse(publish_bh);
-
- LOG_EXIT_STATUS (status);
- return (status);
-} /* ocfs_reset_publish */
-
-/*
- * ocfs_commit_cache()
- *
- * This is in journal.c for lack of a better place.
- *
- * This function must be called with the trans_lock held.
- * No, really this function MUST be called with the trans_lock held!
- *
- * In any case, it will release the trans lock for you.
- */
-int ocfs_commit_cache (ocfs_super * osb, bool data_flush)
-{
- int status = 0, tmpstat;
- ocfs_journal * journal = NULL;
- struct list_head *p, *n;
- struct list_head tmplist;
- ocfs_journal_handle *handle = NULL;
-
- LOG_ENTRY_ARGS("(data_flush = %u)\n", data_flush);
-
- if (down_trylock(&osb->trans_lock) == 0)
- BUG();
-
- journal = &osb->journal;
-
- if (atomic_read(&journal->num_trans) == 0) {
- up(&osb->trans_lock);
-
- LOG_TRACE_STR("No transactions for me to flush!");
- goto flush_data;
- }
-
- /* flush all pending commits and checkpoint the journal. */
- journal_lock_updates(journal->k_journal);
- status = journal_flush(journal->k_journal);
- journal_unlock_updates(journal->k_journal);
- if (status < 0) {
- up(&osb->trans_lock);
-
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- LOG_TRACE_ARGS("flushing %d transactions\n",
- atomic_read(&journal->num_trans));
-
- atomic_set(&journal->num_trans, 0);
-
- /* now we can run an unlock against any pending handles and
- * release them. */
- INIT_LIST_HEAD(&tmplist);
-
- down(&journal->commit_sem);
- /* we want to take everything off the commited list and
- * process it independently, so we can drop the trans_lock
- * earlier. */
- if (!list_empty(&journal->commited)) {
- list_splice(&journal->commited , (&tmplist));
- INIT_LIST_HEAD(&journal->commited);
- }
- up(&journal->commit_sem);
-
- osb->needs_flush = false;
- /* shutdown code wants to hold the trans lock */
- if (journal->state != OCFS_JOURNAL_IN_SHUTDOWN)
- up(&osb->trans_lock);
-
- list_for_each_safe(p, n, &tmplist) {
- handle = list_entry(p, ocfs_journal_handle, h_list);
- tmpstat = ocfs_journal_release_locks(handle, 0);
- if (tmpstat < 0)
- LOG_ERROR_STATUS((status = tmpstat));
- list_del(&(handle->h_list));
- ocfs_free(handle);
- }
-
-flush_data:
- /* flush data buffers if asked. */
- if (data_flush)
- ocfs_sync_blockdev(osb->sb);
-
-finally:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_commit_cache */
-
-#ifdef USE_JOURNAL_CREATE_REPLACEMENT
-/*
- * This code is here because a bug in journal_create exists which will
- * cause us to hang at mount time. This bug exists in all 2.4 kernels
- * before 2.4.22. RHEL3 and RHAS 2.1 (update 3 and later) do not
- * exhibit this bug either.
- *
- * The fix is a one liner, and including this file is a hack which
- * should be removed at the first convenient moment.
- *
- * Unfortunately, we *must* be able to call journal_create at mount
- * time, so we have to keep this here for those unpatched kernels.
- *
- * Taken from the JBD implimentation in 2.4.23
- */
-
-#warning "using replacement code for journal_create"
-
-static void journal_fail_superblock (journal_t *journal)
-{
- struct buffer_head *bh = journal->j_sb_buffer;
- brelse(bh);
- journal->j_sb_buffer = NULL;
-}
-
-static int ocfs_replacement_journal_create(journal_t *journal)
-{
- unsigned long blocknr;
- struct buffer_head *bh;
- journal_superblock_t *sb;
- int i, err = 0;
- unsigned int first, last;
-
- LOG_ENTRY();
-
- if (journal->j_maxlen < JFS_MIN_JOURNAL_BLOCKS) {
- printk (KERN_ERR "Journal length (%d blocks) too short.\n",
- journal->j_maxlen);
- journal_fail_superblock(journal);
- err = -EINVAL;
- goto bail;
- }
-
- if (journal->j_inode == NULL) {
- /*
- * We don't know what block to start at!
- */
- printk(KERN_EMERG "%s: creation of journal on external "
- "device!\n", __FUNCTION__);
- BUG();
- }
-
- /* Zero out the entire journal on disk. We cannot afford to
- have any blocks on disk beginning with JFS_MAGIC_NUMBER. */
- jbd_debug(1, "JBD: Zeroing out journal blocks...\n");
- for (i = 0; i < journal->j_maxlen; i++) {
- err = journal_bmap(journal, i, &blocknr);
- if (err)
- goto bail;
- bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
- wait_on_buffer(bh);
- memset (bh->b_data, 0, journal->j_blocksize);
- BUFFER_TRACE(bh, "marking dirty");
- mark_buffer_dirty(bh);
- BUFFER_TRACE(bh, "marking uptodate");
- mark_buffer_uptodate(bh, 1);
- brelse(bh);
- }
-
- fsync_no_super(journal->j_dev);
- jbd_debug(1, "JBD: journal cleared.\n");
-
- /* OK, fill in the initial static fields in the new superblock */
- sb = journal->j_superblock;
-
- sb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
- sb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
-
- sb->s_blocksize = htonl(journal->j_blocksize);
- sb->s_maxlen = htonl(journal->j_maxlen);
- sb->s_first = htonl(1);
-
- journal->j_transaction_sequence = 1;
-
- journal->j_flags &= ~JFS_ABORT;
- journal->j_format_version = 2;
-
- /* copied out of journal_reset */
- first = ntohl(sb->s_first);
- last = ntohl(sb->s_maxlen);
-
- journal->j_first = first;
- journal->j_last = last;
-
- journal->j_head = first;
- journal->j_tail = first;
- journal->j_free = last - first;
-
- journal->j_tail_sequence = journal->j_transaction_sequence;
- journal->j_commit_sequence = journal->j_transaction_sequence - 1;
- journal->j_commit_request = journal->j_commit_sequence;
-
- journal->j_max_transaction_buffers = journal->j_maxlen / 4;
-
- /* Add the dynamic fields and write it to disk. */
- journal_update_superblock(journal, 1);
-
-bail:
- if (!err) {
- LOG_TRACE_STR("Calling journal_load...");
- err = journal_load(journal);
- }
- LOG_EXIT_STATUS(err);
- return(err);
-}
-#endif
Deleted: trunk/namei.c
===================================================================
--- trunk/namei.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/namei.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1639 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-static int ocfs_fe_smash (ocfs_super * osb, __u64 lock_node_off, __u32 flags, __u64 file_off, ocfs_journal_handle *passed_handle, ocfs_bitmap_free_head **ret_head, struct inode *inode, struct inode *parent_inode);
-static int ocfs_rename_file (ocfs_super * osb, ocfs_journal_handle *handle, __u64 parent_off, struct dentry *dentry, __u64 file_off, struct inode *dir_inode);
-static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir,
- struct dentry *dentry, int mode,
- ocfs_dev dev, struct buffer_head *lock_bh,
- struct buffer_head **new_fe_bh,
- ocfs_journal_handle *handle,
- struct inode *inode);
-static int ocfs_double_lock(ocfs_super *osb, ocfs_journal_handle *handle,
- __u64 id1, __u32 type1, __u32 flags1,
- ocfs_lock_res **res1, struct buffer_head **bh1,
- struct inode *inode1,
- __u64 id2, __u32 type2, __u32 flags2,
- ocfs_lock_res **res2, struct buffer_head **bh2,
- struct inode *inode2);
-
-static struct dentry_operations ocfs_dentry_ops = {
- .d_revalidate = ocfs_dentry_revalidate // let's test it out!
-};
-
-/*
- * ocfs_lookup()
- *
- */
-struct dentry *ocfs_lookup (struct inode *dir, struct dentry *dentry)
-{
- int status;
- ocfs_find_inode_args args;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *fe_bh = NULL;
- ocfs_inode *parentOin = NULL;
- __u64 parentOffset;
- struct inode *inode = NULL;
- struct super_block *sb = dir->i_sb;
- struct dentry *ret;
- ocfs_super *osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", dir, dentry,
- dentry->d_name.len, dentry->d_name.name);
-
- atomic_inc (&dir->i_count);
-
- if (dentry->d_name.len > OCFS_MAX_FILENAME_LENGTH) {
- LOG_ERROR_STR ("name too long");
- ret = ERR_PTR (-ENAMETOOLONG);
- goto bail;
- }
-
- if (!ocfs_linux_get_inode_offset (dir, &parentOffset, &parentOin)) {
- LOG_ERROR_STR ("bad offset in parent inode");
- ret = ERR_PTR (-EACCES);
- goto bail;
- }
-
-// fe = ocfs_allocate_file_entry();
-// if (!fe) {
-// LOG_ERROR_STR("could not allocate file entry");
-// ret = ERR_PTR (-ENOMEM);
-// goto bail;
-// }
-
- status = ocfs_find_files_on_disk (osb, parentOffset, &(dentry->d_name), &fe_bh, NULL, dir);
- if (status >= 0) {
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- args.offset = fe->this_sector;
-// args.entry = fe;
- args.fe_bh = fe_bh;
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
-#ifdef LINUX_2_5
- inode = ocfs_iget (sb, &args);
-#else
- inode =
- iget4 (sb, LO (args.offset),
- (find_inode_t) ocfs_find_inode, (void *) (&args));
-#endif
- if (inode == NULL) {
- LOG_ERROR_STR("access error");
- ret = ERR_PTR (-EACCES);
- goto bail;
- }
- if (is_bad_inode (inode)) {
- LOG_ERROR_STR("access error (bad inode)");
- iput (inode);
- inode = NULL;
- ret = ERR_PTR (-EACCES);
- goto bail;
- }
- }
- dentry->d_op = &ocfs_dentry_ops;
- d_add (dentry, inode);
- ret = NULL;
-
-bail:
-// if (fe)
-// ocfs_release_file_entry (fe);
- if (fe_bh)
- brelse(fe_bh);
-
- atomic_dec (&dir->i_count);
- LOG_EXIT_PTR (ret);
- return ret;
-} /* ocfs_lookup */
-
-int ocfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
- ocfs_dev dev)
-{
- int status = 0;
- struct buffer_head *lock_bh = NULL;
- __u64 parent_off;
- __u64 file_off = 0;
- __u64 dirnode_off;
- __u32 oinflags;
- ocfs_lock_res *lock_res = NULL;
- ocfs_journal_handle *handle = NULL;
- ocfs_super *osb;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *new_fe_bh = NULL;
- ocfs_inode *ParentOin = NULL;
- ocfs_inode *oin = NULL;
- struct inode *inode = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, %d, '%*s')\n", dir, dentry, mode,
- dev, dentry->d_name.len, dentry->d_name.name);
-
- atomic_inc (&dir->i_count);
-
- inode = new_inode (dir->i_sb);
- if (IS_ERR (inode)) {
- status = PTR_ERR(inode);
- LOG_ERROR_STR("new_inode failed!");
- goto leave;
- }
-
- /* get our super block */
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(dir->i_sb);
- if (osb->osb_flags & OCFS_OSB_FLAGS_SHUTDOWN) {
- LOG_ERROR_STR ("Volume has been shutdown");
- status = -EACCES;
- goto leave;
- }
-
- /* need the offset of our parent directory to lock it */
- if (!ocfs_linux_get_inode_offset (dir, &parent_off, NULL)) {
- LOG_ERROR_STATUS (status = -ENOENT);
- goto leave;
- }
-
- /* start the transaction */
- handle = ocfs_start_trans(osb, OCFS_MKNOD_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- ocfs_handle_set_checkpoint(handle, false);
-#ifdef ALLOW_NO_HANDLE_SYNCING
- ocfs_handle_set_sync(handle, false);
-#endif
-
- /* lock the parent directory */
- status = ocfs_acquire_lock (osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE | FLAG_DIR,
- &lock_res, &lock_bh, dir);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- ocfs_abort_trans(handle);
- goto leave;
- }
-
- /* Ok, we got the lock -- we'd better add it to our transaction */
- ocfs_journal_add_lock(handle, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE | FLAG_DIR, lock_res, lock_bh);
-
- /* do the real work now. */
- status = ocfs_mknod_locked(osb, dir, dentry, mode, dev, lock_bh,
- &new_fe_bh, handle, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS(status);
- ocfs_abort_trans(handle);
- goto leave;
- } else if (ocfs_commit_trans(handle) < 0)
- LOG_ERROR_STR("Could not complete create!");
-
- status = ocfs_create_new_oin (&oin, 0ULL, osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(new_fe_bh);
-
- file_off = fe->this_sector;
- dirnode_off = fe->extents[0].disk_off;
- oinflags = OCFS_OIN_CACHE_UPDATE | (S_ISDIR (mode) ? OCFS_OIN_DIRECTORY : 0);
-
- OCFS_BH_PUT_DATA(new_fe_bh);
- fe = NULL;
-
- status = ocfs_initialize_oin (oin, osb, oinflags, file_off,
- S_ISDIR (mode) ? dirnode_off : file_off, true, inode);
-
- if (!ocfs_linux_get_inode_offset (dir, &parent_off, &ParentOin)) {
- LOG_ERROR_STATUS (status = -ENOENT);
- goto leave;
- }
-
- if (ParentOin)
- OCFS_CLEAR_FLAG (ParentOin->oin_flags, OCFS_OIN_IN_USE);
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(new_fe_bh);
-
- /* is this safe if we no longer have it locked? */
- if (oin->lock_res != NULL) {
- oin->lock_res->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
- oin->lock_res->lock_state = DISK_LOCK_FILE_LOCK (fe);
- }
-
- /* Insert the OFile on the OIN list */
- oin->chng_seq_num = DISK_LOCK_SEQNUM (fe);
- oin->parent_dirnode_off = parent_off;
-
- if (S_ISDIR (mode))
- oin->dir_disk_off = fe->extents[0].disk_off;
-
- status = 0;
-
-leave:
- if (status >= 0 && !IS_ERR (inode)) {
- inode->i_ino = LO (oin->file_disk_off);
- oin->inode = inode;
- ocfs_populate_inode (inode, fe, mode, oin);
- insert_inode_hash (inode);
- d_instantiate (dentry, inode);
- } else if (status == -ENOSPC)
- LOG_TRACE_STR ("Disk is full");
- else if (status != -EINTR)
- LOG_ERROR_STATUS(status);
-
- if (new_fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(new_fe_bh);
- brelse(new_fe_bh);
- }
-
- if (lock_bh != NULL)
- brelse(lock_bh);
-
- atomic_dec (&dir->i_count);
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_mknod */
-
-/*
- * ocfs_mknod_locked()
- *
- */
-static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir,
- struct dentry *dentry, int mode,
- ocfs_dev dev, struct buffer_head *lock_bh,
- struct buffer_head **new_fe_bh,
- ocfs_journal_handle *handle,
- struct inode *inode)
-{
- int status = 0;
- ocfs_file_entry *fe = NULL;
- ocfs_dir_node *pLockNode = NULL;
- __u64 t;
- struct buffer_head *fe_bh = NULL;
- bool cache_lock;
- int i;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, %d, '%*s')\n", dir, dentry, mode,
- dev, dentry->d_name.len, dentry->d_name.name);
-
- if (new_fe_bh)
- *new_fe_bh = NULL;
-
- if ((fe = ocfs_allocate_file_entry ()) == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- memset (fe, 0, sizeof (ocfs_file_entry));
- fe->uid = current->fsuid;
- fe->gid = current->fsgid;
- fe->prot_bits = mode & 0007777;
- if (S_ISCHR (mode) || S_ISBLK (mode)) {
-#ifdef LINUX_2_5
- fe->dev_major = major (to_kdev_t(dev));
- fe->dev_minor = minor (to_kdev_t(dev));
-#else
- fe->dev_major = MAJOR (dev);
- fe->dev_minor = MINOR (dev);
-#endif
- } else {
- fe->dev_major = MAJOR (dir->i_sb->s_dev);
- fe->dev_minor = MINOR (dir->i_sb->s_dev);
- }
-
- if (S_ISLNK (mode) || S_ISDIR (mode) || S_ISREG (mode)) {
- atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
- }
-
- if (S_ISLNK (mode))
- fe->attribs |= OCFS_ATTRIB_SYMLINK;
- else if (S_ISCHR (mode))
- fe->attribs |= OCFS_ATTRIB_CHAR;
- else if (S_ISBLK (mode))
- fe->attribs |= OCFS_ATTRIB_BLOCK;
- else if (S_ISFIFO (mode))
- fe->attribs |= OCFS_ATTRIB_FIFO;
- else if (S_ISSOCK (mode))
- fe->attribs |= OCFS_ATTRIB_SOCKET;
- else if (S_ISDIR (mode))
- fe->attribs |= OCFS_ATTRIB_DIRECTORY;
- else
- fe->attribs |= OCFS_ATTRIB_REG;
-
- strncpy (fe->filename, dentry->d_name.name, dentry->d_name.len);
- fe->filename[dentry->d_name.len]='\0';
- fe->filename_len = dentry->d_name.len;
- fe->local_ext = true;
- fe->granularity = -1;
- fe->next_free_ext = 0;
- fe->last_ext_ptr = 0;
- strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
- SET_VALID_BIT (fe->sync_flags);
- fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
- DISK_LOCK_SEQNUM (fe) = osb->curr_trans_id;
- DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_READER_NODE (fe) = osb->node_num;
- DISK_LOCK_WRITER_NODE (fe) = osb->node_num;
- OcfsQuerySystemTime(&t);
- DISK_LOCK_LAST_WRITE(fe) = t;
- DISK_LOCK_LAST_READ(fe) = t;
-
- fe->create_time = fe->modify_time = OCFS_CURRENT_TIME;
-
- pLockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(lock_bh);
- /* is this always going to be false, considering we just
- * passed OCFS_DLM_EXCLUSIVE_LOCK above? */
- cache_lock = (DISK_LOCK_FILE_LOCK (pLockNode) == OCFS_DLM_ENABLE_CACHE_LOCK);
- OCFS_BH_PUT_DATA(lock_bh);
-
-
- if (S_ISDIR (mode)) {
- __u64 bitmapOffset;
- __u64 fileOffset = 0;
- ocfs_dir_node *new_dir = NULL;
- struct buffer_head **dirbhs = NULL;
- int numblks;
- int bufsize;
- void *tmp;
-
- numblks = osb->vol_layout.dir_node_size >> 9;
- bufsize = numblks * sizeof(struct buffer_head *);
- dirbhs = ocfs_malloc(bufsize);
- if (dirbhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(dirbhs, 0, bufsize);
-
- /* allocate directory space and setup pointers */
- status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size, &bitmapOffset, &fileOffset, osb->node_num, DISK_ALLOC_DIR_NODE, handle);
- if (status < 0) {
- ocfs_safefree (dirbhs);
- OCFS_BH_PUT_DATA(lock_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe->alloc_size = osb->vol_layout.dir_node_size;
- fe->extents[0].disk_off = bitmapOffset;
- fe->file_size = osb->vol_layout.dir_node_size;
- fe->next_del = INVALID_DIR_NODE_INDEX;
-
- if (!cache_lock)
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
-
- status = ocfs_read_bhs(osb, bitmapOffset, osb->vol_layout.dir_node_size, dirbhs, OCFS_BH_CACHED, NULL);
- if (status < 0) {
- ocfs_safefree (dirbhs);
- OCFS_BH_PUT_DATA(lock_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- for (i = 0; i < numblks; i++) {
- tmp = OCFS_BH_GET_DATA(dirbhs[i]);
- memset(tmp, 0, osb->sect_size);
- OCFS_BH_PUT_DATA(dirbhs[i]);
- }
-
- new_dir = (ocfs_dir_node *) OCFS_BH_GET_DATA(dirbhs[0]);
- ocfs_initialize_dir_node (osb, new_dir, bitmapOffset,
- fileOffset, osb->node_num);
-
- DISK_LOCK_CURRENT_MASTER (new_dir) = osb->node_num;
- DISK_LOCK_FILE_LOCK (new_dir) = OCFS_DLM_ENABLE_CACHE_LOCK;
- new_dir->dir_node_flags |= DIR_NODE_FLAG_ROOT;
-
- OCFS_BH_PUT_DATA(dirbhs[0]);
- new_dir = NULL;
-
- /* Sunil tells me that, not only does the new dirnode
- * header have to hit disk, but the rest of it has to
- * be zeroed out too. At least this will populate the
- * cache now... */
- status = ocfs_write_bhs(osb, dirbhs, numblks, 0, NULL);
- if (status < 0) {
- for(i=0; i < numblks; i++)
- brelse(dirbhs[i]);
- ocfs_safefree (dirbhs);
- OCFS_BH_PUT_DATA(lock_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* cleanup after ourselves */
- for(i=0; i < numblks; i++)
- brelse(dirbhs[i]);
-
- ocfs_safefree (dirbhs);
- }
-
- if (S_ISDIR (mode) && !cache_lock)
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
-
- status = ocfs_insert_file (osb, fe, lock_bh, &fe_bh, handle, dir, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (new_fe_bh)
- *new_fe_bh = fe_bh;
-
- SET_BH_SEQNUM(inode, fe_bh);
-leave:
- ocfs_release_file_entry(fe);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_mknod_locked */
-
-/*
- * ocfs_mkdir()
- *
- */
-int ocfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, '%*s')\n", dir, dentry, mode,
- dentry->d_name.len, dentry->d_name.name);
- ret = ocfs_mknod (dir, dentry, mode | S_IFDIR, OCFS_NODEV);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_mkdir */
-
-/*
- * ocfs_create()
- *
- */
-int ocfs_create (struct inode *dir, struct dentry *dentry, int mode)
-{
- int ret;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, %d, '%*s')\n", dir, dentry, mode,
- dentry->d_name.len, dentry->d_name.name);
- ret = ocfs_mknod (dir, dentry, mode | S_IFREG, OCFS_NODEV);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_create */
-
-/*
- * ocfs_link()
- *
- */
-int ocfs_link (struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
-{
- int status = -EPERM;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, 0x%08x, old='%*s' new='%*s')\n", old_dentry, dir, dentry,
- old_dentry->d_name.len, old_dentry->d_name.name,
- dentry->d_name.len, dentry->d_name.name);
-
- LOG_EXIT_LONG (status);
- return status;
-} /* ocfs_link */
-
-/*
- * ocfs_unlink()
- *
- */
-int ocfs_unlink (struct inode *dir, struct dentry *dentry)
-{
- int status, tmpstat;
- struct inode *inode;
- ocfs_inode *oin = NULL;
- int retval = -EBUSY;
- ocfs_lock_res *lockres;
- ocfs_super *osb = NULL;
- __u64 parentOff, fileOff;
- bool do_release = false;
- struct inode *parentInode = dentry->d_parent->d_inode;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, '%*s')\n", dir, dentry,
- dentry->d_name.len, dentry->d_name.name);
-
- inode = dentry->d_inode;
- osb = (ocfs_super *)OCFS_GENERIC_SB_P(dir->i_sb);
- if (inode_data_is_oin (inode))
- oin = GET_INODE_OIN(inode);
-
- LOG_TRACE_ARGS("oin = 0x%08x\n", oin);
- ocfs_linux_get_inode_offset (dir, &parentOff, NULL);
-
- if (S_ISDIR (inode->i_mode))
- ocfs_linux_get_dir_entry_offset (osb, &fileOff, parentOff,
- &(dentry->d_name), NULL, dir);
- else
- ocfs_linux_get_inode_offset (inode, &fileOff, NULL);
-
- status = -EBUSY;
- if (atomic_read (&inode->i_count) > 1 || atomic_read (&dentry->d_count) > 2) {
- LOG_TRACE_STR ("i_count > 1 or d_count > 2");
- } else if (!ocfs_empty(dentry)) {
- LOG_TRACE_STR ("dentry is not empty, cannot delete");
- } else if (oin && oin->open_hndl_cnt > 0) {
- LOG_TRACE_STR ("Cannot remove an open file");
- } else if (oin && oin->oin_flags & OCFS_OIN_ROOT_DIRECTORY) {
- LOG_TRACE_STR ("Cannot delete the root directory");
- status = -EPERM;
- } else if (oin && oin->oin_flags & OCFS_OIN_DELETE_ON_CLOSE) {
- LOG_TRACE_STR ("OCFS_OIN_DELETE_ON_CLOSE set");
- status = 0;
- do_release = true;
- } else {
- status = -EFAIL;
- do_release = true;
-
- if (oin) {
- ocfs_down_sem (&(oin->main_res), true);
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
- ocfs_up_sem (&(oin->main_res));
- }
-
- if (fileOff != -1)
- status = ocfs_fe_smash (osb, parentOff, 0, fileOff,
- NULL, NULL, inode, parentInode);
-
- if (status < 0) {
- if (status != -ENOTEMPTY && status != -EPERM &&
- status != -EBUSY && status != -EINTR)
- LOG_ERROR_STATUS(status);
-
- if (oin) {
- ocfs_down_sem (&(oin->main_res), true);
- OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
- OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_OIN_IN_USE);
- ocfs_up_sem (&(oin->main_res));
- }
- }
-
- if (status >= 0 && oin)
- ocfs_release_cached_oin (osb, oin);
- }
-
- if (do_release)
- {
- if (oin)
- ocfs_release_oin (oin, true);
- else {
- if (fileOff != -1) {
- tmpstat = ocfs_lookup_sector_node (osb, fileOff, &lockres);
- if (tmpstat >= 0 && lockres) {
- ocfs_remove_sector_node (osb, lockres);
- ocfs_put_lockres (lockres);
- } else
- LOG_TRACE_STR ("lookup sectornode failed\n");
- }
- }
-
- inode->i_nlink--;
- retval = 0;
- }
-
- if (status < 0 && status != -ENOTEMPTY &&
- status != -EPERM && status != -EBUSY)
- retval = -EBUSY;
- else
- retval = status;
- LOG_EXIT_LONG (retval);
- return retval;
-} /* ocfs_unlink */
-
-/*
- * ocfs_double_lock()
- *
- * The only place this should be used is rename!
- * if they have the same id, then the 1st one is the only one locked.
- */
-static int ocfs_double_lock(ocfs_super *osb, ocfs_journal_handle *handle,
- __u64 id1, __u32 type1, __u32 flags1,
- ocfs_lock_res **res1, struct buffer_head **bh1,
- struct inode *inode1,
- __u64 id2, __u32 type2, __u32 flags2,
- ocfs_lock_res **res2, struct buffer_head **bh2,
- struct inode *inode2)
-{
- int status = 0;
- bool id2_locked = false;
- __u64 tmpid;
- __u32 tmptype, tmpflags;
- ocfs_lock_res **tmpres;
- struct buffer_head **tmpbh;
- struct inode *tmpinode;
-
- LOG_ENTRY_ARGS("(lock_id1 = %u.%u, lock_id2 = %u.%u)\n", HILO(id1),
- HILO(id2));
-
- if (*bh1)
- *bh1 = NULL;
- if (*bh2)
- *bh2 = NULL;
- *res1 = *res2 = NULL;
-
- /* we always want to lock the one with the lower lockid first. */
- if (id1 != id2) {
- if (id1 < id2) {
- /* switch id1 and id2 around */
- LOG_TRACE_STR("switching them around...");
- tmpid = id2;
- id2 = id1;
- id1 = tmpid;
-
- tmptype = type2;
- type2 = type1;
- type1 = tmptype;
-
- tmpflags = flags2;
- flags2 = flags1;
- flags1 = tmpflags;
-
- tmpres = res2;
- res2 = res1;
- res1 = tmpres;
-
- tmpbh = bh2;
- bh2 = bh1;
- bh1 = tmpbh;
-
- tmpinode = inode2;
- inode2 = inode1;
- inode1 = tmpinode;
- }
- /* lock id2 */
- status = ocfs_acquire_lock(osb, id2, type2, flags2, res2, bh2, inode2);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- id2_locked = true;
- }
- /* lock id1 */
- status = ocfs_acquire_lock(osb, id1, type1, flags1,
- res1, bh1, inode1);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-bail:
- if (status < 0) {
- if (id2_locked) {
- status = ocfs_release_lock(osb, id2, type2, flags2,
- *res2, *bh2, inode2);
- ocfs_put_lockres(*res2);
- *res2 = NULL;
- if (bh2) {
- brelse(*bh2);
- *bh2 = NULL;
- }
- }
- } else if (handle) {
- if (id2_locked)
- ocfs_journal_add_lock(handle, id2, type2, flags2,
- *res2, *bh2);
- ocfs_journal_add_lock(handle, id1, type1, flags1, *res1, *bh1);
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_double_lock */
-
-/*
- * ocfs_rename()
- *
- */
-int ocfs_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
-{
- int status = 0;
- struct inode *old_inode = old_dentry->d_inode;
- struct inode *new_inode = new_dentry->d_inode;
- ocfs_inode *newOIN = NULL, *oldOIN = NULL;
- ocfs_file_entry *newfe = NULL, *oldfe = NULL;
- struct buffer_head *oldfe_bh = NULL;
- struct buffer_head *newfe_bh = NULL;
- ocfs_file_entry *tmpfe = NULL;
- ocfs_super *osb = NULL;
- __u64 oldOffset, newDirOff, oldDirOff, t;
- bool DeleteTargetOin = false;
- __u64 tmpoff = 0;
- bool kill_newfe = false;
- ocfs_bitmap_free_head *free_head = NULL;
- ocfs_journal_handle *handle = NULL;
- __u32 dir_lock_flags = FLAG_FILE_CREATE | FLAG_DIR;
- ocfs_lock_res * old_dir_lock = NULL;
- ocfs_lock_res * new_dir_lock = NULL;
- ocfs_lock_res * oldfe_lock = NULL;
- ocfs_lock_res * newfe_lock = NULL;
- struct buffer_head *old_dir_bh = NULL;
- struct buffer_head *new_dir_bh = NULL;
- __u32 oldfe_flags = 0;
- __u32 oldfe_lockid = 0;
- __u32 newfe_flags = 0;
- __u32 newfe_lockid = 0;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, 0x%08x, 0x%08x, from='%*s' to='%*s')\n",
- old_dir, old_dentry, new_dir, new_dentry,
- old_dentry->d_name.len, old_dentry->d_name.name,
- new_dentry->d_name.len, new_dentry->d_name.name);
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(old_dir->i_sb);
-
- /* old parent dir offset */
- ocfs_linux_get_inode_offset (old_dir, &oldDirOff, NULL);
-
- /* old file offset */
- ocfs_linux_get_inode_offset (old_dentry->d_inode, &oldOffset, &oldOIN);
- if (S_ISDIR (old_dentry->d_inode->i_mode)) {
- /* overwrite oldOffset to get ptr to OCFS_FILE_ENTRY
- * not DIR_NODE */
- ocfs_linux_get_dir_entry_offset (osb, &oldOffset, oldDirOff, &(old_dentry->d_name), NULL, old_dir);
- }
-
- /* new parent dir offset */
- if (inode_data_is_oin (new_dir))
- newDirOff = (GET_INODE_OIN(new_dir))->dir_disk_off;
- else
- newDirOff = GET_INODE_OFFSET (new_dir);
-
- if (new_dentry->d_inode != NULL && inode_data_is_oin (new_dentry->d_inode))
- newOIN = GET_INODE_OIN(new_dentry->d_inode);
-
- if (atomic_read (&old_inode->i_count) > 1) {
- status = -EBUSY;
- goto bail;
- } else if (atomic_read (&old_dentry->d_count) > 2) {
- shrink_dcache_parent (old_dentry);
- if (atomic_read (&old_dentry->d_count) > 2) {
- status = -EBUSY;
- goto bail;
- }
- }
-
- if (new_inode && S_ISDIR (old_inode->i_mode) &&
- !ocfs_empty (new_dentry)) {
- status = -ENOTEMPTY;
- LOG_TRACE_STR ("New (directory) dentry NOT empty!");
- goto bail;
- }
-
- if (oldOIN) {
- if (oldOIN->open_hndl_cnt != 0) {
- status = -EBUSY;
- goto finally;
- }
- }
-
- /* Don't ever take the main resource for the OIN before this as */
- /* Locking hierarchy will be broken */
-
- if (newOIN) {
- if (!(newOIN->oin_flags & OCFS_OIN_IN_TEARDOWN) &&
- !(newOIN->oin_flags & OCFS_OIN_DELETE_ON_CLOSE)) {
- /* OIN exists and it's not marked for deletion! */
- ocfs_down_sem (&(newOIN->main_res), true);
- OCFS_SET_FLAG (newOIN->oin_flags, OCFS_OIN_IN_USE);
- ocfs_up_sem (&(newOIN->main_res));
- status = ocfs_verify_update_oin (osb, newOIN);
- DeleteTargetOin = true;
- }
- }
-
- /* start our transaction */
- handle = ocfs_start_trans(osb, OCFS_FILE_RENAME_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto finally;
- }
-
- /* for the (possibly two) parent directory locks, we just put
- * them in the journal handle to be released by
- * commit/abort. For rename, this is only a convenience and if
- * it is a problem, we can move the release_locks into the
- * bottom of this function. */
-
- /* if old and new are the same, this'll just do one lock. */
- status = ocfs_double_lock(osb, handle,
- oldDirOff, OCFS_DLM_EXCLUSIVE_LOCK,
- dir_lock_flags, &old_dir_lock,
- &old_dir_bh, old_dir,
- newDirOff, OCFS_DLM_EXCLUSIVE_LOCK,
- dir_lock_flags, &new_dir_lock,
- &new_dir_bh, new_dir);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- status = ocfs_read_bh(osb, oldOffset, &oldfe_bh, OCFS_BH_CACHED, old_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- /* lock old_fe. we read it ourselves instead of letting
- * acquire_lock do it because if it's a directory, we lock the
- * dirnode instead. */
- oldfe = (ocfs_file_entry *) OCFS_BH_GET_DATA(oldfe_bh);
- if (oldfe->attribs & OCFS_ATTRIB_DIRECTORY) {
- oldfe_lockid = oldfe->extents[0].disk_off;
- oldfe_flags = FLAG_DIR;
- } else
- oldfe_lockid = oldfe->this_sector;
-
- OCFS_BH_PUT_DATA(oldfe_bh);
- oldfe = NULL;
- if (old_dir != new_dir)
- oldfe_flags |= FLAG_FILE_DELETE;
- else
- oldfe_flags |= FLAG_FILE_RENAME;
-
- status = ocfs_acquire_lock(osb, oldfe_lockid, OCFS_DLM_EXCLUSIVE_LOCK,
- oldfe_flags, &oldfe_lock, NULL, old_dir);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- /* check if the target already exists (in which case we need
- * to delete it */
- status = ocfs_find_files_on_disk(osb, newDirOff, &(new_dentry->d_name),
- &newfe_bh, NULL, new_dir);
-
- /* The only error we allow here is -ENOENT because the new
- * file not existing is perfectly valid. */
- if ((status < 0) && (status != -ENOENT)) {
- /* If we cannot find the file specified we should just */
- /* return the error... */
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- if (status == 0)
- kill_newfe = true;
-
- /* In case we need to overwrite an existing file, we blow it
- * away first */
- if (kill_newfe) {
- newfe = (ocfs_file_entry *) OCFS_BH_GET_DATA(newfe_bh);
- if (newfe->attribs & OCFS_ATTRIB_DIRECTORY) {
- newfe_lockid = newfe->extents[0].disk_off;
- newfe_flags = FLAG_DIR;
- } else
- newfe_lockid = newfe->this_sector;
- newfe_flags |= FLAG_FILE_DELETE;
-
- tmpoff = newfe->this_sector;
-
- OCFS_BH_PUT_DATA(newfe_bh);
- brelse(newfe_bh);
- newfe_bh = NULL;
- newfe = NULL;
-
- status = ocfs_acquire_lock(osb, newfe_lockid,
- OCFS_DLM_EXCLUSIVE_LOCK,
- newfe_flags, &newfe_lock, NULL, new_dir);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- status = ocfs_fe_smash (osb, newDirOff, 0,
- tmpoff, handle, &free_head, new_inode, new_dir);
- if (status < 0) {
- /* TODO: we should make this transactional such that */
- /* either we get the new file or the old file stays. */
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- /* If we're moving to a different directory, all we've gotta
- * do is copy the fe information from the old directory to the
- * new one. */
- if (old_dir != new_dir) {
- /* Delete the file Entry only on the source directory */
- LOG_TRACE_STR ("Source & Target Directories are different");
-
- status = ocfs_fe_smash (osb, oldDirOff, FLAG_DEL_NAME,
- oldOffset, handle, NULL, old_inode, old_dir);
- if (status < 0) {
- if (status != -ENOTEMPTY && status != -EINTR &&
- status != -EBUSY)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* we copy this all into a temporary fe because we
- * don't want to modify the old on as it points to
- * buffer head data which might get pushed to disk as
- * a part of a journal operation. */
- tmpfe = ocfs_allocate_file_entry ();
- if (tmpfe == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- oldfe = (ocfs_file_entry *) OCFS_BH_GET_DATA(oldfe_bh);
- memcpy(tmpfe, oldfe, sizeof(ocfs_file_entry));
- OCFS_BH_PUT_DATA(oldfe_bh);
- oldfe = NULL;
-
- tmpfe->sync_flags &= ~OCFS_SYNC_FLAG_VALID;
- strncpy(tmpfe->filename, new_dentry->d_name.name,
- new_dentry->d_name.len);
- tmpfe->filename[new_dentry->d_name.len] = '\0';
- tmpfe->filename_len = new_dentry->d_name.len;
- OcfsQuerySystemTime (&t);
- DISK_LOCK_CURRENT_MASTER (tmpfe) = osb->node_num;
- DISK_LOCK_FILE_LOCK (tmpfe) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_LAST_WRITE (tmpfe) = t;
- DISK_LOCK_LAST_READ (tmpfe) = t;
- DISK_LOCK_READER_NODE (tmpfe) = osb->node_num;
- DISK_LOCK_WRITER_NODE (tmpfe) = osb->node_num;
- tmpfe->modify_time = OCFS_CURRENT_TIME;
-
- status= ocfs_insert_file(osb, tmpfe, new_dir_bh, NULL, handle, new_dir, new_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* move the inode offset over to the new entry */
- if (S_ISDIR (old_dentry->d_inode->i_mode)) {
- SET_INODE_OFFSET(old_dentry->d_inode,
- tmpfe->extents[0].disk_off);
- } else {
- SET_INODE_OFFSET(old_dentry->d_inode,
- tmpfe->this_sector);
- }
- } else {
- /* Ok, we're moving inside of the same directory --
- * this is easy then -- we just change the name on the
- * fe. */
- /* Write the new file name to disk */
- LOG_TRACE_STR ("Source & Target Directories are same");
- status = ocfs_rename_file(osb, handle, oldDirOff,
- new_dentry, oldOffset, new_dir);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
-finally:
- if (status < 0) {
- ocfs_abort_trans(handle);
- goto bail;
- } else {
- /* commit_trans */
- status = ocfs_commit_trans(handle);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- /* free bits, if we deleted anything */
- if (free_head) {
- status = ocfs_process_bitmap_free_head(osb, free_head);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
-
- if (oldOIN) {
- ocfs_release_cached_oin (osb, oldOIN);
- ocfs_release_oin (oldOIN, true);
- if (new_dentry->d_inode)
- fsync_inode_buffers(old_dentry->d_inode);
- }
- if (kill_newfe && DeleteTargetOin) {
- ocfs_release_cached_oin (osb, oldOIN);
- ocfs_release_oin (oldOIN, true);
- }
- }
-
- old_inode->i_nlink++;
- if (new_inode) {
- new_dir->i_mtime = new_dir->i_ctime = OCFS_CURRENT_TIME;
- if (S_ISDIR (old_inode->i_mode))
- new_inode->i_nlink--;
- new_inode->i_nlink--;
- } else {
- if (S_ISDIR (old_inode->i_mode))
- new_dir->i_nlink++;
- }
- old_inode->i_nlink--;
- if (S_ISDIR (old_inode->i_mode)) {
- new_dir->i_mtime = new_dir->i_ctime = OCFS_CURRENT_TIME;
- old_dir->i_nlink--;
- }
-
-bail:
- if (oldfe_lock) {
- status = ocfs_release_lock(osb, oldfe_lockid,
- OCFS_DLM_EXCLUSIVE_LOCK,
- oldfe_flags, oldfe_lock, NULL, old_dir);
- ocfs_put_lockres(oldfe_lock);
- }
-
- if (newfe_lock) {
- status = ocfs_release_lock(osb, newfe_lockid,
- OCFS_DLM_EXCLUSIVE_LOCK,
- newfe_flags, newfe_lock, NULL, new_dir);
- ocfs_put_lockres(newfe_lock);
- }
-
- if (tmpfe)
- ocfs_release_file_entry (tmpfe);
- if (oldfe_bh) {
- if (oldfe)
- OCFS_BH_PUT_DATA(oldfe_bh);
- brelse(oldfe_bh);
- }
- if (newfe_bh) {
- if (newfe)
- OCFS_BH_PUT_DATA(newfe_bh);
- brelse(newfe_bh);
- }
- if (old_dir_bh)
- brelse(old_dir_bh);
- if (new_dir_bh)
- brelse(new_dir_bh);
- if (free_head)
- free_bitmap_free_head(free_head);
-
- LOG_EXIT_STATUS(status);
- return status;
-} /* ocfs_rename */
-
-/*
- * ocfs_symlink()
- *
- */
-int ocfs_symlink (struct inode *dir, struct dentry *dentry, const char *symname)
-{
- ocfs_super *osb = NULL;
- ocfs_inode *oin = NULL;
- struct inode *inode = NULL, *parentInode = NULL;
- __u64 file_off, parent_off;
- __u64 newsize;
- int status;
- struct super_block *sb;
- int l;
- struct buffer_head *new_fe_bh = NULL;
- struct buffer_head *lock_bh = NULL;
- ocfs_file_entry *fe = NULL;
- ocfs_journal_handle *handle = NULL;
- ocfs_lock_res *lock_res = NULL;
-
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, symname='%s' actual='%*s')\n", dir,
- dentry, symname, dentry->d_name.len,
- dentry->d_name.name);
-
- atomic_inc (&dir->i_count);
-
- inode = new_inode (dir->i_sb);
- if (IS_ERR (inode)) {
- status = PTR_ERR(inode);
- LOG_ERROR_STR("new_inode failed!");
- goto bail;
- }
- //atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
-
- parentInode = dentry->d_parent->d_inode;
- sb = parentInode->i_sb;
-
- l = strlen (symname) + 1;
- newsize = l - 1;
-
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(dir->i_sb);
-
- /* need the offset of our parent directory to lock it */
- if (!ocfs_linux_get_inode_offset (parentInode, &parent_off, NULL)) {
- LOG_ERROR_STR ("failed to get parent offset!");
- status = -EIO;
- goto bail;
- }
-
- /* start the transaction */
- handle = ocfs_start_trans(osb, OCFS_SYMLINK_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- /* lock the parent directory */
- status = ocfs_acquire_lock (osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE | FLAG_DIR,
- &lock_res, &lock_bh, dir);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto abort_trans;
- }
-
- status = ocfs_mknod_locked(osb, dir, dentry,
- S_IFLNK | S_IRWXUGO, OCFS_NODEV, lock_bh,
- &new_fe_bh, handle, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto abort_trans;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(new_fe_bh);
- file_off = fe->this_sector;
- printk("ok in symlink, got the fe, this sector is %u.%u\n", file_off);
- OCFS_BH_PUT_DATA(new_fe_bh);
- fe = NULL;
-
- status = ocfs_extend_file (osb, parent_off, NULL, newsize, &file_off, handle, inode, NULL);
- if (status < 0) {
- if (status != -ENOSPC && status != -EINTR) {
- LOG_ERROR_ARGS ("Failed to extend file to %u.%u", HILO (newsize));
- LOG_ERROR_STATUS(status);
- status = -ENOSPC;
- }
- goto abort_trans;
- }
-
-abort_trans:
- if (handle) {
- ocfs_bitmap_free_head *f = osb->alloc_free_head;
- osb->alloc_free_head = NULL;
-
- if (status < 0)
- ocfs_abort_trans(handle);
- else {
- status = ocfs_commit_trans(handle);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
-
- if (f) {
- ocfs_process_bitmap_free_head(osb, f);
- free_bitmap_free_head(f);
- }
- }
-
- if (lock_res != NULL) {
- int tmpstat;
- tmpstat = ocfs_release_lock (osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE | FLAG_DIR, lock_res, lock_bh, dir);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- ocfs_put_lockres (lock_res);
-
- if (status < 0)
- goto bail;
-
- status = ocfs_create_oin_from_entry(osb, new_fe_bh, &oin,
- parent_off, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
-#ifdef LINUX_2_5
- inode->i_rdev = to_kdev_t(OCFS_NODEV);
-#else
- inode->i_rdev = OCFS_NODEV;
-#endif
- inode->i_ino = LO (oin->file_disk_off);
- oin->inode = inode;
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(new_fe_bh);
- ocfs_populate_inode (inode, fe, S_IFLNK | S_IRWXUGO, oin);
- OCFS_BH_PUT_DATA(new_fe_bh);
- fe = NULL;
-
- inode->i_size = newsize;
- inode->i_blocks = (newsize + sb->s_blocksize) >> sb->s_blocksize_bits;
- insert_inode_hash (inode);
- d_instantiate (dentry, inode);
-
- status = ocfs_block_symlink (inode, symname, l);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
-bail:
- if (new_fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(new_fe_bh);
- brelse(new_fe_bh);
- }
- atomic_dec (&dir->i_count);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_symlink */
-
-
-/* ocfs_rename_file()
- *
- */
-static int ocfs_rename_file (ocfs_super * osb, ocfs_journal_handle *handle, __u64 parent_off, struct dentry *dentry, __u64 file_off, struct inode *dir_inode)
-{
- int status = 0;
- ocfs_dir_node *pLockNode = NULL;
- ocfs_file_entry *fe = NULL;
- __u64 changeSeqNum = 0;
- __u32 lockFlags = 0;
- __u64 lockId = 0;
- __u32 index;
- struct buffer_head *fe_bh = NULL, *lockbh = NULL, *dirbh = NULL;
- bool cache_lock = false, needs_reindex = false;
- __u64 dir_node_ptr = 0;
- int flags = 0;
- struct qstr *file_name = &(dentry->d_name);
- struct inode *inode = dentry->d_inode;
-
- LOG_ENTRY ();
-
- status = ocfs_read_bh (osb, file_off, &fe_bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- status = ocfs_journal_access(handle, fe_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* lock file ent for a dir is out in the 1st extent, this_sector
- for file */
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
- dir_node_ptr = fe->dir_node_ptr;
- if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
- lockId = fe->extents[0].disk_off;
- lockFlags = (FLAG_DIR | FLAG_FILE_RENAME);
-
- status = ocfs_read_bh(osb, lockId, &lockbh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- status = ocfs_journal_access(handle, lockbh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else {
- lockId = fe->this_sector;
- lockFlags = FLAG_FILE_RENAME;
- lockbh = fe_bh;
- }
-
- /* Change the name and write it back.... */
- fe->filename[0] = '\0';
- strncpy (fe->filename, file_name->name, file_name->len);
- fe->filename[file_name->len] = '\0';
-
- DISK_LOCK_SEQNUM (fe) = changeSeqNum;
-
- /* Set the Valid bit here */
- SET_VALID_BIT (fe->sync_flags);
- fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
-
- status = ocfs_read_bh (osb, dir_node_ptr, &dirbh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- OCFS_BH_PUT_DATA(fe_bh);
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- status = ocfs_journal_access(handle, dirbh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- OCFS_BH_PUT_DATA(fe_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- pLockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(dirbh);
- pLockNode->index_dirty = 1;
- pLockNode->bad_off = (fe->this_sector - dir_node_ptr) / osb->sect_size;
- pLockNode->bad_off -= 1;
- cache_lock = (DISK_LOCK_FILE_LOCK (pLockNode) == OCFS_DLM_ENABLE_CACHE_LOCK);
-
- for (index = 0; index < pLockNode->num_ent_used; index++) {
- if (pLockNode->index[index] == pLockNode->bad_off)
- break;
- }
- needs_reindex = (index < pLockNode->num_ent_used);
-
- if (needs_reindex) {
- memmove (&pLockNode->index[index], &pLockNode->index[index + 1],
- pLockNode->num_ent_used - (index + 1));
- pLockNode->index[pLockNode->num_ent_used - 1] = pLockNode->bad_off;
- /* is this a safe cast? */
- flags = OCFS_FE_CACHE_FLAGS(osb, ((ocfs_file_entry *) pLockNode));
- OCFS_BH_PUT_DATA(dirbh);
- status = ocfs_journal_dirty(handle, dirbh);
- if (status < 0) {
- OCFS_BH_PUT_DATA(fe_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
- flags = OCFS_FE_CACHE_FLAGS(osb, fe);
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
- status = ocfs_journal_dirty(handle, fe_bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (needs_reindex) {
- status = ocfs_reindex_dir_node (osb, dir_node_ptr, NULL, handle, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
-leave:
- if (fe != NULL)
- OCFS_BH_PUT_DATA(fe_bh);
-
- if (lockbh != fe_bh)
- brelse(lockbh);
- if (fe_bh)
- brelse(fe_bh);
- if (dirbh)
- brelse(dirbh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_rename_file */
-
-/* ocfs_fe_smash()
- *
- * Flags for 'flags' field (no flags means do everything?)
- * FLAG_DEL_NAME - Only want to remove the file entry -- do not free
- * any extents. this flag is used during rename.
- *
- * Two functions call this: ocfs_unlink (no flags) and ocfs_rename
- * (uses both flags under different circumstances).
- *
- * Removes a file entry and (possibly) it's extents. Calls
- * commit_trans or abort_trans to do the actual work.
- *
- * If we're passed a journal handle, then we assume that everything
- * has been setup for us and we don't bother to do any
- * locking. Otherwise we start and commit/abort our own transaction
- * and lock our own stuff. If you give us a handle, we'll also try
- * to pass back a bitmap_free_head (if it's not passed as NULL)
- *
- */
-static int ocfs_fe_smash (ocfs_super * osb, __u64 lock_node_off, __u32 flags, __u64 file_off, ocfs_journal_handle *passed_handle, ocfs_bitmap_free_head **ret_head, struct inode *inode, struct inode *parent_inode)
-{
- int status = 0;
- int tmpstat;
- ocfs_file_entry *fe = NULL;
- __u32 lockFlags = 0;
- bool local_handle = false, is_dir;
- __u64 lock_id = 0;
- struct buffer_head *fe_bh = NULL, *lock_bh = NULL;
- struct buffer_head *lock_node_bh = NULL; /* parent locknode */
- ocfs_lock_res *parent_lock = NULL;
- ocfs_lock_res *file_lock = NULL;
- ocfs_bitmap_free_head *free_head = NULL;
- ocfs_journal_handle *handle = NULL;
-
- LOG_ENTRY ();
-
- if (ret_head)
- *ret_head = NULL;
-
- free_head = alloc_bitmap_free_head();
- if (free_head == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- status = ocfs_read_bh(osb, lock_node_off, &lock_node_bh,
- OCFS_BH_CACHED, parent_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- status = ocfs_read_bh (osb, file_off, &fe_bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (passed_handle) {
- handle = passed_handle;
- /* ok, we're going to skip the locking, but there's
- * one problem: what if this is a directory that we're
- * deleting? in that case, we also need to read the
- * head of it's first dirnode which would have been
- * done implicitely by locking it. */
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
- status = ocfs_read_bh(osb, fe->extents[0].disk_off,
- &lock_bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- OCFS_BH_PUT_DATA(fe_bh);
- goto leave;
- }
- } else /* we don't really need this but just in case... */
- lock_bh = fe_bh;
-
- OCFS_BH_PUT_DATA(fe_bh);
-
- goto skip_lock;
- }
-
- handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- local_handle = true;
-
- /* lock parent directory, yes we use FLAG_FILE_CREATE even
- * though we're deleting ;) */
- status = ocfs_acquire_lock(osb, lock_node_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_DIR, &parent_lock,
- &lock_node_bh, parent_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- /* lock the file entry */
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
-
- if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
- lock_id = fe->extents[0].disk_off;
- lockFlags = (FLAG_FILE_DELETE | FLAG_DIR);
- } else {
- lock_id = fe->this_sector;
- lockFlags = (FLAG_FILE_DELETE);
- lock_bh = fe_bh;
- }
- OCFS_BH_PUT_DATA(fe_bh);
-
- status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, &file_lock, &lock_bh, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-skip_lock:
- status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- is_dir = fe->attribs & OCFS_ATTRIB_DIRECTORY;
- if (is_dir) {
- __u8 numused;
- ocfs_dir_node *pLockNode;
-
- pLockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA(lock_bh);
- numused = pLockNode->num_ent_used;
- OCFS_BH_PUT_DATA(lock_bh);
-
- if (numused && !(flags & FLAG_DEL_NAME)) {
- OCFS_BH_PUT_DATA(fe_bh);
- status = -ENOTEMPTY;
- goto leave;
- }
- }
-
- if (flags & FLAG_DEL_NAME) {
- /* Ok, we don't want to kill it's extents (I.E. we're
- * doing a rename so skip the 1st part of this function. */
- status = 0;
- OCFS_BH_PUT_DATA(fe_bh);
- goto delete_entry;
- }
-
- if (fe->link_cnt) {
- /* Decrement Link count when implementing links... TODO*/
- OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_NAME_DELETED);
- fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
- } else {
- OCFS_SET_FLAG (fe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
- fe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
- }
- OCFS_BH_PUT_DATA(fe_bh);
-
- /* Free up all the bits in the bitmap. */
- if (is_dir) {
- /* Iterate through all the dir nodes for this
- * directory and mark them to be freed */
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- status = ocfs_free_directory_block (osb, fe, free_head, inode);
- OCFS_BH_PUT_DATA(fe_bh);
- if (status < 0) {
- OCFS_BH_PUT_DATA(fe_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else {
- /* mark all the extents (and extent metadata) for
- * this file so we can remove them after commit. */
- status = ocfs_free_file_extents (osb, fe_bh, free_head);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
-delete_entry:
- /* remove the fe from the dirnode.*/
- status = ocfs_remove_file(osb, fe_bh, lock_node_bh, handle, parent_inode, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- status = ocfs_journal_dirty(handle, fe_bh);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
-leave:
-
- if (local_handle && handle && (status < 0))
- ocfs_abort_trans(handle);
- else if (local_handle && handle) {
- status = ocfs_commit_trans(handle);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- else if (free_head) {
- /* Free the bits from the bitmap now. It's OK
- * if none were marked. */
- status = ocfs_process_bitmap_free_head(osb, free_head);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- }
- }
- /* NEW: adding a fake release lock for the dead file entry here */
- /* need this to alert dentry-owners on other nodes */
- /* Release the file lock if we acquired it */
- if (file_lock) {
- tmpstat = ocfs_release_lock(osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, file_lock,
- lock_bh, inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS(tmpstat);
-
- ocfs_put_lockres (file_lock);
- }
-
- if (parent_lock) {
- tmpstat = ocfs_release_lock(osb, lock_node_off,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_DIR,
- parent_lock, lock_node_bh, parent_inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS(tmpstat);
-
- ocfs_put_lockres (parent_lock);
- }
- if (free_head) {
- /* we only return a bitmap_free_head if they asked for
- * it and we succeeded. Otherwise we should free it
- * ourselves. */
- if (ret_head && (status == 0))
- *ret_head = free_head;
- else {
- LOG_TRACE_STR("freeing bitmap_free_head");
- free_bitmap_free_head(free_head);
- }
- }
-
- if (lock_bh != NULL && lock_bh != fe_bh)
- brelse(lock_bh);
-
- if (fe_bh != NULL)
- brelse(fe_bh);
-
- if (lock_node_bh != NULL)
- brelse(lock_node_bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_fe_smash */
Deleted: trunk/nm.c
===================================================================
--- trunk/nm.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/nm.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1468 +0,0 @@
-/*
- * ocfsgennm.c
- *
- * process vote, nm thread, etc.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_NM
-
-static struct inode * ocfs_get_inode_from_offset(ocfs_super * osb, __u64 fileoff);
-static int ocfs_release_dir_cache_lock (ocfs_super *osb, struct buffer_head **dir_bhs, struct inode *inode);
-static inline int get_process_vote_action(ocfs_super * osb, ocfs_lock_res *lockres, __u32 node_num, __u32 flags, int status, bool *master_alive, ocfs_inode **oin);
-static int ocfs_disk_update_resource (ocfs_super * osb, ocfs_lock_res * lock_res, struct buffer_head **bh, __u32 timeout, struct inode *inode);
-static int ocfs_search_commited(ocfs_super *osb, ocfs_lock_res *lockres);
-static void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode);
-static int ocfs_schedule_process_vote(ocfs_super *osb, struct buffer_head *bh, int vote_node);
-
-void ocfs_process_vote_worker(void *val);
-
-static const char *process_vote_strings[] = {
- "INVALID_REQUEST", // reply with a NO vote
- "UPDATE_OIN_INODE", // update both oin and inode
- "UPDATE_INODE", // no oin, so only update inode
- "DELETE_RENAME", // delete or rename request (EX)
- "RELEASE_CACHE", // release a cache lock I hold
- "CHANGE_MASTER", // request to change master to requestor
- "ADD_OIN_MAP", // add requestor into oin map
- "NOT_MASTER", // I am not master, retry
- "REMASTER_THIS", // remaster lock to me
- "REMASTER_REQUESTOR" // remaster lock to requestor
-};
-
-/*
- * ocfs_recv_thread()
- *
- */
-int ocfs_recv_thread (void *unused)
-{
- int status = 0;
- ocfs_recv_ctxt *recv_ctxt = NULL;
-
- LOG_ENTRY ();
-
-#define LISTENER_PROCESS_NAME "ocfslsnr"
- ocfs_daemonize (LISTENER_PROCESS_NAME, strlen(LISTENER_PROCESS_NAME));
-
- OcfsIpcCtxt.task = current;
-
- while (1) {
- recv_ctxt = ocfs_malloc (sizeof (ocfs_recv_ctxt));
- if (recv_ctxt == NULL) {
- LOG_ERROR_STATUS (-ENOMEM);
- goto bail;
- }
-
- memset (recv_ctxt, 0, sizeof (ocfs_recv_ctxt));
- recv_ctxt->msg_len = OCFS_MAX_DLM_PKT_SIZE;
-
- status = ocfs_recv_udp_msg (recv_ctxt);
- if (status < 0) {
- ocfs_safefree (recv_ctxt);
- if (status != -EBADF) {
- LOG_ERROR_STATUS (status);
- } else {
- /* Thread is being killed. */
- goto finally;
- }
- }
- }
-
-finally:
- if (OcfsIpcCtxt.send_sock) {
- sock_release (OcfsIpcCtxt.send_sock);
- OcfsIpcCtxt.send_sock = NULL;
- }
-
- if (OcfsIpcCtxt.recv_sock) {
- sock_release (OcfsIpcCtxt.recv_sock);
- OcfsIpcCtxt.recv_sock = NULL;
- }
-
- /* Flush all scheduled tasks */
-#ifdef LINUX_2_5
- flush_scheduled_work ();
-#else
- flush_scheduled_tasks ();
-#endif
- /* signal main thread of ipcdlm's exit */
- complete (&(OcfsIpcCtxt.complete));
-
-bail:
- LOG_EXIT ();
- return 0;
-} /* ocfs_recv_thread */
-
-
-struct ocfs_sched_vote {
- ocfs_super *osb;
- ocfs_vote_request_ctxt ctxt;
- __u8 publish_sect[512];
-#ifdef LINUX_2_5
- struct work_struct ipc_wq;
-#else
- struct tq_struct ipc_tq;
-#endif
-};
-
-void ocfs_process_vote_worker(void *val)
-{
- struct ocfs_sched_vote *sv = (struct ocfs_sched_vote *) val;
- ocfs_super *osb = NULL;
-
- LOG_ENTRY();
-
- if (!val)
- BUG();
-
- osb = sv->osb;
-
- ocfs_process_vote(osb, &(sv->ctxt));
-
- /* we should free this when done. */
- ocfs_free(sv);
-
- LOG_EXIT();
- return;
-}
-
-/*
- * ocfs_schedule_process_vote
- *
- */
-static int ocfs_schedule_process_vote(ocfs_super *osb,
- struct buffer_head *bh,
- int vote_node)
-{
- int status = 0;
- ocfs_vote_request_ctxt *ctxt = NULL;
- ocfs_publish * publish;
- struct ocfs_sched_vote *sv = NULL;
-
- LOG_ENTRY_ARGS("(vote_node = %d, bh = 0x%x)\n", vote_node, bh);
-
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(bh);
-
- if (osb->last_publ_seq_num[vote_node] == publish->publ_seq_num){
- LOG_TRACE_ARGS("Already voted on node %d, seqnum (%u.%u)\n",
- vote_node, HILO(publish->publ_seq_num));
- OCFS_BH_PUT_DATA(bh);
- status = 0;
- goto bail;
- }
- osb->last_publ_seq_num[vote_node] = publish->publ_seq_num;
-
- sv = ocfs_malloc(sizeof(struct ocfs_sched_vote));
- if (sv == NULL) {
- OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto bail;
- }
- memset(sv, 0, sizeof(struct ocfs_sched_vote));
-
- ctxt = (ocfs_vote_request_ctxt *) &(sv->ctxt);
- ctxt->u.publish = (ocfs_publish *) &(sv->publish_sect);
- memcpy(ctxt->u.publish, publish, osb->sect_size);
- OCFS_BH_PUT_DATA(bh);
-
- ctxt->request_method = DISK_VOTE;
- ctxt->node_num = vote_node;
-
- sv->osb = osb;
-
-#ifdef LINUX_2_5
- INIT_WORK (&sv->ipc_wq, ocfs_process_vote_worker, sv);
- schedule_work (&sv->ipc_wq);
-#else
- INIT_TQUEUE (&sv->ipc_tq, ocfs_process_vote_worker, sv);
- schedule_task (&sv->ipc_tq);
-#endif
-
-bail:
- /* if no error, then the workqueue should clear it? */
- if ((status < 0) && ctxt) {
- if (ctxt->u.publish)
- ocfs_free(ctxt->u.publish);
- ocfs_free(ctxt);
- }
-
- LOG_EXIT_STATUS(status);
- return(status);
-} /* ocfs_schedule_process_vote */
-
-#define OCFS_NM_MAX_FLUSH_MISSES 150
-
-/*
- * ocfs_volume_thread()
- *
- * This function is executed as a kernel thread for each mounted ocfs volume.
- */
-int ocfs_volume_thread (void *arg)
-{
- ocfs_super *osb;
- char proc[16];
- int status = 0;
-#ifdef DO_PERIODIC_SYNC
- int flush_counter = 0;
-#endif
- __u8 *buffer = NULL;
- ocfs_publish *publish;
- __u32 i;
- __u32 highest_vote_node;
- __u64 offset = 0;
- __u32 num_nodes = 0;
- __u32 vote_node;
- ocfs_node_config_hdr *node_cfg_hdr = NULL;
- __u64 curr_node_map;
- __u64 cfg_seq_num;
- int which;
- int flush_misses = 0;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY ();
-
- osb = (ocfs_super *) arg;
- if (osb->obj_id.type != OCFS_TYPE_OSB)
- goto eek;
-
- sprintf (proc, "ocfsnm-%d", osb->osb_id);
- ocfs_daemonize (proc, strlen(proc));
-
- osb->dlm_task = current;
-
- /* The delay changes based on multiplier */
- while (!(OcfsGlobalCtxt.flags & OCFS_FLAG_SHUTDOWN_VOL_THREAD) &&
- !(osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED)) {
-
- buffer = NULL;
- vote_node = OCFS_INVALID_NODE_NUM;
- highest_vote_node = 0;
-
- if (OcfsGlobalCtxt.hbm == 0)
- OcfsGlobalCtxt.hbm = DISK_HBEAT_NO_COMM;
-
- status = ocfs_wait (osb->flush_event,
- atomic_read (&osb->flush_event_woken), OCFS_NM_HEARTBEAT_TIME);
- atomic_set (&osb->flush_event_woken, 0);
-
- if (status == -ETIMEDOUT)
- LOG_TRACE_STR("FLUSH_EVENT: timed out");
- else if (status == -EINTR)
- LOG_TRACE_STR("FLUSH_EVENT: interrupted");
- else if (status == 0)
- LOG_TRACE_STR("FLUSH_EVENT: woken!!!");
- else
- LOG_TRACE_STR("FLUSH_EVENT: ??????");
-
- if ((OcfsGlobalCtxt.flags & OCFS_FLAG_SHUTDOWN_VOL_THREAD) ||
- (osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED))
- break;
-
- if (!time_after (jiffies, (unsigned long) (osb->hbt)))
- goto finally;
-
- if (osb->vol_state == VOLUME_MOUNTED) {
- if (osb->needs_flush && down_trylock(&osb->trans_lock) == 0) {
- if (osb->trans_in_progress == false) {
- flush_misses = 0;
- status = ocfs_commit_cache(osb, false);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
- } else if (osb->needs_flush) {
- flush_misses++;
- if (flush_misses > OCFS_NM_MAX_FLUSH_MISSES) {
- printk("ocfs: nm thread has not been "
- "able to commit cache in %d "
- "iterations!\n", flush_misses);
- }
- }
- }
-
- /* lock publish to prevent overwrites from vote_req and vote_reset */
- down (&(osb->publish_lock));
-
- /* Get the Publish Sector start Offset */
- offset = osb->vol_layout.new_cfg_off;
-
- /* Read disk for Publish Sectors of all nodes */
- status = ocfs_read_bhs(osb, offset, osb->cfg_len, osb->cfg_bhs, 0, NULL);
- if (status < 0) {
- up (&(osb->publish_lock));
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, false);
-
- /* release publish lock */
- up (&(osb->publish_lock));
-
- /* If another node was added to the config read and update the cfg */
- node_cfg_hdr = (ocfs_node_config_hdr *) OCFS_BH_GET_DATA(osb->cfg_bhs[1]);
- num_nodes = node_cfg_hdr->num_nodes;
- cfg_seq_num = node_cfg_hdr->cfg_seq_num;
- OCFS_BH_PUT_DATA(osb->cfg_bhs[1]);
-
- if ((osb->cfg_seq_num != cfg_seq_num) ||
- (osb->num_cfg_nodes != num_nodes)) {
- status = ocfs_chk_update_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
-
- num_nodes = OCFS_MAXIMUM_NODES;
-
- /* Refresh the publish map */
- ocfs_update_publish_map (osb, &(osb->cfg_bhs[OCFS_VOLCFG_NEWCFG_SECTORS]), false);
-
- /* send signal to mount thread to continue */
- if (atomic_read (&osb->nm_init) < OCFS_HEARTBEAT_INIT) {
- atomic_inc (&osb->nm_init);
- } else if (atomic_read(&osb->nm_init) == OCFS_HEARTBEAT_INIT) {
- wake_up (&osb->nm_init_event);
- atomic_inc (&osb->nm_init);
- }
-
- LOG_TRACE_ARGS ("Publish map: 0x%08x\n", LO (osb->publ_map));
-
- /* map of local node */
- curr_node_map = (__u64) ((__u64)1 << osb->node_num);
-
- /* Check for the highest node looking for a vote, if anybody is looking */
- for (i = 0, which = OCFS_VOLCFG_NEWCFG_SECTORS; i < num_nodes; i++, which++) {
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(osb->cfg_bhs[which]);
-
- if (publish->time == (__u64) 0)
- goto loop;
-
- if (publish->vote != FLAG_VOTE_NODE ||
- !(publish->vote_map & curr_node_map))
- goto loop;
-
- LOG_TRACE_ARGS ("node(%u): vote=%d dirty=%d type=%u\n",
- i, publish->vote, publish->dirty,
- publish->vote_type);
-
- highest_vote_node = i;
-
- /* Check if the node is alive or not */
- if (IS_NODE_ALIVE (osb->publ_map, highest_vote_node,
- num_nodes)) {
- vote_node = highest_vote_node;
- } else {
- OCFS_BH_PUT_DATA(osb->cfg_bhs[which]);
- publish = NULL;
- /* I guess we don't even have to do
- * anything here... */
- LOG_TRACE_ARGS("Node %d asked for a vote, "
- "but he's dead now!\n",
- highest_vote_node);
- continue;
- }
-loop:
- publish = NULL;
- OCFS_BH_PUT_DATA(osb->cfg_bhs[which]);
- }
-
-
- if ((vote_node != OCFS_INVALID_NODE_NUM) &&
- (vote_node != osb->node_num)) {
- LOG_TRACE_ARGS("vote_node = %d\n", vote_node);
-
- bh = osb->cfg_bhs[OCFS_VOLCFG_NEWCFG_SECTORS
- + osb->node_num];
- down(&(osb->publish_lock));
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(bh);
- if (publish->vote) {
- publish->vote = 0;
- OCFS_BH_PUT_DATA(bh);
- status = ocfs_write_bh(osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- } else
- OCFS_BH_PUT_DATA(bh);
- publish = NULL;
- up(&(osb->publish_lock));
-
- which = vote_node + OCFS_VOLCFG_NEWCFG_SECTORS;
- bh = osb->cfg_bhs[which];
-
- status= ocfs_schedule_process_vote(osb, bh, vote_node);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- }
- osb->hbt = 50 + jiffies;
-
-finally:
- status = 0; // ??????????????????????????
-
- if (status < 0) {
- if (osb->osb_flags & OCFS_OSB_FLAGS_BEING_DISMOUNTED)
- break;
- }
-#ifdef DO_PERIODIC_SYNC
- /* do a syncdev every 2 minutes currently that is 500ms per cycle */
- if (flush_counter++ == 240) {
- ocfs_sync_blockdev(osb->sb);
- flush_counter = 0;
- }
-#endif
- } /* while (!OCFS_FLAG_SHUTDOWN_VOL_THREAD && !OCFS_OSB_FLAGS_BEING_DISMOUNTED) */
-
- /* Flush all scheduled tasks */
-#ifdef LINUX_2_5
- flush_scheduled_work ();
-#else
- flush_scheduled_tasks ();
-#endif
-
- complete (&(osb->complete));
-eek:
- LOG_EXIT_LONG (0);
- return 0;
-} /* ocfs_volume_thread */
-
-/*
- * ocfs_disk_update_resource()
- *
- * @osb: ocfs super block for the volume
- * @lock_res: lockres to be updated
- * @file_ent: corresponding file entry
- *
- * Updates the in memory lock resource from the disklock info
- * stored in the file entry on disk.
- *
- * Returns 0 if success, < 0 if error.
- */
-static int ocfs_disk_update_resource (ocfs_super * osb, ocfs_lock_res * lock_res, struct buffer_head **bh, __u32 timeout, struct inode *inode)
-{
- int status = 0;
- ocfs_file_entry *fe;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x, 0x%08x)\n", osb, lock_res, bh);
-
- /* Don't sync-read if we already own the lock as it may not
- * have hit disk yet. */
- status = ocfs_read_bh (osb, lock_res->sector_num, bh,
- (lock_res->master_node_num == osb->node_num) ?
- OCFS_BH_CACHED : 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- status = ocfs_acquire_lockres_ex (lock_res, timeout);
- if (status < 0) {
- LOG_TRACE_ARGS ("Timedout locking lockres for id: %u.%u\n",
- HILO (lock_res->sector_num));
- goto finally;
- }
-
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(*bh);
- lock_res->lock_type = DISK_LOCK_FILE_LOCK (fe);
- lock_res->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
- lock_res->oin_openmap = DISK_LOCK_OIN_MAP (fe);
- OCFS_BH_PUT_DATA(*bh);
-
- ocfs_release_lockres (lock_res);
-
-finally:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_disk_update_resource */
-
-/*
- * ocfs_find_update_res()
- *
- * @osb: ocfs super block for the volume
- * @lock_id: sector number of the resource to be locked
- * @lockres: lockres of the resource
- * @fe: corresponding file entry
- * @updated: set to 1 if lockres is refreshed from disk
- *
- * Searches for the lockres for the given lockid in the hashtable.
- * If not found, it allocates a lockres for the lockid, and adds
- * it to the hashtable. If found and it's master node is not the
- * same as the current node, the lockres is refreshed from the disk.
- *
- * Returns 0 if success, < 0 if error.
- */
-int ocfs_find_update_res (ocfs_super * osb, __u64 lock_id, ocfs_lock_res ** lockres, struct buffer_head **bh, __u32 * updated, __u32 timeout, struct inode *inode)
-{
- int status = 0;
- ocfs_lock_res *tmp_lockres = NULL;
- struct buffer_head *tmpbh = NULL, **b = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, %u.%u, 0x%08x, 0x%08x, 0x%08x)\n", osb,
- HI (lock_id), LO (lock_id), lockres, bh, updated);
-
- if (bh == NULL)
- b = &tmpbh;
- else
- b = bh;
-
- status = ocfs_lookup_sector_node (osb, lock_id, lockres);
- if (status < 0) {
- *lockres = ocfs_allocate_lockres();
- if (*lockres == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- ocfs_init_lockres (osb, *lockres, lock_id);
-
- ocfs_get_lockres (*lockres);
-
- status = ocfs_disk_update_resource (osb, *lockres, b, timeout, inode);
- if (status < 0) {
- if (status != -ETIMEDOUT) {
- LOG_ERROR_STR ("Disabling Volume");
- osb->vol_state = VOLUME_DISABLED;
- }
- goto finally;
- }
-
- if (lock_id != (*lockres)->sector_num) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto finally;
- }
-
- if (updated)
- *updated = 1;
-
- status = ocfs_insert_sector_node (osb, *lockres, &tmp_lockres);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- if (!tmp_lockres)
- goto finally;
- else {
- ocfs_put_lockres (*lockres);
- *lockres = tmp_lockres;
- }
- }
-
- /* sanity checks */
- if ((*lockres)->signature != 0x55AA) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto finally;
- }
-
- if (lock_id != (*lockres)->sector_num) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto finally;
- }
-
- /* If we found the lockres in the hash and it's asked for, we still
- * need to return a buffer_head */
- if (status >= 0) {
- status = ocfs_read_bh(osb, (*lockres)->sector_num, b,
- OCFS_BH_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
-
- if ((*lockres)->master_node_num != osb->node_num) {
- status = ocfs_disk_update_resource (osb, *lockres, b, timeout, inode);
- if (status < 0) {
- if (status != -ETIMEDOUT) {
- LOG_ERROR_STR ("Disabling Volume");
- osb->vol_state = VOLUME_DISABLED;
- }
- goto finally;
- }
- if (updated)
- *updated = 1;
- }
-
-finally:
- if (status < 0)
- *lockres = NULL;
-
- if (tmpbh != NULL)
- brelse(tmpbh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_find_update_res */
-
-#undef OCFS_DEBUG_CONTEXT
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_DLM
-
-/*
- * ocfs_get_inode_from_offset()
- *
- */
-struct inode * ocfs_get_inode_from_bh(ocfs_super * osb, struct buffer_head *bh)
-{
- struct inode *inode = NULL;
- ocfs_file_entry *fe = NULL;
- ocfs_find_inode_args args;
-
- LOG_ENTRY ();
-
- args.fe_bh = bh;
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(bh);
- args.offset = fe->this_sector;
- OCFS_BH_PUT_DATA(bh);
- fe = NULL;
-
-#ifdef LINUX_2_5
- inode = ocfs_iget(osb->sb, &args);
-#else
- inode = iget4 (osb->sb, (__u32) LO (args.offset),
- (find_inode_t) ocfs_find_inode,
- (void *) (&args));
-#endif
- if (inode != NULL && is_bad_inode (inode)) {
- iput (inode);
- inode = NULL;
- }
- if (inode)
- SET_BH_SEQNUM(inode, bh);
-
- LOG_EXIT_PTR (inode);
- return inode;
-} /* ocfs_get_inode_from_offset */
-
-
-
-/*
- * ocfs_get_inode_from_offset()
- *
- */
-static struct inode * ocfs_get_inode_from_offset(ocfs_super * osb, __u64 fileoff)
-{
- int status;
- struct inode *inode = NULL;
- struct buffer_head *fe_bh = NULL;
-
- LOG_ENTRY ();
-
- status = ocfs_read_bh(osb, fileoff, &fe_bh, OCFS_BH_CACHED, NULL);
- inode = ocfs_get_inode_from_bh(osb, fe_bh);
- brelse(fe_bh);
-
- LOG_EXIT_PTR (inode);
- return inode;
-} /* ocfs_get_inode_from_offset */
-
-
-
-static inline int get_process_vote_action(ocfs_super * osb, ocfs_lock_res *lockres, __u32 node_num,
- __u32 flags, int status, bool *master_alive, ocfs_inode **oin)
-{
- int vote_type = INVALID_REQUEST;
- bool my_node_wins = false;
-
- LOG_ENTRY_ARGS("(status=%d)\n", status);
-
- *oin = NULL;
- *master_alive = true;
- if (status < 0) {
- if (status == -ETIMEDOUT) {
- LOG_TRACE_STR("(INVALID_REQUEST) status == -ETIMEDOUT");
- return INVALID_REQUEST;
- }
- } else if (lockres) {
- *master_alive = lockres->master_node_num != OCFS_INVALID_NODE_NUM &&
- IS_NODE_ALIVE(osb->publ_map,
- lockres->master_node_num, OCFS_MAXIMUM_NODES);
- my_node_wins = lockres->vote_state & LOCK_STATE_IN_VOTING &&
- node_num < osb->node_num;
- if (lockres->oin)
- *oin = lockres->oin;
- }
-
- if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME))
- vote_type = DELETE_RENAME;
- else if (flags & FLAG_FILE_RELEASE_CACHE)
- vote_type = RELEASE_CACHE;
- else if (flags & FLAG_FILE_UPDATE_OIN) {
- if (*oin)
- vote_type = UPDATE_OIN_INODE;
- else
- vote_type = UPDATE_INODE;
- } else if (lockres->master_node_num == osb->node_num) {
- if (flags & FLAG_CHANGE_MASTER)
- vote_type = CHANGE_MASTER;
- else if (flags & FLAG_ADD_OIN_MAP)
- vote_type = ADD_OIN_MAP;
- else {
- LOG_TRACE_STR("(INVALID_REQUEST) am master, but no more types");
- vote_type = INVALID_REQUEST;
- }
- } else {
- if (*master_alive)
- vote_type = NOT_MASTER;
- else if (my_node_wins)
- vote_type = REMASTER_THIS;
- else
- vote_type = REMASTER_REQUESTOR;
- }
-
- /* the only allowable action if we failed to */
- /* get the lockres is a simple inode update */
- if (status < 0 && vote_type != UPDATE_INODE) {
- LOG_TRACE_STR("(INVALID_REQUEST) (status < 0 && vote_type != UPDATE_INODE)");
- vote_type = INVALID_REQUEST;
- }
-
- LOG_EXIT_STATUS(vote_type);
-
- return vote_type;
-}
-
-
-/* Search the journals committed transactions list for a given
- * lockres. If it's in there, return true, zero otherwise and -1 on
- * error. Must hold the journal->commit_sem before going here! */
-static int ocfs_search_commited(ocfs_super *osb, ocfs_lock_res *lockres)
-{
- struct list_head *handle_p;
- struct list_head *lock_p;
- int found = 0;
- ocfs_journal *journal;
- ocfs_journal_handle *handle = NULL;
- ocfs_journal_lock *lock;
-
- LOG_ENTRY();
-
- journal = &osb->journal;
-
- list_for_each(handle_p, &journal->commited) {
- handle = list_entry(handle_p, ocfs_journal_handle, h_list);
-
- list_for_each(lock_p, &(handle->locks)) {
- lock= list_entry(lock_p, ocfs_journal_lock, lock_list);
-
- if (lock->id == lockres->sector_num) {
- found = 1;
- break;
- }
- }
- }
-
- LOG_EXIT_STATUS(found);
-
- return(found);
-}
-
-/*
- * ocfs_process_vote()
- *
- * @osb:
- * @publish:
- * @node_num: node asking for the vote
- *
- */
-int ocfs_process_vote (ocfs_super * osb, ocfs_vote_request_ctxt *ctxt)
-{
- int status = 0;
- int tmpstat = 0;
- ocfs_lock_res *lockres = NULL;
- __u32 flags, num_nodes, i;
- __u64 offset;
- ocfs_file_entry *fe = NULL;
- ocfs_vote *vote = NULL;
- struct buffer_head *fe_bh = NULL, *vote_bh = NULL;
- int vote_type = INVALID_REQUEST, vote_response = 0;
- ocfs_inode *oin = NULL;
- ocfs_sem *oin_sem = NULL;
- struct inode *inode = NULL;
- bool master_alive = true, is_dir = false;
- bool is_locked, open_handle;
- int lockflags = 0, in_cache = 0;
- bool inc_inode_seq = false;
- bool disk_vote = (ctxt->request_method == DISK_VOTE);
- bool comm_vote = (ctxt->request_method == COMM_VOTE);
- bool have_trans_lock = false;
- ocfs_publish *publish = (disk_vote ? ctxt->u.publish : NULL);
- ocfs_dlm_msg *dlm_msg = (comm_vote ? ctxt->u.dlm_msg : NULL);
- __u32 node_num = ctxt->node_num;
- __u64 lock_id, seq_num;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", osb, ctxt);
-
- if (!publish && !dlm_msg) {
- status = -EINVAL;
- LOG_ERROR_STR("invalid vote reply context!");
- LOG_ERROR_STATUS (status);
- LOG_EXIT_STATUS (status);
- return status;
- }
-
- num_nodes = OCFS_MAXIMUM_NODES;
- if (disk_vote) {
- flags = publish->vote_type;
- lock_id = publish->dir_ent;
- seq_num = publish->publ_seq_num;
- } else {
- ocfs_dlm_req_master *req_master = (ocfs_dlm_req_master *)dlm_msg->msg_buf;
- flags = req_master->flags;
- lock_id = req_master->lock_id;
- seq_num = req_master->lock_seq_num;
- }
- lockflags = (lock_id >= osb->vol_layout.bitmap_off ? OCFS_BH_CACHED : 0);
-
- LOG_TRACE_ARGS ("node=%u, id=%u.%u, seq=%u.%u\n", node_num,
- HILO (lock_id), HILO (seq_num));
-
- if (disk_vote) {
- offset = osb->vol_layout.vote_sect_off + (osb->node_num * osb->sect_size);
- status = ocfs_read_bh(osb, offset, &vote_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
- /* if we're lucky this will not need to do an IO */
- inode = ocfs_get_inode_from_offset(osb, lock_id);
- status = ocfs_find_update_res (osb, lock_id, &lockres, NULL, NULL,
- (OCFS_NM_HEARTBEAT_TIME/2), inode);
- if (status < 0) {
- if (status == -ETIMEDOUT)
- goto leave;
- LOG_ERROR_STATUS (status);
- } else {
- status = ocfs_acquire_lockres_ex (lockres, (OCFS_NM_HEARTBEAT_TIME/2));
- if (status < 0) {
- LOG_TRACE_ARGS ("Timedout locking lockres for id: %u.%u\n",
- HILO (lockres->sector_num));
- ocfs_put_lockres(lockres);
- goto leave;
- }
- }
-
- vote_type = get_process_vote_action(osb, lockres, node_num, flags,
- status, &master_alive, &oin);
-
- printk("ocfs_process_vote: %s request for lockid: %u.%u, action: %s, type: %s\n",
- flags & FLAG_RELEASE_LOCK ? "RELEASE" :
- (flags & FLAG_ACQUIRE_LOCK ? "ACQUIRE" : "INVALID!!!"), lock_id,
- process_vote_strings[vote_type], disk_vote ? "disk vote" : "net vote" );
-
-
- if (disk_vote) {
- /* Zero out the vote for everybody, if any already set and hung */
- vote = (ocfs_vote *) OCFS_BH_GET_DATA(vote_bh);
- for (i = 0; i < num_nodes; i++)
- vote->vote[i] = 0;
- OCFS_BH_PUT_DATA(vote_bh);
- }
-
- vote_response = 0;
- open_handle = false;
- switch (vote_type) {
- case UPDATE_INODE:
- LOG_TRACE_STR("UPDATE_INODE");
- if (inode)
- ocfs_truncate_inode_pages(inode, 0);
- /* TODO: figure this out... */
- if (disk_vote) {
- if (lockres)
- ocfs_remove_sector_node (osb, lockres);
- }
- vote_response = FLAG_VOTE_OIN_UPDATED;
- break;
-
- case UPDATE_OIN_INODE:
- LOG_TRACE_STR("UPDATE_OIN_INODE");
- ocfs_down_sem (&(oin->main_res), true);
- oin->needs_verification = true;
- tmpstat = ocfs_verify_update_oin(osb, oin);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- ocfs_up_sem (&(oin->main_res));
- vote_response = FLAG_VOTE_OIN_UPDATED;
- break;
-
- case DELETE_RENAME:
- LOG_TRACE_STR("DELETE_RENAME");
- oin = lockres->oin;
-
- /* all cases except open_hndl_cnt > 0 will vote YES */
- vote_response = FLAG_VOTE_NODE;
-
- if (oin) {
- oin_sem = &(oin->main_res);
- ocfs_down_sem (oin_sem, true);
- oin->needs_verification = true;
- tmpstat = ocfs_verify_update_oin(osb, oin);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
-
- /* If OIN_IN_USE is set we should go back and retry */
- for (i=0; i<5 && oin->oin_flags & OCFS_OIN_IN_USE; i++) {
- ocfs_up_sem (oin_sem);
- ocfs_sleep (20);
- ocfs_down_sem (oin_sem, true);
- }
-
- /* make sure that lockres->oin has not changed */
- oin = lockres->oin;
-
- if (oin && oin->open_hndl_cnt > 0) {
- /* the NO vote for delete/rename */
- vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
- } else if (oin && !(oin->oin_flags & OCFS_OIN_IN_TEARDOWN)) {
- inode = oin->inode;
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_NEEDS_DELETION);
- ocfs_up_sem (oin_sem);
- ocfs_release_lockres (lockres);
- lockres = NULL;
- oin_sem = NULL;
- }
- }
- if (!lockres) {
- /* is there an inode to dump? */
- if (inode) {
- inode->i_nlink = 0;
- d_prune_aliases (inode);
- if (oin)
- fsync_inode_buffers (inode);
- }
- break;
- }
-
- /* Set the always update master on open flag */
- lockres->lock_state |= FLAG_ALWAYS_UPDATE_OPEN;
- lockres->last_upd_seq_num = seq_num;
- if (lockres->master_node_num == OCFS_INVALID_NODE_NUM || !master_alive)
- lockres->master_node_num = node_num;
-
- /* Change the master if there is no lock */
- if (lockres->master_node_num == osb->node_num &&
- lockres->lock_state <= OCFS_DLM_SHARED_LOCK) {
- /* Change the lock ownership to the node asking for vote */
- /* and write new master on the disk */
-
- status = ocfs_read_bh(osb, lock_id, &fe_bh, lockflags, inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- if (status >= 0) {
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- DISK_LOCK_CURRENT_MASTER (fe) = node_num;
- OCFS_BH_PUT_DATA(fe_bh);
- status = ocfs_write_bh(osb, fe_bh, 0, inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- else
- lockres->master_node_num = node_num;
- brelse(fe_bh);
- }
- }
- if (oin_sem)
- ocfs_up_sem (oin_sem);
-
- break;
-
- case RELEASE_CACHE:
- case CHANGE_MASTER:
- if (vote_type == RELEASE_CACHE)
- LOG_TRACE_STR("RELEASE_CACHE");
- else
- LOG_TRACE_STR("CHANGE_MASTER");
-
- status = -EFAIL;
-
-#if 0
- if (vote_type == CHANGE_MASTER
- && lockres->lock_type != OCFS_DLM_NO_LOCK) {
- LOG_TRACE_STR("FLAG_VOTE_UPDATE_RETRY (1)");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- status = 0;
- break;
- }
-#endif
- /* If nobody currently owns the lock, then
- * fastpath it. */
- if (lockres->lock_holders == 0)
- goto give_lock;
-
- /* Slow path. We might still be able to give
- * him the lock if it's part of the cache and
- * we can flush it... */
-
- LOG_TRACE_ARGS("Lock id (%u.%u) has %u holders\n",
- HILO(lockres->sector_num),
- lockres->lock_holders);
-
- /* Try to take the trans_lock. We try a couple
- * times, with some sleep just in case a
- * transaction is about to complete. */
- have_trans_lock = false;
- for(i = 0; i < 2; i++) {
- if (down_trylock(&osb->trans_lock) == 0) {
- have_trans_lock = true;
- break;
- }
- ocfs_sleep(100);
- }
-
- /* We couldn't get the trans_lock. There's no
- * point in going any further. */
- if (!have_trans_lock) {
- LOG_TRACE_STR("FLAG_VOTE_UPDATE_RETRY (2)");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- status = 0;
- break;
- }
-
- /* We have the trans_lock! If it's in the
- * commited list, then dump cache and give it
- * to the other node. Otherwise, it's
- * currently in use by another transaction. */
- down(&(osb->journal.commit_sem));
- in_cache = ocfs_search_commited(osb, lockres);
- up(&(osb->journal.commit_sem));
-
- if (in_cache) {
- /* if we keep the lockres locked, then
- * the call to release_lock in
- * commit_cache will deadlock. On the
- * other hand, we don't want it
- * destroyed behind us. */
- ocfs_get_lockres(lockres);
- ocfs_release_lockres(lockres);
-
- status = ocfs_commit_cache(osb, false);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- ocfs_put_lockres(lockres);
- goto leave;
- }
-
- status = ocfs_acquire_lockres_ex(lockres,
- (OCFS_NM_HEARTBEAT_TIME/2));
- ocfs_put_lockres(lockres);
- if (status < 0)
- LOG_TRACE_STR("Timed out locking "
- "lockres again.");
- else if (lockres->lock_holders == 0)
- goto give_lock;
- } else
- up(&osb->trans_lock);
-
- /* Ok, either we couldn't find it in the
- * cache, or it became busy again while we
- * were dumping cache. */
- LOG_TRACE_STR("FLAG_VOTE_UPDATE_RETRY (3)");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- status = 0;
- break;
-
-give_lock:
- if (vote_type == CHANGE_MASTER)
- lockres->master_node_num = node_num;
-
- if (inode) {
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
- }
- if (oin != NULL) {
- lockres->lock_type = lockres->lock_state = OCFS_DLM_NO_LOCK;
- lockres->cache_lock_held = false;
- }
-
- status = ocfs_read_bh(osb, lock_id, &fe_bh, lockflags, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- break;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- is_dir = IS_VALID_DIR_NODE(fe);
- is_locked = DISK_LOCK_FILE_LOCK (fe) > OCFS_DLM_NO_LOCK;
- if (vote_type == CHANGE_MASTER) {
- if (oin)
- DISK_LOCK_OIN_MAP (fe) |= (1 << osb->node_num);
- DISK_LOCK_CURRENT_MASTER (fe) = node_num;
- }
- OCFS_BH_PUT_DATA(fe_bh);
-
- if (is_dir) {
- struct buffer_head **dir_bhs = NULL;
- int dirblks = osb->vol_layout.dir_node_size / osb->sect_size;
-
- dir_bhs = ocfs_malloc(dirblks * sizeof(*dir_bhs));
- if (dir_bhs == NULL) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- brelse(fe_bh);
- break;
- }
- memset(dir_bhs, 0, dirblks * sizeof(*dir_bhs));
-
- status = ocfs_read_bhs(osb, lock_id,
- dirblks * osb->sect_size,
- dir_bhs, OCFS_BH_CACHED,
- inode);
- if (status >= 0)
- ocfs_release_dir_cache_lock(osb, dir_bhs, inode);
-
- /* we need to do a safe cleanup in either case, so */
- /* we just jump in case of error later. */
- for (i = 0; i < dirblks; i++)
- if (dir_bhs[i])
- brelse(dir_bhs[i]);
- ocfs_safefree(dir_bhs);
-
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- brelse(fe_bh);
- break;
- }
- }
-
- /* need to do the write only if fe lock values need to change */
- if (is_locked || vote_type == CHANGE_MASTER) {
- if (vote_type == RELEASE_CACHE) {
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_NO_LOCK;
- OCFS_BH_PUT_DATA(fe_bh);
- }
- status = ocfs_write_bh(osb, fe_bh, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- brelse(fe_bh);
- break;
- }
- if (vote_type == RELEASE_CACHE)
- lockres->lock_type = lockres->lock_state = OCFS_DLM_NO_LOCK;
- else
- lockres->master_node_num = node_num;
- }
- brelse(fe_bh);
- vote_response = FLAG_VOTE_NODE;
- //dump_inode_clean_queue_buffers(inode);
- inc_inode_seq = true;
- status = 0;
- break;
-
- case ADD_OIN_MAP:
- LOG_TRACE_STR("ADD_OIN_MAP");
- status = ocfs_read_bh(osb, lock_id, &fe_bh, lockflags, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- break;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA(fe_bh);
-
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- vote_response = FLAG_VOTE_FILE_DEL;
- OCFS_BH_PUT_DATA(fe_bh);
- } else {
- __u64 tmpmap;
- DISK_LOCK_OIN_MAP (fe) |= (1 << node_num);
- tmpmap = DISK_LOCK_OIN_MAP (fe);
- OCFS_BH_PUT_DATA(fe_bh);
-
- /* Write new map on the disk */
- status = ocfs_write_bh(osb, fe_bh, 0, inode);
- if (status < 0) {
- brelse(fe_bh);
- LOG_ERROR_STATUS (status);
- break;
- }
-
- /* Add this node to the oin map on the file entry */
- lockres->oin_openmap = tmpmap;
- vote_response = FLAG_VOTE_NODE;
- }
- brelse(fe_bh);
- break;
-
- case NOT_MASTER:
- LOG_TRACE_STR("NOT_MASTER");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- if (flags & (FLAG_FILE_EXTEND|FLAG_FILE_TRUNCATE) &&
- lockres->master_node_num == node_num) {
- LOG_TRACE_STR("owner is requesting extend/truncate");
- vote_response = FLAG_VOTE_NODE;
- }
- break;
-
- case REMASTER_THIS:
- LOG_TRACE_STR("REMASTER_THIS");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- break;
-
- case REMASTER_REQUESTOR:
- LOG_TRACE_STR("REMASTER_REQUESTOR");
- vote_response = FLAG_VOTE_NODE;
- if (oin && flags & (FLAG_FILE_EXTEND|FLAG_FILE_UPDATE) &&
- !(flags & FLAG_DIR))
- open_handle = true;
- break;
-
- case INVALID_REQUEST:
- default:
- LOG_TRACE_STR("INVALID_REQUEST");
- vote_response = 0;
- break;
- }
-
- if (inode)
- iput(inode);
-
- if (flags & (FLAG_FILE_EXTEND|FLAG_FILE_TRUNCATE) &&
- ((flags & FLAG_ACQUIRE_LOCK && vote_response==FLAG_VOTE_NODE) ||
- (flags & FLAG_RELEASE_LOCK))) {
- oin = NULL;
- if (lockres && lockres->oin)
- oin = lockres->oin;
-
- LOG_TRACE_ARGS("responding YES to %s %s request, oin=%p, node=%u\n", flags & FLAG_FILE_EXTEND ?
- "extend" : "truncate", flags & FLAG_RELEASE_LOCK ?
- "release" : "acquire", oin, node_num);
- if (oin) {
- if (flags & FLAG_ACQUIRE_LOCK) {
- bool got_it = false;
-
- for (i=0; i<5; i++) {
- if (ocfs_down_sem (&oin->main_res, false)) {
- oin->open_hndl_cnt++;
- got_it = true;
- break;
- }
- ocfs_sleep(20);
- }
- ocfs_down_sem (&(osb->osb_res), true);
- if (oin->oin_flags & OCFS_OIN_IN_RECOVER_LIST)
- list_del(&oin->recovery_list);
- if (got_it) {
- LOG_TRACE_ARGS("successfully grabbed oin->main_res!\n");
- list_add_tail (&oin->recovery_list,
- &osb->lock_recovery_lists[node_num]);
- oin->oin_flags |= OCFS_OIN_IN_RECOVER_LIST;
- }
- else {
- LOG_TRACE_ARGS("tried to grab oin->main_res but failed! changing vote!\n");
- vote_response = FLAG_VOTE_UPDATE_RETRY;
- oin->oin_flags &= ~OCFS_OIN_IN_RECOVER_LIST;
- }
- ocfs_up_sem (&(osb->osb_res));
- } else if (flags & FLAG_RELEASE_LOCK) {
- ocfs_down_sem (&(osb->osb_res), true);
- if (oin->oin_flags & OCFS_OIN_IN_RECOVER_LIST) {
- LOG_TRACE_ARGS("freeing oin->main_res and resetting\n");
- list_del(&oin->recovery_list);
- oin->oin_flags &= ~OCFS_OIN_IN_RECOVER_LIST;
- oin->open_hndl_cnt--;
- ocfs_up_sem (&oin->main_res);
- } else {
- LOG_ERROR_ARGS("not freeing oin->main_res since it was never taken!\n");
- }
- ocfs_up_sem (&(osb->osb_res));
- }
- }
- }
-
- if (disk_vote) {
- vote = (ocfs_vote *) OCFS_BH_GET_DATA(vote_bh);
- vote->dir_ent = lock_id;
- vote->vote_seq_num = seq_num;
- vote->open_handle = open_handle;
- vote->vote[node_num] = vote_response;
- OCFS_BH_PUT_DATA(vote_bh);
- status = ocfs_write_bh(osb, vote_bh, 0, NULL);
- brelse(vote_bh);
- } else {
- status = ocfs_send_vote_reply(osb, dlm_msg, vote_response, open_handle);
- }
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- if (lockres) {
- ocfs_release_lockres (lockres);
- ocfs_put_lockres(lockres);
- }
-
- if (inc_inode_seq) {
- ocfs_inc_inode_seq(osb, inode);
- }
-leave:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_process_vote */
-
-
-static void ocfs_inc_inode_seq(ocfs_super *osb, struct inode *inode)
-{
- atomic_t *seq = GET_INODE_CLEAN_SEQ(inode);
-
- LOG_TRACE_ARGS("incrementing inode seq... current is %d\n",
- atomic_read(seq));
-
- /* wrap to ONE after 13 bits, will need a spinlock */
- spin_lock (&osb->clean_buffer_lock);
- if ((atomic_read(&osb->clean_buffer_seq)+1) % STATE_BIT_MAX == 0)
- atomic_set(&osb->clean_buffer_seq, 1);
- else
- atomic_inc(&osb->clean_buffer_seq);
- spin_unlock (&osb->clean_buffer_lock);
-
- /* doesn't matter if this another process */
- /* has already incremented the global seq */
- atomic_set(seq, atomic_read(&osb->clean_buffer_seq));
-
- LOG_TRACE_ARGS("done incrementing inode seq... new is %d\n",
- atomic_read(seq));
-
- fsync_inode_buffers(inode);
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- fsync_inode_data_buffers(inode);
-#endif
-}
-
-
-void ocfs_recover_oin_locks(ocfs_super *osb, __u32 node_num)
-{
- struct list_head *iter, *temp;
- ocfs_inode *oin;
-
- ocfs_down_sem (&(osb->osb_res), true);
- list_for_each_safe (iter, temp, &osb->lock_recovery_lists[node_num]) {
- oin = list_entry (iter, ocfs_inode, recovery_list);
- if (oin->obj_id.type != OCFS_TYPE_OIN) {
- LOG_ERROR_ARGS("node %u recovery: invalid oin!\n", node_num);
- continue;
- }
- if (oin->oin_flags & OCFS_OIN_IN_RECOVER_LIST) {
- LOG_TRACE_ARGS("node %u recovery: freeing oin->main_res and resetting\n", node_num);
- list_del(&oin->recovery_list);
- oin->oin_flags &= ~OCFS_OIN_IN_RECOVER_LIST;
- oin->open_hndl_cnt--;
- ocfs_up_sem (&oin->main_res);
- } else {
- LOG_ERROR_ARGS("node %u recovery: not freeing oin->main_res since it was never taken!\n", node_num);
- }
- }
- ocfs_up_sem (&(osb->osb_res));
-}
-
-/*
- * ocfs_release_dir_cache_lock()
- *
- * The dir_bhs structure after this may point to a different set of
- * buffer_heads than the ones passed in (because we iterate through
- * each dirnode). You still have to clean those up though (brelse
- * them). The original ones passed in will be properly brelsed by this
- * function, so no need to worry about them.
- */
-static int ocfs_release_dir_cache_lock (ocfs_super *osb, struct buffer_head **dir_bhs, struct inode *inode)
-{
- ocfs_file_entry *fe;
- int status = 0;
- int i;
- ocfs_dir_node *dirnode = NULL;
- int dirblks = osb->vol_layout.dir_node_size / osb->sect_size;
- __u64 next_node_ptr;
-
- LOG_ENTRY_ARGS ("(osb=0x%08x, dirnd=0x%08x)\n", osb, dirnode);
-
- dirnode = (ocfs_dir_node *) OCFS_BH_GET_DATA(dir_bhs[0]);
-
- for(i = 0; i < dirnode->num_ent_used; i++) {
- fe = (ocfs_file_entry *) FILEENT_GETBH(dirnode, dir_bhs, i);
-
- if (DISK_LOCK_FILE_LOCK(fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
- DISK_LOCK_FILE_LOCK(fe) = OCFS_DLM_NO_LOCK;
-
- FILEENT_PUTBH(dirnode, dir_bhs, i);
- }
-
- next_node_ptr = dirnode->next_node_ptr;
- OCFS_BH_PUT_DATA(dir_bhs[0]);
- dirnode = NULL;
-
- status = ocfs_write_bhs(osb, dir_bhs, dirblks, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- while (next_node_ptr != -1) {
- /* clean it up */
- for (i = 0; i < dirblks; i++)
- if (dir_bhs[i])
- brelse(dir_bhs[i]);
- memset(dir_bhs, 0, dirblks * sizeof(*dir_bhs));
-
- status = ocfs_read_bhs(osb, dirnode->next_node_ptr,
- dirblks, dir_bhs, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- dirnode = (ocfs_dir_node *)OCFS_BH_GET_DATA(dir_bhs[0]);
- if(!IS_VALID_DIR_NODE(dirnode))
- break;
-
- DISK_LOCK_FILE_LOCK(dirnode) = OCFS_DLM_NO_LOCK;
-
- for(i = 0; i < dirnode->num_ent_used; i++) {
- fe = FILEENT_GETBH(dirnode, dir_bhs, i);
- if (DISK_LOCK_FILE_LOCK(fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
- DISK_LOCK_FILE_LOCK(fe) = OCFS_DLM_NO_LOCK;
- FILEENT_PUTBH(dirnode, dir_bhs, i);
- }
-
- /* for loop back */
- next_node_ptr = dirnode->next_node_ptr;
-
- OCFS_BH_PUT_DATA(dir_bhs[0]);
- dirnode = NULL;
-
- status = ocfs_write_bhs(osb, dir_bhs, dirblks, 0, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- }
-
- bail:
- if (dirnode)
- OCFS_BH_PUT_DATA(dir_bhs[0]);
-
- LOG_EXIT_STATUS(status);
- return (status);
-} /* ocfs_release_dir_cache_lock */
Deleted: trunk/oin.c
===================================================================
--- trunk/oin.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/oin.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,756 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_IOSUP
-
-
-
-/*
- * ocfs_verify_update_oin()
- *
- * This function searches the cached oin list for a volume for a given
- * filename. We currently cache all the oin's. We should hash this list.
- *
- */
-int ocfs_verify_update_oin (ocfs_super * osb, ocfs_inode * oin)
-{
- int status = 0;
- struct buffer_head *fe_bh = NULL;
- ocfs_file_entry *fe = NULL;
- ocfs_lock_res *pLockRes;
- struct inode *inode = NULL;
- struct list_head *iter;
- struct list_head *temp_iter;
- int disk_len;
-
- /* We are setting the oin Updated flag in the end. */
- LOG_ENTRY ();
-
- OCFS_ASSERT (oin);
-
- status = ocfs_read_bh(osb, oin->file_disk_off, &fe_bh, OCFS_BH_COND_CACHED, oin->inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- /* Make sure that what we found is not a directory. */
- if (!(oin->oin_flags & OCFS_OIN_DIRECTORY)) {
- /* Add checks as needed */
- if ((fe->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- if (fe->sync_flags & OCFS_SYNC_FLAG_MARK_FOR_DELETION) {
- LOG_TRACE_STR
- ("File Entry is marked for deletion");
- } else {
- LOG_TRACE_STR ("File Entry is invalid");
- }
-
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
- /* ?? I think we should remove the oin here from the oin list */
- status = -ENOENT;
- goto leave;
- }
-
- disk_len = strlen(fe->filename);
- inode = oin->inode;
- if (inode == NULL) {
- LOG_ERROR_STR ("oin has no matching inode!!!!");
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
- status = -ENOENT;
- goto leave;
- }
-
- status = -ENOENT;
- list_for_each_safe (iter, temp_iter, &(inode->i_dentry)) {
- struct dentry *dentry = list_entry (iter, struct dentry, d_alias);
- if (dentry->d_name.len == disk_len &&
- strncmp(dentry->d_name.name, fe->filename, disk_len)==0)
- {
- status = 0;
- }
- }
- if (status < 0) {
- LOG_TRACE_STR ("file entry name did not match inode");
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_INVALID);
- goto leave;
- }
-
-
- if ((oin->alloc_size != (__s64) fe->alloc_size) ||
- (inode->i_size != (__s64) fe->file_size) ||
- (oin->chng_seq_num != DISK_LOCK_SEQNUM (fe)) ||
- inode->i_uid != fe->uid ||
- inode->i_gid != fe->gid || inode->i_mode != fe->prot_bits) {
-
- if (oin->alloc_size > (__s64)fe->alloc_size) {
- ocfs_extent_map_destroy (&oin->map);
- ocfs_extent_map_init (&oin->map);
- }
-
- LOG_TRACE_STR
- ("Allocsize, filesize or seq no did not match");
- oin->alloc_size = fe->alloc_size;
- inode->i_size = fe->file_size;
- oin->chng_seq_num = DISK_LOCK_SEQNUM (fe);
-
- inode->i_blocks = (inode->i_size + 512) >> 9;
- inode->i_uid = fe->uid;
- inode->i_gid = fe->gid;
- inode->i_mode = fe->prot_bits;
- inode->i_blksize = (__u32) osb->vol_layout.cluster_size;
- OCFS_SET_INODE_TIME(inode, i_ctime, fe->create_time);
- OCFS_SET_INODE_TIME(inode, i_atime, fe->modify_time);
- OCFS_SET_INODE_TIME(inode, i_mtime, fe->modify_time);
- if (!S_ISDIR (inode->i_mode)) {
- ocfs_truncate_inode_pages(inode, 0);
- }
-
- switch (fe->attribs) {
- case OCFS_ATTRIB_DIRECTORY:
- inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
- inode->i_blocks = (inode->i_size + 512) >> 9;
- inode->i_mode |= S_IFDIR;
- break;
- case OCFS_ATTRIB_SYMLINK:
- inode->i_mode |= S_IFLNK;
- break;
- case OCFS_ATTRIB_REG:
- inode->i_mode |= S_IFREG;
- break;
- case OCFS_ATTRIB_CHAR:
- case OCFS_ATTRIB_BLOCK:
- case OCFS_ATTRIB_FIFO:
- case OCFS_ATTRIB_SOCKET:
- {
-#ifdef LINUX_2_5
- dev_t dev;
-#else
- kdev_t kdev;
-#endif
- if (fe->attribs == OCFS_ATTRIB_CHAR)
- inode->i_mode |= S_IFCHR;
- else if (fe->attribs == OCFS_ATTRIB_BLOCK)
- inode->i_mode |= S_IFBLK;
- else if (fe->attribs == OCFS_ATTRIB_FIFO)
- inode->i_mode |= S_IFIFO;
- else if (fe->attribs == OCFS_ATTRIB_SOCKET)
- inode->i_mode |= S_IFSOCK;
-
- inode->i_rdev = NODEV;
-#ifdef LINUX_2_5
- dev = MKDEV (fe->dev_major, fe->dev_minor);
-#else
- kdev = MKDEV (fe->dev_major, fe->dev_minor);
-#endif
-
-#ifdef LINUX_2_5
- init_special_inode (inode, inode->i_mode,
- dev);
-#else
- init_special_inode (inode, inode->i_mode,
- kdev_t_to_nr(kdev));
-#endif
- break;
- }
- default:
- LOG_ERROR_ARGS ("attribs=%d", fe->attribs);
- inode->i_mode |= S_IFREG;
- break;
- }
-
- if (fe->local_ext) {
- __s64 tempVbo;
- __s64 tempLbo;
- __u64 tempSize;
- __u32 j;
-
- /* Add the Extents to extent map */
- for (j = 0; j < fe->next_free_ext; j++) {
- tempVbo = fe->extents[j].file_off;
- tempLbo = fe->extents[j].disk_off;
- tempSize = fe->extents[j].num_bytes;
-
- if (!ocfs_add_extent_map_entry (osb, &oin->map,
- tempVbo, tempLbo,
- tempSize))
- goto leave;
- }
- }
- }
-
- pLockRes = oin->lock_res;
- ocfs_get_lockres (pLockRes);
-
- /* ??? we need to the lock resource before updating it */
- if (pLockRes) {
- pLockRes->lock_type = DISK_LOCK_FILE_LOCK (fe);
- pLockRes->master_node_num = DISK_LOCK_CURRENT_MASTER (fe);
- pLockRes->oin_openmap = DISK_LOCK_OIN_MAP (fe);
- pLockRes->last_write_time = DISK_LOCK_LAST_WRITE (fe);
- pLockRes->last_read_time = DISK_LOCK_LAST_READ (fe);
- pLockRes->reader_node_num = DISK_LOCK_READER_NODE (fe);
- pLockRes->writer_node_num = DISK_LOCK_WRITER_NODE (fe);
- }
- ocfs_put_lockres (pLockRes);
-
- status = 0;
- } else {
- /* Update for the DIRECTORY */
- }
-
-leave:
- if (status == 0)
- OIN_UPDATED (oin);
-
- if (fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_verify_update_oin */
-
-
-/* ocfs_create_oin_from_entry()
- *
- */
-int ocfs_create_oin_from_entry (ocfs_super * osb, struct buffer_head * fe_bh, ocfs_inode ** new_oin, __u64 parent_dir_off, struct inode *inode)
-{
- int status = 0;
- ocfs_inode *oin;
- __u64 lockId;
- int j;
- __s64 tempVbo;
- __s64 tempLbo;
- __u64 tempSize;
- __u64 tempoff;
- ocfs_extent_group *extent = NULL;
- struct buffer_head *extent_bh = NULL;
- bool bRet;
- ocfs_file_entry *fe = NULL;
- void *tmp;
-
- LOG_ENTRY ();
-
- *new_oin = NULL;
-
- /* get a copy of fe, used readonly in this path and */
- /* ocfs_create_new_oin will deadlock if fe_bh is locked */
- fe = ocfs_allocate_file_entry();
- if (fe == NULL) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto leave;
- }
- tmp = OCFS_BH_GET_DATA(fe_bh);
- memcpy(fe, tmp, sizeof(ocfs_file_entry));
- OCFS_BH_PUT_DATA(fe_bh);
-
- /* We have a new file on disk , so create an oin for the file */
- status = ocfs_create_new_oin (&oin, fe->alloc_size, osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- oin->parent_dirnode_off = parent_dir_off;
- oin->chng_seq_num = DISK_LOCK_SEQNUM (fe);
-
- if (fe->this_sector == 0)
- LOG_ERROR_STR ("this_sector=0");
-
- tempoff = fe->this_sector;
-
- /* The oins gets Linked into the osb in this function */
-
- if (fe->attribs & OCFS_ATTRIB_DIRECTORY) {
- lockId = fe->extents[0].disk_off;
-
- status = ocfs_initialize_oin (oin, osb,
- OCFS_OIN_DIRECTORY | OCFS_OIN_IN_USE,
- tempoff, lockId, false, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- oin->dir_disk_off = fe->extents[0].disk_off;
- } else {
- __u32 flags = OCFS_OIN_IN_USE;
-
- if((DISK_LOCK_FILE_LOCK(fe) == OCFS_DLM_ENABLE_CACHE_LOCK)
- && (DISK_LOCK_CURRENT_MASTER(fe) == osb->node_num))
- flags |= OCFS_OIN_CACHE_UPDATE;
- status = ocfs_initialize_oin (oin, osb, flags,
- tempoff, tempoff, false, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (fe->local_ext) {
- for (j = 0; j < fe->next_free_ext; j++) {
- tempVbo = fe->extents[j].file_off;
- tempLbo = fe->extents[j].disk_off;
- tempSize = fe->extents[j].num_bytes;
-
- /* Add the Extent to extent map */
- bRet = ocfs_add_extent_map_entry (osb,
- &oin->map,
- tempVbo,
- tempLbo,
- tempSize);
- if (!bRet) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- }
- } else {
- __u64 next_data_ext;
-
- /* Extents are branched and we are no longer using */
- /* Local Extents for this File Entry. */
-
- status = ocfs_get_leaf_extent (osb, fe, 0, &extent_bh, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- while (1) {
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
-
- if (!IS_VALID_EXTENT_DATA (extent)) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto leave;
- }
-
- for (j = 0; j < extent->next_free_ext; j++) {
- tempVbo = extent->extents[j].file_off;
- tempLbo = extent->extents[j].disk_off;
- tempSize = extent->extents[j].num_bytes;
-
- /* Add the Extent to extent map */
- bRet =
- ocfs_add_extent_map_entry (osb,
- &oin->map,
- tempVbo,
- tempLbo,
- tempSize);
- if (!bRet) {
- LOG_ERROR_STATUS (status =
- -ENOMEM);
- goto leave;
- }
- }
-
- if (extent->next_data_ext > 0) {
- if (!extent->next_data_ext) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto leave;
- }
- next_data_ext = extent->next_data_ext;
- OCFS_BH_PUT_DATA(extent_bh);
- extent = NULL;
- extent_bh = NULL;
-
- status = ocfs_read_bh(osb,
- next_data_ext,
- &extent_bh,
- OCFS_BH_COND_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else
- break;
- }
- }
- }
-
- *new_oin = oin;
-leave:
- if (!*new_oin && oin)
- ocfs_release_oin (oin, true);
-
- /* this fe was a copy */
- if (fe)
- ocfs_release_file_entry (fe);
-
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_oin_from_entry */
-
-
-/*
- * ocfs_initialize_oin()
- *
- * Initialize a oin structure and file object. This function is called
- * whenever a file is recognized for the first time.
- */
-int ocfs_initialize_oin (ocfs_inode * oin, ocfs_super * osb, __u32 flags, __u64 file_off, __u64 lock_id, bool new_file, struct inode *inode)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- if (!(flags & OCFS_OIN_ROOT_DIRECTORY)) {
- status = ocfs_create_update_lock (osb, oin, lock_id, flags, new_file, inode);
- if (status < 0) {
- /* This can be okay as the other node can tell us the
- * file was deleted. */
- goto leave;
- }
- }
-
- oin->dir_disk_off = 0;
- oin->osb = osb;
- oin->oin_flags |= flags;
- oin->open_hndl_cnt = 0;
- oin->file_disk_off = file_off;
- oin->journal_inode = false;
- ocfs_extent_map_init (&oin->map);
-
-leave:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_initialize_oin */
-
-/*
- * ocfs_create_new_oin()
- *
- * Create a new oin.
- */
-int ocfs_create_new_oin (ocfs_inode ** Returnedoin, __u64 alloc_size, ocfs_super * osb)
-{
- int status = 0;
- ocfs_inode *oin = NULL;
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (osb);
-
- oin = ocfs_allocate_oin ();
- *Returnedoin = oin;
-
- if (oin == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- ocfs_init_sem (&(oin->main_res));
- OCFS_SET_FLAG (oin->oin_flags, OCFS_INITIALIZED_MAIN_RESOURCE);
-
- /* Initialize the alloc size value here, file size will come
- * later in i_size */
- oin->alloc_size = alloc_size;
-
- /* Insert the pointer to osb in the oin and also Initialize
- * the OFile list */
- oin->osb = osb;
-
-finally:
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_new_oin */
-
-/* ocfs_create_root_oin()
- *
- */
-int ocfs_create_root_oin (ocfs_super * osb, struct inode *root)
-{
- int status = 0;
- int tmpstat;
- ocfs_inode *oin = NULL;
- ocfs_vol_disk_hdr *volDiskHdr = NULL;
- struct buffer_head *hdr_bh = NULL;
- ocfs_lock_res *LockResource = NULL;
- struct buffer_head *bh = NULL;
- __u64 root_off, int_off;
-
- LOG_ENTRY ();
-
- if (osb->vol_layout.root_start_off == 0) {
- status = ocfs_wait_for_disk_lock_release (osb, OCFS_VOLUME_LOCK_OFFSET,
- 10000, OCFS_DLM_NO_LOCK);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- status = ocfs_acquire_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, FLAG_FILE_CREATE,
- &LockResource, &bh, NULL);
- if (status >= 0) {
- status = ocfs_read_bh(osb, 0, &hdr_bh, 0, NULL);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- tmpstat = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET, OCFS_DLM_EXCLUSIVE_LOCK, 0, LockResource, bh, NULL);
-
- if (bh)
- brelse(bh);
-
- if (tmpstat < 0) {
- LOG_ERROR_STATUS (tmpstat);
- osb->vol_state = VOLUME_DISABLED;
- if (status >= 0)
- status = tmpstat;
- }
- }
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- volDiskHdr = (ocfs_vol_disk_hdr *) OCFS_BH_GET_DATA(hdr_bh);
- root_off = volDiskHdr->root_off;
- int_off = volDiskHdr->internal_off;
- OCFS_BH_PUT_DATA(hdr_bh);
-
- if (root_off != 0) {
- ocfs_wait_for_disk_lock_release (osb,
- OCFS_VOLUME_LOCK_OFFSET,
- 30000, OCFS_DLM_NO_LOCK);
- osb->vol_layout.root_start_off = root_off;
- osb->vol_layout.root_int_off = int_off;
- }
-
- status = ocfs_create_root_dir_node (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- /* if it fails, Release the memory for the OFile we allocated above */
- }
-
- /* Create the root directory oin. This is done either here or in */
- /* FindNewoin's if it fails, Release the memory for the OFile we */
- /* allocated above */
- status = ocfs_create_new_oin (&oin, 0ULL, osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* This is for root . */
- status = ocfs_initialize_oin (oin, osb,
- OCFS_OIN_DIRECTORY | OCFS_OIN_ROOT_DIRECTORY,
- 0, osb->vol_layout.root_start_off, true, root);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
-
- // oin->Parentoin = NULL; /* Root has no parent */
-
- /* Set the Rootdirectories root Dir Node */
-
- osb->oin_root_dir = oin;
-
- oin->dir_disk_off = osb->vol_layout.root_start_off;
-
-finally:
- if (status < 0 && oin)
- ocfs_release_oin (oin, true);
-
- if (hdr_bh) {
- lock_buffer(hdr_bh);
- mark_buffer_uptodate(hdr_bh, false);
- unlock_buffer(hdr_bh);
- brelse(hdr_bh);
- }
-
- ocfs_put_lockres (LockResource);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_root_oin */
-
-/*
- * ocfs_release_oin()
- *
- */
-void ocfs_release_oin (ocfs_inode * oin, bool FreeMemory)
-{
- ocfs_lock_res *lockres = NULL;
- ocfs_super *osb = NULL;
- struct inode *inode;
-
- LOG_ENTRY_ARGS ("oin = %p, free = %s\n", oin, FreeMemory? "yes" : "no");
-
- if (!oin || !oin->osb)
- goto bail;
-
- osb = oin->osb;
- lockres = oin->lock_res;
-
- if (lockres != NULL) {
- ocfs_get_lockres (lockres);
- ocfs_acquire_lockres (lockres);
- if (lockres->oin == oin)
- lockres->oin = NULL;
- ocfs_release_lockres (lockres);
- }
- if (oin->oin_flags & OCFS_OIN_IN_RECOVER_LIST) {
- oin->oin_flags &= ~OCFS_OIN_IN_RECOVER_LIST;
- ocfs_down_sem (&(osb->osb_res), true);
- list_del(&oin->recovery_list);
- ocfs_up_sem (&(osb->osb_res));
- }
-
- inode = (struct inode *) oin->inode;
-
- if (inode) {
- __u64 savedOffset = oin->file_disk_off;
-
- SET_INODE_OIN (inode, NULL);
- SET_INODE_OFFSET (inode, savedOffset);
- LOG_TRACE_ARGS ("inode oin cleared / flags: %d / offset: %u.%u\n",
- inode->i_flags, savedOffset);
- }
-
- ocfs_extent_map_destroy (&oin->map);
-
- /* Delete the ocfs_sem objects */
- if (oin->oin_flags & OCFS_INITIALIZED_MAIN_RESOURCE) {
- ocfs_del_sem (&(oin->main_res));
- OCFS_CLEAR_FLAG (oin->oin_flags, OCFS_INITIALIZED_MAIN_RESOURCE);
- }
- if (oin->oin_flags & OCFS_INITIALIZED_PAGING_IO_RESOURCE) {
- ocfs_del_sem (&(oin->paging_io_res));
- OCFS_CLEAR_FLAG (oin->oin_flags,
- OCFS_INITIALIZED_PAGING_IO_RESOURCE);
- }
-
- if (FreeMemory) {
-#ifdef OCFS_MEM_DBG
- ocfs_dbg_slab_free (OcfsGlobalCtxt.oin_cache, oin);
-#else
- kmem_cache_free (OcfsGlobalCtxt.oin_cache, oin);
-#endif
- oin = NULL;
- ocfs_put_lockres (lockres);
- }
- ocfs_put_lockres (lockres);
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_release_oin */
-
-/*
- * ocfs_release_cached_oin()
- *
- */
-void ocfs_release_cached_oin (ocfs_super * osb, ocfs_inode * oin)
-{
- bool bAcquiredOIN = false;
- ocfs_lock_res *lockResource = NULL;
- ocfs_lock_res *val=NULL;
- struct dentry *dentry;
- struct list_head *iter;
- struct list_head *temp_iter;
- struct inode *inode;
- int refcount = 0;
- int status = 0;
-
-
- LOG_ENTRY_ARGS ("(oin = 0x%08x)\n", oin);
-
- if (oin == NULL)
- goto bail;
-
- ocfs_down_sem (&(oin->main_res), true);
- bAcquiredOIN = true;
- inode = oin->inode;
-
- if (inode) {
- list_for_each_safe (iter, temp_iter, &(inode->i_dentry)) {
- dentry = list_entry (iter, struct dentry, d_alias);
- refcount += atomic_read(&dentry->d_count);
- }
- }
-
-
- if (refcount != 0 || oin->open_hndl_cnt != 0 ||
- oin->oin_flags & OCFS_OIN_IN_USE) {
- if (bAcquiredOIN) {
- ocfs_up_sem (&(oin->main_res));
- bAcquiredOIN = false;
- }
- goto bail;
- } else {
- OCFS_SET_FLAG (oin->oin_flags, OCFS_OIN_IN_TEARDOWN);
-
- if (bAcquiredOIN) {
- ocfs_up_sem (&(oin->main_res));
- bAcquiredOIN = false;
- }
-
- lockResource = (ocfs_lock_res *) oin->lock_res;
- if (lockResource == NULL) {
- LOG_ERROR_STR ("lockres=null");
- goto bail;
- }
-
- if (lockResource->signature != 0x55AA) {
- LOG_ERROR_STR("Invalid lock resource");
- goto bail;
- }
- ocfs_get_lockres (lockResource);
-
- if (lockResource->sector_num == 0 || lockResource->oin != oin) {
- LOG_ERROR_STR ("id=0 or oin invalid");
- goto bail;
- }
-
- lockResource->oin = NULL;
- if (oin->in_needs_flush_list) {
- list_del (& (oin->needs_flush_list));
- oin->in_needs_flush_list = false;
- }
- if (lockResource->in_cache_list) {
- list_del (& (lockResource->cache_list));
- lockResource->in_cache_list = false;
- }
-
- status = ocfs_lookup_sector_node (osb, lockResource->sector_num, &val);
- if (status >= 0) {
- if (val == lockResource)
- ocfs_remove_sector_node (osb, val);
- else
- LOG_ERROR_ARGS("(lres=0x%08x) != (val=0x%08x)",
- lockResource, val);
- ocfs_put_lockres (val);
- } else {
- if (status == -EFAIL) {
- ocfs_put_lockres (oin->lock_res);
- oin->lock_res = NULL;
- LOG_TRACE_ARGS ("hashtable already destroyed\n");
- goto bail;
- }
- LOG_ERROR_ARGS("lres=0x%08x is not in the hash!",
- lockResource);
- }
- ocfs_put_lockres (oin->lock_res);
- oin->lock_res = NULL;
- }
-
-bail:
- ocfs_put_lockres (lockResource);
- LOG_EXIT ();
- return;
-} /* ocfs_release_cached_oin */
-
Deleted: trunk/osb.c
===================================================================
--- trunk/osb.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/osb.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,626 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-
-/*
- * ocfs_initialize_osb()
- *
- */
-int ocfs_initialize_osb (ocfs_super * osb, ocfs_vol_disk_hdr * vdh, ocfs_vol_label * vol_label, __u32 sect_size)
-{
- int status = 0;
- ocfs_publish *publish = NULL;
- __u32 bitmap_bits, length;
- __u64 offset;
- ocfs_vol_layout *vol_layout;
- struct buffer_head *publish_bh = NULL; /* our own publish sector */
- struct buffer_head *publish_bhs[OCFS_MAXIMUM_NODES]; /* all the publish sectors */
- int i;
-
- LOG_ENTRY ();
-
- memset(publish_bhs, 0, OCFS_MAXIMUM_NODES * sizeof (struct buffer_head *));
- if (osb == NULL) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto finally;
- }
-
- OCFS_CLEAR_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_SHUTDOWN);
-
- vol_layout = &(osb->vol_layout);
-
- vol_layout->cluster_size = (__u32) (vdh->cluster_size);
- osb->obj_id.type = OCFS_TYPE_OSB;
- osb->obj_id.size = sizeof (ocfs_super);
-
-#define HASHBITS 12
-
- if (!ocfs_hash_create (&(osb->root_sect_node), HASHBITS)) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- ocfs_init_sem (&(osb->osb_res));
- ocfs_init_sem (&(osb->map_lock));
- ocfs_init_sem (&(osb->log_lock));
- ocfs_init_sem (&(osb->recovery_lock));
- ocfs_init_sem (&(osb->dir_alloc_lock));
- ocfs_init_sem (&(osb->file_alloc_lock));
- ocfs_init_sem (&(osb->vol_alloc_lock));
-
- init_MUTEX (&(osb->comm_lock));
- init_MUTEX (&(osb->trans_lock));
-
- spin_lock_init(&osb->recovery_map_lock);
- osb->recovery_map = 0;
-
- osb->needs_flush = false;
- osb->log_disk_off = 0;
- osb->log_meta_disk_off = 0;
- osb->trans_in_progress = false;
-
- init_MUTEX (&(osb->publish_lock));
- atomic_set (&osb->node_req_vote, 0);
-
- init_waitqueue_head (&osb->nm_init_event);
- atomic_set (&osb->nm_init, 0);
-
- osb->publish_dirty = false;
- osb->in_voting = NOT_VOTING;
- ocfs_init_sem (&(osb->voting_lock));
- init_waitqueue_head (&osb->flush_event);
- atomic_set (&osb->flush_event_woken, 0);
- atomic_set (&osb->clean_buffer_seq, 1);
- spin_lock_init (&osb->clean_buffer_lock);
-
- ocfs_extent_map_init (&osb->metadata_map);
- ocfs_extent_map_init (&osb->trans_map);
-
- INIT_LIST_HEAD (&(osb->cache_lock_list));
- INIT_LIST_HEAD (&(osb->needs_flush_head));
- for (i=0; i<32; i++) {
- INIT_LIST_HEAD(&(osb->lock_recovery_lists[i]));
- }
- osb->sect_size = sect_size;
- osb->oin_root_dir = NULL;
- osb->node_num = OCFS_INVALID_NODE_NUM;
-
- memcpy (vol_layout->mount_point, vdh->mount_point, strlen (vdh->mount_point));
- vol_layout->serial_num = vdh->serial_num;
- vol_layout->size = (__u64) (vdh->device_size);
- vol_layout->start_off = vdh->start_off;
- vol_layout->bitmap_off = (__u64) vdh->bitmap_off;
- vol_layout->publ_sect_off = vdh->publ_off;
- vol_layout->vote_sect_off = vdh->vote_off;
- vol_layout->root_bitmap_off = vdh->root_bitmap_off;
- vol_layout->root_start_off = vdh->root_off;
- vol_layout->root_int_off = vdh->internal_off;
- vol_layout->root_size = vdh->root_size;
- vol_layout->cluster_size = (__u32) vdh->cluster_size;
- vol_layout->num_nodes = (__u32) vdh->num_nodes;
- vol_layout->data_start_off = vdh->data_start_off;
- vol_layout->root_bitmap_size = vdh->root_bitmap_size;
- vol_layout->num_clusters = vdh->num_clusters;
- vol_layout->dir_node_size = vdh->dir_node_size;
- vol_layout->file_node_size = vdh->file_node_size;
- vol_layout->node_cfg_off = vdh->node_cfg_off;
- vol_layout->node_cfg_size = vdh->node_cfg_size;
- vol_layout->new_cfg_off = vdh->new_cfg_off;
- vol_layout->prot_bits = vdh->prot_bits;
- vol_layout->uid = vdh->uid;
- vol_layout->gid = vdh->gid;
-
- memcpy (vol_layout->vol_id, vol_label->vol_id, MAX_VOL_ID_LENGTH);
-
- if (vol_layout->dir_node_size == 0)
- vol_layout->dir_node_size = OCFS_DEFAULT_DIR_NODE_SIZE;
-
- if (vol_layout->file_node_size == 0)
- vol_layout->file_node_size = OCFS_DEFAULT_FILE_NODE_SIZE;
-
- osb->max_dir_node_ent =
- (__u32) (vol_layout->dir_node_size / sect_size) - 2;
- bitmap_bits = (__u32) vol_layout->num_clusters;
-
- ocfs_initialize_bitmap (&osb->cluster_bitmap, bitmap_bits, ONE_MEGA_BYTE * 8);
- /* read the whole cluster bitmap off disk, even though we only
- * need the beginning of it. */
- status = ocfs_read_bhs(osb, vol_layout->bitmap_off, ONE_MEGA_BYTE, osb->cluster_bitmap.chunk, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- osb->prealloc_lock = 0;
- osb->data_prealloc = ocfs_malloc (IORUN_ALLOC_SIZE);
- if (!osb->data_prealloc) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- osb->md_prealloc = ocfs_malloc (IORUN_ALLOC_SIZE);
- if (!osb->md_prealloc) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- osb->cfg_numblocks = OCFS_MAXIMUM_NODES + OCFS_VOLCFG_NEWCFG_SECTORS;
- osb->cfg_len = osb->cfg_numblocks * sect_size;
- osb->cfg_bhs = ocfs_malloc (osb->cfg_numblocks
- * sizeof(struct buffer_head *));
- if (!osb->cfg_bhs) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
- memset(osb->cfg_bhs, 0,
- osb->cfg_numblocks * sizeof(struct buffer_head *));
-
- status = ocfs_get_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* Read the Publish Sector of local Node */
- offset = vol_layout->publ_sect_off + (osb->node_num * osb->sect_size);
- status = ocfs_read_bh(osb, offset, &publish_bh, 0, NULL);
-/* status = ocfs_read_force_disk_ex (osb, (void **)&publish,
- osb->sect_size, osb->sect_size, offset);*/
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(publish_bh);
-
- /* Zero out the time stamp to write a new value */
- publish->time = 0;
- OcfsQuerySystemTime (&publish->time);
-
- OCFS_BH_PUT_DATA(publish_bh);
- publish = NULL;
- status = ocfs_write_bh (osb, publish_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- brelse(publish_bh);
-
- /* Read disk for all Publish Sectors */
- length = OCFS_MAXIMUM_NODES * osb->sect_size;
- status = ocfs_read_bhs(osb, vol_layout->publ_sect_off, length,
- publish_bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- ocfs_update_publish_map (osb, publish_bhs, true);
-
- for(i = 0; i < OCFS_MAXIMUM_NODES; i++)
- osb->last_publ_seq_num[i] = (__u64) (-1);
-
- /* We might need to add a variable in Global List of osb to */
- /* delay any creation, if any other node is already creating a file */
-
- /* Link this osb onto the global linked list of all osb structures. */
- /* The Global Link List is mainted for the whole driver . */
- ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
- list_add_tail (&(osb->osb_next), &(OcfsGlobalCtxt.osb_next));
- ocfs_up_sem (&(OcfsGlobalCtxt.res));
-
- /* Mark the fact that this osb structure is initialized. */
- OCFS_SET_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_OSB_INITIALIZED);
-
- /* skip the frees which happen on error only */
- goto finally;
-
-bail:
- if (osb->root_sect_node.buckets)
- ocfs_hash_destroy (&(osb->root_sect_node), NULL);
- ocfs_safefree (osb->data_prealloc);
- ocfs_safefree (osb->md_prealloc);
- ocfs_safefree (osb->cfg_bhs);
-
-finally:
- if (publish) {
- if (publish_bh) {
- OCFS_BH_PUT_DATA(publish_bh);
- brelse(publish_bh);
- }
- }
- if (publish_bhs[0]) {
- int i;
- for(i = 0; i < OCFS_MAXIMUM_NODES; i++)
- if (publish_bhs[i])
- brelse(publish_bhs[i]);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_initialize_osb */
-
-/*
- * ocfs_verify_volume()
- *
- */
-int ocfs_verify_volume (ocfs_vol_disk_hdr * vdh)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- if (vdh == NULL) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- /* Compare the Signature with the one we read from disk */
- if (memcmp (vdh->signature, OCFS_VOLUME_SIGNATURE,
- strlen (OCFS_VOLUME_SIGNATURE)) != 0) {
- LOG_ERROR_STR ("Invalid volume signature");
- status = -EINVAL;
- goto bail;
- }
-
- /* Check the Volume Length and the ClusterSize. */
- if (vdh->device_size == 0) {
- LOG_ERROR_STR ("Device size cannot be zero");
- status = -EINVAL;
- goto bail;
- }
-
- if (vdh->cluster_size == 0) {
- LOG_ERROR_STR ("Cluster size cannot be zero");
- status = -EINVAL;
- goto bail;
- }
-
- if (vdh->major_version != OCFS_MAJOR_VERSION) {
- LOG_ERROR_ARGS ("Version number not compatible: %u.%u",
- vdh->major_version, vdh->minor_version);
- status = -EINVAL;
- goto bail;
- }
-
- /* Verify if mount point and volume size are valid */
- /* Read the root directory and make sure it is valid */
- /* Check to see who else is alive. */
- /* Kick in the NM i/f to start writing time stamps to the disk */
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_verify_volume */
-
-/*
- * ocfs_check_volume()
- *
- */
-int ocfs_check_volume (ocfs_super * osb)
-{
- int status = 0;
- __u64 offset = 0;
- ocfs_publish *publish = NULL;
- int node_num = osb->node_num;
- ocfs_node_config_info *config = osb->node_cfg_info[node_num];
- struct buffer_head * publish_bh = NULL;
- bool dirty, mounted;
-
- LOG_ENTRY ();
-
- /* Read the node's publish sector */
- offset = osb->vol_layout.publ_sect_off +
- (osb->node_num * osb->sect_size);
- status = ocfs_read_bh(osb, offset, &publish_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- publish = (ocfs_publish *) OCFS_BH_GET_DATA(publish_bh);
- /* we copy these two flags out of the publish sector and then unlock
- * the bh as other functions will need to modify it. */
- dirty = publish->dirty;
- mounted = publish->mounted;
-
- OCFS_BH_PUT_DATA(publish_bh);
- publish = NULL;
-
-
- /* Init our journal object. */
- status = ocfs_journal_init(osb);
- if (status < 0) {
- LOG_ERROR_STR("Could not initialize journal!");
- goto finally;
- }
-
- /* Need to check if we have never had a journal here
- * before. If not, we have to create the journal structures .*/
- LOG_TRACE_ARGS("Node config states a journal version of %d\n", \
- (int) config->journal_version);
- if (config->journal_version < OCFS_JOURNAL_CURRENT_VERSION) {
- if (dirty) {
- LOG_ERROR_STR("Volume is dirty, please remount with " \
- "old version of ocfs before upgrading.");
- status = -1;
- goto finally;
- }
-
- printk("ocfs: Old journal type found, converting to new" \
- "style. You will no longer be able to mount " \
- "with old versions of ocfs.\n");
-
- /* do our "journal_create" */
- status = ocfs_journal_create(&osb->journal);
- if (status < 0) {
- LOG_ERROR_STR("Could not create journal!");
- goto finally;
- }
-
- /* increment the journal version number in the autoconfig */
- status = ocfs_journal_update_config(osb,
- OCFS_JOURNAL_CURRENT_VERSION);
- if (status < 0) {
- LOG_ERROR_STR("Could not update node config!");
- goto finally;
- }
-
- /* Ok, piggy-back local alloc file creation here. If
- * this is also a 1st mount of the filesystem, then
- * the worst that'll happen is we stamp the new local
- * alloc twice -- not really a big deal :) */
- status = ocfs_create_new_local_alloc(osb, osb->node_num);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- goto skip_load;
- }
-
- /* If the journal was unmounted cleanly then we don't want to
- * recover anything. Otherwise, journal_load will do that
- * dirty work for us :) */
- if (!mounted)
- ocfs_journal_wipe(&osb->journal, 0);
- else
- printk(KERN_NOTICE "ocfs: File system was not unmounted "
- "cleanly, recovering volume.\n");
-
- /* will play back anything left in the journal. */
- ocfs_journal_load(&osb->journal);
-
- if (mounted) {
- /* recover my local alloc if we didn't unmount cleanly. */
- status = ocfs_recover_local_alloc(osb, node_num);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
-
-skip_load:
- /* 'mounted' flag in publish sector should not be set until
- * after we successfully load the journal. */
- status = ocfs_journal_set_mounted(osb, osb->node_num);
- if (status < 0)
- LOG_ERROR_STR("Could not set mounted flag!");
- LOG_TRACE_STR("Journal loaded.");
-
- status = ocfs_load_local_alloc(osb);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
-finally:
- if (publish_bh) {
- if (publish)
- OCFS_BH_PUT_DATA(publish_bh);
- brelse(publish_bh);
- }
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_check_volume */
-
-
-/*
- * ocfs_delete_osb()
- *
- * The routine gets called from dismount or close whenever a dismount on
- * volume is requested and the osb open count becomes 1.
- * It will remove the osb from the global list and also free up all the
- * initialized resources and fileobject.
- */
-void ocfs_delete_osb (ocfs_super * osb)
-{
- int i;
- LOG_ENTRY ();
-
- /* This function assumes that the caller has the main osb resource */
-
- /* Remove the osb from the global linked list of all osb structures. */
- /* The Global Link List is mainted for the whole driver */
- ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
- list_del (&(osb->osb_next));
- ocfs_up_sem (&(OcfsGlobalCtxt.res));
-
- for (i=0; i<32; i++)
- ocfs_recover_oin_locks(osb, i);
-
- ocfs_del_sem (&(osb->osb_res));
- ocfs_del_sem (&(osb->log_lock));
- ocfs_del_sem (&(osb->recovery_lock));
- ocfs_del_sem (&(osb->map_lock));
- ocfs_extent_map_destroy (&osb->metadata_map);
- ocfs_extent_map_destroy (&osb->trans_map);
- ocfs_safefree(osb->data_prealloc);
- ocfs_safefree(osb->md_prealloc);
- for(i = 0; i < osb->cfg_numblocks; i++)
- if (osb->cfg_bhs[i])
- brelse(osb->cfg_bhs[i]);
- ocfs_safefree(osb->cfg_bhs);
- memset (osb, 0, sizeof (ocfs_super));
-
- LOG_EXIT ();
- return;
-} /* ocfs_delete_osb */
-
-/* ocfs_create_root_dir_node()
- *
- */
-int ocfs_create_root_dir_node (ocfs_super * osb)
-{
- int status = 0, tempstat;
- __u64 bitmapOffset, numClustersAlloc, fileOffset = 0;
- ocfs_vol_disk_hdr *volDiskHdr = NULL;
- ocfs_lock_res *LockResource = NULL;
- bool lock_acq = false;
- char *buf = NULL;
- struct buffer_head *lock_bh = NULL;
- struct buffer_head **dirnode_bhs = NULL;
- struct buffer_head *hdr_bh = NULL;
- ocfs_dir_node *NewDirNode = NULL;
- int size, i;
-
- LOG_ENTRY ();
-
- size = (__u32) ( OCFS_DEFAULT_DIR_NODE_SIZE / osb->sect_size)
- * sizeof(struct buffer_head *);
- //NewDirNode = ocfs_malloc (size);
- dirnode_bhs = ocfs_malloc (size);
- if (dirnode_bhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- memset (dirnode_bhs, 0, size);
-
- if ((buf = ocfs_malloc (OCFS_MAX_FILENAME_LENGTH)) == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- /* Acquire volume Lock ... */
- status = ocfs_acquire_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, FLAG_FILE_CREATE,
- &LockResource, &lock_bh, NULL);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- } else
- lock_acq = true;
-
-
- size = (ONE_MEGA_BYTE > osb->vol_layout.cluster_size) ?
- ONE_MEGA_BYTE : osb->vol_layout.cluster_size;
-
- status = ocfs_find_contiguous_space_from_bitmap (osb, size,
- &bitmapOffset, &numClustersAlloc,
- false, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- osb->vol_layout.root_int_off = (bitmapOffset * 512) + osb->vol_layout.data_start_off;
-
- /* Create Files in root for directory, file node allocations */
- /* Create the dir alloc file now that we have a internal */
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- ocfs_init_system_file (osb, OCFS_FILE_VOL_META_DATA + i, buf);
- ocfs_init_system_file (osb, OCFS_FILE_VOL_LOG_FILE + i, buf);
- ocfs_init_system_file (osb, OCFS_FILE_DIR_ALLOC + i, buf);
- ocfs_init_system_file (osb, OCFS_FILE_DIR_ALLOC_BITMAP + i, buf);
- ocfs_init_system_file (osb, OCFS_FILE_FILE_ALLOC + i, buf);
- ocfs_init_system_file (osb, OCFS_FILE_FILE_ALLOC_BITMAP + i, buf);
- ocfs_init_system_file (osb, LOG_FILE_BASE_ID + i, buf);
- ocfs_init_system_file (osb, CLEANUP_FILE_BASE_ID + i, buf);
- status = ocfs_create_new_local_alloc(osb, i);
- }
-
- status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size,
- &bitmapOffset, &fileOffset,
- osb->node_num, DISK_ALLOC_DIR_NODE, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- status = ocfs_read_bhs(osb, bitmapOffset, OCFS_DEFAULT_DIR_NODE_SIZE,
- dirnode_bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto bail;
- }
-
- for (i = 0; i < OCFS_DEFAULT_DIR_NODE_SECTS; i++) {
- char *sect = OCFS_BH_GET_DATA(dirnode_bhs[i]);
- memset(sect, 0, osb->sect_size);
- OCFS_BH_PUT_DATA(dirnode_bhs[i]);
- }
-
- NewDirNode = (ocfs_dir_node *) OCFS_BH_GET_DATA(dirnode_bhs[0]);
- osb->vol_layout.root_start_off = bitmapOffset;
- ocfs_initialize_dir_node (osb, NewDirNode, bitmapOffset, fileOffset, osb->node_num);
- NewDirNode->dir_node_flags |= DIR_NODE_FLAG_ROOT;
- OCFS_BH_PUT_DATA(dirnode_bhs[0]);
-
- //status = ocfs_write_dir_node (osb, NewDirNode, -1);
- status = ocfs_write_bhs(osb, dirnode_bhs, OCFS_DEFAULT_DIR_NODE_SECTS, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- /* Read the first sector bytes from the target device */
- size = osb->sect_size;
- status = ocfs_read_bh(osb, 0, &hdr_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- volDiskHdr = (ocfs_vol_disk_hdr *) OCFS_BH_GET_DATA(hdr_bh);
- volDiskHdr->root_off = osb->vol_layout.root_start_off;
- volDiskHdr->internal_off = osb->vol_layout.root_int_off;
- OCFS_BH_PUT_DATA(hdr_bh);
- volDiskHdr = NULL;
-
- status = ocfs_write_bh(osb, hdr_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
-bail:
- if (hdr_bh)
- brelse(hdr_bh);
-
- if (status < 0) {
- LOG_ERROR_STR ("Disabling Volume");
- osb->vol_state = VOLUME_DISABLED;
- }
-
- /* Release Volume Lock */
- if (lock_acq) {
- tempstat = ocfs_release_lock (osb, OCFS_VOLUME_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK, 0, LockResource, lock_bh, NULL);
- if (tempstat < 0) {
- LOG_ERROR_STATUS (tempstat);
- osb->vol_state = VOLUME_DISABLED;
- }
- }
- if (lock_bh)
- brelse(lock_bh);
-
- if (dirnode_bhs && dirnode_bhs[0])
- for(i = 0; i < OCFS_DEFAULT_DIR_NODE_SECTS; i++)
- if (dirnode_bhs[i])
- brelse(dirnode_bhs[i]);
-
- ocfs_safefree(dirnode_bhs);
- ocfs_safefree (buf);
- ocfs_put_lockres (LockResource);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_create_root_dir_node */
Deleted: trunk/proc.c
===================================================================
--- trunk/proc.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/proc.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,491 +0,0 @@
-/*
- * ocfsproc.c
- *
- * ocfs proc interface
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts
- */
-
-#define OCFSPROC_PRIVATE_DECLS
-
-#include <ocfs.h>
-
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_PROC
-
-
-
-static int ocfs_proc_globalctxt(char *page, char **start, off_t off, int count, int *eof, void *data);
-static int ocfs_proc_version (char *page, char **start, off_t off, int count, int *eof, void *data);
-static int ocfs_proc_nodename (char *page, char **start, off_t off, int count, int *eof, void *data);
-static int ocfs_proc_mountpoint (char *page, char **start, off_t off, int count, int *eof, void *data);
-static int ocfs_proc_statistics (char *page, char **start, off_t off, int count, int *eof, void *data);
-static int ocfs_proc_hash_stats (char *page, char **start, off_t off, int count, int *eof, void *data);
-
-
-/*
- * ocfs_proc_init()
- *
- */
-int ocfs_proc_init (void)
-{
- static struct
- {
- char *name;
- char *data;
- int (*read_proc) (char *, char **, off_t, int, int *, void *);
- }
- *p, ProcList[] =
- {
- { "ocfs/version", NULL, ocfs_proc_version },
- { "ocfs/nodename", NULL, ocfs_proc_nodename },
- { "ocfs/globalctxt", NULL, ocfs_proc_globalctxt },
-#ifdef OCFS_LINUX_MEM_DEBUG
- { "ocfs/memallocs", NULL, ocfs_proc_memallocs },
-#endif
- { NULL, }
- };
-
- LOG_ENTRY ();
-
- proc_mkdir ("ocfs", 0);
-
- for (p = ProcList; p->name; p++)
- create_proc_read_entry (p->name, 0, NULL, p->read_proc,
- p->data);
-
- LOG_EXIT_LONG (0);
- return 0;
-} /* ocfs_proc_init */
-
-/*
- * ocfs_proc_deinit()
- *
- */
-void ocfs_proc_deinit (void)
-{
- LOG_ENTRY ();
-
- remove_proc_entry ("ocfs/version", NULL);
- remove_proc_entry ("ocfs/nodename", NULL);
- remove_proc_entry ("ocfs/memallocs", NULL);
- remove_proc_entry ("ocfs", NULL);
-
- LOG_EXIT ();
- return;
-} /* ocfs_proc_deinit */
-
-/*
- * ocfs_proc_calc_metrics()
- *
- */
-static int ocfs_proc_calc_metrics (char *page, char **start, off_t off,
- int count, int *eof, int len)
-{
- LOG_ENTRY ();
-
- if (len <= off + count)
- *eof = 1;
-
- *start = page + off;
-
- len -= off;
-
- if (len > count)
- len = count;
-
- if (len < 0)
- len = 0;
-
- LOG_EXIT ();
- return len;
-} /* ocfs_proc_calc_metrics */
-
-#ifdef OCFS_LINUX_MEM_DEBUG
-/*
- * ocfs_proc_memallocs()
- *
- */
-static int ocfs_proc_memallocs (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int ret = 0;
- int proc_overflow = 0;
- struct list_head *iter;
- struct list_head *temp_iter;
- alloc_item *item;
- int len = 0;
- char *slabname;
- char *tmpstr = NULL;
-
- LOG_ENTRY ();
-
-#define MEMDBG_LEN 255
- tmpstr = ocfs_malloc(MEMDBG_LEN);
- if (!tmpstr) {
- LOG_ERROR_STATUS (-ENOMEM);
- goto bail;
- }
-
- sprintf (tmpstr, "%-8s %-9s %s\n", "Pointer", "Size/Slab", "Line:File");
- printk("%s", tmpstr);
- ret = sprintf ((char *) (page + len), "%s", tmpstr);
- len += ret;
-
- list_for_each_safe (iter, temp_iter, &OcfsGlobalCtxt.item_list) {
- if (len >= 4096)
- proc_overflow = 1;
- item = list_entry (iter, alloc_item, list);
- switch (item->type) {
- case SLAB_ITEM:
- if (item->u.slab == OcfsGlobalCtxt.oin_cache)
- slabname = "oin";
- else if (item->u.slab == OcfsGlobalCtxt.ofile_cache)
- slabname = "ofile";
- else if (item->u.slab == OcfsGlobalCtxt.lockres_cache)
- slabname = "lockres";
- else if (item->u.slab == OcfsGlobalCtxt.fe_cache)
- slabname = "fe";
- else
- slabname = "unknown";
-
- if (item->u.slab == OcfsGlobalCtxt.lockres_cache) {
- ocfs_lock_res *p = item->address;
- sprintf(tmpstr,
- "%08x %9s %-40s %5d %u.%u\n",
- item->address, slabname, item->tag,
- atomic_read(&p->lr_ref_cnt),
- HILO(p->sector_num));
- } else
- sprintf(tmpstr, "%08x %9s %-40s\n", item->address,
- slabname, item->tag);
-
- printk("%s", tmpstr);
- if (!proc_overflow) {
- ret = snprintf ((char *) (page + len),
- (4096 - len), "%s", tmpstr);
- len += ret;
- }
- break;
- case KMALLOC_ITEM:
- case VMALLOC_ITEM:
- default:
- sprintf(tmpstr, "%08x %9d %s\n", item->address,
- item->u.length, item->tag);
- printk("%s", tmpstr);
- if (!proc_overflow) {
- ret = snprintf ((char *) (page + len),
- (4096 - len), "%s", tmpstr);
- len += ret;
- }
-
- break;
- }
- if (ret < 0)
- proc_overflow = 1;
- }
-
-
- if (proc_overflow)
- LOG_ERROR_STR ("proc output truncated");
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
-bail:
- ocfs_safefree (tmpstr);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_memallocs */
-#endif
-
-/*
- * ocfs_proc_globalctxt()
- *
- */
-static int ocfs_proc_globalctxt(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- int ret;
-
- LOG_ENTRY ();
-
- sprintf (page, "lockres count: %d\n", atomic_read (&OcfsGlobalCtxt.cnt_lockres));
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_version */
-
-
-/*
- * ocfs_proc_version()
- *
- */
-static int ocfs_proc_version (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- extern char *ocfs_version;
- int len;
- int ret;
-
- LOG_ENTRY ();
-
- strcpy (page, ocfs_version);
- strcat (page, "\n");
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_version */
-
-/*
- * ocfs_proc_nodenum()
- *
- */
-static int ocfs_proc_nodenum (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- int ret;
- ocfs_super *osb;
-
- LOG_ENTRY ();
-
- osb = (ocfs_super *) data;
- sprintf (page, "%d\n", osb->node_num);
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_nodenum */
-
-/*
- * ocfs_proc_nodename()
- *
- */
-static int ocfs_proc_nodename (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- int ret;
-
- LOG_ENTRY ();
-
- strcpy (page, OcfsGlobalCtxt.node_name);
- strcat (page, "\n");
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_nodename */
-
-/*
- * ocfs_proc_add_volume()
- *
- */
-void ocfs_proc_add_volume (ocfs_super * osb)
-{
- char *newdir = NULL;
- char *tmp = NULL;
- static struct
- {
- char *name;
- char *data;
- int (*read_proc) (char *, char **, off_t, int, int *, void *);
- }
- *p, ProcList[] =
- {
- { "nodenum", NULL, ocfs_proc_nodenum },
- { "mountpoint", NULL, ocfs_proc_mountpoint },
- { "statistics", NULL, ocfs_proc_statistics },
- { "hashstat", NULL, ocfs_proc_hash_stats },
- { NULL, }
- };
-
- LOG_ENTRY ();
-
- newdir = ocfs_malloc (32);
- tmp = ocfs_malloc (100);
- if (!newdir || !tmp) {
- LOG_ERROR_STATUS (-ENOMEM);
- goto bail;
- }
-
- ProcList[0].data = (char *) osb;
- ProcList[1].data = osb->vol_layout.mount_point;
- ProcList[2].data = (char *) osb;
- ProcList[3].data = (char *) osb;
-
- sprintf (newdir, "ocfs/%-d", osb->osb_id);
- proc_mkdir (newdir, 0);
-
- for (p = ProcList; p->name; p++) {
- sprintf (tmp, "%s/%s", newdir, p->name);
- create_proc_read_entry (tmp, 0, NULL, p->read_proc, p->data);
- }
-
-bail:
- ocfs_safefree (tmp);
- ocfs_safefree (newdir);
- LOG_EXIT ();
- return;
-} /* ocfs_proc_add_volume */
-
-/*
- * ocfs_proc_remove_volume()
- *
- */
-void ocfs_proc_remove_volume (ocfs_super * osb)
-{
- char tmp[50];
-
- LOG_ENTRY ();
-
- sprintf (tmp, "ocfs/%-d/nodenum", osb->osb_id);
- remove_proc_entry (tmp, NULL);
-
- sprintf (tmp, "ocfs/%-d/mountpoint", osb->osb_id);
- remove_proc_entry (tmp, NULL);
-
- sprintf (tmp, "ocfs/%-d/statistics", osb->osb_id);
- remove_proc_entry (tmp, NULL);
-
- sprintf (tmp, "ocfs/%-d", osb->osb_id);
- remove_proc_entry (tmp, NULL);
-
- LOG_EXIT ();
- return;
-} /* ocfs_proc_remove_volume */
-
-/*
- * ocfs_proc_mountpoint()
- *
- */
-static int ocfs_proc_mountpoint (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- int ret;
-
- LOG_ENTRY ();
-
- strcpy (page, data);
- strcat (page, "\n");
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_mountpoint */
-
-/*
- * ocfs_proc_statistics()
- *
- */
-static int ocfs_proc_statistics (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- char *pubmap = NULL;
- ocfs_super *osb;
- ocfs_vol_layout *vol;
- int ret = 0, i;
- char *ptr;
-
- LOG_ENTRY ();
-
- osb = (ocfs_super *) data;
- vol = &(osb->vol_layout);
-
- pubmap = ocfs_malloc (100);
- if (!pubmap) {
- LOG_ERROR_STATUS (-ENOMEM);
- goto bail;
- }
-
- ptr = pubmap;
- for (i = 0; i < 32; i++) {
- if (osb->publ_map & (1 << i))
- ptr += sprintf (ptr, "%d ", i);
- }
- if (pubmap != ptr)
- *(ptr - 1) = '\0';
-
-#define PROC_STATS \
- "File open count : %d.%u\n" \
- "Publish map : %s\n" \
- "Number of nodes : %u\n" \
- "Cluster size : %u\n" \
- "Volume size : %u.%u\n" \
- "Dir node size : %u.%u\n" \
- "File node size : %u.%u\n" \
- "Failed Large Allocs : %u\n" \
- "Retry Large Allocs : %u\n"
-
- len = sprintf (page, PROC_STATS, HILO (osb->file_open_cnt), pubmap,
- vol->num_nodes, vol->cluster_size, HILO (vol->size),
- HILO (vol->dir_node_size), HILO (vol->file_node_size),
- osb->cluster_bitmap.failed, osb->cluster_bitmap.ok_retries);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
-bail:
- ocfs_safefree (pubmap);
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_statistics */
-
-/*
- * ocfs_proc_hash_stats()
- *
- */
-static int ocfs_proc_hash_stats (char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len;
- int ret;
- ocfs_super *osb;
-
- LOG_ENTRY ();
-
- osb = (ocfs_super *) data;
-
- *page = '\0';
- ocfs_hash_stat (&(osb->root_sect_node), page, 1024);
-
- len = strlen (page);
-
- ret = ocfs_proc_calc_metrics (page, start, off, count, eof, len);
-
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_proc_hash_stats */
Deleted: trunk/sem.c
===================================================================
--- trunk/sem.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/sem.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,120 +0,0 @@
-#include <ocfs.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-/*
- * ocfs_init_sem()
- *
- */
-void ocfs_init_sem (ocfs_sem * res)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", res);
-
- memset (res, 0, sizeof (ocfs_sem));
- init_MUTEX (&(res->sem));
- res->magic = OCFS_SEM_MAGIC;
-
- LOG_EXIT ();
-} /* ocfs_init_sem */
-
-/*
- * ocfs_down_sem()
- *
- * Counter layer atop the sem. If a process which already owns the sem,
- * attempts to re-acquire it, ocfs_down_sem() increments the
- * count by 1. If however, a different process attempts to acquire that
- * sem, it blocks waiting for the sem to be released.
- * ocfs_up_sem() decrements the count by 1, if the owning
- * process releases the sem. The sem is released when the counter hits 0.
- * NT Port leftover, we want to get rid of this as soon as possible
- */
-bool ocfs_down_sem (ocfs_sem * res, bool wait)
-{
- bool ret = true;
-
- LOG_ENTRY_ARGS ("(0x%08x, %s, pid=%d, count=%d, semcount=%d, semsleepers=%d)\n",
- res, wait ? "wait" : "nowait",
- res->pid, res->count, res->sem.count, res->sem.sleepers);
-
- if (res->magic != OCFS_SEM_MAGIC) {
- LOG_ERROR_ARGS("semaphore magic value is bad!\n");
- ret = false;
- goto bail;
- }
-
- if (res->pid == 0) {
- if (wait) {
- down(&(res->sem));
- res->pid = current->pid;
- res->count = 1;
- } else {
- if (!down_trylock(&(res->sem))) {
- res->pid = current->pid;
- res->count = 1;
- }
- else
- ret = false;
- }
- } else {
- if (res->pid == current->pid)
- res->count++;
- else {
- if (wait) {
- down(&(res->sem));
- res->pid = current->pid;
- res->count = 1;
- } else
- ret = false;
- }
- }
-
-bail:
- LOG_EXIT_ULONG (ret);
- return ret;
-} /* ocfs_down_sem */
-
-/*
- * ocfs_up_sem()
- *
- * ocfs_up_sem() decrements the count by 1, if the owning
- * process releases the sem. The sem is released when the counter hits 0.
- * Remained of NT port, we really really do not want this nesting
- * but for now it's there, we'll clean it up
- */
-void ocfs_up_sem (ocfs_sem * res)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", res);
-
- if (res->magic != OCFS_SEM_MAGIC) {
- LOG_ERROR_ARGS("semaphore magic value is bad!\n");
- goto bail;
- }
-
- if (res->count && current->pid == res->pid) {
- res->count--;
- if (!res->count) {
- res->pid = 0;
- up (&(res->sem));
- }
- }
-
-bail:
- LOG_EXIT ();
- return;
-} /* ocfs_up_sem */
-
-/*
- * ocfs_del_sem()
- *
- */
-int ocfs_del_sem (ocfs_sem * res)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", res);
-
- res->magic = OCFS_SEM_DELETED;
-
- LOG_EXIT ();
- return 0;
-} /* ocfs_del_sem */
-
-
Copied: trunk/src/alloc.c (from rev 10, trunk/alloc.c)
Copied: trunk/src/bitmap.c (from rev 10, trunk/bitmap.c)
Copied: trunk/src/dcache.c (from rev 7, trunk/dcache.c)
Copied: trunk/src/dir.c (from rev 9, trunk/dir.c)
Copied: trunk/src/divdi3.c (from rev 7, trunk/divdi3.c)
Copied: trunk/src/dlm.c (from rev 10, trunk/dlm.c)
Copied: trunk/src/extmap.c (from rev 7, trunk/extmap.c)
Copied: trunk/src/file.c (from rev 10, trunk/file.c)
Copied: trunk/src/hash.c (from rev 7, trunk/hash.c)
Copied: trunk/src/heartbeat.c (from rev 8, trunk/heartbeat.c)
Copied: trunk/src/inode.c (from rev 10, trunk/inode.c)
Copied: trunk/src/ioctl.c (from rev 7, trunk/ioctl.c)
Copied: trunk/src/journal.c (from rev 10, trunk/journal.c)
Copied: trunk/src/namei.c (from rev 10, trunk/namei.c)
Copied: trunk/src/nm.c (from rev 10, trunk/nm.c)
Copied: trunk/src/oin.c (from rev 7, trunk/oin.c)
Copied: trunk/src/osb.c (from rev 10, trunk/osb.c)
Copied: trunk/src/proc.c (from rev 7, trunk/proc.c)
Copied: trunk/src/sem.c (from rev 7, trunk/sem.c)
Copied: trunk/src/super.c (from rev 10, trunk/super.c)
Copied: trunk/src/symlink.c (from rev 7, trunk/symlink.c)
Copied: trunk/src/sysfile.c (from rev 10, trunk/sysfile.c)
Copied: trunk/src/util.c (from rev 7, trunk/util.c)
Copied: trunk/src/ver.c (from rev 7, trunk/ver.c)
Copied: trunk/src/volcfg.c (from rev 7, trunk/volcfg.c)
Copied: trunk/src/vote.c (from rev 7, trunk/vote.c)
Deleted: trunk/super.c
===================================================================
--- trunk/super.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/super.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1133 +0,0 @@
-#include <ocfs.h>
-#include <linux/utsname.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_SUPER
-
-/*
-** Globals
-*/
-ocfs_global_ctxt OcfsGlobalCtxt;
-spinlock_t osb_id_lock;
-__u32 osb_id; /* Keeps track of next available OSB Id */
-spinlock_t mount_cnt_lock;
-__u32 mount_cnt; /* Number of volumes currently mounted */
-bool mount_cnt_inc; /* true when mount_cnt is inc by 1 during first mount */
-
-
-char *node_name = NULL;
-__u32 node_number = OCFS_INVALID_NODE_NUM;
-__u32 debug_context = 0;
-__u32 debug_level = 0;
-__u32 debug_exclude = 0;
-char *ip_address = NULL;
-__u32 ip_port = 0;
-char *guid = NULL;
-__u32 cs = 0;
-__u32 comm_voting = 0;
-char *ocfs_hostname;
-
-#if 0
-extern ctl_table *ocfs_dbg_table;
-extern ctl_table *ocfs_kern_table;
-extern ctl_table *ocfs_root_table;
-extern struct ctl_table_header *ocfs_table_header;
-#endif
-
-#define KERN_OCFS 989
-static ctl_table ocfs_dbg_table[] = {
- {1, "debug_level", &debug_level, sizeof (__u32), 0644, NULL, &proc_dointvec,
- &sysctl_intvec, NULL, NULL, NULL},
- {2, "debug_context", &debug_context, sizeof (__u32), 0644, NULL, &proc_dointvec,
- &sysctl_intvec, NULL, NULL, NULL},
- {3, "debug_exclude", &debug_exclude, sizeof (__u32), 0644, NULL, &proc_dointvec,
- &sysctl_intvec, NULL, NULL, NULL},
- {4, "comm_voting", &comm_voting, sizeof (__u32), 0644, NULL, &proc_dointvec,
- &sysctl_intvec, NULL, NULL, NULL},
- {0}
-};
-
-static ctl_table ocfs_kern_table[] = {
- {KERN_OCFS, "ocfs", NULL, 0, 0555, ocfs_dbg_table},
- {0}
-};
-static ctl_table ocfs_root_table[] = {
- {CTL_KERN, "kernel", NULL, 0, 0555, ocfs_kern_table},
- {0}
-};
-static struct ctl_table_header *ocfs_table_header = NULL;
-
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR("Oracle Corporation");
-//MODULE_DESCRIPTION("Oracle Clustered FileSystem");
-
-#ifdef LINUX_2_5
-module_param (node_name, charp, 0);
-module_param (node_number, ulong, 0);
-module_param (debug_context, ulong, 0);
-module_param (debug_level, ulong, 0);
-module_param (debug_exclude, ulong, 0);
-module_param (ip_address, charp, 0);
-module_param (ip_port, ulong, 0);
-module_param (guid, charp, 0);
-module_param (cs, ulong, 0);
-module_param (comm_voting, ulong, 0);
-#else /* LINUX_2_5 */
-MODULE_PARM (node_name, "s");
-MODULE_PARM_DESC(node_name, "Name of this machine in the cluster");
-MODULE_PARM (node_number, "l");
-MODULE_PARM_DESC(node_number, "Slot number for this machine within volume");
-MODULE_PARM (debug_context, "l");
-MODULE_PARM_DESC(debug_context, "Debug context");
-MODULE_PARM (debug_level, "l");
-MODULE_PARM_DESC(debug_level, "Debug level");
-MODULE_PARM (debug_exclude, "l");
-MODULE_PARM_DESC(debug_exclude, "Process ID to exclude from tracing");
-MODULE_PARM (ip_address, "s");
-MODULE_PARM_DESC(ip_address, "IP address for the network dlm on this node");
-MODULE_PARM (ip_port, "l");
-MODULE_PARM_DESC(ip_port, "Port number for the network dlm on this node");
-MODULE_PARM (guid, "s");
-MODULE_PARM_DESC(guid, "GUID for this machine");
-MODULE_PARM (cs, "l");
-MODULE_PARM_DESC(cs, "Checksum");
-MODULE_PARM (comm_voting, "l");
-MODULE_PARM_DESC(comm_voting, "Enable/Disable network dlm");
-#endif /* Linux 2.4 stuff */
-
-static int ocfs_parse_options (char *options, __u32 * uid, __u32 * gid, bool * reclaim_id);
-static struct super_block *ocfs_read_super (struct super_block *sb, void *data, int silent);
-static int __init ocfs_driver_entry (void);
-static void __exit ocfs_driver_exit (void);
-static void ocfs_put_super (struct super_block *sb);
-static int ocfs_statfs (struct super_block *sb, struct statfs *buf);
-static void lockres_hash_free_func (const void *p);
-static int ocfs_mount_volume (struct super_block *sb, bool reclaim_id, struct inode *root);
-static int ocfs_read_params(void);
-static int ocfs_initialize_mem_lists (void);
-static void ocfs_free_mem_lists (void);
-
-static struct super_operations ocfs_sops = {
- .statfs = ocfs_statfs,
- .put_inode = ocfs_put_inode,
- .clear_inode = ocfs_clear_inode,
- //put_inode = force_delete,
- //delete_inode = ocfs_delete_inode,
-#ifndef LINUX_2_5
- .read_inode = ocfs_read_inode,
- .read_inode2 = ocfs_read_inode2,
-#endif
- .put_super = ocfs_put_super,
-
-};
-
-
-#ifdef LINUX_2_5
-
-static struct file_system_type ocfs_fs_type = {
- .owner = THIS_MODULE,
- .name = "ocfs",
- .get_sb = ocfs_get_sb, /* is this called when we mount
- * the fs? */
- .kill_sb = kill_block_super, /* set to the generic one
- * right now, but do we
- * need to change that? */
- .fs_flags = FS_REQUIRES_DEV,
- .next = NULL
-};
-
-
-static int ocfs_fill_super (struct super_block *sb, void *data, int silent)
-{
- struct dentry *root_dentry;
- int status = -1;
- struct inode *root_inode = NULL;
- __u32 uid = current->fsuid;
- __u32 gid = current->fsgid;
- bool reclaim_id;
- ocfs_super *osb;
-
- LOG_ENTRY ();
-
- if (ocfs_parse_options (data, &uid, &gid, &reclaim_id) != 0) {
- LOG_ERROR_STR ("bad mount option");
- status=-EINVAL;
- goto read_super_error;
- }
-
- sb->s_magic = OCFS_MAGIC;
- sb->s_op = &ocfs_sops;
- sb->s_flags |= MS_NOATIME;
-
- /* this is needed to support O_LARGE_FILE */
- sb->s_maxbytes = OCFS_LINUX_MAX_FILE_SIZE;
-
- if (!sb_set_blocksize(sb, 512)) {
- LOG_ERROR_STR("Could not set block size");
- status=-EIO;
- goto read_super_error;
- }
-
- status = ocfs_mount_volume (sb, reclaim_id, NULL);
- if (status < 0) {
- goto read_super_error;
- }
- osb = ((ocfs_super *)(sb->s_fs_info));
- if (!osb) {
- status=-EINVAL;
- goto read_super_error;
- }
-
- root_inode = ocfs_iget(sb, NULL);
- if (!root_inode) {
- status=-EIO;
- LOG_ERROR_STATUS (status);
- goto read_super_error;
- }
-
- root_dentry = d_alloc_root (root_inode);
- if (!root_dentry) {
- status=-ENOMEM;
- LOG_ERROR_STATUS (status);
- goto read_super_error;
- }
-
- sb->s_root = root_dentry;
- printk ("ocfs: Mounting device (%u,%u) on %s (node %d)\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev),
- osb->node_cfg_info[osb->node_num]->node_name, osb->node_num);
-
- status = 0;
- LOG_EXIT_STATUS (status);
- return status;
-
-read_super_error:
- if (root_inode != NULL) {
- iput (root_inode);
- root_inode = NULL;
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_fill_super */
-
-static struct super_block *ocfs_get_sb(struct file_system_type *fs_type, int flags, char *dev_name, void *data)
-{
- return get_sb_bdev(fs_type, flags, dev_name, data, ocfs_fill_super);
-}
-
-#else /* We're a 2.4 kernel */
-
-
-/*
- * ocfs_read_super()
- *
- */
-static struct super_block *ocfs_read_super (struct super_block *sb, void *data, int silent)
-{
- struct dentry *root;
- int status;
- struct inode *inode = NULL;
- __u32 uid = current->fsuid;
- __u32 gid = current->fsgid;
- bool reclaim_id;
- ocfs_super *osb = NULL;
-
- LOG_ENTRY ();
-
- MOD_INC_USE_COUNT;
-
- if (ocfs_parse_options (data, &uid, &gid, &reclaim_id) != 0) {
- LOG_ERROR_STR ("ocfs_read_super: bad mount option");
- goto read_super_error;
- }
-
- /* TODO: fix this */
- sb->s_blocksize = 512;
- sb->s_blocksize_bits = 9;
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,18)
- status = set_blocksize (sb->s_dev, 512);
- if (status < 0) {
- LOG_ERROR_STR ("ocfs_read_super: set_blocksize failed!");
- goto read_super_error;
- }
-#else
- set_blocksize (sb->s_dev, 512);
-#endif
-
- sb->s_magic = OCFS_MAGIC;
- sb->s_op = &ocfs_sops;
- sb->s_flags |= MS_NOATIME;
-
- /* this is needed to support O_LARGE_FILE */
- sb->s_maxbytes = OCFS_LINUX_MAX_FILE_SIZE;
-
- status = ocfs_mount_volume (sb, reclaim_id, NULL);
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
- if (status < 0 || !osb)
- goto read_super_error;
-
- inode = iget4 (sb, OCFS_ROOT_INODE_NUMBER, 0, NULL);
- if (!inode) {
- LOG_ERROR_STATUS (status);
- goto read_super_error;
- }
-
- root = d_alloc_root (inode);
- if (!root) {
- LOG_ERROR_STATUS (status);
- iput (inode);
- goto read_super_error;
- }
-
- sb->s_root = root;
-
- printk ("ocfs: Mounting device (%u,%u) on %s (node %d)\n",
- MAJOR(sb->s_dev), MINOR(sb->s_dev),
- osb->node_cfg_info[osb->node_num]->node_name, osb->node_num);
-
- LOG_EXIT_PTR (sb);
- return sb;
-
-read_super_error:
- if (osb)
- ocfs_dismount_volume (sb);
-
- MOD_DEC_USE_COUNT;
- if (inode != NULL) {
- iput (inode);
- inode = NULL;
- }
-
- LOG_EXIT_PTR (0);
- return NULL;
-} /* ocfs_read_super */
-
-
-static DECLARE_FSTYPE (ocfs_fs_type, "ocfs", ocfs_read_super, FS_REQUIRES_DEV);
-#endif /* #if LINUX_2_5 ... #else */
-
-
-
-/*
- * ocfs_parse_options()
- *
- * e.g., gid=9999,uid=9999,[no]cache,reclaimid
- */
-static int ocfs_parse_options (char *options, __u32 * uid, __u32 * gid, bool * reclaim_id)
-{
- char *c;
- char *value;
- int ret = 1;
-
- LOG_ENTRY ();
-
- *reclaim_id = false;
- if (!options) {
- ret = 0;
- goto bail;
- }
-
- LOG_TRACE_ARGS("strlen(options) = %d, options = \"%s\"\n", strlen(options), options);
-
-#ifdef LINUX_2_5
- while ( (c = strsep(&options, ",")) != NULL)
-#else
- for (c = strtok (options, ","); c != NULL; c = strtok (NULL, ","))
-#endif
-// while ( (c = strsep(&options, ",")) != NULL)
- {
- if ((value = strchr (c, '=')) != NULL)
- *value++ = 0;
- if (!strcmp (c, "gid")) {
- if (!value || !*value) {
- LOG_ERROR_STR
- ("gid option requires an argument");
- goto bail;
- }
- *gid = simple_strtoul (value, &value, 0);
- if (*value) {
- LOG_ERROR_ARGS ("Invalid gid option: %s", value);
- goto bail;
- }
- } else if (!strcmp (c, "uid")) {
- if (!value || !*value) {
- LOG_ERROR_STR
- ("ERROR: uid option requires an argument");
- goto bail;
- }
- *uid = simple_strtoul (value, &value, 0);
- if (*value) {
- LOG_ERROR_ARGS ("Invalid uid option: %s", value);
- goto bail;
- }
- } else if (!strcmp (c, "reclaimid")) {
- *reclaim_id = true;
- } else {
- LOG_ERROR_ARGS ("Invalid mount option: %s", c);
- goto bail;
- }
- }
- ret = 0;
-
-bail:
- LOG_EXIT_LONG (ret);
- return ret;
-} /* ocfs_parse_options */
-
-/*
- * ocfs_driver_entry()
- *
- * Driver entry point. Called on insmod.
- */
-static int __init ocfs_driver_entry (void)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- ocfs_version_print();
-
- ocfs_hostname = kmalloc(strlen(system_utsname.nodename) + 1, GFP_KERNEL);
- if (ocfs_hostname==NULL)
- return -EINVAL;
- strcpy(ocfs_hostname, system_utsname.nodename);
- printk("ocfs: hostname is %s\n", ocfs_hostname);
-
- ocfs_table_header = register_sysctl_table(ocfs_root_table, 0);
- if (!ocfs_table_header) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto leave;
- }
-
- memset (&OcfsGlobalCtxt, 0, sizeof (ocfs_global_ctxt));
- memset (&OcfsIpcCtxt, 0, sizeof (ocfs_ipc_ctxt));
-
-#ifdef OCFS_LINUX_MEM_DEBUG
- INIT_LIST_HEAD (&(OcfsGlobalCtxt.item_list));
-#endif
- INIT_LIST_HEAD (&(OcfsGlobalCtxt.osb_next));
- INIT_LIST_HEAD (&(OcfsGlobalCtxt.osb_next));
-
- /* Read remaining insmod params */
- if ((status = ocfs_read_params ()) < 0)
- goto leave;
-
- /* Initialize some required fields */
- OcfsGlobalCtxt.obj_id.type = OCFS_TYPE_GLOBAL_DATA;
- OcfsGlobalCtxt.obj_id.size = sizeof (ocfs_global_ctxt);
-
- /* Initialize the global data resource */
- ocfs_init_sem (&(OcfsGlobalCtxt.res));
- OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_GLBL_CTXT_RESOURCE_INITIALIZED);
-
- /* Initialize the memory slabs for oin, ofile, and file entry */
- status = ocfs_initialize_mem_lists ();
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* Initialize the DLM */
- status = ocfs_init_dlm ();
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- OcfsGlobalCtxt.hbm = DISK_HBEAT_COMM_ON;
-
- spin_lock_init (&osb_id_lock);
- spin_lock (&osb_id_lock);
- osb_id = 0;
- spin_unlock (&osb_id_lock);
-
- spin_lock_init (&mount_cnt_lock);
- spin_lock (&mount_cnt_lock);
- mount_cnt = 0;
- mount_cnt_inc = false;
- spin_unlock (&mount_cnt_lock);
-
- spin_lock_init (&OcfsGlobalCtxt.comm_seq_lock);
- spin_lock (&OcfsGlobalCtxt.comm_seq_lock);
- OcfsGlobalCtxt.comm_seq_num = 0;
- spin_unlock (&OcfsGlobalCtxt.comm_seq_lock);
-
- /* Initialize the proc interface */
- ocfs_proc_init ();
-
-leave:
- if (status < 0) {
- /* Free up lookaside lists */
- if (OcfsGlobalCtxt.flags & OCFS_FLAG_MEM_LISTS_INITIALIZED)
- ocfs_free_mem_lists ();
-
- /* Delete the global context resource */
- if (OcfsGlobalCtxt.flags & OCFS_FLAG_GLBL_CTXT_RESOURCE_INITIALIZED)
- OCFS_CLEAR_FLAG (OcfsGlobalCtxt.flags,
- OCFS_FLAG_GLBL_CTXT_RESOURCE_INITIALIZED);
-
- if (ocfs_table_header)
- unregister_sysctl_table(ocfs_table_header);
- }
-
- LOG_EXIT_STATUS (status);
-
- if (status >= 0) {
- return register_filesystem (&ocfs_fs_type);
- } else
- return -1;
-} /* ocfs_driver_entry */
-
-/*
- * ocfs_read_params()
- *
- * Read insmod params
- */
-static int ocfs_read_params(void)
-{
- int status = 0;
- __u32 check_sum = 0;
- int i;
-
- /* Read remaining insmod params */
- if (node_number != OCFS_INVALID_NODE_NUM) {
- if (node_number >= 0 && node_number < OCFS_MAXIMUM_NODES) {
- OcfsGlobalCtxt.pref_node_num = node_number;
- LOG_TRACE_ARGS("Preferred node number: %d\n",
- node_number);
- }
- else {
- status = -EINVAL;
- LOG_ERROR_STR("'node_number' must be between 0 and 31");
- }
- }
-
- if (ip_port == 0)
- OcfsGlobalCtxt.comm_info.ip_port = OCFS_IPC_DEFAULT_PORT;
- else
- OcfsGlobalCtxt.comm_info.ip_port = ip_port;
- LOG_TRACE_ARGS("IP port: %d\n", OcfsGlobalCtxt.comm_info.ip_port);
-
- if (node_name && strlen (node_name) < MAX_NODE_NAME_LENGTH) {
- OcfsGlobalCtxt.node_name = node_name;
- LOG_TRACE_ARGS ("Node name: %s\n", OcfsGlobalCtxt.node_name);
- } else {
- status = -EINVAL;
- LOG_ERROR_STR ("'node_name' not set or too long");
- }
-
- if (ip_address && strlen (ip_address) < MAX_IP_ADDR_LEN) {
- OcfsGlobalCtxt.comm_info.ip_addr = ip_address;
- LOG_TRACE_ARGS ("IP address: %s\n", ip_address);
- } else {
- status = -EINVAL;
- LOG_ERROR_STR ("'ip_address' not set or too long");
- }
-
- if (guid && strlen (guid) == GUID_LEN) {
- memcpy (&OcfsGlobalCtxt.guid.guid, guid, GUID_LEN);
- LOG_TRACE_ARGS ("Node guid: %s\n", guid);
- } else {
- status = -EINVAL;
- LOG_ERROR_STR ("'guid' not set correctly");
- }
-
- if (status == 0) {
- for (i = 0; i < GUID_LEN; ++i)
- check_sum += (__u32) guid[i];
- if (cs != check_sum) {
- status = -EINVAL;
- LOG_ERROR_STR ("load module using load_ocfs");
- }
- }
-
- /* hardcoding... not used yet */
- OcfsGlobalCtxt.comm_info.type = OCFS_UDP;
- OcfsGlobalCtxt.comm_info.ip_mask = NULL;
-
- return status;
-} /* ocfs_read_params */
-
-
-#ifdef OCFS_LINUX_MEM_DEBUG
-/*
- * ocfs_memcheck()
- *
- */
-static void ocfs_memcheck (void)
-{
- struct list_head *iter;
- struct list_head *temp_iter;
- alloc_item *item;
- char *memtype;
- char sizeinfo[20];
-
- list_for_each_safe (iter, temp_iter, &OcfsGlobalCtxt.item_list) {
- item = list_entry (iter, alloc_item, list);
- switch (item->type)
- {
- case SLAB_ITEM:
- /* TODO: use the actual slab name */
- memtype = "SLAB";
- snprintf(sizeinfo, 20, "slab=%p", item->u.slab);
- break;
- case KMALLOC_ITEM:
- memtype = "KMALLOC";
- snprintf(sizeinfo, 20, "size=%d", item->u.length);
- break;
- case VMALLOC_ITEM:
- memtype = "VMALLOC";
- snprintf(sizeinfo, 20, "size=%d", item->u.length);
- break;
- default:
- memtype = "UNKNOWN";
- snprintf(sizeinfo, 20, "size=%d", item->u.length);
- break;
- }
- LOG_ERROR_ARGS ("unfreed %s mem %x: %s tag='%s'", memtype,
- item->address, sizeinfo, item->tag);
- }
-} /* ocfs_memcheck */
-
-#endif /* OCFS_LINUX_MEM_DEBUG */
-
-/*
- * ocfs_driver_exit()
- *
- * Called on rmmod
- */
-static void __exit ocfs_driver_exit (void)
-{
-
- LOG_ENTRY ();
-
- if (ocfs_table_header)
- unregister_sysctl_table(ocfs_table_header);
-
- /* Signal DLM thread to exit */
- ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
- OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_SHUTDOWN_VOL_THREAD);
-
- if (OcfsGlobalCtxt.flags & OCFS_FLAG_MEM_LISTS_INITIALIZED)
- ocfs_free_mem_lists ();
-
- ocfs_up_sem (&(OcfsGlobalCtxt.res));
-
- /* Deinit the proc interface */
- ocfs_proc_deinit ();
-
- unregister_filesystem (&ocfs_fs_type);
-
-#ifdef OCFS_LINUX_MEM_DEBUG
- ocfs_memcheck ();
-#endif
-
- printk("Unloaded OCFS Driver module\n");
- LOG_EXIT ();
- return;
-} /* ocfs_driver_exit */
-
-
-
-/*
- * ocfs_put_super()
- *
- */
-static void ocfs_put_super (struct super_block *sb)
-{
- LOG_ENTRY_ARGS ("(0x%08x)\n", sb);
-
- ocfs_sync_blockdev(sb);
- LOG_TRACE_STR ("put super... do nothing! DONE!!!!");
- MOD_DEC_USE_COUNT;
-
- LOG_EXIT ();
- return;
-} /* ocfs_put_super */
-
-
-
-/*
- * ocfs_statfs()
- *
- */
-static int ocfs_statfs (struct super_block *sb, struct statfs *buf)
-{
- ocfs_super *osb = NULL;
- __u32 numbits, freebits = 0;
- // ocfs_lock_res *pLockResource;
- int status = 0;
- ocfs_bitmap_lock *bm_lock = NULL;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY_ARGS ("(0x%08x, 0x%08x)\n", sb, buf);
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
- numbits = osb->cluster_bitmap.validbits;
-
- status = ocfs_read_bh (osb, OCFS_BITMAP_LOCK_OFFSET, &bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STR("failed to read bitmap data");
- return -EIO;
- }
- bm_lock = (ocfs_bitmap_lock *)OCFS_BH_GET_DATA(bh);
-
- if (numbits >= bm_lock->used_bits)
- freebits = numbits - bm_lock->used_bits;
-
- /* take out the space reserved for system files */
- freebits -= (8 * ONE_MEGA_BYTE / osb->vol_layout.cluster_size);
-
- buf->f_type = OCFS_MAGIC;
- buf->f_bsize = sb->s_blocksize;
- buf->f_namelen = OCFS_MAX_FILENAME_LENGTH;
- buf->f_blocks =
- (unsigned long) ((unsigned long) (numbits) *
- (unsigned long) (osb->vol_layout.cluster_size >> 9) -
- (8 * ONE_MEGA_BYTE / osb->vol_layout.cluster_size));
- buf->f_bfree =
- (unsigned long) (freebits * (osb->vol_layout.cluster_size >> 9));
- buf->f_bavail = buf->f_bfree;
- buf->f_files = (unsigned long) (numbits);
- buf->f_ffree = (unsigned long) (numbits) - freebits;
-
- OCFS_BH_PUT_DATA(bh);
- lock_buffer(bh);
- mark_buffer_uptodate(bh, false);
- unlock_buffer(bh);
- brelse(bh);
-
- LOG_EXIT_LONG (0);
- return 0;
-} /* ocfs_statfs */
-
-#ifdef CDTOR_FOR_SLAB
-static void lockres_ctor(void *p, kmem_cache_t *slab, unsigned long flags)
-{
- ocfs_lock_res *lockres;
- lockres = p;
- lockres->signature = 0x55AA;
-}
-
-static void lockres_dtor(void *p, kmem_cache_t *slab, unsigned long flags)
-{
- ocfs_lock_res *lockres;
- lockres = p;
- if (lockres->signature == 0x55AA)
- ocfs_free_lockres((ocfs_lock_res *)p);
-}
-#endif
-
-/*
- * ocfs_initialize_mem_lists()
- *
- */
-static int ocfs_initialize_mem_lists (void)
-{
- OcfsGlobalCtxt.oin_cache = kmem_cache_create ("oin_cache",
- sizeof (ocfs_inode) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
- OcfsGlobalCtxt.ofile_cache = kmem_cache_create ("ofile_cache",
- sizeof (ocfs_file) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
- OcfsGlobalCtxt.lockres_cache = kmem_cache_create ("lockres_cache",
- sizeof (ocfs_lock_res) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
- OcfsGlobalCtxt.fe_cache = kmem_cache_create ("fileentry_cache",
- OCFS_SECTOR_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN, NULL, NULL);
-
- OcfsGlobalCtxt.extent_cache = kmem_cache_create ("extent_cache",
- sizeof(ocfs_extent) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
- OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
-
- return 0;
-} /* ocfs_initialize_mem_lists */
-
-/*
- * ocfs_free_mem_lists()
- *
- */
-static void ocfs_free_mem_lists (void)
-{
- kmem_cache_destroy (OcfsGlobalCtxt.oin_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.ofile_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.fe_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.lockres_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.extent_cache);
- OCFS_CLEAR_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
-} /* ocfs_free_mem_lists */
-
-
-/*
- * ocfs_mount_volume()
- *
- */
-static int ocfs_mount_volume (struct super_block *sb, bool reclaim_id, struct inode *root)
-{
- int status = 0;
- ocfs_super *osb = NULL;
- ocfs_vol_disk_hdr *vol_header = NULL;
- ocfs_vol_label *vol_label = NULL;
- int child_pid, i;
- struct buffer_head *bhs[] = { NULL, NULL };
-
- LOG_ENTRY ();
-
- /* get first two blocks */
- for (i=0; i<2; i++) {
- bhs[i] = getblk (OCFS_GET_BLOCKDEV(sb), i, 512);
- if (bhs[i] == NULL) {
- LOG_ERROR_STATUS(status = -EIO);
- goto leave;
- }
-
- lock_buffer(bhs[i]);
- if (!buffer_dirty(bhs[i]))
-#ifdef LINUX_2_5
- clear_buffer_uptodate(bhs[i]);
-#else
- mark_buffer_uptodate(bhs[i], false);
-#endif
- unlock_buffer(bhs[i]);
- }
-
- ll_rw_block(READ, 2, bhs);
- for (i=0; i<2; i++)
- wait_on_buffer(bhs[i]);
-
- vol_header = (ocfs_vol_disk_hdr *) OCFS_BH_GET_DATA(bhs[0]);
- vol_label = (ocfs_vol_label *) OCFS_BH_GET_DATA(bhs[1]);
-
- LOG_TRACE_STR ("ocfs_verify_volume...");
- status = ocfs_verify_volume (vol_header);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* Check if the cluster name on the disk matches the one in the registry */
-#ifdef ENABLE_CLUSTER_NAME_CHECK /* TODO */
- if (OcfsGlobalCtxt.ClusterName == NULL ||
- vol_label->ClusterNameLength < 1 ||
- vol_label->ClusterName[0] == '\0' ||
- memcmp (OcfsGlobalCtxt.ClusterName, vol_label->ClusterName,
- vol_label->ClusterNameLength) != 0) {
- LOG_ERROR_ARGS
- ("expected cluster name: '%s' volume cluster name: '%s'",
- OcfsGlobalCtxt.ClusterName, vol_label->ClusterName);
- status = -EINVAL;
- goto leave;
- }
-#endif
-
- if ((osb = ocfs_malloc (sizeof (ocfs_super))) == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(osb, 0, sizeof(ocfs_super));
-
- OCFS_GENERIC_SB_P(sb) = (void *) osb;
-
- osb->sb = sb;
-
- osb->reclaim_id = reclaim_id;
-
- status = ocfs_initialize_osb (osb, vol_header, vol_label, 512);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- OCFS_BH_PUT_DATA(bhs[0]);
- vol_header = NULL;
- OCFS_BH_PUT_DATA(bhs[1]);
- vol_label = NULL;
-
- if (osb->vol_layout.root_start_off == 0 && osb->node_num != 0) {
- LOG_ERROR_ARGS("The volume must be mounted by node 0 before it can "
- "be used and you are node %u", osb->node_num);
- status = -EINVAL;
- goto leave;
- }
-
- osb->sect_size = 512;
-
- spin_lock (&osb_id_lock);
- osb->osb_id = osb_id;
- if (osb_id < ULONG_MAX)
- osb_id++;
- else {
- spin_unlock (&osb_id_lock);
- LOG_ERROR_STR ("Too many volumes mounted");
- status = -ENOMEM;
- goto leave;
- }
- spin_unlock (&osb_id_lock);
-
- /* Launch the NM thread for the mounted volume */
- ocfs_down_sem (&(osb->osb_res), true);
- osb->dlm_task = NULL;
- child_pid = kernel_thread (ocfs_volume_thread, osb,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (child_pid < 0) {
- LOG_ERROR_ARGS ("unable to launch ocfsnm thread, error=%d",
- child_pid);
- ocfs_up_sem (&(osb->osb_res));
- status = -EFAIL;
- goto leave;
- } else {
- init_completion (&osb->complete);
- }
- ocfs_up_sem (&(osb->osb_res));
-
- /* Add proc entry for this volume */
- ocfs_proc_add_volume (osb);
-
- /* GlobalMountCount */
- spin_lock (&mount_cnt_lock);
- mount_cnt++;
- if (mount_cnt == 1) {
- OcfsIpcCtxt.dlm_msg_size = OCFS_DLM_MAX_MSG_SIZE;
- OcfsIpcCtxt.version = OCFS_IPC_DLM_VERSION;
- /* start the listener thread */
- status = ocfs_init_udp_sock (&OcfsIpcCtxt.send_sock, &OcfsIpcCtxt.recv_sock);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- OcfsIpcCtxt.task = NULL;
- child_pid = kernel_thread (ocfs_recv_thread, NULL,
- CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- if (child_pid >= 0) {
- init_completion (&(OcfsIpcCtxt.complete));
- } else {
- status = -EFAIL;
- LOG_ERROR_ARGS ("unable to launch ocfslsnr thread, error=%d", child_pid);
- goto leave;
- }
-
- OcfsIpcCtxt.init = true;
- if (mount_cnt_inc == false) {
- MOD_INC_USE_COUNT;
- mount_cnt_inc = true;
- }
- }
- spin_unlock (&mount_cnt_lock);
-
- /* wait for nm thread to be init */
- ocfs_wait (osb->nm_init_event, (atomic_read (&osb->nm_init) >= OCFS_HEARTBEAT_INIT ), 0);
-
- /* Join or Form the cluster... */
- LOG_TRACE_STR ("ocfs_vol_member_reconfig...");
- ocfs_down_sem (&(osb->osb_res), true);
- osb->hbm = DISK_HBEAT_COMM_ON;
-
- down (&(osb->publish_lock));
- ocfs_nm_heart_beat (osb, HEARTBEAT_METHOD_DISK, true);
- up (&(osb->publish_lock));
-
- osb->publ_map |= (1 << osb->node_num);
- osb->vol_state = VOLUME_INIT;
- status = ocfs_create_root_oin (osb, NULL);
- if (status >= 0)
- osb->vol_state = VOLUME_ENABLED;
- ocfs_up_sem (&(osb->osb_res));
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- /* Read the publish sector for this node and cleanup dirent being */
- /* modified when we crashed. */
- LOG_TRACE_STR ("ocfs_check_volume...");
- ocfs_down_sem (&(osb->osb_res), true);
- status = ocfs_check_volume (osb);
- ocfs_up_sem (&(osb->osb_res));
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- osb->vol_state = VOLUME_MOUNTED;
-
-leave:
- if (bhs[0] != NULL) {
- if (vol_header)
- OCFS_BH_PUT_DATA(bhs[0]);
- brelse(bhs[0]);
- }
- if (bhs[1] != NULL) {
- if (vol_label)
- OCFS_BH_PUT_DATA(bhs[1]);
- brelse(bhs[1]);
- }
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_mount_volume */
-
-
-/*
- * lockres_hash_free_func()
- *
- */
-static void lockres_hash_free_func (const void *p)
-{
- ocfs_free_lockres((ocfs_lock_res *)p);
-} /* lockres_hash_free_func */
-
-
-/*
- * ocfs_dismount_volume()
- *
- */
-int ocfs_dismount_volume (struct super_block *sb)
-{
- int status = 0;
- bool AcquiredOSB = false;
- ocfs_super *osb = NULL;
- ocfs_inode *rootoin;
- __u32 nodemap;
- __u32 tempmap;
- int i;
-
- LOG_ENTRY_ARGS ("(0x%08x)\n", sb);
-
- if (sb == NULL) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto leave;
- }
-
- osb = (ocfs_super *) OCFS_GENERIC_SB_P(sb);
-
- if ( osb == NULL) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto leave;
- }
- rootoin = osb->oin_root_dir;
-
- ocfs_down_sem (&(osb->osb_res), true);
- AcquiredOSB = true;
-
-#ifdef UMOUNT_CHECK
- if (osb->file_open_cnt > 0) {
- LOG_ERROR_ARGS ("Dismount failed... file_open_cnt(%d) > 0",
- osb->file_open_cnt);
- LOG_ERROR_STR
- ("WARNING!!! Need to uncomment this when file opens are correct!\n");
-/* commenting this out for now until we deal with open files properly */
- status = -EBUSY;
- goto leave;
- }
-#endif
-
- /* Shutdown the journal and sync up and clear the local alloc. */
- ocfs_journal_shutdown(osb);
- ocfs_shutdown_local_alloc(osb, NULL, true);
-
- /* unset the mounted flag -- we're done with the journal and
- * the local alloc bitmap */
- status = ocfs_journal_set_unmounted(osb, osb->node_num);
- if (status < 0)
- LOG_ERROR_STR("Could not set mounted flag!");
-
- ocfs_sync_blockdev(sb);
- ocfs_release_oin (rootoin, true);
-
- /* Destroy the Hash table */
- ocfs_hash_destroy (&(osb->root_sect_node), lockres_hash_free_func);
-
- /* Remove the proc element for this volume */
- ocfs_proc_remove_volume (osb);
-
- /* Dismount */
- OCFS_SET_FLAG (osb->osb_flags, OCFS_OSB_FLAGS_BEING_DISMOUNTED);
- osb->vol_state = VOLUME_BEING_DISMOUNTED;
-
- /* Wait for this volume's NM thread to exit */
- if (osb->dlm_task) {
- LOG_TRACE_STR ("Waiting for ocfsnm to exit....");
- send_sig (SIGINT, osb->dlm_task, 0);
- wait_for_completion (&(osb->complete));
- osb->dlm_task = NULL;
- }
-
- /* create map of all active nodes except self */
- nodemap = (__u32)osb->publ_map;
- tempmap = (1 << osb->node_num);
- nodemap &= (~tempmap);
-
- /* send dismount msg to all */
- status = ocfs_send_dismount_msg (osb, (__u64)nodemap);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- /* decrement mount count */
- spin_lock (&mount_cnt_lock);
- mount_cnt--;
- if (mount_cnt == 0) {
- /* Shutdown ocfslsnr */
- if (OcfsIpcCtxt.task) {
- LOG_TRACE_STR ("Waiting for ocfslsnr to exit....");
- send_sig (SIGINT, OcfsIpcCtxt.task, 0);
- wait_for_completion (&(OcfsIpcCtxt.complete));
- OcfsIpcCtxt.task = NULL;
- }
- }
- spin_unlock (&mount_cnt_lock);
-
- ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
- ocfs_uninitialize_bitmap(&osb->cluster_bitmap);
-// list_del(&osb->osb_next); /* this has been moved into ocfs_delete_osb */
- ocfs_up_sem (&(OcfsGlobalCtxt.res));
-
- osb->vol_state = VOLUME_DISMOUNTED;
- if (AcquiredOSB) {
- ocfs_up_sem (&(osb->osb_res));
- AcquiredOSB = false;
- }
-
- printk ("ocfs: Unmounting device (%u,%u) on %s (node %d)\n",
- MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev),
- osb->node_cfg_info[osb->node_num]->node_name, osb->node_num);
-
- /* Free all nodecfgs */
- for (i = 0; i < OCFS_MAXIMUM_NODES; ++i) {
- ocfs_node_config_info *p;
-
- p = osb->node_cfg_info[i];
- ocfs_safefree (p);
- }
-
- ocfs_delete_osb (osb);
- ocfs_safefree (osb);
- sb->s_dev = 0;
-
- spin_lock (&mount_cnt_lock);
- if (!mount_cnt && !atomic_read(&OcfsGlobalCtxt.cnt_lockres) && mount_cnt_inc) {
- MOD_DEC_USE_COUNT;
- mount_cnt_inc = false;
- } else {
- LOG_TRACE_ARGS("Could not decrement use count, there are %u" \
- " lockres' that haven't been freed.\n", \
- atomic_read(&OcfsGlobalCtxt.cnt_lockres));
- }
- spin_unlock (&mount_cnt_lock);
-
-leave:
- if (AcquiredOSB) {
- ocfs_up_sem (&(osb->osb_res));
- AcquiredOSB = false;
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_dismount_volume */
-
-
-module_init (ocfs_driver_entry);
-module_exit (ocfs_driver_exit);
Deleted: trunk/symlink.c
===================================================================
--- trunk/symlink.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/symlink.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,260 +0,0 @@
-/*
- * linux/cluster/ssi/cfs/symlink.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE
- * or NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Questions/Comments/Bugfixes to ssic-linux-devel at lists.sourceforge.net
- *
- * Copyright (C) 1992 Rick Sladkey
- *
- * Optimization changes Copyright (C) 1994 Florian La Roche
- *
- * Jun 7 1999, cache symlink lookups in the page cache. -DaveM
- *
- * Portions Copyright (C) 2001 Compaq Computer Corporation
- *
- * ocfs symlink handling code
- * for CDSL support
- */
-
-#include <ocfs.h>
-#include <linux/utsname.h>
-
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_EXTENT
-
-struct ocfs_symlink_ops {
- const char *name;
- const unsigned int len;
- unsigned int (*subst_fn) (char *str, void *data);
-};
-
-static unsigned int ocfs_link_size(struct ocfs_symlink_ops *ops, char *str, struct inode *inode);
-static void ocfs_link_expand(struct ocfs_symlink_ops *ops, char *out, char *in, struct inode *inode);
-
-int ocfs_follow_link(struct dentry *dentry, struct nameidata *nd);
-
-
-/* Context Dependent Symbolic Link (CDSL) code */
-
-/**
- *** sym_hostname - Substitute system host name
- *** @str: String for result
- *** @len: Length of result buffer
- ***
- *** Returns: Length of hostname
- ***/
-static unsigned int
-sym_hostname(char *str, void *data)
-{
- unsigned int l = strlen(system_utsname.nodename);
-
- if (str)
- memcpy(str, system_utsname.nodename, l);
-
- return l;
-}
-
-/**
- *** sym_machine - Substitute machine type
- *** @str: String for result
- *** @len: Length of result buffer
- ***
- *** Returns: Length of machine type
- ***/
-
-static unsigned int
-sym_machine(char *str, void *data)
-{
- unsigned int l = strlen(system_utsname.machine);
-
- if (str)
- memcpy(str, system_utsname.machine, l);
-
- return l;
-}
-
-/**
- *** sym_os - Substitute OS name
- *** @str: String for result
- *** @len: Length of result buffer
- ***
- *** Returns: Length of OS name
- ***/
-
-static unsigned int
-sym_os(char *str, void *data)
-{
- unsigned int l = strlen(system_utsname.sysname);
-
- if (str)
- memcpy(str, system_utsname.sysname, l);
-
- return l;
-}
-
-/**
- *** sym_nodenum - Substitute node number
- *** @str: String for result
- *** @len: Length of result buffer
- ***
- *** Returns: Length of nodeNum
- ***/
-
-static unsigned int
-sym_nodenum(char *str, void *data)
-{
- unsigned l;
- char buf[10];
- struct inode *inode = (struct inode *)data;
- ocfs_super *osb = (ocfs_super *) OCFS_GENERIC_SB_P(inode->i_sb);
-
- sprintf(buf,"%ld",osb->node_num);
- l = strlen(buf);
-
- if (str) {
- memcpy(str, buf, l);
- str[l] ='\0';
- }
-
- return l;
-}
-
-static struct ocfs_symlink_ops symlink_ops[] = {
- {"hostname}", 9, sym_hostname},
- {"mach}", 5, sym_machine},
- {"os}", 3, sym_os},
- {"nodenum}", 8, sym_nodenum},
- {NULL, 0, NULL}
-};
-
-/* CDSL code - end
- **/
-
-static char *my_page_getlink(struct dentry * dentry, struct page **ppage);
-
-/* get the link contents into pagecache */
-static char *my_page_getlink(struct dentry * dentry, struct page **ppage)
-{
- struct page * page;
- struct address_space *mapping = dentry->d_inode->i_mapping;
- page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
- NULL);
- if (IS_ERR(page))
- goto sync_fail;
- wait_on_page(page);
- if (!Page_Uptodate(page))
- goto async_fail;
- *ppage = page;
- return kmap(page);
-
-async_fail:
- page_cache_release(page);
- return ERR_PTR(-EIO);
-
-sync_fail:
- return (char*)page;
-}
-
-
-int ocfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
- struct inode *inode = dentry->d_inode;
- struct page *page = NULL;
- char *orig_link,*new_link;
- unsigned int len = 0,res=0;
-
- orig_link = my_page_getlink(dentry, &page);
- len = ocfs_link_size(symlink_ops,orig_link,inode);
- new_link = (char *)kmalloc(len,GFP_KERNEL);
- if (new_link == NULL) {
- res = ENOMEM;
- goto out;
- }
- ocfs_link_expand(symlink_ops,new_link,orig_link,inode);
- res = vfs_follow_link(nd,new_link);
- out:
- if (page) {
- kunmap(page);
- page_cache_release(page);
- }
- return res;
-}
-
-
-
-/**
- *** ocfs_link_expand - Expand a context sensitive symlink
- *** @ops: The symlink substitution operations table
- *** @out: Buffer to place result in
- *** @in: Buffer to get symlink from
- ***
- *** Returns: 0 or error code
- ***/
-
-static void ocfs_link_expand(struct ocfs_symlink_ops *ops, char *out, char *in, struct inode *inode)
-{
- unsigned int i;
-
- while (*in) {
- *out++ = *in;
- if (*in++ != '{')
- continue;
-
- for (i = 0; ops[i].name; i++) {
- if (memcmp(in, ops[i].name, ops[i].len) == 0) {
- out--;
- out += ops[i].subst_fn(out, inode);
- in += ops[i].len;
- }
- }
- }
-
- *out = 0;
-}
-
-
-/**
- *** ocfs_link_size - Return expanded size required to store a symlink
- *** @str: The symlink
- *** @ops: The symlink substitution operations table
- ***
- *** Returns: The size of the expanded symlink.
- ***/
-
-
-static unsigned int ocfs_link_size(struct ocfs_symlink_ops *ops, char *str, struct inode *inode)
-{
- unsigned int len = 0;
- unsigned int i;
-
- while (*str) {
- len++;
- if (*str++ != '{')
- continue;
-
- for (i = 0; ops[i].name; i++) {
- if (memcmp(str, ops[i].name, ops[i].len) == 0) {
- len--;
- len += ops[i].subst_fn(NULL, inode);
- str += ops[i].len;
- break;
- }
- }
- }
-
- return len + 1;
-}
-
Deleted: trunk/sysfile.c
===================================================================
--- trunk/sysfile.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/sysfile.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,888 +0,0 @@
-/*
- * ocfsgensysfile.c
- *
- * Initialize, read, write, etc. system files.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#ifdef __KERNEL__
-#include <ocfs.h>
-#else
-#include <dummy.h>
-#include <ocfsmalloc.h>
-#endif
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_MISC
-
-static int ocfs_find_extents_of_system_file (ocfs_super * osb, __u64 file_off, __u64 Length, ocfs_file_entry * fe, void **Buffer, __u32 * NumEntries);
-
-/*
- * ocfs_init_system_file()
- *
- */
-int ocfs_init_system_file (ocfs_super * osb, __u32 file_id, char *filename)
-{
- int status = 0;
- __u64 offset = 0;
- ocfs_file_entry *fe = NULL;
- struct buffer_head *fe_bh = NULL;
-
- LOG_ENTRY_ARGS ("(file_id = %u)\n", file_id);
-
- memset (filename, 0, sizeof (OCFS_MAX_FILENAME_LENGTH));
-
- if ((file_id >= OCFS_FILE_DIR_ALLOC) &&
- (file_id < (OCFS_FILE_DIR_ALLOC + 32))) {
- sprintf (filename, "%s%d", OCFS_DIR_FILENAME, file_id);
- } else if ((file_id >= OCFS_FILE_DIR_ALLOC_BITMAP) &&
- (file_id < (OCFS_FILE_DIR_ALLOC_BITMAP + 32))) {
- sprintf (filename, "%s%d", OCFS_DIR_BITMAP_FILENAME, file_id);
- } else if ((file_id >= OCFS_FILE_FILE_ALLOC) &&
- (file_id < (OCFS_FILE_FILE_ALLOC + 32))) {
- sprintf (filename, "%s%d", OCFS_FILE_EXTENT_FILENAME, file_id);
- } else if ((file_id >= OCFS_FILE_FILE_ALLOC_BITMAP) &&
- (file_id < (OCFS_FILE_FILE_ALLOC_BITMAP + 32))) {
- sprintf (filename, "%s%d", OCFS_FILE_EXTENT_BITMAP_FILENAME,
- file_id);
- } else if ((file_id >= LOG_FILE_BASE_ID)
- && (file_id < (LOG_FILE_BASE_ID + 32))) {
- sprintf (filename, "%s%d", OCFS_RECOVER_LOG_FILENAME, file_id);
- } else if ((file_id >= CLEANUP_FILE_BASE_ID) &&
- (file_id < (CLEANUP_FILE_BASE_ID + 32))) {
- sprintf (filename, "%s%d", OCFS_CLEANUP_LOG_FILENAME, file_id);
- } else if ((file_id >= OCFS_FILE_VOL_META_DATA) &&
- (file_id < (OCFS_FILE_VOL_META_DATA + 32))) {
- sprintf (filename, "%s", "VolMetaDataFile");
- } else if ((file_id >= OCFS_FILE_VOL_LOG_FILE) &&
- (file_id < (OCFS_FILE_VOL_LOG_FILE + 32))) {
- sprintf (filename, "%s", "VolMetaDataLogFile");
- } else if ((file_id >= OCFS_VOL_BITMAP_FILE) &&
- (file_id < (OCFS_VOL_BITMAP_FILE + 32))) {
- /* do nothing! should use create_new_local_alloc! */
- return(0);
- } else {
- sprintf (filename, "%s", "UKNOWNSysFile");
- }
-
- offset = (file_id * osb->sect_size) + osb->vol_layout.root_int_off;
- status = ocfs_read_bh(osb, offset, &fe_bh, OCFS_BH_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- memset (fe, 0, sizeof (ocfs_file_entry));
- /* Set the Flag to use the Local Extents */
- fe->local_ext = true;
- fe->granularity = -1;
-
- strcpy (fe->signature, OCFS_FILE_ENTRY_SIGNATURE);
- fe->next_free_ext = 0;
-
- /* Add a file Name */
- memcpy (fe->filename, filename, strlen (filename));
- (fe->filename)[strlen (filename)] = '\0';
-
- /* Set the Valid bit here */
- SET_VALID_BIT (fe->sync_flags);
- fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
- fe->this_sector = offset;
- fe->last_ext_ptr = 0;
-
- OCFS_BH_PUT_DATA(fe_bh);
- status = ocfs_write_bh(osb, fe_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-leave:
- if (fe_bh) {
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_init_system_file */
-
-/*
- * ocfs_read_system_file()
- *
- * make sure that the bhs array is either all NULL'd out or you really
- * know what you're doing! Also, those bh's will have to be brelse'd
- * after you're done with them!
- *
- */
-int ocfs_read_system_file (ocfs_super * osb, __u32 FileId, struct buffer_head *bhs[], __u64 Length, __u64 Offset)
-{
- int status = 0;
- ocfs_file_entry *fe = NULL;
- void *extentBuffer = NULL;
- __u32 numExts = 0, i, j, numblocks;
- ocfs_io_runs *IoRuns = NULL;
- __u64 tmplen;
- __u64 tmpoff = 0;
- struct buffer_head * fe_bh = NULL;
- int flags = OCFS_BH_CACHED;
- bool bWriteThru = false;
-
- LOG_ENTRY_ARGS ("(FileId = %u, metadatafile = %u, offset = (%u.%u), "
- "Length = (%u.%u))\n", FileId,
- OCFS_FILE_VOL_META_DATA + osb->node_num, HILO(Offset),
- HILO(Length));
-
- if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
- (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
- bWriteThru = true;
- flags = 0;
- }
-
- status = ocfs_read_bh(osb, (FileId * osb->sect_size) +
- osb->vol_layout.root_int_off, &fe_bh, flags, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto leave;
- }
-
- status = ocfs_find_extents_of_system_file (osb, Offset, Length,
- fe, &extentBuffer, &numExts);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- OCFS_ASSERT (extentBuffer);
-
- if (numExts < 1) {
- LOG_ERROR_ARGS("numExts < 1 (= %d)\n", numExts);
- goto leave;
- }
- IoRuns = (ocfs_io_runs *) extentBuffer;
- tmpoff = 0;
- tmplen = 0;
- j = 0;
- numblocks = 0;
-
- for (i = 0; i < numExts; i++) {
- //tempBuffer += tmplen;
- /* ?? need to align both the length and buffer and also */
- /* offset ( atleast the starting one) */
- tmpoff = IoRuns[i].disk_off;
- tmplen = IoRuns[i].byte_cnt;
-
- status = ocfs_read_bhs(osb, tmpoff, tmplen, &(bhs[j]), flags, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- numblocks = tmplen / osb->sect_size;
-
- j += numblocks;
- }
-
-leave:
- if (fe) {
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- if (extentBuffer)
- vfree(extentBuffer);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_read_system_file */
-
-
-/*
- * ocfs_write_system_file()
- * This should disappear actually -- we oughta just use ocfs_write_bhs
- *
- * NOTE: 'Length' and 'Offset' are essentially ignored -- the
- * entire buffer_head array is written out to disk!
- */
-int ocfs_write_system_file (ocfs_super * osb, __u64 FileId, struct buffer_head *bhs[], __u64 Length, __u64 Offset)
-{
- int status = 0;
- __u32 numblocks;
-
- LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
-
- if (Offset != 0)
- LOG_ERROR_STR("Asked to write at non zero offset, but we" \
- " don't support that yet!");
-
- numblocks = (Length + 511) >> 9;
- status = ocfs_write_bhs(osb, bhs, numblocks, 0, NULL);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_system_file */
-
-/*
- * ocfs_file_to_disk_off()
- *
- */
-__u64 ocfs_file_to_disk_off (ocfs_super * osb, __u32 FileId, __u64 Offset)
-{
- int status = 0;
- __u64 StartOffset = 0;
- void *Buffer = NULL;
- ocfs_file_entry *fe = NULL;
- ocfs_io_runs *IoRuns;
- __u32 NumExts = 0;
- struct buffer_head *fe_bh = NULL;
-
- LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
-
- /* Read the File Entry corresponding to File Id */
- status = ocfs_read_bh (osb, (FileId * osb->sect_size) +
- osb->vol_layout.root_int_off, &fe_bh, OCFS_BH_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto leave;
- }
-
- status = ocfs_find_extents_of_system_file (osb, Offset, osb->sect_size,
- fe, &Buffer, &NumExts);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- OCFS_ASSERT (Buffer);
-
- IoRuns = (ocfs_io_runs *) Buffer;
- /* Return the disk offset of first run . */
- StartOffset = (IoRuns[0].disk_off);
-
- leave:
- if (fe_bh) {
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- if (Buffer)
- vfree(Buffer);
-
- LOG_EXIT_ARGS ("%u.%u", HI (StartOffset), LO (StartOffset));
- return StartOffset;
-} /* ocfs_file_to_disk_off */
-
-
-/*
- * ocfs_get_system_file_size()
- *
- */
-int ocfs_get_system_file_size (ocfs_super * osb, __u32 FileId, __u64 * Length, __u64 * AllocSize)
-{
- int status = 0;
- ocfs_file_entry *fe = NULL;
- __u64 offset;
- struct buffer_head *fe_bh = NULL;
- bool bWriteThru = false;
- int flags = OCFS_BH_CACHED;
-
- LOG_ENTRY_ARGS ("(FileId = %u)\n", FileId);
-
- if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
- (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
- bWriteThru = true;
- flags = 0;
- }
-
- *AllocSize = *Length = 0;
-
- offset = (FileId * osb->sect_size) + osb->vol_layout.root_int_off;
-
- status = ocfs_read_bh (osb, offset, &fe_bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_ARGS("offset=%u.%u", HILO (offset));
- status = -EINVAL;
- goto leave;
- }
-
- *Length = (__u64) (fe->file_size);
- *AllocSize = (__u64) (fe->alloc_size);
-
-leave:
- if (fe) {
- OCFS_BH_PUT_DATA(fe_bh);
- brelse(fe_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_get_system_file_size */
-
-#ifdef __KERNEL__
-/*
- * ocfs_extend_system_file()
- *
- * fe_bh can be null and we'll just read it off disk.
- * of course, if you've already read it off disk, then give us fe_bh to avoid
- * an extra read. We always do the write out of the new fe.
- */
-int ocfs_extend_system_file (ocfs_super * osb, __u32 FileId, __u64 FileSize, struct buffer_head *fe_bh, ocfs_journal_handle *handle)
-{
- int status = 0;
- __u64 actualDiskOffset = 0, actualLength = 0;
- bool bWriteThru = false;
- bool local_fe = false;
- ocfs_file_entry *fe = NULL;
- int flags = OCFS_BH_COND_CACHED;
-
- LOG_ENTRY_ARGS ("(FileId = %u, Size = %u.%u)\n", FileId, HI (FileSize),
- LO (FileSize));
-
- OCFS_ASSERT (osb);
-
- if ((FileId == (OCFS_FILE_VOL_LOG_FILE + osb->node_num)) ||
- (FileId == (OCFS_FILE_VOL_META_DATA + osb->node_num))) {
- bWriteThru = true;
- flags = 0; /* want to force everything out */
- }
-
- if (!fe_bh) {
- local_fe = true;
- status = ocfs_read_bh(osb, (FileId * osb->sect_size) + osb->vol_layout.root_int_off, &fe_bh, flags, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto leave;
- }
-
- if (handle) {
- OCFS_BH_PUT_DATA(fe_bh);
- status = ocfs_journal_access(handle, fe_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
- if (FileSize <= fe->alloc_size) {
- fe->file_size = FileSize;
- } else {
- /* We need to allocate from bitmap */
- __u64 numClusterAlloc = 0, BitmapOffset = 0;
-
- status =
- ocfs_find_contiguous_space_from_bitmap (osb,
- FileSize - fe->alloc_size,
- &BitmapOffset,
- &numClusterAlloc, true,
- NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- actualDiskOffset =
- (BitmapOffset * osb->vol_layout.cluster_size) +
- osb->vol_layout.data_start_off;
- actualLength =
- (__u64) (numClusterAlloc * osb->vol_layout.cluster_size);
-
-#ifdef ZERO_METADATA_BLOCKS
- /* zero the entire metadata block! */
- {
- int nbhs, bufsize, j;
- __u64 iosize;
- struct buffer_head **bhs = NULL;
- char *mem;
-
- iosize = OCFS_ALIGN(actualLength, 512);
- nbhs = (int) (iosize >> 9);
- bufsize = nbhs * sizeof(struct buffer_head *);
- LOG_TRACE_ARGS("about to zero out %d new metadata blocks, newlen=%u.%u\n",
- nbhs, iosize);
-
- bhs = (struct buffer_head **)ocfs_malloc(bufsize);
- if (bhs == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(bhs, 0, bufsize);
- status = ocfs_read_bhs(osb, actualDiskOffset, iosize, bhs, 0, NULL);
- if (status < 0) {
- ocfs_safefree(bhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- for (j=0; j<nbhs; j++) {
- mem = OCFS_BH_GET_DATA(bhs[j]);
- memset(mem, 0, 512);
- OCFS_BH_PUT_DATA(bhs[j]);
- }
-
- LOG_TRACE_STR("writing zeroed blocks now");
-
- status = ocfs_write_bhs(osb, bhs, nbhs, 0, NULL);
- for (j=0; j<nbhs; j++)
- brelse(bhs[j]);
- ocfs_safefree(bhs);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-#endif
-
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
-
- status = ocfs_allocate_extent (osb, NULL, fe_bh, handle,
- actualDiskOffset, actualLength, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA(fe_bh);
- fe->alloc_size += actualLength;
- fe->file_size = FileSize;
- }
-
- if (!bWriteThru) {
- DISK_LOCK_CURRENT_MASTER (fe) = osb->node_num;
- DISK_LOCK_FILE_LOCK (fe) = OCFS_DLM_ENABLE_CACHE_LOCK;
- }
-
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
- if (handle)
- status = ocfs_journal_dirty(handle, fe_bh);
- else
- status = ocfs_write_bh(osb, fe_bh, flags, NULL);
-
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
-leave:
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
- if (local_fe)
- brelse(fe_bh);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_extend_system_file */
-
-#endif /* __KERNEL__ */
-
-/*
- * ocfs_find_extents_of_system_file()
- *
- * Searches for the extents in the file entry passed starting from
- * file offset up to the length specified.
- */
-static int ocfs_find_extents_of_system_file (ocfs_super * osb, __u64 file_off, __u64 Length, ocfs_file_entry * fe, void **Buffer, __u32 * NumEntries)
-{
- int status = -EFAIL;
- __u32 size;
- __u32 k = 0, j;
- __u32 Runs, Runoffset;
- struct buffer_head *extent_bh = NULL;
- ocfs_extent_group *extent = NULL;
- ocfs_io_runs *IoRuns;
- __u64 newOffset = 0, searchVbo, remainingLength = 0;
-
-
- LOG_ENTRY ();
-
- OCFS_ASSERT (osb);
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS (status = -EFAIL);
- goto leave;
- }
-
- if (fe->local_ext)
- {
- size = OCFS_MAX_FILE_ENTRY_EXTENTS * sizeof (ocfs_io_runs);
- }
- else
- {
- int pow = fe->granularity + 1;
- /* extent tree looks like
- * fe[0] fe[1] fe[2]
- * hdr[0]...hdr[17] .....
- * dat[0]..dat[17]
- *
- * granularity of fe is tree height
- * so max runs (total of all leaves) is
- * 3 x 18 ^ (granularity+1)
- * (OCFS_MAX_DATA_EXTENTS = 18)
- *
- * g=0: 1296 bytes
- * g=1: 23328 bytes
- * g=2: 419904 bytes!
- */
- size = 3;
- while (pow)
- {
- size *= OCFS_MAX_DATA_EXTENTS;
- pow--;
- }
- size *= sizeof (ocfs_io_runs);
- }
- size = OCFS_ALIGN (size, osb->sect_size);
- IoRuns = vmalloc(size);
-
- if (IoRuns == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- memset (IoRuns, 0, size);
-
- remainingLength = Length;
- Runs = 1;
- Runoffset = 0;
- newOffset = file_off;
-
- if (fe->local_ext) {
- for (j = 0; j < OCFS_MAX_FILE_ENTRY_EXTENTS; j++) {
- if ((fe->extents[j].file_off +
- fe->extents[j].num_bytes) > newOffset) {
- IoRuns[Runoffset].disk_off =
- fe->extents[j].disk_off +
- (newOffset - fe->extents[j].file_off);
- IoRuns[Runoffset].byte_cnt =
- (__u32) ((fe->extents[j].file_off +
- fe->extents[j].num_bytes) -
- newOffset);
- if (IoRuns[Runoffset].byte_cnt >=
- remainingLength) {
- IoRuns[Runoffset].byte_cnt =
- (__u32) remainingLength;
- status = 0;
- break;
- } else {
- newOffset += IoRuns[Runoffset].byte_cnt;
- remainingLength -=
- IoRuns[Runoffset].byte_cnt;
- Runs++;
- Runoffset++;
- }
- }
- }
-
- *NumEntries = Runs;
- *Buffer = IoRuns;
- goto leave;
- } else {
- /* Extents are branched and we are no longer using Local
- * Extents for this File Entry. */
-
- while (1) {
- /* Keep going downwards looking for the Entry, till
- * we hit the last Data entry */
- for (k = 0; k < OCFS_MAX_FILE_ENTRY_EXTENTS; k++) {
- if ((__s64) (fe->extents[k].file_off +
- fe->extents[k].num_bytes) >
- newOffset) {
- break;
- }
- }
-
- if (k == OCFS_MAX_FILE_ENTRY_EXTENTS) {
- LOG_ERROR_STR ("data extents maxed");
- }
-
- if (fe->extents[k].disk_off == 0) {
- LOG_ERROR_STR ("disk_off=0");
- }
-
- status = ocfs_read_bh(osb, fe->extents[k].disk_off,
- &extent_bh, OCFS_BH_COND_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);;
- while (extent->type != OCFS_EXTENT_DATA) {
- __u64 diskoffset;
-
- if (!IS_VALID_EXTENT_HEADER (extent)) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto leave;
- }
-
- OCFS_GET_EXTENT ((__s64) newOffset, extent, k);
- if (k == OCFS_MAX_DATA_EXTENTS) {
- LOG_ERROR_STR ("data extents maxed");
- }
-
- if (extent->extents[k].disk_off == 0) {
- LOG_ERROR_STR ("disk_off=0");
- }
-
- diskoffset = extent->extents[k].disk_off;
-
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- extent = NULL; extent_bh = NULL;
-
- status = ocfs_read_bh(osb, diskoffset,
- &extent_bh,
- OCFS_BH_CACHED, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA(extent_bh);
- }
-
- searchVbo = newOffset;
-
- OCFS_ASSERT (extent->type ==
- OCFS_EXTENT_DATA);
-
- if (!IS_VALID_EXTENT_DATA (extent)) {
- LOG_ERROR_STATUS(status = -EFAIL);
- goto leave;
- }
-
- for (j = 0; j < OCFS_MAX_DATA_EXTENTS; j++) {
- if ((extent->extents[j].file_off +
- extent->extents[j].
- num_bytes) > newOffset) {
- IoRuns[Runoffset].disk_off =
- extent->extents[j].
- disk_off + (newOffset -
- extent->
- extents[j].
- file_off);
- IoRuns[Runoffset].byte_cnt =
- (__u32) ((extent->
- extents[j].
- file_off +
- extent->
- extents[j].
- num_bytes) -
- newOffset);
-
- if (IoRuns[Runoffset].
- byte_cnt >=
- remainingLength) {
- IoRuns[Runoffset].
- byte_cnt = (__u32)
- remainingLength;
- status = 0;
- break;
- } else {
- newOffset +=
- IoRuns[Runoffset].
- byte_cnt;
- remainingLength -=
- IoRuns[Runoffset].
- byte_cnt;
- Runs++;
- Runoffset++;
- if (Runs >=
- OCFS_MAX_DATA_EXTENTS)
- {
- LOG_ERROR_ARGS ("Runs=%d", Runs);
- }
- }
- }
- }
-
- if (j == OCFS_MAX_DATA_EXTENTS) {
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- extent = NULL; extent_bh = NULL;
- continue;
- } else {
- *NumEntries = Runs;
- *Buffer = IoRuns;
- goto leave;
- }
- } /* while (1) */
- }
-
-leave:
- /* Don't free the IoRuns Memory here */
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_find_extents_of_system_file */
-
-#ifndef USERSPACE_TOOL
-/*
- * ocfs_write_map_file()
- *
- */
-int ocfs_write_map_file (ocfs_super * osb)
-{
- int status = 0;
-/* function is mostly commented out as we may not be using it anymore. */
-#if 0
- __u32 RunsInMap;
- __u32 MapIndex;
- __u32 length;
- ocfs_offset_map *pMapBuffer = NULL;
- __u64 fileSize;
- __u64 allocSize;
- __u64 neededSize;
- __s64 foundVolOffset;
- __s64 foundlogOffset;
- __u32 numRec;
- ocfs_file_entry *fe = NULL;
-#endif
- LOG_ENTRY ();
-#if 0
- RunsInMap = osb->trans_map.count;
-
- LOG_TRACE_ARGS ("NumRuns in trans_map=%u\n", RunsInMap);
-
- if (RunsInMap == 0) {
- status = -EWARNING;
- goto leave;
- }
-
- neededSize =
- OCFS_ALIGN ((RunsInMap * sizeof (ocfs_offset_map)), osb->sect_size);
-
- status = ocfs_get_system_file_size (osb,
- (OCFS_FILE_VOL_META_DATA + osb->node_num),
- &fileSize, &allocSize);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (allocSize < neededSize) {
- LOG_TRACE_ARGS ("allocSize(%u.%u) < neededSize(%u.%u)",
- HILO (allocSize), HILO (neededSize));
- status = ocfs_extend_system_file (osb,
- (OCFS_FILE_VOL_META_DATA + osb->node_num),
- neededSize, NULL, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
-
- pMapBuffer = ocfs_malloc (neededSize);
- if (pMapBuffer == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
-
- numRec = 0;
- for (MapIndex = 0; MapIndex < RunsInMap; MapIndex++) {
- if (!ocfs_get_next_extent_map_entry (osb, &osb->trans_map, MapIndex,
- &foundVolOffset,
- &foundlogOffset, &length)) {
- /* It means this is a hole */
- continue;
- }
-
- pMapBuffer[numRec].length = length;
- pMapBuffer[numRec].actual_disk_off = foundVolOffset;
- pMapBuffer[numRec].log_disk_off = foundlogOffset;
- numRec++;
- }
-
- status = ocfs_force_get_file_entry (osb, &fe,
- ((OCFS_FILE_VOL_META_DATA +
- osb->node_num) * osb->sect_size) +
- osb->vol_layout.root_int_off, true);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- if (!IS_VALID_FILE_ENTRY (fe)) {
- LOG_ERROR_STATUS (status = -EINVAL);
- goto leave;
- }
-
-// status = ocfs_write_force_disk (osb, (void *) pMapBuffer, neededSize,
- osb->log_meta_disk_off);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- fe->file_size = (numRec * sizeof (ocfs_offset_map));
-
- status = ocfs_force_put_file_entry (osb, fe, true);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
-leave:
- ocfs_release_file_entry (fe);
- ocfs_safefree (pMapBuffer);
-
-#endif
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_map_file */
-
-#endif /* ! USERSPACE_TOOL */
Deleted: trunk/util.c
===================================================================
--- trunk/util.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/util.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,362 +0,0 @@
-/*
- * ocfsport.c
- *
- * Linux specific utilities
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#ifdef __KERNEL__
-#include <ocfs.h>
-#else
-#include <debugocfs.h>
-#endif
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_PORT
-
-
-#ifndef USERSPACE_TOOL
-
-/*
- * ocfs_daemonize()
- *
- */
-#ifdef LINUX_2_5
-/* yes, len is unused but kept here for backwards compatibility. */
-void ocfs_daemonize (char *name, int len)
-{
- sigset_t tmpsig;
-
- daemonize (name);
-
- /* Unblock SIGKILL, SIGSTOP, SIGHUP and SIGINT */
- sigemptyset(&tmpsig);
- sigaddsetmask(&tmpsig, SHUTDOWN_SIGS);
- sigprocmask(SIG_UNBLOCK, &tmpsig, NULL);
-
- return;
-} /* ocfs_daemonize */
-#else
-void ocfs_daemonize (char *name, int len)
-{
- sigset_t tmpsig;
-
- daemonize ();
- reparent_to_init ();
-
- if (len > 0) {
- if (len > 15)
- BUG();
- strncpy (current->comm, name, len);
- current->comm[len] = '\0';
- }
-
- /* Block all signals except SIGKILL, SIGSTOP, SIGHUP and SIGINT */
-#ifdef HAVE_NPTL
- spin_lock_irq (¤t->sighand->siglock);
- tmpsig = current->blocked;
- siginitsetinv (¤t->blocked, SHUTDOWN_SIGS);
- recalc_sigpending ();
- spin_unlock_irq (¤t->sighand->siglock);
-#else
- spin_lock_irq (¤t->sigmask_lock);
- tmpsig = current->blocked;
- siginitsetinv (¤t->blocked, SHUTDOWN_SIGS);
- recalc_sigpending (current);
- spin_unlock_irq (¤t->sigmask_lock);
-#endif
-
- return;
-} /* ocfs_daemonize */
-#endif
-
-/*
- * ocfs_sleep()
- *
- * The interval time is in milliseconds
- *
- * This function needs to be removed.
- * Instead call schedule_timeout() directly and handle signals.
- */
-int ocfs_sleep (__u32 ms)
-{
- __u32 numJiffies;
-
- LOG_ENTRY ();
-
- /* 10ms = 1 jiffy, minimum resolution is one jiffy */
- numJiffies = ms * HZ / 1000;
- numJiffies = (numJiffies < 1) ? 1 : numJiffies;
-
- set_current_state (TASK_INTERRUPTIBLE);
- numJiffies = schedule_timeout (numJiffies);
-
- LOG_EXIT ();
- return 0;
-} /* ocfs_sleep */
-
-#ifdef OCFS_LINUX_MEM_DEBUG
-#define SUPER_VERBOSE_MEM_DEBUG 1
-#endif
-
-/*
- * ocfs_dbg_slab_alloc()
- *
- */
-void *ocfs_dbg_slab_alloc (kmem_cache_t *slab, char *file, int line)
-{
- void *m;
- m = kmem_cache_alloc(slab, GFP_NOFS);
-#ifdef OCFS_LINUX_MEM_DEBUG
- if (m == NULL) {
- LOG_ERROR_ARGS("failed to alloc from slab = %p", slab);
- } else {
- alloc_item *new;
- new = kmalloc (sizeof (alloc_item), GFP_NOFS);
- new->type = SLAB_ITEM;
- new->address = m;
- new->u.slab = slab;
- snprintf (new->tag, 30, "%d:%s", line, file);
- new->tag[29] = '\0';
- list_add (&new->list, &OcfsGlobalCtxt.item_list);
-#ifdef SUPER_VERBOSE_MEM_DEBUG
- LOG_TRACE_ARGS (" + %x (%p, '%s')\n", m, slab, new->tag);
-#endif
- }
-#endif
- return m;
-} /* ocfs_dbg_slab_alloc */
-
-/*
- * ocfs_dbg_slab_free()
- *
- */
-void ocfs_dbg_slab_free (kmem_cache_t *slab, void *m)
-{
-
-#ifdef OCFS_LINUX_MEM_DEBUG
- struct list_head *iter, *tmpiter;
- alloc_item *item = NULL;
- bool do_free = false;
-
- list_for_each_safe (iter, tmpiter, &OcfsGlobalCtxt.item_list) {
- item = list_entry (iter, alloc_item, list);
-
- if (item->address == m && item->type == SLAB_ITEM) {
-#ifdef SUPER_VERBOSE_MEM_DEBUG
- LOG_TRACE_ARGS (" - %x (%p, '%s')\n", m, item->u.slab, item->tag);
-#endif
- list_del (&item->list);
- do_free = true;
- break;
- }
- }
-
- if (do_free) {
- kmem_cache_free(slab, m);
- kfree (item);
- return;
- }
- LOG_ERROR_ARGS ("tried to free mem never allocated: %x", m);
-#endif
-#ifndef OCFS_LINUX_MEM_DEBUG
- kmem_cache_free(slab, m);
-#endif
-} /* ocfs_dbg_slab_free */
-
-
-
-/*
- * ocfs_linux_dbg_alloc()
- *
- */
-void *ocfs_linux_dbg_alloc (int Size, char *file, int line)
-{
- void *m;
-
- m = kmalloc (Size, GFP_NOFS);
-#ifdef OCFS_LINUX_MEM_DEBUG
- if (m == NULL) {
- LOG_ERROR_ARGS ("failed! (size=%d)", Size);
- } else {
- alloc_item *new;
- new = kmalloc (sizeof (alloc_item), GFP_NOFS);
- new->type = KMALLOC_ITEM;
- new->address = m;
- new->u.length = Size;
- snprintf (new->tag, 30, "%d:%s", line, file);
- new->tag[29] = '\0';
- list_add (&new->list, &OcfsGlobalCtxt.item_list);
-#ifdef SUPER_VERBOSE_MEM_DEBUG
- LOG_TRACE_ARGS (" + %x (%d, '%s')\n", m, Size, new->tag);
-#endif
- }
-#endif
- return m;
-} /* ocfs_linux_dbg_alloc */
-
-/*
- * ocfs_linux_dbg_free()
- *
- */
-void ocfs_linux_dbg_free (const void *Buffer)
-{
-
-#ifdef OCFS_LINUX_MEM_DEBUG
- struct list_head *iter, *tmpiter;
- alloc_item *item = NULL;
- bool do_free = false;
-
- list_for_each_safe (iter, tmpiter, &OcfsGlobalCtxt.item_list) {
- item = list_entry (iter, alloc_item, list);
-
- if (item->address == Buffer && item->type == KMALLOC_ITEM) {
-#ifdef SUPER_VERBOSE_MEM_DEBUG
- LOG_TRACE_ARGS (" - %x (%d, '%s')\n", Buffer,
- item->u.length, item->tag);
-#endif
- list_del (&item->list);
- do_free = true;
- break;
- }
- }
- if (do_free) {
- kfree (Buffer);
- kfree (item);
- return;
- }
- LOG_ERROR_ARGS ("tried to free mem never allocated: %x", Buffer);
-#endif
-#ifndef OCFS_LINUX_MEM_DEBUG
- kfree (Buffer);
-#endif
-} /* ocfs_linux_dbg_free */
-
-
-/*
- * ocfs_linux_get_inode_offset()
- *
- */
-bool ocfs_linux_get_inode_offset (struct inode * inode, __u64 * off, ocfs_inode ** oin)
-{
- if (off == NULL)
- return false;
-
- if (oin != NULL)
- *oin = NULL;
-
- if (inode_data_is_oin (inode)) {
- ocfs_inode *f = GET_INODE_OIN(inode);
-
- if (f == NULL) {
- LOG_ERROR_STR ("bad inode oin");
- *off = -1;
- return false;
- } else {
- if (oin != NULL)
- *oin = f;
- if (S_ISDIR (inode->i_mode))
- *off = f->dir_disk_off;
- else
- *off = f->file_disk_off;
- }
- } else {
- *off = GET_INODE_OFFSET (inode);
- }
- return (*off != -1);
-} /* ocfs_linux_get_inode_offset */
-
-
-/*
- * ocfs_linux_get_dir_entry_offset()
- *
- */
-bool ocfs_linux_get_dir_entry_offset (ocfs_super * osb, __u64 * off, __u64 parentOff, struct qstr * fileName, struct buffer_head ** fe_bh, struct inode *parent_inode)
-{
- int status;
- ocfs_file_entry *ent = NULL;
- struct buffer_head *ent_bh = NULL;
-
- if (off == NULL)
- return false;
-
- *off = -1;
-
- status = ocfs_find_files_on_disk (osb, parentOff, fileName, &ent_bh, NULL, parent_inode);
- if (status >= 0) {
- ent = (ocfs_file_entry *) OCFS_BH_GET_DATA(ent_bh);
- *off = ent->this_sector;
- OCFS_BH_PUT_DATA(ent_bh);
- } else
- LOG_ERROR_STATUS(status);
-
- /* if the caller wants the file entry let him free it */
- if (fe_bh)
- *fe_bh = ent_bh;
- else if (ent_bh)
- brelse(ent_bh);
-
- return (*off != -1);
-} /* ocfs_linux_get_dir_entry_offset */
-
-
-
-/* prefetch has been declared to allow to build in debug mode */
-#ifdef DEBUG
-#ifndef ARCH_HAS_PREFETCH
-inline void prefetch (const void *x)
-{;
-}
-#endif
-#endif
-
-#endif /* !USERSPACE_TOOL */
-
-/*
- * ocfs_compare_qstr()
- *
- */
-int ocfs_compare_qstr (struct qstr * s1, struct qstr * s2)
-{
- int s = strncmp ((const char *) s1->name, (const char *) s2->name,
- s1->len < s2->len ? s1->len : s2->len);
-
- if (s != 0)
- return s;
- if (s1->len > s2->len)
- return 1;
- else if (s1->len < s2->len)
- return -1;
- else
- return s;
-} /* ocfs_compare_qstr */
-
-
-void ocfs_truncate_inode_pages(struct inode *inode, loff_t off)
-{
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,4,10)
- LOG_TRACE_ARGS ("NOT truncating pages for inode %p from offset %u.%u\n", inode, off);
-#else
- LOG_TRACE_ARGS ("truncating pages for inode %p from offset %u.%u\n", inode, off);
- truncate_inode_pages(&inode->i_data, off);
-#endif
-} /* ocfs_truncate_inode_pages */
Deleted: trunk/ver.c
===================================================================
--- trunk/ver.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/ver.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,18 +0,0 @@
-#include <ocfs.h>
-#include <linux/kernel.h>
-
-#include <linux/module.h>
-
-MODULE_DESCRIPTION("The Oracle Cluster Filesystem (version "
- OCFS_BUILD_VERSION
- ")");
-
-char *ocfs_version = OCFS_BUILD_VERSION;
-
-void ocfs_version_print (void)
-{
- printk(KERN_INFO "Oracle Cluster FileSystem "
- OCFS_BUILD_VERSION " "
- OCFS_BUILD_DATE " "
- "(build " OCFS_BUILD_MD5 ")\n");
-}
Deleted: trunk/volcfg.c
===================================================================
--- trunk/volcfg.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/volcfg.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,1039 +0,0 @@
-/*
- * ocfsgenvolcfg.c
- *
- * Auto configuration, namely, node number.
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_VOLCFG
-static void ocfs_worker (void *arg);
-static void ocfs_assert_lock_owned (unsigned long arg);
-static int ocfs_add_to_disk_config (ocfs_super * osb, __u32 pref_node_num, ocfs_disk_node_config_info * new_disk_node);
-static int ocfs_write_volcfg_header (ocfs_super * osb, ocfs_volcfg_op op);
-static int ocfs_update_disk_config (ocfs_super * osb, __u32 node_num, ocfs_disk_node_config_info * disk);
-static int ocfs_release_disk_lock (ocfs_super * osb, __u64 lock_off);
-static int ocfs_add_node_to_config (ocfs_super * osb);
-static bool ocfs_has_node_config_changed (ocfs_super * osb);
-static int ocfs_refresh_node_config (ocfs_super * osb);
-static void ocfs_show_all_node_cfgs (ocfs_super * osb);
-static int ocfs_disknode_to_node (ocfs_node_config_info ** node, ocfs_disk_node_config_info * disk);
-
-/*
- * ocfs_worker()
- *
- * This function reiterates the lock on the disk from this node once
- * it has obtained it.
- */
-static void ocfs_worker (void *arg)
-{
- __u32 length;
- int status;
- ocfs_super *osb;
- __u64 offset;
- ocfs_cfg_task *cfg_task;
- struct buffer_head *bh = NULL;
-
- LOG_ENTRY ();
-
- cfg_task = (ocfs_cfg_task *) arg;
-
- /* Obtain the volume for which we need to reiterate the lock */
- osb = cfg_task->osb;
- //buffer = cfg_task->buffer;
- bh = cfg_task->bh;
- length = osb->sect_size;
- offset = cfg_task->lock_off;
-
- /* Write the sector back */
- status = ocfs_write_bh(osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- /* deliberate no exit jump here */
- }
-
- if (atomic_read (&osb->lock_stop)) {
- LOG_TRACE_ARGS ("Last Lock written : %d\n", jiffies);
- atomic_set (&osb->lock_event_woken, 1);
- brelse(bh);
- wake_up (&osb->lock_event);
- } else {
- LOG_TRACE_ARGS ("Lock written : %d\n", jiffies);
- mod_timer (&osb->lock_timer, jiffies + OCFS_VOLCFG_LOCK_ITERATE);
- }
-
- LOG_EXIT ();
- return;
-} /* ocfs_worker */
-
-/*
- * ocfs_assert_lock_owned()
- *
- * Routine called by a timer to reiterate the disk lock.
- */
-static void ocfs_assert_lock_owned (unsigned long arg)
-{
- ocfs_cfg_task *cfg_task;
-
- LOG_ENTRY ();
-
- cfg_task = (ocfs_cfg_task *) arg;
-
- /* initialize the task and submit it */
-#ifdef LINUX_2_5
- INIT_WORK (&(cfg_task->cfg_wq), ocfs_worker, cfg_task);
- schedule_work (&cfg_task->cfg_wq);
-#else
- INIT_TQUEUE (&(cfg_task->cfg_tq), ocfs_worker, cfg_task);
- schedule_task (&cfg_task->cfg_tq);
-#endif
-
- LOG_EXIT ();
- return ;
-} /* ocfs_assert_lock_owned */
-
-/*
- * ocfs_add_to_disk_config()
- *
- */
-static int ocfs_add_to_disk_config (ocfs_super * osb, __u32 pref_node_num, ocfs_disk_node_config_info * new_disk_node)
-{
- int status = 0;
- __u64 offset;
- int i;
- ocfs_disk_node_config_info *disk_node = NULL;
- __u8 *p;
- __u32 node_num;
- __u32 sect_size;
- __u32 size;
- struct buffer_head *cfg_bhs[OCFS_MAXIMUM_NODES];
- ocfs_bool done = false;
-
- LOG_ENTRY ();
-
- memset(cfg_bhs, 0, OCFS_MAXIMUM_NODES * sizeof(*cfg_bhs));
-
- sect_size = osb->sect_size;
-
- /* Read the nodecfg info for all nodes from disk */
- size = OCFS_VOLCFG_HDR_SECTORS * sect_size;
- offset = osb->vol_layout.node_cfg_off + size;
- size = osb->vol_layout.node_cfg_size - size;
-
- status = ocfs_read_bhs(osb, offset, size, cfg_bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* Check if preferred node num is available */
- node_num = OCFS_INVALID_NODE_NUM;
- if (pref_node_num >= 0 && pref_node_num < OCFS_MAXIMUM_NODES) {
- p = OCFS_BH_GET_DATA(cfg_bhs[pref_node_num]);
- disk_node = (ocfs_disk_node_config_info *)p;
- if (disk_node->node_name[0] == '\0')
- node_num = pref_node_num;
- OCFS_BH_PUT_DATA(cfg_bhs[pref_node_num]);
- }
-
- /* if not, find the first available empty slot */
- if (node_num == OCFS_INVALID_NODE_NUM) {
- for (node_num = 0; node_num < OCFS_MAXIMUM_NODES; node_num++) {
- p = OCFS_BH_GET_DATA(cfg_bhs[node_num]);
- disk_node = (ocfs_disk_node_config_info *) p;
- if (disk_node->node_name[0] == '\0')
- done = true;
- OCFS_BH_PUT_DATA(cfg_bhs[node_num]);
- if (done)
- break;
- }
- }
-
- /* If no free slots, error out */
- if (node_num >= OCFS_MAXIMUM_NODES) {
- LOG_ERROR_STR ("Unable to allocate node number as no slots " \
- "are available");
- status = -ENOSPC;
- goto finally;
- }
-
- /* Copy the new nodecfg into the memory buffer */
- p = OCFS_BH_GET_DATA(cfg_bhs[node_num]);
- memcpy (p, new_disk_node, sect_size);
- OCFS_BH_PUT_DATA(cfg_bhs[node_num]);
-
- /* Write the new node details on disk */
- status = ocfs_write_bh(osb, cfg_bhs[node_num], 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* Update the nodecfg hdr on disk */
- status = ocfs_write_volcfg_header (osb, OCFS_VOLCFG_ADD);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- finally:
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++)
- if (cfg_bhs[i])
- brelse(cfg_bhs[i]);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_add_to_disk_config */
-
-/*
- * ocfs_write_volcfg_header()
- *
- */
-static int ocfs_write_volcfg_header (ocfs_super * osb, ocfs_volcfg_op op)
-{
- int status = 0;
- ocfs_node_config_hdr *hdr;
- ocfs_node_config_hdr *hdr_copy;
- __u64 offset;
- struct buffer_head *node_cfg_bhs[2];
-
- LOG_ENTRY ();
-
- node_cfg_bhs[0] = node_cfg_bhs[1] = NULL;
- /* Read the nodecfg header */
- offset = osb->vol_layout.node_cfg_off;
- status = ocfs_read_bh(osb, offset, &node_cfg_bhs[0], 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- offset = osb->vol_layout.new_cfg_off + osb->sect_size;
- status = ocfs_read_bh(osb, offset, &node_cfg_bhs[1], 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- hdr = (ocfs_node_config_hdr *) OCFS_BH_GET_DATA(node_cfg_bhs[0]);
- hdr_copy = (ocfs_node_config_hdr *) OCFS_BH_GET_DATA(node_cfg_bhs[1]);
-
- if (op == OCFS_VOLCFG_ADD)
- hdr->num_nodes++;
-
- /* Increment the seq# to trigger other nodes to re-read node cfg */
- hdr->cfg_seq_num++;
-
- memcpy(hdr_copy, hdr, osb->sect_size);
- OCFS_BH_PUT_DATA(node_cfg_bhs[0]);
- OCFS_BH_PUT_DATA(node_cfg_bhs[1]);
- /* Write the nodecfg header */
- /* Write the nodecfg hdr into the second sector of newcfg also. */
- /* We do so so that we can read the nodecfg hdr easily when we */
- /* read the publish sector, for e.g. in ocfs_nm_thread() */
- status = ocfs_write_bhs(osb, node_cfg_bhs, 2, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- brelse(node_cfg_bhs[0]);
- brelse(node_cfg_bhs[1]);
- node_cfg_bhs[0] = node_cfg_bhs[1] = NULL;
-
-bail:
- if (node_cfg_bhs[0])
- brelse(node_cfg_bhs[0]);
- if (node_cfg_bhs[1])
- brelse(node_cfg_bhs[1]);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_volcfg_header */
-
-/*
- * ocfs_config_with_disk_lock()
- *
- * This function tries to obtain the lock on the disk for the volume
- * specified. The logic for obtaining a disk lock is as follows :
- *
- * Read the volcfg lock sector. If it is not locked, lock it by stamping
- * ones node number. Read the same sector after OCFS_VOLCFG_LOCK_TIME.
- * If the contents have not been modified, the lock is ours. Retain the
- * lock by reiterating the lock write operation every OCFS_VOLCFG_ITERATE_TIME.
- *
- * If the volcfg lock sector is owned by someone else, wait for
- * OCFS_VOLCFG_LOCK_TIME and read the lock sector again. If the lock sector
- * is owned by the same node as before attempt to break the lock as the
- * node may have died. If however, the lock sector is now owned by someone
- * else, wait for OCFS_VOLCFG_LOCK_TIME before repeating the entire exercise
- * again.
- *
- * Returns 0 if success, < 0 if error.
- */
-int ocfs_config_with_disk_lock (ocfs_super * osb, __u64 lock_off, __u8 * cfg_buf, __u32 node_num, ocfs_volcfg_op op)
-{
- int status = 0;
- char *lock_buf = NULL;
- bool tried_acq = false;
- bool break_lock = false;
- bool bh_locked = false;
- ocfs_disk_lock *disk_lock;
- ocfs_cfg_task *cfg_task = NULL;
- __u32 sect_size;
- __u64 lock_node_num = OCFS_INVALID_NODE_NUM;
- struct buffer_head *bh = NULL;
- int i;
-
- LOG_ENTRY ();
-
- sect_size = osb->sect_size;
-
- cfg_task = ocfs_malloc (sizeof (ocfs_cfg_task));
- if (cfg_task == NULL)
- {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finito;
- }
-
- /* initialize cfg_task with info reqd to reiterate the volcfg lock */
- cfg_task->osb = osb;
- cfg_task->lock_off = lock_off;
-
- /* Initialize the kernel timer */
- init_timer(&osb->lock_timer);
- osb->lock_timer.function = ocfs_assert_lock_owned;
- osb->lock_timer.expires = 0;
- osb->lock_timer.data = (unsigned long) cfg_task;
-
- init_waitqueue_head (&osb->lock_event);
- atomic_set (&osb->lock_event_woken, 0);
- atomic_set (&osb->lock_stop, 0);
-
- status = ocfs_read_bh(osb, lock_off, &bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
- cfg_task->bh = bh;
-
- //while (1) {
- for (i=0; i<50; i++) {
- /* Read the volcfg lock sector */
- lock_buffer(bh);
- if (!buffer_dirty(bh)) {
-#ifdef LINUX_2_5
- clear_buffer_uptodate(bh);
-#else
- mark_buffer_uptodate(bh, false);
-#endif
- }
- unlock_buffer(bh);
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
-
- lock_buf = OCFS_BH_GET_DATA(bh);
- bh_locked = true;
-
-
- disk_lock = (ocfs_disk_lock *) lock_buf;
- lock_node_num = DISK_LOCK_CURRENT_MASTER(disk_lock);
-
- if (DISK_LOCK_FILE_LOCK (disk_lock) == 0 || break_lock) {
- if (DISK_LOCK_FILE_LOCK (disk_lock) != 0)
- LOG_TRACE_STR ("Try to break node config lock");
- else
- LOG_TRACE_STR ("Lock node config");
-
- /* Attempt to lock volcfg */
- memcpy(disk_lock, cfg_buf, osb->sect_size);
-
- DISK_LOCK_CURRENT_MASTER (disk_lock) = osb->node_num;
- DISK_LOCK_FILE_LOCK (disk_lock) = 1;
- memcpy(cfg_buf, disk_lock, osb->sect_size);
-
- /* Write into volcfg lock sector... */
- OCFS_BH_PUT_DATA(bh);
- bh_locked = false;
- status = ocfs_write_bh(osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
- tried_acq = true;
- }
-
- ocfs_sleep (OCFS_VOLCFG_LOCK_TIME);
-
- if (bh_locked)
- OCFS_BH_PUT_DATA(bh);
- bh_locked = false;
-
- /* Read the volcfg lock sector again... */
- lock_buffer(bh);
- if (!buffer_dirty(bh)) {
-#ifdef LINUX_2_5
- clear_buffer_uptodate(bh);
-#else
- mark_buffer_uptodate(bh, false);
-#endif
- }
- unlock_buffer(bh);
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
-
- lock_buf = OCFS_BH_GET_DATA(bh);
-
- /* If we tried to acquire and we still own it we take it... */
- if ((tried_acq) && (memcmp (lock_buf, cfg_buf, sect_size) == 0)) {
- memcpy (lock_buf, cfg_buf, sect_size);
- OCFS_BH_PUT_DATA(bh);
- lock_buf = NULL;
-
- /* Set timer to reiterate lock every few jiffies */
- LOG_TRACE_ARGS ("Start Timer: %d\n", jiffies);
- osb->lock_timer.expires = jiffies +
- OCFS_VOLCFG_LOCK_ITERATE;
- /* we get_bh here because we brelse later in
- * this function, and so does the timer routine. */
- get_bh(bh);
- add_timer(&osb->lock_timer);
-
- /* Write the config info into the disk */
- disk_lock = (ocfs_disk_lock *) cfg_buf;
- DISK_LOCK_CURRENT_MASTER (disk_lock) =
- OCFS_INVALID_NODE_NUM;
- DISK_LOCK_FILE_LOCK (disk_lock) = 0;
-
- if (op == OCFS_VOLCFG_ADD)
- status = ocfs_add_to_disk_config (osb, node_num,
- (ocfs_disk_node_config_info *) cfg_buf);
- else if (op == OCFS_VOLCFG_UPD)
- status = ocfs_update_disk_config(osb, node_num,
- (ocfs_disk_node_config_info *) cfg_buf);
- else
- status = -EFAIL;
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finito;
- }
- break;
- } else {
- disk_lock = (ocfs_disk_lock *) lock_buf;
- if (DISK_LOCK_CURRENT_MASTER (disk_lock) == lock_node_num)
- break_lock = true;
- else {
- LOG_TRACE_ARGS ("Node config locked by node: %d\n",
- DISK_LOCK_CURRENT_MASTER (disk_lock));
- ocfs_sleep (OCFS_VOLCFG_LOCK_TIME);
- }
- OCFS_BH_PUT_DATA(bh);
- }
-
- }
- if (i >= 50)
- status = -EFAIL;
-
- finito:
- ocfs_release_disk_lock (osb, lock_off);
-
- ocfs_safefree (cfg_task);
- if (bh)
- brelse(bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_config_with_disk_lock */
-
-/*
- * ocfs_release_disk_lock()
- *
- * This function Cancels the timer to reiterate we own the disk lock and
- * then frees it by writing the sector for the disk lock.
- *
- * Returns 0 if success, < 0 if error.
- */
-static int ocfs_release_disk_lock (ocfs_super * osb, __u64 lock_off)
-{
- int status = 0;
- __s8 *buffer = NULL;
- __u32 sect_size = osb->sect_size;
- struct buffer_head *bh = NULL;
- struct super_block *sb;
- __u64 blocknum;
-
- LOG_ENTRY ();
-
- sb = osb->sb;
-
- if (sect_size != sb->s_blocksize) {
- LOG_ERROR_STR("sector_size != sb->s_blocksize!");
- status = -999;
- goto finally;
- }
-
- blocknum = lock_off >> sb->s_blocksize_bits;
- bh = getblk(OCFS_GET_BLOCKDEV(sb), blocknum, sb->s_blocksize);
- if (bh == NULL) {
- LOG_ERROR_STATUS (status = -EIO);
- goto finally;
- }
-
- buffer = OCFS_BH_GET_DATA(bh);
-
- /* reset lock... */
- memset (buffer, 0, sect_size);
-#ifdef LINUX_2_5
- set_buffer_uptodate(bh);
-#else
- mark_buffer_uptodate(bh, true);
-#endif
- mark_buffer_dirty(bh);
- OCFS_BH_PUT_DATA(bh);
-
- /* Cancel the timer so that we don't reiterate the lock anymore */
- LOG_TRACE_STR ("Waiting for osb->lock_event");
- atomic_set (&osb->lock_stop, 1);
- ocfs_wait (osb->lock_event, atomic_read (&osb->lock_event_woken), 0);
- atomic_set (&osb->lock_event_woken, 0);
- del_timer_sync(&osb->lock_timer);
-
- /* Release the lock */
- status = ocfs_write_bh(osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- finally:
- if (bh)
- brelse(bh);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_release_disk_lock */
-
-/*
- * ocfs_add_node_to_config()
- *
- */
-static int ocfs_add_node_to_config (ocfs_super * osb)
-{
- int status = 0;
- ocfs_disk_node_config_info *disk;
- void *buffer = NULL;
- __u64 offset;
- __u32 sect_size = osb->sect_size;
-
- LOG_ENTRY ();
-
- buffer = ocfs_malloc (sect_size);
- if (buffer == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
- memset (buffer, 0, sect_size);
-
- disk = (ocfs_disk_node_config_info *) buffer;
-
- /* populate the disknodecfg info from global context */
- ocfs_volcfg_gblctxt_to_disknode (disk);
-
- /* Write this nodes config onto disk */
- offset = osb->vol_layout.new_cfg_off;
- status = ocfs_config_with_disk_lock (osb, offset, (__u8 *) disk,
- OcfsGlobalCtxt.pref_node_num,
- OCFS_VOLCFG_ADD);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- status = ocfs_chk_update_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- bail:
- ocfs_safefree (buffer);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_add_node_to_config */
-
-/*
- * ocfs_disknode_to_node()
- *
- */
-static int ocfs_disknode_to_node (ocfs_node_config_info ** node, ocfs_disk_node_config_info * disk)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- if (*node == NULL) {
- if ((*node = (ocfs_node_config_info *)
- ocfs_malloc (sizeof (ocfs_node_config_info))) == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
- memset (*node, 0, sizeof (ocfs_node_config_info));
- }
-
- strncpy ((*node)->node_name, disk->node_name, MAX_NODE_NAME_LENGTH);
-
- memcpy((*node)->guid.guid, disk->guid.guid, GUID_LEN);
-
- (*node)->ipc_config.type = disk->ipc_config.type;
- (*node)->ipc_config.ip_port = disk->ipc_config.ip_port;
- strncpy((*node)->ipc_config.ip_addr, disk->ipc_config.ip_addr,
- MAX_IP_ADDR_LEN);
- strncpy((*node)->ipc_config.ip_mask, disk->ipc_config.ip_mask,
- MAX_IP_ADDR_LEN);
-
- (*node)->journal_version = disk->journal_version;
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_disknode_to_node */
-
-/*
- * ocfs_update_disk_config()
- *
- */
-static int ocfs_update_disk_config (ocfs_super * osb, __u32 node_num, ocfs_disk_node_config_info * disk)
-{
- int status = 0;
- __u64 offset;
- __u32 blocknum;
- struct buffer_head *bh = NULL;
- struct super_block *sb = NULL;
- char *buf = NULL;
-
- LOG_ENTRY ();
-
- sb = osb->sb;
- /* Write the node details */
- offset = osb->vol_layout.node_cfg_off +
- ((node_num + OCFS_VOLCFG_HDR_SECTORS) * osb->sect_size);
- blocknum = offset >> sb->s_blocksize_bits;
-
- bh = getblk(OCFS_GET_BLOCKDEV(sb), blocknum, sb->s_blocksize);
- if (bh == NULL) {
- status = -EIO;
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- buf = OCFS_BH_GET_DATA(bh);
- memcpy(buf, disk, osb->sect_size);
-#ifdef LINUX_2_5
- set_buffer_uptodate(bh);
-#else
- mark_buffer_uptodate(bh, true);
-#endif
- mark_buffer_dirty(bh);
- OCFS_BH_PUT_DATA(bh);
-
- status = ocfs_write_bh(osb, bh, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- status = ocfs_write_volcfg_header (osb, OCFS_VOLCFG_UPD);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- finally:
- if (bh)
- brelse(bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_update_disk_config */
-
-/*
- * ocfs_volcfg_gblctxt_to_disknode()
- *
- */
-void ocfs_volcfg_gblctxt_to_disknode(ocfs_disk_node_config_info *disk)
-{
- ocfs_ipc_config_info *ipc;
- ocfs_comm_info *g_ipc;
-
- LOG_ENTRY ();
-
- ipc = &(disk->ipc_config);
- g_ipc = &(OcfsGlobalCtxt.comm_info);
-
- if (OcfsGlobalCtxt.node_name)
- strncpy (disk->node_name, OcfsGlobalCtxt.node_name,
- MAX_NODE_NAME_LENGTH);
-
- memcpy(disk->guid.guid, OcfsGlobalCtxt.guid.guid, GUID_LEN);
-
- ipc->type = g_ipc->type;
- ipc->ip_port = g_ipc->ip_port;
- if (g_ipc->ip_addr)
- strncpy (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN);
- if (g_ipc->ip_mask)
- strncpy (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN);
-
- LOG_EXIT ();
- return ;
-} /* ocfs_volcfg_gblctxt_to_disknode */
-
-/*
- * ocfs_volcfg_gblctxt_to_node()
- *
- */
-void ocfs_volcfg_gblctxt_to_node(ocfs_node_config_info *node)
-{
- ocfs_ipc_config_info *ipc;
- ocfs_comm_info *g_ipc;
-
- LOG_ENTRY ();
-
- ipc = &(node->ipc_config);
- g_ipc = &(OcfsGlobalCtxt.comm_info);
-
- if (OcfsGlobalCtxt.node_name)
- strncpy (node->node_name, OcfsGlobalCtxt.node_name,
- MAX_NODE_NAME_LENGTH);
-
- memcpy(node->guid.guid, OcfsGlobalCtxt.guid.guid, GUID_LEN);
-
- ipc->type = g_ipc->type;
- ipc->ip_port = g_ipc->ip_port;
- if (g_ipc->ip_addr)
- strncpy (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN);
- if (g_ipc->ip_mask)
- strncpy (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN);
-
- LOG_EXIT ();
- return ;
-} /* ocfs_volcfg_gblctxt_to_node */
-
-/*
- * ocfs_chk_update_config()
- *
- */
-int ocfs_chk_update_config (ocfs_super * osb)
-{
- int status = 0;
- ocfs_node_config_hdr *hdr = NULL;
- ocfs_disk_node_config_info *disk = NULL;
- __u64 offset;
- __s32 i;
- __u32 numblocks = 0;
- struct super_block *sb = osb->sb;
- struct buffer_head **cfg_bhs = NULL;
-
- LOG_ENTRY ();
-
- /* Read in the config on the disk */
- offset = osb->vol_layout.node_cfg_off;
- numblocks = osb->vol_layout.node_cfg_size >> sb->s_blocksize_bits;
-
- cfg_bhs = ocfs_malloc(numblocks * sizeof(*cfg_bhs));
- if (cfg_bhs == NULL) {
- status = -ENOMEM;
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- memset(cfg_bhs, 0, numblocks * sizeof(*cfg_bhs));
-
- status = ocfs_read_bhs(osb, offset, osb->vol_layout.node_cfg_size, cfg_bhs, 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* 1st block in buffer is the NodeCfgHdr */
- hdr = (ocfs_node_config_hdr *) OCFS_BH_GET_DATA(cfg_bhs[0]);
-
- if (strncmp (hdr->signature, NODE_CONFIG_HDR_SIGN,
- NODE_CONFIG_SIGN_LEN)) {
- LOG_ERROR_STR ("Invalid node config signature");
- status = -EINVAL;
- goto finally;
- }
-
- if (hdr->version < NODE_MIN_SUPPORTED_VER ||
- hdr->version > NODE_CONFIG_VER) {
- LOG_ERROR_ARGS ("Node config version mismatch, (%d) < minimum" \
- " (%d) or > current (%d)", hdr->version,
- NODE_MIN_SUPPORTED_VER, NODE_CONFIG_VER);
- status = -EINVAL;
- goto finally;
- }
-
- /* Exit if nodecfg on disk has remained unchanged... */
- if ((osb->cfg_initialized) && (osb->cfg_seq_num == hdr->cfg_seq_num) &&
- (osb->num_cfg_nodes == hdr->num_nodes))
- goto finally;
-
- /* ... else refresh nodecfg in memory */
-
- /* Read the nodecfg for all possible nodes as there may be holes */
- /* i.e., node numbers need not be dolled out in sequence */
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {//, p += sect_size) {
- int which;
- which = i + OCFS_VOLCFG_HDR_SECTORS;
- disk = (ocfs_disk_node_config_info *)
- OCFS_BH_GET_DATA(cfg_bhs[which]);
-
- if (disk->node_name[0] == '\0')
- goto loop;
-
- status = ocfs_disknode_to_node (&osb->node_cfg_info[i], disk);
- if (status < 0) {
- OCFS_BH_PUT_DATA(cfg_bhs[which]);
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- /* If nodenum is set, goto next node */
- if (osb->node_num != OCFS_INVALID_NODE_NUM)
- goto loop;
-
- /*
- * If node num is not set, set it if guid matches.
- * If guid does not match and the hostid also does not
- * match, goto next slot.
- * However if the guid does not natch but the hostid
- * matches, it means that the user re-ran ocfs_uid_gen
- * with the -r option to reclaim its node number. In
- * this case, allow the reclaim only if the user mounts
- * the volume with the reclaimid option. Else, error.
- */
- if (!memcmp(&OcfsGlobalCtxt.guid.guid, disk->guid.guid,
- GUID_LEN)) {
- osb->node_num = i;
- goto loop;
- }
-
- /* If the hostid does not match, goto next... */
- if (memcmp(&OcfsGlobalCtxt.guid.id.host_id,
- disk->guid.id.host_id, HOSTID_LEN))
- goto loop;
-
- /* ...else allow node to reclaim the number if reclaimid set */
- if (osb->reclaim_id) {
- osb->node_num = i;
- /* Write this node's cfg with the new guid on disk */
- status = ocfs_refresh_node_config (osb);
- if (status < 0) {
- OCFS_BH_PUT_DATA(cfg_bhs[which]);
- LOG_ERROR_STATUS(status);
- goto finally;
- }
- }
- else {
- OCFS_BH_PUT_DATA(cfg_bhs[which]);
- LOG_ERROR_STR("Re-mount volume with the reclaimid " \
- "option to reclaim the node number");
- status = -EFAIL;
- goto finally;
- }
- loop:
- OCFS_BH_PUT_DATA(cfg_bhs[which]);
- continue;
- }
-
- osb->cfg_initialized = true;
- osb->cfg_seq_num = hdr->cfg_seq_num;
- osb->num_cfg_nodes = hdr->num_nodes;
- LOG_TRACE_ARGS ("Num of configured nodes (%u)\n", osb->num_cfg_nodes);
- IF_TRACE(ocfs_show_all_node_cfgs (osb));
-
-finally:
- if (cfg_bhs) {
- if (cfg_bhs[0] && buffer_locked(cfg_bhs[0]))
- OCFS_BH_PUT_DATA(cfg_bhs[0]);
- for (i = 0; i < numblocks; i++)
- if (cfg_bhs[i])
- brelse(cfg_bhs[i]);
- ocfs_safefree(cfg_bhs);
- }
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_chk_update_config */
-
-/*
- * ocfs_get_config()
- *
- */
-int ocfs_get_config (ocfs_super * osb)
-{
- int status = 0;
-
- LOG_ENTRY ();
-
- /* Update our config info for this volume from the disk */
- status = ocfs_chk_update_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (osb->node_num == OCFS_INVALID_NODE_NUM) {
- if (osb->reclaim_id) {
- LOG_ERROR_STR ("unable to reclaim id");
- status = -EINVAL;
- goto bail;
- }
- status = ocfs_add_node_to_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- } else {
- if (ocfs_has_node_config_changed (osb)) {
- status = ocfs_refresh_node_config (osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- }
- }
-
- LOG_TRACE_ARGS ("Node Num: %d\n", osb->node_num);
-
- bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_get_config */
-
-/*
- * ocfs_has_node_config_changed()
- *
- */
-static bool ocfs_has_node_config_changed (ocfs_super * osb)
-{
- ocfs_node_config_info *node;
- ocfs_ipc_config_info *ipc;
- ocfs_comm_info *g_ipc;
- bool chg = false;
-
- LOG_ENTRY ();
-
- node = osb->node_cfg_info[osb->node_num];
- ipc = &(node->ipc_config);
- g_ipc = &(OcfsGlobalCtxt.comm_info);
-
- if (OcfsGlobalCtxt.node_name &&
- strncmp (node->node_name, OcfsGlobalCtxt.node_name,
- MAX_NODE_NAME_LENGTH))
- chg = true;
-
- if (!chg && ipc->type != g_ipc->type)
- chg = true;
-
- if (!chg && ipc->ip_port != g_ipc->ip_port)
- chg = true;
-
- if (!chg && g_ipc->ip_addr &&
- strncmp (ipc->ip_addr, g_ipc->ip_addr, MAX_IP_ADDR_LEN))
- chg = true;
-
- if (!chg && g_ipc->ip_mask &&
- strncmp (ipc->ip_mask, g_ipc->ip_mask, MAX_IP_ADDR_LEN))
- chg = true;
-
- LOG_EXIT_LONG (chg);
- return chg;
-} /* ocfs_has_node_config_changed */
-
-/*
- * ocfs_refresh_node_config()
- *
- */
-static int ocfs_refresh_node_config (ocfs_super * osb)
-{
- ocfs_node_config_info *node;
- ocfs_disk_node_config_info *disk;
- __u64 offset;
- __u8 *buffer = NULL;
- int status = 0;
-
- LOG_ENTRY ();
-
- buffer = ocfs_malloc (osb->sect_size);
- if (buffer == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto bail;
- }
-
- memset ((void *) buffer, 0, osb->sect_size);
- disk = (ocfs_disk_node_config_info *) buffer;
-
- /* populate the nodecfg info in disk from global context */
- ocfs_volcfg_gblctxt_to_disknode (disk);
-
- /* populate the nodecfg info in mem from global context */
- node = osb->node_cfg_info[osb->node_num];
- ocfs_volcfg_gblctxt_to_node (node);
-
- /* Update the nodecfg on disk with the new info */
- offset = osb->vol_layout.new_cfg_off;
- status = ocfs_config_with_disk_lock (osb, offset, (__u8 *) disk,
- osb->node_num, OCFS_VOLCFG_UPD);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- bail:
- ocfs_safefree(buffer);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_refresh_node_config */
-
-/*
- * ocfs_show_all_node_cfgs()
- *
- */
-static void ocfs_show_all_node_cfgs (ocfs_super * osb)
-{
- ocfs_node_config_info *node;
- __u32 i;
-
- for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- node = osb->node_cfg_info[i];
-
- if (!node || node->node_name[0] == '\0')
- continue;
-
- LOG_TRACE_ARGS ("Node (%u) is (%s)\n", i, node->node_name);
- LOG_TRACE_ARGS ("ip=%s, port=%d\n", node->ipc_config.ip_addr,
- node->ipc_config.ip_port);
- }
-
- return;
-} /* ocfs_show_all_node_cfgs */
Deleted: trunk/vote.c
===================================================================
--- trunk/vote.c 2003-12-16 23:55:26 UTC (rev 10)
+++ trunk/vote.c 2003-12-18 23:17:02 UTC (rev 11)
@@ -1,541 +0,0 @@
-/*
- * ocfsgenvote.c
- *
- * IPC based DLM
- *
- * Copyright (C) 2002 Oracle Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have recieved a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- * Authors: Neeraj Goyal, Suchit Kaura, Kurt Hackel, Sunil Mushran,
- * Manish Singh, Wim Coekaerts, Mark Fasheh
- */
-
-#include <ocfs.h>
-
-/* Tracing */
-#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_VOTE
-
-ocfs_ipc_ctxt OcfsIpcCtxt;
-
-
-static void ocfs_dlm_recv_msg (void *val);
-static bool ocfs_check_ipc_msg (__u8 * msg, __u32 msg_len);
-static int ocfs_comm_process_vote_reply (ocfs_super * osb, ocfs_dlm_msg * dlm_msg);
-static int ocfs_comm_process_msg (__u8 * msg);
-
-
-/*
- * ocfs_recv_udp_msg()
- *
- */
-int ocfs_recv_udp_msg (ocfs_recv_ctxt * recv_ctxt)
-{
- int status = -EFAIL, error;
- mm_segment_t oldfs;
- struct sockaddr_in sin;
- struct iovec iov = {
- .iov_len = recv_ctxt->msg_len,
- .iov_base = recv_ctxt->msg
- };
- struct msghdr msg = {
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_iovlen = 1,
- .msg_iov = &iov,
- .msg_name = (struct sockaddr *) &sin,
- .msg_namelen = sizeof (sin),
- .msg_flags = 0
- };
-
- LOG_ENTRY ();
-
- /* Initialize the workitem with our worker routine and Q it. */
-#ifdef LINUX_2_5
- INIT_WORK (&recv_ctxt->ipc_wq, ocfs_dlm_recv_msg, recv_ctxt);
-#else
- INIT_TQUEUE (&recv_ctxt->ipc_tq, ocfs_dlm_recv_msg, recv_ctxt);
-#endif
-
- memset (&sin, 0, sizeof (sin));
- oldfs = get_fs ();
- set_fs (get_ds ());
- error = sock_recvmsg (OcfsIpcCtxt.recv_sock, &msg, recv_ctxt->msg_len, msg.msg_flags);
- set_fs (oldfs);
-
- if (error < 0) {
- if (error == -ERESTARTSYS) {
- status = -EBADF;
- LOG_TRACE_STR ("Shutting down ocfslsnr");
- } else {
- status = -EFAIL;
- LOG_ERROR_ARGS ("unable to recvmsg, error=%d", error);
- LOG_ERROR_STATUS (status);
- }
- goto bail;
- } else if (msg.msg_namelen) {
- recv_ctxt->msg_len = iov.iov_len;
- status = 0;
- }
-
- LOG_TRACE_ARGS ("Received packet from: %d.%d.%d.%d\n",
- NIPQUAD (sin.sin_addr.s_addr));
-
- if (status == 0)
-#ifdef LINUX_2_5
- schedule_work (&recv_ctxt->ipc_wq);
-#else
- schedule_task (&recv_ctxt->ipc_tq);
-#endif
-
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_recv_udp_msg */
-
-/*
- * ocfs_send_bcast()
- *
- */
-int ocfs_send_bcast (ocfs_super * osb, __u64 votemap, ocfs_dlm_msg * dlm_msg)
-{
- int status = 0, error;
- __u32 map, num;
- ocfs_node_config_info *node;
- struct sockaddr_in sin;
- mm_segment_t oldfs;
-
- LOG_ENTRY_ARGS ("(votemap=0x%x)\n", LO(votemap));
-
- oldfs = get_fs ();
- for (map = LO(votemap), num = 0; map != 0; map >>= 1, num++) {
- if (num == osb->node_num)
- continue;
-
- if (!(map & 0x1))
- continue;
-
- node = osb->node_cfg_info[num];
- if (!node)
- continue;
-
- LOG_TRACE_ARGS ("Sending msg to node=%u, name=%s\n",
- num, node->node_name);
- memset (&sin, 0, sizeof (sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = in_aton(node->ipc_config.ip_addr);
- sin.sin_port = htons(node->ipc_config.ip_port);
-
- LOG_TRACE_ARGS ("about to send to %s:%u\n", node->ipc_config.ip_addr,
- node->ipc_config.ip_port);
-
- status = -EFAIL;
- if (OcfsIpcCtxt.send_sock) {
- struct iovec iov = {
- .iov_base = dlm_msg,
- .iov_len = dlm_msg->msg_len
- };
- struct msghdr msg = {
- .msg_iov = &iov,
- .msg_iovlen = 1,
- .msg_control = NULL,
- .msg_controllen = 0,
- .msg_name = (struct sockaddr *) &sin,
- .msg_namelen = sizeof (sin),
- .msg_flags = 0
- };
-
- status = 0;
- set_fs (get_ds ());
- error = sock_sendmsg (OcfsIpcCtxt.send_sock, &msg, dlm_msg->msg_len);
- set_fs (oldfs);
-
- if (error < 0) {
- LOG_ERROR_ARGS ("unable to sendmsg, error=%d", error);
- status = -EFAIL;
- }
- }
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
-
- status = 0;
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_send_bcast */
-
-/*
- * ocfs_init_udp_sock()
- *
- */
-int ocfs_init_udp_sock (struct socket **send_sock, struct socket **recv_sock)
-{
- struct sockaddr_in sin;
- int status = -EFAIL;
- ocfs_comm_info *comm;
-
- LOG_ENTRY ();
-
- /* Create Send Socket */
- status = sock_create (PF_INET, SOCK_DGRAM, IPPROTO_UDP, send_sock);
- if (status < 0) {
- LOG_ERROR_ARGS ("unable to create socket, error=%d", status);
- goto bail;
- }
-
- /* Bind Send Socket */
- memset (&sin, 0, sizeof (sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl (INADDR_ANY);
- sin.sin_port = htons (0);
-
- status = (*send_sock)->ops->bind (*send_sock, (struct sockaddr *) &sin,
- sizeof (sin));
- if (status < 0) {
- LOG_ERROR_ARGS ("unable to bind socket, error=%d", status);
- goto bail;
- }
-
- /* Create Receive Socket */
- status = sock_create (PF_INET, SOCK_DGRAM, IPPROTO_UDP, recv_sock);
- if (status < 0) {
- LOG_ERROR_ARGS ("unable to create socket, error=%d", status);
- goto bail;
- }
-
- comm = &(OcfsGlobalCtxt.comm_info);
-
- /* Bind Receive Socket */
- memset (&sin, 0, sizeof (sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl (INADDR_ANY);
- sin.sin_port = htons (comm->ip_port);
-
- status = (*recv_sock)->ops->bind (*recv_sock, (struct sockaddr *) &sin,
- sizeof (sin));
- if (status < 0) {
- LOG_ERROR_ARGS ("unable to bind socket, error=%d", status);
- goto bail;
- }
-
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_init_udp_sock */
-
-
-/*
- * ocfs_send_vote_reply()
- *
- */
-int ocfs_send_vote_reply (ocfs_super * osb, ocfs_dlm_msg * dlm_msg, __u32 vote_status, bool inode_open)
-{
- ocfs_dlm_req_master *req_master;
- ocfs_dlm_reply_master *reply_master;
- ocfs_dlm_msg *send_dlm_msg;
- __u64 vote_map;
- int status = 0;
- __u8 *buf = NULL;
- __u32 msg_len;
-
- LOG_ENTRY ();
-
- msg_len = sizeof (ocfs_dlm_msg) - 1 + sizeof (ocfs_dlm_reply_master);
-
- buf = ocfs_malloc (msg_len);
- if (buf == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- req_master = (ocfs_dlm_req_master *) dlm_msg->msg_buf;
-
- send_dlm_msg = (ocfs_dlm_msg *)buf;
- ocfs_init_dlm_msg (osb, send_dlm_msg, msg_len);
- send_dlm_msg->msg_type = OCFS_VOTE_REPLY;
-
- reply_master = (ocfs_dlm_reply_master *) send_dlm_msg->msg_buf;
- reply_master->h.lock_id = req_master->lock_id;
- reply_master->status = vote_status;
- reply_master->h.lock_seq_num = req_master->lock_seq_num;
- reply_master->h.open_handle = inode_open;
- reply_master->h.flags = req_master->flags;
-
- vote_map = (1 << dlm_msg->src_node);
- ocfs_send_bcast (osb, vote_map, send_dlm_msg);
-
-finally:
- ocfs_safefree (buf);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_send_vote_reply */
-
-
-/*
- * ocfs_check_ipc_msg()
- *
- */
-bool ocfs_check_ipc_msg (__u8 * msg, __u32 msg_len)
-{
- bool bret = false;
- ocfs_dlm_msg *dlm_msg;
-
- LOG_ENTRY ();
-
- dlm_msg = (ocfs_dlm_msg *) msg;
-
- if (dlm_msg == NULL) {
- LOG_TRACE_STR("Null netdlm message");
- goto bail;
- }
-
- if (msg_len < sizeof(ocfs_dlm_msg)) {
- LOG_TRACE_STR("Netdlm message too short");
- goto bail;
- }
-
- /* Compute and Compare the checksum */
- if (dlm_msg->magic != OCFS_DLM_MSG_MAGIC) {
- LOG_TRACE_ARGS ("Magic number mismatch in netdlm message: "
- "0x%08x != 0x%08x\n",
- dlm_msg->magic, OCFS_DLM_MSG_MAGIC);
- goto bail;
- }
-
- if ((dlm_msg->src_node < 0) ||
- (dlm_msg->src_node > OCFS_MAXIMUM_NODES)) {
- LOG_TRACE_ARGS ("Invalid source node in netdlm message: %d\n",
- dlm_msg->src_node);
- goto bail;
- }
-
- bret = true;
-
-bail:
- LOG_EXIT_LONG (bret);
- return bret;
-} /* ocfs_check_ipc_msg */
-
-
-/*
- * ocfs_comm_process_vote_reply()
- *
- */
-int ocfs_comm_process_vote_reply (ocfs_super * osb, ocfs_dlm_msg * dlm_msg)
-{
- int status = 0;
- ocfs_lock_res *lockres = NULL;
- ocfs_dlm_reply_master *reply;
- ocfs_dlm_msg_hdr *reply_msg;
- ocfs_vote_reply_ctxt ctxt;
-
- LOG_ENTRY ();
-
- down (&(osb->comm_lock));
-
- reply = (ocfs_dlm_reply_master *) dlm_msg->msg_buf;
- reply_msg = &(reply->h);
-
- status = ocfs_lookup_sector_node (osb, reply_msg->lock_id, &lockres);
- if (status < 0) {
- lockres = NULL;
- LOG_ERROR_STATUS (status);
- goto bail;
- }
-
- if (!(lockres->vote_state & LOCK_STATE_IN_VOTING) ||
- (lockres->last_upd_seq_num != reply_msg->lock_seq_num)) {
- LOG_TRACE_STR ("Ignoring netdlm message");
- goto bail;
- }
-
- LOG_TRACE_ARGS("node=%u, lockid=%u.%u, seq=%u.%u, vote=%d\n",
- dlm_msg->src_node, HI(reply_msg->lock_id),
- LO(reply_msg->lock_id), HI(reply_msg->lock_seq_num),
- LO(reply_msg->lock_seq_num), reply->status);
-
- ctxt.reply_method = COMM_VOTE;
- ctxt.got_vote_map = &(lockres->got_vote_map);
- ctxt.open_map = &(lockres->tmp_openmap);
- ctxt.status = &(lockres->vote_status);
- ctxt.flags = reply_msg->flags;
- ctxt.u.reply = reply;
-
- ocfs_process_one_vote_reply(osb, &ctxt, dlm_msg->src_node);
-
- if (lockres->vote_status != 0) {
- lockres->vote_state = 0;
- atomic_set (&lockres->voted_event_woken, 1);
- wake_up (&lockres->voted_event);
- goto bail;
- }
-
- if (lockres->got_vote_map == lockres->req_vote_map) {
- if ((reply_msg->flags & FLAG_FILE_EXTEND) ||
- (reply_msg->flags & FLAG_FILE_UPDATE))
- lockres->oin_openmap = lockres->tmp_openmap;
- lockres->tmp_openmap = 0;
- LOG_TRACE_ARGS ("OK vote, lockid=%u.%u, map: 0x%08x\n",
- HI(lockres->sector_num), LO(lockres->sector_num),
- LO(lockres->got_vote_map));
- lockres->vote_state = 0;
- atomic_set (&lockres->voted_event_woken, 1);
- wake_up (&lockres->voted_event);
- }
-
-bail:
- ocfs_put_lockres (lockres);
- up (&(osb->comm_lock));
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_comm_process_vote_reply */
-
-/*
- * ocfs_dlm_recv_msg()
- *
- */
-void ocfs_dlm_recv_msg (void *val)
-{
- ocfs_recv_ctxt *recv_ctxt;
- __u8 *dlm_packet;
-
- LOG_ENTRY ();
-
- recv_ctxt = (ocfs_recv_ctxt *) val;
- dlm_packet = (__u8 *) recv_ctxt->msg;
-
- if (recv_ctxt->status >= 0) {
- if (ocfs_check_ipc_msg (dlm_packet, recv_ctxt->msg_len))
- ocfs_comm_process_msg (dlm_packet);
- }
-
- ocfs_safefree (recv_ctxt);
-
- LOG_EXIT ();
- return;
-} /* ocfs_dlm_recv_msg */
-
-/*
- * ocfs_comm_process_msg()
- *
- */
-int ocfs_comm_process_msg (__u8 * msg)
-{
- int status = 0;
- ocfs_super *osb = NULL;
- ocfs_dlm_msg *dlm_msg;
- __u64 nodemap;
- ocfs_dlm_req_master *req_master;
- struct list_head *iter_osb, *temp_iter;
- ocfs_vote_request_ctxt ctxt;
- __u32 src_node;
-
- LOG_ENTRY ();
-
- dlm_msg = (ocfs_dlm_msg *) msg;
-
- ocfs_down_sem (&(OcfsGlobalCtxt.res), true);
- list_for_each_safe (iter_osb, temp_iter, &(OcfsGlobalCtxt.osb_next)) {
- osb = list_entry (iter_osb, ocfs_super, osb_next);
- if (!memcmp (osb->vol_layout.vol_id, dlm_msg->vol_id,
- MAX_VOL_ID_LENGTH))
- break;
- osb = NULL;
- }
- ocfs_up_sem (&(OcfsGlobalCtxt.res));
-
- if (osb == NULL) {
- LOG_TRACE_STR("Ignoring netdlm message with invalid volume id");
- goto bail;
- }
-
- nodemap = (1 << dlm_msg->src_node);
- if (!(osb->publ_map & nodemap)) {
- LOG_TRACE_STR("Ignoring netdlm message from dead node");
- goto bail;
- }
-
- switch (dlm_msg->msg_type) {
- case OCFS_VOTE_REQUEST:
- ctxt.request_method = COMM_VOTE;
- ctxt.u.dlm_msg = dlm_msg;
- ctxt.node_num = dlm_msg->src_node;
- ctxt.status = 0;
- ocfs_process_vote (osb, &ctxt);
- break;
-
- case OCFS_VOTE_REPLY:
- ocfs_comm_process_vote_reply (osb, dlm_msg);
- break;
-
- case OCFS_INFO_DISMOUNT:
- src_node = dlm_msg->src_node;
- req_master = (ocfs_dlm_req_master *) dlm_msg->msg_buf;
- printk ("ocfs: Received dismount message for device (%u,%u) "
- "from %s (node %d)\n", MAJOR(osb->sb->s_dev),
- MINOR(osb->sb->s_dev), osb->node_cfg_info[src_node]->node_name,
- src_node);
- atomic_set (&(osb->vol_node_map.dismount[src_node]), 1);
- break;
-
- default:
- break;
- }
-
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_comm_process_msg */
-
-
-/*
- * ocfs_send_dismount_msg()
- *
- */
-int ocfs_send_dismount_msg (ocfs_super * osb, __u64 vote_map)
-{
- int status = 0;
- ocfs_dlm_msg *dlm_msg = NULL;
- __u32 msg_len;
- ocfs_dlm_msg_hdr *req;
-
- LOG_ENTRY_ARGS ("(osb=0x%08x, vm=0x%08x)\n", osb, LO(vote_map));
-
- msg_len = sizeof (ocfs_dlm_msg) - 1 + sizeof (ocfs_dlm_req_master);
-
- dlm_msg = ocfs_malloc (msg_len);
- if (dlm_msg == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto finally;
- }
-
- ocfs_init_dlm_msg (osb, dlm_msg, msg_len);
-
- dlm_msg->msg_type = OCFS_INFO_DISMOUNT;
-
- req = (ocfs_dlm_msg_hdr *) dlm_msg->msg_buf;
- req->lock_id = 0;
- req->flags = 0;
- req->lock_seq_num = 0;
- req->open_handle = 0;
-
- ocfs_send_bcast (osb, vote_map, dlm_msg);
-
-finally:
- ocfs_safefree (dlm_msg);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_send_dismount_msg */
More information about the Ocfs2-commits
mailing list