[Ocfs2-commits]
khackel commits r932 - in branches/new-dir-format/src: . inc
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Mon May 24 17:34:50 CDT 2004
Author: khackel
Date: 2004-05-24 16:34:48 -0500 (Mon, 24 May 2004)
New Revision: 932
Modified:
branches/new-dir-format/src/alloc.c
branches/new-dir-format/src/dcache.c
branches/new-dir-format/src/dir.c
branches/new-dir-format/src/dlm.c
branches/new-dir-format/src/file.c
branches/new-dir-format/src/hash.c
branches/new-dir-format/src/inc/io.h
branches/new-dir-format/src/inc/ocfs.h
branches/new-dir-format/src/inc/proto.h
branches/new-dir-format/src/inode.c
branches/new-dir-format/src/io.c
branches/new-dir-format/src/journal.c
branches/new-dir-format/src/lockres.c
branches/new-dir-format/src/namei.c
branches/new-dir-format/src/nm.c
branches/new-dir-format/src/osb.c
branches/new-dir-format/src/proc.c
branches/new-dir-format/src/super.c
branches/new-dir-format/src/util.c
Log:
first commit of the new directory stuff
cuz people were getting antsy ;-)
Modified: branches/new-dir-format/src/alloc.c
===================================================================
--- branches/new-dir-format/src/alloc.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/alloc.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -184,11 +184,9 @@
__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_free_rec *tmp_log;
- struct inode **dirnode_inode = NULL;
struct inode **extnode_inode = NULL;
struct inode *vol_inode = NULL;
__u32 tmp_indx;
@@ -206,20 +204,14 @@
} \
} 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_inode,
- OCFS_MAXIMUM_NODES * sizeof (struct inode *), status);
ALLOC_BLOCK(extnode_inode,
OCFS_MAXIMUM_NODES * sizeof (struct inode *), status);
/* init */
for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
- free_dir_node[i] = NULL;
free_ext_node[i] = NULL;
- dirnode_inode[i] = NULL;
extnode_inode[i] = NULL;
}
@@ -227,19 +219,6 @@
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;
@@ -293,28 +272,6 @@
/* 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) {
- dirnode_inode[i] = ocfs_iget(osb, lock_id, NULL);
- if (!dirnode_inode[i]) {
- status = -EINVAL;
- LOG_ERROR_STATUS (status);
- goto finally;
- }
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- NULL, dirnode_inode[i]);
- 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) {
@@ -364,10 +321,6 @@
/* 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);
@@ -395,21 +348,6 @@
}
}
- 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,
- NULL, dirnode_inode[i]);
- 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) {
@@ -431,8 +369,6 @@
for (i = 0; i < OCFS_MAXIMUM_NODES; i++) {
if (extnode_inode[i])
iput(extnode_inode[i]);
- if (dirnode_inode[i])
- iput(dirnode_inode[i]);
}
if (globalbh)
brelse(globalbh);
@@ -440,13 +376,11 @@
iput(vol_inode);
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_inode);
+
ocfs_safefree (extnode_inode);
ocfs_safefree (free_vol_bits);
@@ -520,28 +454,17 @@
ocfs_alloc_bm AllocBitmap;
ocfs_alloc_bm *tmpbitmap = NULL;
__u32 i;
- int needs_uninit = 0;
- int needs_unlock = 0;
LOG_ENTRY ();
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=%llu, file_off=%llu, type=%d, node_num=%d)\n", i, FreeLog->update[i].length, FreeLog->update[i].file_off, FreeLog->update[i].type, FreeLog->update[i].node_num);
+ LOG_TRACE_ARGS("(upd=%u, length=%llu, file_off=%llu, type=%d, node_num=%d)\n",
+ i, FreeLog->update[i].length, 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;
- blockSizeBits = osb->dir_alloc_bits;
-
- 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;
@@ -553,96 +476,73 @@
}
break;
- case DISK_ALLOC_VOLUME:
+ case DISK_ALLOC_INODE:
+ fileId = OCFS_INODE_BITMAP + NodeNum;
+ blockSize = (__u32) osb->inode_size;
+ blockSizeBits = osb->inode_alloc_bits;
break;
+ case DISK_ALLOC_VOLUME:
+ down (&(osb->vol_alloc_sem));
+ status = ocfs_free_main_bitmap(osb, FreeLog);
+ up (&(osb->vol_alloc_sem));
+ if (status < 0)
+ LOG_ERROR_STATUS (status);
+ goto leave;
default:
goto leave;
}
- if (Type == DISK_ALLOC_VOLUME) {
- down (&(osb->vol_alloc_sem));
- needs_unlock = 1;
+ if (!IS_VALID_NODE_NUM (NodeNum)) {
+ LOG_ERROR_STATUS(status = -EINVAL);
+ goto leave;
+ }
- /* don't need to read it here as
- * ocfs_free_main_bitmap handles that for us. */
- tmpbitmap = &osb->cluster_bitmap;
- } else {
- down(&(osb->node_alloc_sem));
- needs_unlock = 1;
+ down(&(osb->node_alloc_sem));
- /* 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 = 1;
- 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;
- }
-
+ /* 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) {
+ up (&(osb->node_alloc_sem));
+ 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 >>
- blockSizeBits);
- ocfs_clear_bits(tmpbitmap, (__u32) foundBit,
- (__u32) FreeLog->update[i].length);
- }
- }
+ ocfs_initialize_bitmap(&AllocBitmap, fileSize * 8, allocSize * 8);
+ tmpbitmap = &AllocBitmap;
+ bitmapblocks = (OCFS_ALIGN(tmpbitmap->validbits, OCFS_BITS_IN_CHUNK) / OCFS_BITS_IN_CHUNK);
- /* ocfs_free_main_bitmap handles all the reads/writes for the
- * main bitmap */
- if (Type != DISK_ALLOC_VOLUME) {
- /* we don't know which blocks we've changed and which
- * haven't, so just write them all out */
- for(i = 0; i < bitmapblocks; i++) {
- OCFS_BH_GET_DATA_WRITE(tmpbitmap->chunk[i]);
- OCFS_BH_PUT_DATA(tmpbitmap->chunk[i]);
- }
- status = ocfs_write_bhs(osb, tmpbitmap->chunk, bitmapblocks,
- 0, NULL);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
+ status = ocfs_read_system_file(osb, fileId, AllocBitmap.chunk,
+ bitmapblocks * osb->sect_size,
+ offset);
+ if (status < 0) {
+ up (&(osb->node_alloc_sem));
+ LOG_ERROR_STATUS (status);
+ goto leave;
}
-leave:
- if (needs_unlock) {
- if (Type == DISK_ALLOC_VOLUME)
- up (&(osb->vol_alloc_sem));
- else
- up (&(osb->node_alloc_sem));
+
+ for (i = 0; i < FreeLog->num_updates; i++) {
+ foundBit = (__u32) (FreeLog->update[i].file_off >> blockSizeBits);
+ ocfs_clear_bits(tmpbitmap, (__u32) foundBit,
+ (__u32) FreeLog->update[i].length);
}
- if (needs_uninit)
+ /* we don't know which blocks we've changed and which
+ * haven't, so just write them all out */
+ for(i = 0; i < bitmapblocks; i++) {
+ OCFS_BH_GET_DATA_WRITE(tmpbitmap->chunk[i]);
+ OCFS_BH_PUT_DATA(tmpbitmap->chunk[i]);
+ }
+ status = ocfs_write_bhs(osb, tmpbitmap->chunk, bitmapblocks,
+ 0, NULL);
+ if (status < 0)
+ LOG_ERROR_STATUS (status);
+
+ up (&(osb->node_alloc_sem));
+
+leave:
+ if (tmpbitmap)
ocfs_uninitialize_bitmap(tmpbitmap);
LOG_EXIT_STATUS (status);
@@ -2471,7 +2371,7 @@
__u64 cnt;
__u32 NumIndex;
- LOG_ENTRY ();
+ LOG_ENTRY_ARGS("(vbo=%llu, sectors=%u, inode=%llu)\n", Vbo, sectors, GET_INODE_FEOFF(inode));
OCFS_ASSERT (osb);
OCFS_ASSERT (inode);
@@ -2937,20 +2837,24 @@
LOG_ENTRY_ARGS("(FileSize = (%llu), Type=%d)\n", FileSize,Type);
- if (Type == DISK_ALLOC_DIR_NODE) {
- bm_file = OCFS_FILE_DIR_ALLOC_BITMAP + NodeNum;
- blockSize = (__u32) osb->vol_layout.dir_node_size;
- blockSizeBits = osb->dir_alloc_bits;
- alloc_file = OCFS_FILE_DIR_ALLOC + NodeNum;
-
- atomic_inc(&osb->alloc_stats.dir_allocs);
- } else if (Type == DISK_ALLOC_EXTENT_NODE) {
- bm_file = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
- alloc_file = OCFS_FILE_FILE_ALLOC + NodeNum;
- blockSize = (__u32) osb->vol_layout.file_node_size;
- blockSizeBits = osb->file_alloc_bits;
-
- atomic_inc(&osb->alloc_stats.ext_allocs);
+ switch (Type) {
+ case DISK_ALLOC_EXTENT_NODE:
+ bm_file = OCFS_FILE_FILE_ALLOC_BITMAP + NodeNum;
+ alloc_file = OCFS_FILE_FILE_ALLOC + NodeNum;
+ blockSize = (__u32) osb->vol_layout.file_node_size;
+ blockSizeBits = osb->file_alloc_bits;
+ atomic_inc(&osb->alloc_stats.ext_allocs);
+ break;
+ case DISK_ALLOC_INODE:
+ bm_file = OCFS_INODE_BITMAP + NodeNum;
+ alloc_file = OCFS_INODE_FILE + NodeNum;
+ blockSize = (__u32) osb->inode_size;
+ blockSizeBits = osb->inode_alloc_bits;
+ break;
+ default:
+ status = -EINVAL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
}
/* Allocate a block of size blocksize from the relevant file/bitmap */
@@ -3074,10 +2978,7 @@
foundBit = prevFileSize * 8;
delay_lockrel = 1;
-
- if (Type == DISK_ALLOC_DIR_NODE)
- atomic_inc(&osb->alloc_stats.dir_extends);
- else
+ if (Type == DISK_ALLOC_EXTENT_NODE)
atomic_inc(&osb->alloc_stats.ext_extends);
}
@@ -3143,74 +3044,6 @@
} /* ocfs_alloc_node_block */
/*
- * ocfs_free_directory_block()
- *
- */
-int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe,
- ocfs_journal_handle *handle,
- struct inode *inode)
-{
- int status = 0;
- struct buffer_head *dir_hdr_bh = NULL;
- ocfs_dir_node *dirnode = NULL;
- __u64 currentDirNode;
-
- LOG_ENTRY ();
-
- currentDirNode = fe->u.child_dirnode;
-
- 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_READ(dir_hdr_bh); /* read */
-
- while ((dirnode->node_disk_off != INVALID_NODE_POINTER) &&
- (IS_VALID_DIR_NODE (dirnode))) {
-
- status = ocfs_handle_add_commit_bits(handle, 1,
- dirnode->alloc_file_off,
- dirnode->alloc_node,
- DISK_ALLOC_DIR_NODE);
-
- currentDirNode = dirnode->next_node_ptr;
- OCFS_BH_PUT_DATA(dir_hdr_bh);
- dir_hdr_bh = NULL;
- dirnode = NULL;
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- 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_READ(dir_hdr_bh); /* read */
- 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()
*
*/
@@ -3415,51 +3248,6 @@
goto bail;
}
OCFS_BH_PUT_DATA(local_alloc_bh);
-
- if (bm_lock_bh) {
- local_lock = 0;
- bh = bm_lock_bh;
- }
-
- if (bm_inode) {
- atomic_inc(&bm_inode->i_count);
- local_inode = bm_inode;
- } else {
- local_inode = ocfs_iget(osb, OCFS_BITMAP_LOCK_OFFSET, NULL);
- if (!local_inode) {
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
-
- if (local_lock) {
- down (&(osb->vol_alloc_sem));
-
- /* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- (in_recovery) ? FLAG_FILE_RECOVERY
- : 0, &bh, local_inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto bail;
- }
- got_lock = 1;
- }
-
- 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 = ocfs_alloc_bitmap_free_head();
if (*f == NULL) {
@@ -3500,24 +3288,6 @@
OCFS_BH_PUT_DATA(local_alloc_bh);
bail:
- if (local_lock) {
- up (&(osb->vol_alloc_sem));
-
- if (got_lock) {
- tmpstat = ocfs_release_lock (osb,
- OCFS_BITMAP_LOCK_OFFSET,
- OCFS_DLM_EXCLUSIVE_LOCK,
- 0, bh, local_inode);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
- }
- if (bh != NULL)
- brelse(bh);
- }
-
- if (local_inode)
- iput(local_inode);
-
LOG_EXIT_STATUS(status);
return(status);
} /* ocfs_sync_local_to_main */
@@ -3997,7 +3767,7 @@
else
bh = osb->local_alloc_bh;
- status = ocfs_sync_local_to_main(osb, &f, NULL, NULL, NULL,
+ status = ocfs_sync_local_to_main(osb, &f, bh, NULL, NULL,
in_recovery);
if (status < 0)
LOG_ERROR_STATUS(status);
Modified: branches/new-dir-format/src/dcache.c
===================================================================
--- branches/new-dir-format/src/dcache.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/dcache.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -58,16 +58,15 @@
OCFS_ASSERT(osb);
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+ if (inode == osb->root_inode) {
ret = 1;
goto bail;
}
/* did we or someone else delete this inode? */
if (INODE_DELETED(inode)) {
- LOG_TRACE_ARGS("dentry_revalidate: inode %lu (%llu) deleted, "
- "returning false\n", inode->i_ino,
- GET_INODE_FEOFF(inode));
+ LOG_TRACE_ARGS("dentry_revalidate: inode (%llu) deleted, "
+ "returning false\n", GET_INODE_FEOFF(inode));
goto bail;
}
Modified: branches/new-dir-format/src/dir.c
===================================================================
--- branches/new-dir-format/src/dir.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/dir.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -28,173 +28,154 @@
#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_DIR
-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 int 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, int sync);
-static int 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
+static unsigned char ocfs_filetype_table[] = {
+ DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK
+};
/*
* ocfs_readdir()
*
*/
-int ocfs_readdir (struct file *filp, void *dirent, filldir_t filldir)
+int ocfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
- int pos;
- struct super_block *sb;
- ocfs_super *osb;
- ocfs_file *ofile;
- struct buffer_head *entry_bh = NULL;
- ocfs_file_entry *entry = NULL;
- int ret = 0;
+ int error = 0;
+ unsigned long offset, blk;
+ int i, num, stored;
+ struct buffer_head * bh, * tmp, * bha[16];
+ struct ocfs2_dir_entry * de;
+ int err;
struct inode *inode = filp->f_dentry->d_inode;
+ struct super_block * sb = inode->i_sb;
+ char *buf = NULL;
- LOG_ENTRY_ARGS ("(0x%p, 0x%p, '%*s')\n", filp, dirent,
- filp->f_dentry->d_name.len, filp->f_dentry->d_name.name);
+ LOG_ENTRY_ARGS("dirino=%llu\n", GET_INODE_FEOFF(inode));
- pos = filp->f_pos;
- sb = inode->i_sb;
- osb = OCFS_SB(sb);
+ stored = 0;
+ bh = NULL;
+ offset = filp->f_pos & (sb->s_blocksize - 1);
- if (!osb) {
- LOG_TRACE_STR ("Invalid OSB");
- goto bail;
- }
+ while (!error && !stored && filp->f_pos < inode->i_size) {
+ blk = (filp->f_pos) >> OCFS_SB(sb)->sect_size_bits;
+ bh = ocfs_bread (0, inode, blk, 0, &err, 0);
+ if (!bh) {
+ LOG_ERROR_ARGS ("directory #%llu contains a hole at offset %lu\n",
+ GET_INODE_FEOFF(inode), (unsigned long)filp->f_pos);
+ filp->f_pos += sb->s_blocksize - offset;
+ continue;
+ }
- if (!S_ISDIR (inode->i_mode)) {
- LOG_TRACE_STR ("Not a dir");
- ret = -ENOTDIR;
- goto bail;
- }
+ /*
+ * Do the readahead (8k)
+ */
+ if (!offset) {
+ for (i = 16 >> (OCFS_SB(sb)->sect_size_bits - 9), num = 0;
+ i > 0; i--) {
+ tmp = ocfs_bread (NULL, inode, ++blk, 0, &err, 1);
+ brelse (tmp);
+ }
+ }
- 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;
- }
- }
+ if (buf) {
+#warning take this out later
+ LOG_ERROR_ARGS("uhoh! buf not null... block=%lu\n", bh->b_blocknr);
+ BUG();
+ }
+ buf = OCFS_BH_GET_DATA_READ(bh); /* read */
+revalidate:
+ /* If the dir block has changed since the last call to
+ * readdir(2), then we might be pointing to an invalid
+ * dirent right now. Scan from the start of the block
+ * to make sure. */
+ if (filp->f_version != inode->i_version) {
+ for (i = 0; i < sb->s_blocksize && i < offset; ) {
+ de = (struct ocfs2_dir_entry *) (bh->b_data + i);
+ /* It's too expensive to do a full
+ * dirent test each time round this
+ * loop, but we do have to test at
+ * least that it is non-zero. A
+ * failure will be detected in the
+ * dirent test below. */
+ if (le16_to_cpu(de->rec_len) <
+ OCFS_DIR_REC_LEN(1))
+ break;
+ i += le16_to_cpu(de->rec_len);
+ }
+ offset = i;
+ filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
+ | offset;
+ filp->f_version = inode->i_version;
+ }
- ofile = (ocfs_file *) filp->private_data;
- while (1) {
- int r;
- ino_t ino;
- __u64 voteoff;
- /* 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 {
- r = ocfs_find_files_on_disk (osb, NULL, &entry_bh,
- ofile, inode, 1);
- if (r < 0)
- break;
- entry = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(entry_bh); /* read */
-
- voteoff = entry->this_sector;
- ino = ocfs_inode_hash_lookup_ino(osb, voteoff);
- r=filldir (dirent, entry->filename, strlen (entry->filename), filp->f_pos, ino, DT_UNKNOWN);
- if (r < 0) {
- memcpy(ofile->filldir.fname, entry->filename, OCFS_MAX_FILENAME_LENGTH);
- ofile->filldir.pos = filp->f_pos;
- ofile->filldir.ino = ino;
- }
- OCFS_BH_PUT_DATA(entry_bh);
- brelse(entry_bh);
- entry_bh = NULL; entry = NULL;
- if (r < 0)
- goto bail;
- }
- pos++;
- filp->f_pos++;
- }
-
- break;
- }
+ while (!error && filp->f_pos < inode->i_size
+ && offset < sb->s_blocksize) {
+ de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
+ if (!ocfs_check_dir_entry (inode, de, bh, offset)) {
+ /* On error, skip the f_pos to the
+ next block. */
+ filp->f_pos = (filp->f_pos |
+ (sb->s_blocksize - 1)) + 1;
+ if (buf) {
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ }
+ brelse (bh);
+ return stored;
+ }
+ offset += le16_to_cpu(de->rec_len);
+ if (le64_to_cpu(de->inode)) {
+ /* We might block in the next section
+ * if the data destination is
+ * currently swapped out. So, use a
+ * version stamp to detect whether or
+ * not the directory has been modified
+ * during the copy operation.
+ */
+ unsigned long version = filp->f_version;
+ unsigned char d_type = DT_UNKNOWN;
+
+ if (de->file_type < OCFS_FT_MAX)
+ d_type = ocfs_filetype_table[de->file_type];
+ error = filldir(dirent, de->name,
+ de->name_len,
+ filp->f_pos,
+ ino_from_off(sb, le64_to_cpu(de->inode)),
+ d_type);
+ if (error)
+ break;
+ if (version != filp->f_version)
+ goto revalidate;
+ stored ++;
+ }
+ filp->f_pos += le16_to_cpu(de->rec_len);
+ }
+ if (buf) {
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ }
+ offset = 0;
+ brelse (bh);
}
+ UPDATE_ATIME(inode);
+ LOG_EXIT_STATUS(0);
+ return 0;
+}
-bail:
- if (entry_bh) {
- if (entry)
- OCFS_BH_PUT_DATA(entry_bh);
- brelse(entry_bh);
- }
- LOG_EXIT_INT (ret);
- return ret;
-} /* ocfs_readdir */
/* ocfs_find_files_on_disk()
* NOTE: this should always be called with inode->i_sem taken!
*/
/* parent off changed to file entry offset of parent! */
-int ocfs_find_files_on_disk (ocfs_super * osb, struct qstr * file_name, struct buffer_head ** fe_bh, ocfs_file * ofile, struct inode *inode, int take_lock)
+int ocfs_find_files_on_disk (ocfs_super * osb, struct dentry * dentry, struct buffer_head ** fe_bh, struct inode *inode, struct inode *file_inode, int take_lock, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent)
{
int status = -ENOENT;
- __u64 thisDirNode;
int tmpstat;
- int temp_bhs = 0;
int lock_acq = 0;
- int sync = 1;
struct buffer_head *bh = NULL;
- struct buffer_head **bhs = NULL;
- int bufsz, nbhs, i;
__u32 lock_type = OCFS_DLM_ENABLE_CACHE_LOCK;
__u64 parent_off = GET_INODE_FEOFF(inode);
+
+ LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, dentry=%p, fe_bh=%p, inode=%p)\n", osb, parent_off, dentry, fe_bh, inode);
- LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, fname=%p, fe_bh=%p, ofile=%p, inode=%p)\n", osb, parent_off, file_name, fe_bh, ofile, inode);
-
- nbhs = osb->vol_layout.dir_node_size >> osb->sect_size_bits;
- bufsz = nbhs * (sizeof(struct buffer_head *));
-
- thisDirNode = OCFS_I(inode)->u.child_dirnode;
- if (ofile == NULL) {
- temp_bhs = 1;
- bhs = ocfs_malloc (bufsz);
- if (bhs == NULL) {
- temp_bhs = 0;
- 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);
-
- sync = 0;
if (take_lock) {
/* Get a lock on the directory... */
status = ocfs_acquire_lock (osb, parent_off, lock_type, FLAG_DIR|FLAG_READDIR,
@@ -206,33 +187,19 @@
goto leave;
}
lock_acq = 1;
- // used to set sync if not locally owned
- // should not need to anymore...
- // sync = 1;
}
- if (bhs[0]==NULL || bhs[0]->b_blocknr != (thisDirNode >> osb->sect_size_bits)) {
- for (i=0; i<nbhs; i++) {
- if (bhs[i]) {
- brelse(bhs[i]);
- bhs[i]=NULL;
- }
- }
- status = ocfs_read_dirnode(osb, thisDirNode, sync, &bhs[0], inode);
- if (status < 0) {
- /* Volume should be disabled in this case */
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
+ status = -ENOENT;
+ *dirent_bh = ocfs_find_entry (dentry, dirent);
+ if (!*dirent_bh || !*dirent)
+ 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, sync))
+ status = ocfs_read_bh(osb, (*dirent)->inode, fe_bh, OCFS_BH_CACHED, file_inode);
+ if (status < 0) {
+ brelse(*dirent_bh);
+ LOG_ERROR_STATUS(status);
status = -ENOENT;
-
+ }
leave:
if (take_lock && lock_acq)
@@ -247,1078 +214,81 @@
if (bh != NULL)
brelse(bh);
-
- /* 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);
+ if (status < 0) {
+ *dirent = NULL;
+ if (*dirent_bh) {
+ brelse(*dirent_bh);
+ *dirent_bh = NULL;
+ }
}
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 */
-
/*
- * ocfs_write_dir_node()
- *
+ * routine to check that the specified directory is empty (for rmdir)
*/
-static int ocfs_write_dir_node (ocfs_super * osb, struct buffer_head *bhs[], __s32 idx, struct inode *dir_inode, struct inode *file_inode)
+int empty_dir (struct inode * inode)
{
- int status = 0;
- __u64 offset;
- ocfs_dir_node *DirNode = NULL;
- ocfs_file_entry *fe = NULL;
- int sync_fe_write = 0;
-
- LOG_ENTRY ();
+ unsigned long offset;
+ struct buffer_head * bh;
+ struct ocfs2_dir_entry * de, * de1;
+ struct super_block * sb;
+ int err;
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bhs[0]); /* read */
-
- offset = DirNode->node_disk_off + ((idx + 1) * osb->sect_size);
-
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (idx != -1) {
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA_READ(bhs[idx+1]); /* read */
-
- if(!IS_VALID_FILE_ENTRY(fe)) {
- OCFS_BH_PUT_DATA(bhs[idx+1]);
- status = -EIO; // ???
- goto bail;
- }
-
- sync_fe_write = 1;
-
- OCFS_BH_PUT_DATA(bhs[idx+1]);
+ sb = inode->i_sb;
+ if (inode->i_size < OCFS_DIR_REC_LEN(1) + OCFS_DIR_REC_LEN(2) ||
+ !(bh = ocfs_bread (NULL, inode, 0, 0, &err, 0))) {
+ LOG_ERROR_ARGS ("bad directory (dir #%llu) - no data block\n",
+ GET_INODE_FEOFF(inode));
+ return 1;
}
- /* Write the file entry at idx, if given */
- if (sync_fe_write) {
- status = ocfs_write_bh (osb, bhs[idx+1], 0, file_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
+ de = (struct ocfs2_dir_entry *) OCFS_BH_GET_DATA_READ(bh);
+ de1 = (struct ocfs2_dir_entry *)
+ ((char *) de + le16_to_cpu(de->rec_len));
+ if (le64_to_cpu(de->inode) != GET_INODE_FEOFF(inode) ||
+ !le64_to_cpu(de1->inode) ||
+ strcmp (".", de->name) ||
+ strcmp ("..", de1->name)) {
+ LOG_ERROR_ARGS ("bad directory (dir #%llu) - no `.' or `..'\n",
+ GET_INODE_FEOFF(inode));
+ OCFS_BH_PUT_DATA(bh);
+ brelse (bh);
+ return 1;
}
-
- /* Write the first sector last */
- status = ocfs_write_bh (osb, bhs[0], 0, dir_inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
-
-bail:
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_write_dir_node */
-
-
-/*
- * ocfs_search_dir_node()
- *
- */
-static int 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, int sync)
-{
- __u32 start;
- __u32 i;
- ocfs_file_entry *fe;
- int status;
- int ret = 0;
- ocfs_dir_node * DirNode = NULL, *tmp;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *) ocfs_malloc(osb->sect_size);
- if (DirNode == NULL) {
- LOG_ERROR_STR("Out of memory");
- ret = 0;
- goto bail;
- }
-
- tmp = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bhs[0]); /* read */
- memcpy(DirNode, tmp, osb->sect_size);
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (OFile != NULL)
- start = OFile->curr_byte_off;
- else
- start = 0;
-
-
- if (!IS_VALID_DIR_NODE (DirNode)) {
- LOG_TRACE_STR("Invalid Dir Node!\n");
- ret = 0;
- goto bail;
- }
-
- while (1) {
- /* Iterate thru this dirnode and find a matching entry */
- for (i = start; i < DirNode->num_ent_used; i++) {
- int found = 1;
-
- if (SearchName != NULL) {
- found = ocfs_find_index (osb, bhs, SearchName, (int *) &i);
- }
-
- if (found) {
- fe = FILEENT_GETBH(DirNode, bhs, i); /* read */
-
- 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;
- }
- ret = 1;
- 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_dirnode(osb, next, sync, bhs, dir_inode);
- if (status < 0) {
- LOG_ERROR_STR("failed to read directory");
- ret = 0;
- goto bail;
- }
-
- tmp = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bhs[0]); /* read */
- memcpy(DirNode, tmp, osb->sect_size);
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (!IS_VALID_DIR_NODE (DirNode)) {
- LOG_TRACE_STR("Invalid Dir Node!\n");
- ret = 0;
- 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_INT (ret);
- return ret;
-} /* ocfs_search_dir_node */
-
-
-/*
- * ocfs_find_index()
- *
- * Locks the dirnode bh, and then only one fe at a time.
- */
-static int 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 = 0;
- struct qstr q;
- ocfs_dir_node * DirNode = NULL;
-
- LOG_ENTRY ();
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bhs[0]); /* read */
- if (!IS_VALID_DIR_NODE (DirNode) || FileName==NULL) {
- ret = 0;
- 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); /* read */
-
- if ((fe->sync_flags & OCFS_SYNC_FLAG_NAME_DELETED) ||
- (!(fe->sync_flags & OCFS_SYNC_FLAG_VALID))) {
- FILEENT_PUTBH(DirNode, bhs, index);
+ offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len);
+ de = (struct ocfs2_dir_entry *) ((char *) de1 + le16_to_cpu(de1->rec_len));
+ while (offset < inode->i_size ) {
+ if (!bh || (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+ OCFS_BH_PUT_DATA(bh);
+ brelse (bh);
+ bh = ocfs_bread (NULL, inode, offset >> sb->s_blocksize_bits, 0, &err, 0);
+ if (!bh) {
+ LOG_ERROR_ARGS ("directory #%llu contains a hole at offset %lu\n",
+ GET_INODE_FEOFF(inode), offset);
+ offset += sb->s_blocksize;
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 = 1;
- goto bail;
- }
+ de = (struct ocfs2_dir_entry *) OCFS_BH_GET_DATA_READ(bh);
}
- *Index = index;
- ret = 0;
- goto bail;
- }
-
- for (lowBnd = start, upBnd = (DirNode->num_ent_used - start); upBnd; upBnd >>= 1) {
- index = lowBnd + (upBnd >> 1);
- fe = FILEENT_GETBH(DirNode, bhs, index); /* read */
-
- 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); /* read */
- 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 = 1;
- goto bail;
- }
- if (res < 0) {
- *Index = index;
- ret = 0;
- goto bail;
- }
- }
- *Index = lowBnd + upBnd - 1;
- ret = 0;
- goto bail;
+ if (!ocfs_check_dir_entry (inode, de, bh, offset)) {
+ OCFS_BH_PUT_DATA(bh);
+ brelse (bh);
+ return 1;
}
-
- 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 = 1;
- goto bail;
+ if (le64_to_cpu(de->inode)) {
+ OCFS_BH_PUT_DATA(bh);
+ brelse (bh);
+ return 0;
}
-
- if (res > 0) {
- lowBnd = index + 1;
- --upBnd;
- }
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ocfs2_dir_entry *)
+ ((char *) de + le16_to_cpu(de->rec_len));
}
-
- *Index = index;
-
-bail:
- if (DirNode)
- OCFS_BH_PUT_DATA(bhs[0]);
- LOG_EXIT_INT (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 = NULL;
- 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 >> osb->sect_size_bits;
- bufsz = nbhs * (sizeof(struct buffer_head *));
-
- if (bhs == NULL) {
- arr = ocfs_malloc (bufsz);
- if (arr == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- memset(arr, 0, bufsz);
- status = ocfs_read_dirnode(osb, DirNodeOffset, 0, arr, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- } else
- arr = bhs;
-
- dir = (ocfs_dir_node *)OCFS_BH_GET_DATA_WRITE(arr[0]); /* write */
- 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;
-
- /* To preserve locking order, (we only want to lock 1
- * fe at a time, in incremental order), we copy this
- * one off. */
- target = ocfs_allocate_file_entry();
- if (target == NULL) {
- OCFS_BH_PUT_DATA(arr[0]);
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto leave;
- }
- memcpy(target, OCFS_BH_GET_DATA_READ(arr[offset+1]),
- sizeof(ocfs_file_entry)); /* read */
- OCFS_BH_PUT_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); /* read */
-
- 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);
- }
-
- 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]);
- } else
- OCFS_BH_PUT_DATA(arr[0]);
-
-leave:
- if (bhs == NULL)
- ocfs_safefree (arr);
- if (target)
- ocfs_release_file_entry(target);
-
- 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_WRITE(bhs[0]); /* write */
-
- 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_WRITE(bhs[0]); /* write */
- }
-
- /* 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_WRITE(bhs[0]); /* write */
-
- if (index < DirNode->num_ent_used) {
- fe = FILEENT_GETBH(DirNode, bhs, index); /* read */
-
- 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_READ(bhs[freeOffset+1]); /* read */
- 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;
- }
-
- set_buffer_uptodate(bhs[freeOffset+1]);
- status = ocfs_journal_access(handle, bhs[freeOffset+1],
- OCFS_JOURNAL_ACCESS_CREATE);
- 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_WRITE(bhs[freeOffset+1]); /* write */ /* journal access */
- 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) * osb->sect_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;
- 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);
-
- /* briefly grab LockNode and get useful bits of info. */
- LockNode = (ocfs_dir_node *) OCFS_BH_GET_DATA_READ(lockbh); /* read */
- if (!IS_VALID_DIR_NODE(LockNode))
- BUG();
-
- 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;
- }
-
- EntryToDel = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(febh); /* write */
-
- /* 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) {
- dirbhs[0] = lockbh;
- } else {
- 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, dirbhs[0],
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- }
- PDirNode = (ocfs_dir_node *) OCFS_BH_GET_DATA_WRITE(dirbhs[0]); /* write */ /* journal access */
- parent_off = PDirNode->node_disk_off;
- offset= ((EntryToDel->this_sector - parent_off) >> osb->sect_size_bits) - 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 >> osb->sect_size_bits)) {
- LOG_TRACE_STR("febh->b_blocknr != (EntryToDel->this_sector >> osb->sect_size_bits)");
- 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_WRITE(lockbh); /* write */ /* journal access */
- if (LockNode->head_del_ent_node == INVALID_NODE_POINTER)
- 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;
- }
- 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 **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;
- int parent_is_lock_node;
- struct buffer_head **bhs = NULL;
- const int numbhs = 256;
- const int length = numbhs * sizeof(struct buffer_head *);
- int i = 0;
- int dirtyall = 0;
- void *buf;
- __u64 locknode_off, dir_next_node, new_head_del = 0;
- __u64 locknode_head_del;
- __u8 dir_num_ent_used;
- unsigned long blk;
- struct buffer_head *lock_bh = NULL;
-
- 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. */
-
- dir_off = OCFS_I(dir_inode)->u.child_dirnode;
- status = ocfs_read_bh(osb, dir_off, &lock_bh, OCFS_BH_CACHED,
- dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- /* 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;
- }
- 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_READ(lock_bh); /* read */
- if (!IS_VALID_DIR_NODE(LockNode)) {
- LOG_ERROR_STR ("Invalid dir node");
- status = -EFAIL;
- goto leave;
- }
-
- locknode_off = LockNode->node_disk_off;
- locknode_head_del = LockNode->head_del_ent_node;
-
- LOG_TRACE_ARGS("ocfs_insert_file: head_del=%llu, free_node=%llu, locknode=%llu\n",
- LockNode->head_del_ent_node, LockNode->free_node_ptr,
- 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 %llu\n", 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_dirnode(osb, dir_off, 0, bhs, 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_READ(bhs[0]); /* read */
- 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_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 %llu\n", dir_off);
- status = ocfs_read_dirnode(osb, dir_off, 0, bhs, dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- DirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(bhs[0]); /* read */
- 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 %llu 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 %llu is %llu\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_READ(bhs[0]); /* read */
- dir_num_ent_used = DirNode->num_ent_used;
- dir_next_node = DirNode->next_node_ptr;
- 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;
- }
-
- /* we always want to mark lock_bh at least once as it's going
- * to the journal, so leave this get_data_write outside of the
- * if statement. */
- LockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_WRITE(lock_bh); /* write */ /* journal access */
- if (new_head_del != 0)
- 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_dirnode(osb, dir_next_node, 0, newbhs, 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");
-
- down(&osb->node_alloc_sem);
- status = ocfs_alloc_node_block(osb,
- osb->vol_layout.dir_node_size,
- &bitmapOffset, &fileOffset,
- osb->node_num,
- DISK_ALLOC_DIR_NODE, handle);
- up(&osb->node_alloc_sem);
- if (status < 0) {
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
-
- dirtyall = 1;
- blk = (unsigned long)(bitmapOffset >> osb->sect_size_bits);
- for (i = 0; i < numbhs; i++) {
- newbhs[i] = getblk(OCFS_GET_BLOCKDEV(osb->sb),
- blk++,
- osb->sb->s_blocksize);
- set_buffer_uptodate(newbhs[i]);
- /* clear all 128k, all garbage currently */
- status = ocfs_journal_access(handle, newbhs[i],
- OCFS_JOURNAL_ACCESS_CREATE);
- if (status < 0) {
- while (i >= 0)
- brelse(newbhs[i--]);
- ocfs_safefree(newbhs);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- buf = OCFS_BH_GET_DATA_WRITE(newbhs[i]); /* write */
- memset(buf, 0, osb->sect_size);
- OCFS_BH_PUT_DATA(newbhs[i]);
- }
- pNewDirNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_WRITE(newbhs[0]); /* write */
- 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_WRITE(newbhs[0]); /* write */
- new_disk_off = pNewDirNode->node_disk_off;
- 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_WRITE(lock_bh); /* write */
- 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_WRITE(bhs[0]); /* write */
- 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);
- }
-
- if (lock_bh)
- brelse(lock_bh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_insert_file */
+ OCFS_BH_PUT_DATA(bh);
+ brelse (bh);
+ return 1;
+}
Modified: branches/new-dir-format/src/dlm.c
===================================================================
--- branches/new-dir-format/src/dlm.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/dlm.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -1120,8 +1120,8 @@
}
}
- LOG_ERROR_ARGS("DISKVOTE!!: lock_type=%u, flags=%08x, offset=%llu, inode=%lu\n",
- lock_type, flags, lock_id, inode?inode->i_ino:0);
+ LOG_ERROR_ARGS("DISKVOTE!!: lock_type=%u, flags=%08x, offset=%llu, inode=%llu\n",
+ lock_type, flags, lock_id, inode?GET_INODE_FEOFF(inode):0ULL);
LOG_ERROR_ARGS("DISKVOTE!!: this=%d, master=%d, locktype=%d, ronode=%d, romap=%08x\n",
osb->node_num, lockres->master_node_num, lockres->lock_type,
lockres->readonly_node, (__u32)(lockres->readonly_map & 0xFFFFFFFFULL));
@@ -1217,8 +1217,8 @@
if (OCFS_BH_GET_DATA_WRITE_TRYLOCK(bh) == NULL) {
tries++;
ocfs_release_lockres(lockres); // ocfs_release_lock
- LOG_ERROR_ARGS("failed to get bh sem (%llu), attempt %d, trying again\n",
- (unsigned long long)bh->b_blocknr, tries);
+ LOG_ERROR_ARGS("failed to get bh sem (%lu), attempt %d, trying again\n",
+ bh->b_blocknr, tries);
ocfs_sleep(100);
goto again;
}
@@ -1300,7 +1300,7 @@
int tmpstat;
ocfs_file_entry *fe = NULL;
__u64 lock_id;
- __u32 lock_write_flags = DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK;
+ __u32 lock_write_flags = DLOCK_FLAG_MASTER | DLOCK_FLAG_LOCK | DLOCK_FLAG_OPEN_MAP;
__u32 lock_type = requested_lock;
int need_to_zap_buffers = 0, need_lock_write = 1;
int is_readdir = (flags & FLAG_READDIR) ? 1 : 0;
@@ -1391,8 +1391,8 @@
}
- LOG_ERROR_ARGS("DISKVOTE!!: req_lock=%u, flags=%08x, offset=%llu, inode=%lu\n",
- requested_lock, flags, lock_id, inode?inode->i_ino:0);
+ LOG_ERROR_ARGS("DISKVOTE!!: req_lock=%u, flags=%08x, offset=%llu, inode=%llu\n",
+ requested_lock, flags, lock_id, inode?GET_INODE_FEOFF(inode):0ULL);
LOG_ERROR_ARGS("DISKVOTE!!: this=%d, master=%d, locktype=%d, ronode=%d, romap=%08x\n",
osb->node_num, lockres->master_node_num, lockres->lock_type,
lockres->readonly_node, (__u32)(lockres->readonly_map & 0xFFFFFFFFULL));
Modified: branches/new-dir-format/src/file.c
===================================================================
--- branches/new-dir-format/src/file.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/file.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -119,7 +119,7 @@
OCFS_BH_PUT_DATA(fe_bh);
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER)
+ if (inode == osb->root_inode)
goto leave;
if (local_handle) {
@@ -194,13 +194,6 @@
down (&(OCFS_I(inode)->priv_sem));
have_oin_sem = 1;
- if (OCFS_I(inode)->oin_flags & OCFS_OIN_DELETE_ON_CLOSE) {
- LOG_ERROR_STR ("oin deleted");
- up(&inode->i_sem);
- status = -ENOENT;
- goto leave;
- }
-
/* first open, we've gotta update the lock state. */
if (!OCFS_I(inode)->open_hndl_cnt) {
status = ocfs_read_bh(osb, GET_INODE_FEOFF(inode), &fe_bh,
@@ -338,7 +331,6 @@
*/
int ocfs_file_release (struct inode *inode, struct file *file)
{
- ocfs_file *ofile = NULL;
ocfs_super * osb;
struct dentry *dentry;
int last_close = 0;
@@ -348,32 +340,11 @@
dentry = file->f_dentry;
- if (file->private_data)
- ofile = (ocfs_file *) file->private_data;
-
osb = OCFS_SB(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 >> osb->sect_size_bits;
- 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;
- }
- ocfs_release_ofile (ofile);
- }
goto bail;
}
@@ -382,7 +353,7 @@
if (!OCFS_I(inode)->open_hndl_cnt)
last_close = 1;
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+ if (inode == osb->root_inode) {
up (&(OCFS_I(inode)->priv_sem));
goto bail;
}
@@ -409,9 +380,9 @@
down(&recovery_list_sem);
spin_lock(&oin_num_ext_lock);
if (OCFS_I(inode)->num_extends) {
- LOG_TRACE_ARGS("ocfs2: closing inode %lu -- had %u "
+ LOG_TRACE_ARGS("ocfs2: closing inode %llu -- had %u "
"extends pending from another node!\n",
- inode->i_ino,
+ GET_INODE_FEOFF(inode),
OCFS_I(inode)->num_extends);
OCFS_I(inode)->num_extends = 0;
list_del(&OCFS_I(inode)->recovery_list);
@@ -1558,7 +1529,7 @@
goto bail;
osb = OCFS_SB(inode->i_sb);
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER)
+ if (inode == osb->root_inode)
goto bail;
/* yay, locking hell! Why do we hit disk for this?! */
Modified: branches/new-dir-format/src/hash.c
===================================================================
--- branches/new-dir-format/src/hash.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/hash.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -35,19 +35,14 @@
extern int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
#endif
-struct _ocfs_inode_num;
-static int ocfs_inode_hash_prune_all(ocfs_inode_hash *h);
-static struct _ocfs_inode_num * __ocfs_inode_hash_lookup(ocfs_inode_hash *h,
- __u64 off);
-static inline struct _ocfs_inode_num * __ocfs_inode_hash_remove(ocfs_inode_hash *h,
- __u64 off);
+/*
+ *
+ * BH SEM HASH
+ *
+ */
-
-/* bh semaphore hashtable stuff */
-
-
static ocfs_bh_sem *ocfs_bh_sem_alloc(void)
{
return kmem_cache_alloc(OcfsGlobalCtxt.bh_sem_cache, GFP_NOFS);
@@ -67,8 +62,8 @@
{
if (atomic_dec_and_lock(&sem->s_refcnt, &OcfsGlobalCtxt.bh_sem_hash_lock)) {
if (buffer_modified(sem->s_bh)) {
- LOG_ERROR_ARGS("putting last refcount of a modified buffer! block %llu\n",
- (unsigned long long)sem->s_bh->b_blocknr);
+ LOG_ERROR_ARGS("putting last refcount of a modified buffer! block %lu\n",
+ sem->s_bh->b_blocknr);
}
put_bh(sem->s_bh);
sem->s_bh = NULL;
@@ -166,11 +161,9 @@
sem->s_bh = bh;
}
if (sem->s_bh != bh) {
- LOG_ERROR_ARGS("bad bh_sem->bh: sem(%p,%llu,%llu), new(%p,%llu)\n",
- sem->s_bh,
- (unsigned long long)(sem->s_bh ? sem->s_bh->b_blocknr : 0),
- (unsigned long long)sem->s_blocknr,
- bh, (unsigned long long)bh->b_blocknr);
+ LOG_ERROR_ARGS("bad bh_sem->bh: sem(%p,%lu,%lu), new(%p,%lu)\n",
+ sem->s_bh, sem->s_bh ? sem->s_bh->b_blocknr : 0,
+ sem->s_blocknr, bh, bh->b_blocknr);
BUG();
}
break;
@@ -200,9 +193,9 @@
// sem->s_pid);
if (buffer_modified(sem->s_bh) && sem->s_pid == 0) {
- LOG_ERROR_ARGS("found a%s sem with a modified bh but no pid!!! (block=%llu)\n",
+ LOG_ERROR_ARGS("found a%s sem with a modified bh but no pid!!! (block=%lu)\n",
newsem != sem ? "n old" : " new",
- (unsigned long long)sem->s_bh->b_blocknr);
+ sem->s_bh->b_blocknr);
}
} else {
/* first pass. not found. do alloc */
@@ -425,8 +418,8 @@
/* only do one buffer at a time. */
spin_unlock(&OcfsGlobalCtxt.bh_sem_hash_lock);
- LOG_ERROR_ARGS("blocknr = %llu, pid = %d\n",
- (unsigned long long)sem->s_bh->b_blocknr, pid);
+ LOG_ERROR_ARGS("blocknr = %lu, pid = %d\n",
+ sem->s_bh->b_blocknr, pid);
ocfs_clear_buffer_modified(sem->s_bh);
ocfs_bh_sem_put(sem);
goto again;
@@ -464,9 +457,8 @@
sem = list_entry (iter, ocfs_bh_sem, s_list);
if (atomic_read(&sem->s_refcnt) < 1) {
if (sem->s_bh) {
- LOG_ERROR_ARGS("killing off bh_sem with bh still attached! block=%llu, count=%d\n",
- (unsigned long long)sem->s_bh->b_blocknr,
- atomic_read(&sem->s_bh->b_count));
+ LOG_ERROR_ARGS("killing off bh_sem with bh still attached! block=%lu, count=%d\n",
+ sem->s_bh->b_blocknr, atomic_read(&sem->s_bh->b_count));
}
list_del(&sem->s_list);
list_add(&sem->s_list, &tmp);
@@ -509,8 +501,7 @@
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
- LOG_ENTRY_ARGS("(block=%llu, sem->s_pid=%d)\n",
- (unsigned long long)bh->b_blocknr,
+ LOG_ENTRY_ARGS("(block=%lu, sem->s_pid=%d)\n", bh->b_blocknr,
sem->s_pid );
add_wait_queue(&sem->s_wait, &wait);
@@ -543,13 +534,11 @@
if (buffer_modified(bh) &&
sem->s_pid != current->pid && sem->s_pid != 0) {
#ifdef BH_SEM_DEBUG
- LOG_ERROR_ARGS("possible deadlock: block=%llu, owner=%d, this=%d, modifier='%s'\n",
- (unsigned long long)bh->b_blocknr,
- sem->s_pid, current->pid, sem->s_modifier);
+ LOG_ERROR_ARGS("possible deadlock: block=%lu, owner=%d, this=%d, modifier='%s'\n",
+ bh->b_blocknr, sem->s_pid, current->pid, sem->s_modifier);
#else
- LOG_ERROR_ARGS("possible deadlock: block=%llu, owner=%d, this=%d\n",
- (unsigned long long)bh->b_blocknr,
- sem->s_pid, current->pid);
+ LOG_ERROR_ARGS("possible deadlock: block=%lu, owner=%d, this=%d\n",
+ bh->b_blocknr, sem->s_pid, current->pid);
#endif
}
}
@@ -588,558 +577,3 @@
}
LOG_EXIT();
}
-
-static inline ocfs_inode_num *ocfs_create_inode_num(void)
-{
- ocfs_inode_num *inum = NULL;
-
- inum = kmem_cache_alloc(OcfsGlobalCtxt.inum_cache, GFP_NOFS);
- if (inum == NULL) {
- LOG_ERROR_STATUS(-ENOMEM);
- goto bail;
- }
- memset(inum, 0, sizeof(ocfs_inode_num));
-
- INIT_LIST_HEAD(&inum->i_list);
- inum->i_state = INUM_UNBOUND;
- inum->i_inode = NULL;
- inum->i_feoff = 0;
-
-bail:
- return(inum);
-}
-
-#define ocfs_free_inode_num(inum) \
- kmem_cache_free(OcfsGlobalCtxt.inum_cache, inum)
-
-/*
- * ocfs_inode_hash_init()
- *
- * init the inode hash off an osb
- */
-int ocfs_inode_hash_init(ocfs_super *osb)
-{
- ocfs_inode_hash *h = &osb->inode_hash;
- int i, status = 0;
-
- LOG_ENTRY();
-
- spin_lock_init(&h->lock);
- h->num_ents = 0;
-
- /* we only want one page for the hash. */
- h->hash = (struct list_head *)__get_free_pages(GFP_KERNEL, 0);
- if (!h->hash) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto bail;
- }
-
- h->size = PAGE_SIZE / sizeof(struct list_head);
-
- LOG_TRACE_ARGS("h->size = %d\n", h->size);
-
- for (i = 0; i < h->size; i++)
- INIT_LIST_HEAD(&(h->hash[i]));
-
-bail:
- LOG_EXIT_STATUS(status);
- return status;
-} /* ocfs_inode_hash_init */
-
-/*
- * ocfs_inode_hash_prune_all
- *
- * forcefully prunes the hash -- anything left with ANY refcount will
- * be deleted. Returns the number of hash items we had to prune.
- */
-static int ocfs_inode_hash_prune_all(ocfs_inode_hash *h)
-{
- int retval = 0;
- int i = 0;
- struct list_head *head;
- struct list_head *iter = NULL;
- struct list_head *tmpiter = NULL;
- ocfs_inode_num *inum;
- LIST_HEAD(tmp);
-
- LOG_ENTRY();
-
- spin_lock(&h->lock);
-
- for(i = 0; i < h->size; i++) {
- head = &h->hash[i];
-
- if (list_empty(head))
- continue;
-
- list_for_each_safe(iter, tmpiter, head) {
- inum = list_entry(iter, ocfs_inode_num, i_list);
-
- list_del(&inum->i_list);
- list_add(&inum->i_list, &tmp);
-
- retval++;
- h->num_ents--;
- }
- }
-
- spin_unlock(&h->lock);
-
- list_for_each_safe(iter, tmpiter, &tmp) {
- inum = list_entry(iter, ocfs_inode_num, i_list);
- list_del(&inum->i_list);
-
- if (inum->i_inode) {
- /* this log_error_args is mainly for debugging */
- if (atomic_read(&inum->i_inode->i_count) > 1)
- LOG_ERROR_ARGS("inode (%lu) with i_count = %u "
- "left in system, fileoff = %llu)\n",
- inum->i_inode->i_ino,
- atomic_read(&inum->i_inode->i_count),
- inum->i_feoff);
-
- iput(inum->i_inode);
- }
- ocfs_free_inode_num(inum);
- }
-
- LOG_EXIT_STATUS(retval);
- return retval;
-} /* ocfs_inode_hash_prune_all */
-
-/*
- * ocfs_inode_hash_destroy()
- */
-void ocfs_inode_hash_destroy(ocfs_inode_hash *h)
-{
- int n;
-
- LOG_ENTRY();
-
- /* by shutdown, we shouldn't have anything left in the hash. */
- n = ocfs_inode_hash_prune_all(h);
- if (n)
- LOG_TRACE_ARGS("%d items pruned from inode hash.\n", n);
-
- spin_lock(&h->lock);
- free_pages((unsigned long) h->hash, 0);
- h->hash = NULL;
- h->num_ents = 0;
- h->size = 0;
-
- LOG_EXIT();
- return;
-} /* ocfs_inode_hash_destroy */
-
-#define OCFS_INODE_HASH(h, off) ((__u32)(off >> 9) % (h->size))
-
-/*
- * __ocfs_inode_hash_lookup()
- *
- * You MUST be holding the inode hash lock before calling this!
- */
-static ocfs_inode_num * __ocfs_inode_hash_lookup(ocfs_inode_hash *h,
- __u64 off)
-{
- ocfs_inode_num *inum = NULL;
- int bucket;
- struct list_head *head;
- struct list_head *iter = NULL;
-
- bucket = OCFS_INODE_HASH(h, off);
-
- head = &h->hash[bucket];
-
- if (list_empty(head))
- goto bail;
-
- list_for_each(iter, head) {
- inum = list_entry(iter, ocfs_inode_num, i_list);
-
- if (inum->i_feoff == off)
- break;
- inum = NULL;
- }
-
-bail:
- return(inum);
-} /* __ocfs_inode_hash_lookup */
-
-#if 0
-static ocfs_inode_num * __ocfs_inode_hash_feoff_lookup(ocfs_inode_hash *h,
- __u64 feoff)
-{
- ocfs_inode_num *inum = NULL;
- int bucket;
- struct list_head *head;
- struct list_head *iter = NULL;
-
- for(bucket = 0; bucket < h->size; bucket++) {
- head = &h->hash[bucket];
-
- if (list_empty(head))
- continue;
-
- list_for_each(iter, head) {
- inum = list_entry(iter, ocfs_inode_num, i_list);
-
- if (inum->i_feoff == feoff)
- break;
- inum = NULL;
- }
-
- if (inum)
- break;
- }
-
- return(inum);
-} /* __ocfs_inode_hash_feoff_lookup */
-#endif
-
-/*
- * ocfs_inode_hash_lookup()
- *
- */
-struct inode *ocfs_inode_hash_lookup(ocfs_super *osb,
- __u64 offset)
-{
- ocfs_inode_num *inum = NULL;
- ocfs_inode_hash *h = &osb->inode_hash;
- struct inode * inode = NULL;
-
-// LOG_ENTRY_ARGS("(offset=%llu, reverse = %s)\n", offset,
-// reverse ? "true" : "false");
-
-search:
- spin_lock(&h->lock);
-
- inum = __ocfs_inode_hash_lookup(h, offset);
-
- if (inum) {
- if (inum->i_state == INUM_UNBOUND) {
- spin_unlock(&h->lock);
- LOG_TRACE_ARGS("waiting for inum (%lu, %llu) to be "
- "bound\n", inum->i_ino, offset);
-
- yield();
- goto search;
- }
-
- inode = inum->i_inode;
- if (ocfs_inc_icount(inode) < 0)
- BUG();
- }
-
- spin_unlock(&h->lock);
-
-// LOG_EXIT_PTR(inode);
- return(inode);
-}
-
-/* used for filldir. We don't want the whole inode just i_ino if it
- * exists, otherwise we return an unused inode number */
-ino_t ocfs_inode_hash_lookup_ino(ocfs_super *osb, __u64 off)
-{
- ocfs_inode_num *inum = NULL;
- ocfs_inode_hash *h = &osb->inode_hash;
- ino_t ino = OCFS_UNUSED_INODE_NUMBER;
-
- LOG_ENTRY_ARGS("(off=%llu)\n", off);
-
- spin_lock(&h->lock);
-
- inum = __ocfs_inode_hash_lookup(h, off);
-
- if (inum)
- ino = inum->i_ino;
-
- spin_unlock(&h->lock);
-
- LOG_EXIT_ULONG(ino);
-
- return(ino);
-}
-
-static inline void ocfs_debug_print_inum(ocfs_inode_num *inum,
- struct inode * inode)
-{
-
- if (inum) {
- printk("ocfs2: inum info\n");
- printk(" i_state = %s\n", (inum->i_state == INUM_BOUND)
- ? "INUM_BOUND" : "INUM_UNBOUND");
- printk(" i_ino = %lu\n", inum->i_ino);
- printk(" i_feoff = %llu\n", inum->i_feoff);
- printk(" i_inode = 0x%p\n", inum->i_inode);
- }
-
- if (!inode)
- return;
-
- if (inum && inode != inum->i_inode)
- printk("ocfs: Inode pointer (0x%p) is different from inum!\n",
- inode);
- printk("ocfs: inode info\n");
- printk(" inode = 0x%p\n", inode);
- printk(" i_ino = %lu\n", inode->i_ino);
- printk(" feoff = %llu\n", OCFS_I(inode)->feoff);
- printk(" i_count = %u\n", atomic_read(&inode->i_count));
- printk(" deleted = %s\n", INODE_DELETED(inode) ? "yes" : "no");
- return;
-}
-
-/*
- * ocfs_inode_hash_insert()
- *
- * returns the inode number for that offset if it already exists in
- * the hash, otherwise inserts a new inode and returns the inode
- * number passed in.
- */
-unsigned long ocfs_inode_hash_insert(ocfs_super *osb,
- __u64 offset)
-{
- ocfs_inode_hash *h = &osb->inode_hash;
- ocfs_inode_num *inum = NULL;
- ocfs_inode_num *new_inum = NULL;
- struct list_head *head;
- int bucket;
- unsigned long ino = 0;
- struct super_block *sb = osb->sb;
-
- LOG_ENTRY_ARGS("(offset = %llu)\n)", offset);
-
-again:
- spin_lock(&h->lock);
-
- inum = __ocfs_inode_hash_lookup(h, offset);
-
- /* whoa, offset better be the same! */
- if (inum && (inum->i_feoff != offset)) {
- LOG_ERROR_ARGS("inum=%p, i_feoff=%llu, fe_off=%llu)\n",
- inum, inum ? inum->i_feoff : 0ULL,
- offset);
- BUG();
- }
-
- /* (second pass) we didn't find anything, insert new one. */
- if (inum == NULL && new_inum) {
- bucket = OCFS_INODE_HASH(h, offset);
- head = &h->hash[bucket];
-
- list_add(&new_inum->i_list, head);
- h->num_ents++;
- }
-
- spin_unlock(&h->lock);
-
- /* if this is our first pass and we haven't found anything,
- * create it now and go back up to try an insert. */
- if (inum == NULL && new_inum == NULL) {
- new_inum = ocfs_create_inode_num();
-
- /* root inode always has the same inode number. */
- if (offset == OCFS_ROOT_INODE_FE_OFF)
- ino = OCFS_ROOT_INODE_NUMBER;
- else
- ino = iunique(sb, OCFS_ROOT_INODE_NUMBER);
- new_inum->i_ino = ino;
- new_inum->i_feoff = offset;
-
- goto again;
- }
-
- /* we created a new one to add, but someone added it before we
- * could start our second pass, so just clean up. */
- if (inum && new_inum) {
- ocfs_free_inode_num(new_inum);
- new_inum = NULL;
- }
-
- /* if we never did an insert, then return the looked up ino. */
- if (inum) {
- ino = inum->i_ino;
- LOG_TRACE_ARGS("Returning an inum that was already in the "
- "hash (%lu)\n", ino);
- }
-
- LOG_EXIT_ULONG(ino);
-
- return ino;
-} /* ocfs_inode_hash_insert */
-
-/*
- * bind an inode to an inum.
- */
-void ocfs_inode_hash_bind(ocfs_super *osb, __u64 feoff, struct inode *inode)
-{
- ocfs_inode_hash *h = &osb->inode_hash;
- ocfs_inode_num *inum = NULL;
-
- LOG_ENTRY_ARGS("(feoff=%llu, inode->i_ino = %lu)\n",
- feoff, inode->i_ino);
-
- spin_lock(&h->lock);
-
- inum = __ocfs_inode_hash_lookup(h, feoff);
-
- if (!inum) {
- printk("ocfs2: lost inum (feoff = %llu)! AIEEEE!\n",
- feoff);
- ocfs_debug_print_inum(inum, inode);
- BUG();
- }
-
- if ((inum->i_feoff != feoff)
- || (GET_INODE_FEOFF(inode) != feoff)) {
- LOG_ERROR_ARGS("passed=%llu, on inode=%llu, "
- "(inum feoff = %llu)\n",
- feoff, GET_INODE_FEOFF(inode),
- inum->i_feoff);
- BUG();
- }
-
- if (inum->i_ino != inode->i_ino) {
- LOG_ERROR_ARGS("inode numbers don't match! "
- "(inum=%lu, inode=%lu)\n",
- inum->i_ino, inode->i_ino);
- LOG_ERROR_ARGS("passed=%llu, on inode=%llu, "
- "(inum feoff = %llu)\n",
- feoff, GET_INODE_FEOFF(inode),
- inum->i_feoff);
- BUG();
- }
-
- if (inum->i_state == INUM_UNBOUND) {
- inum->i_inode = inode;
- inum->i_state = INUM_BOUND;
- if (ocfs_inc_icount(inode) < 0)
- BUG();
-
- LOG_TRACE_ARGS("bound to ino %lu, feoff=%llu)\n",
- inode->i_ino, inum->i_feoff);
- } else if (inum->i_inode != inode) {
- LOG_ERROR_ARGS("Inum is bound to a different inode! "
- "(%llu) (%lu) (%lu) (deleted = %u)\n",
- feoff, inode->i_ino,
- inum->i_inode->i_ino,
- INODE_DELETED(inum->i_inode));
- ocfs_debug_print_inum(inum, inode);
- BUG();
- }
-
- spin_unlock(&h->lock);
-
- LOG_EXIT();
- return;
-}
-
-/*
- * __ocfs_inode_hash_remove()
- *
- * only return inum if we're supposed to free it, otherwise return NULL.
- */
-static inline ocfs_inode_num * __ocfs_inode_hash_remove(ocfs_inode_hash *h,
- __u64 off)
-{
- ocfs_inode_num *inum;
-
- inum = __ocfs_inode_hash_lookup(h, off);
-
- if (inum == NULL) {
- printk("ocfs2: Cannot remove a nonexistent inum from hash!"
- "(%llu)\n", off);
- BUG();
- }
-
- list_del(&inum->i_list);
- h->num_ents--;
-
- return(inum);
-} /* __ocfs_inode_hash_remove */
-
-/*
- * ocfs_inode_hash_remove()
- */
-void ocfs_inode_hash_remove(ocfs_inode_hash *h, __u64 off)
-{
- ocfs_inode_num *inum = NULL;
-
- LOG_ENTRY_ARGS("(off = %llu)\n", off);
-
- spin_lock(&h->lock);
-
- inum = __ocfs_inode_hash_remove(h, off);
-
- spin_unlock(&h->lock);
-
- if (!inum->i_inode || inum->i_state == INUM_UNBOUND)
- LOG_ERROR_ARGS("deleting inum in unbound state! (state = %d, "
- "feoff = %llu, i_ino = %lu\n",
- inum->i_state, inum->i_feoff, inum->i_ino);
-
- if (inum->i_inode)
- iput(inum->i_inode);
-
- ocfs_free_inode_num(inum);
-
- LOG_EXIT();
- return;
-} /* ocfs_inode_hash_remove */
-
-/*
- * ocfs_inode_rehash()
- *
- * update the offset value returned by a lookup on this key. Used
- * during rename.
- *
- * TODO: This should also take an inode argument and reset
- * the offset on that while holding the hash lock.
- */
-int ocfs_inode_rehash(ocfs_inode_hash *h,
- __u64 oldoff,
- __u64 newoff)
-{
- int status = 0;
- ocfs_inode_num *inum = NULL;
- ocfs_inode_num *target = NULL;
- struct list_head *head;
- int bucket;
-
- LOG_ENTRY_ARGS("(oldoff = %llu, newoff = %llu)\n", oldoff, newoff);
-
- spin_lock(&h->lock);
-
- /* Sanity check. If we're going to be moving buckets, make
- * sure someone else isn't in the new one. */
- if (newoff != oldoff) {
- target = __ocfs_inode_hash_lookup(h, newoff);
- if (target) {
- LOG_ERROR_ARGS("Rehashing on top of an existing inum!"
- "oldoff = %llu, newoff = %llu\n",
- oldoff, newoff);
- BUG();
- }
- }
-
- inum = __ocfs_inode_hash_lookup(h, oldoff);
- if (inum == NULL)
- BUG();
-
- if (inum->i_state != INUM_BOUND)
- BUG();
-
- list_del(&inum->i_list);
-
- inum->i_feoff = newoff;
-
- bucket = OCFS_INODE_HASH(h, newoff);
- head = &h->hash[bucket];
- list_add(&inum->i_list, head);
-
- spin_unlock(&h->lock);
-
- LOG_EXIT_STATUS(status);
- return status;
-} /* ocfs_inode_rehash */
-
-
Modified: branches/new-dir-format/src/inc/io.h
===================================================================
--- branches/new-dir-format/src/inc/io.h 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/inc/io.h 2004-05-24 21:34:48 UTC (rev 932)
@@ -54,16 +54,6 @@
int flags,
struct inode *inode);
-struct inode * ocfs_get_fileent_inode(ocfs_super *osb, int idx, struct buffer_head *bhs[],
- struct inode *parent);
-
-void ocfs_put_fileent_inode(int idx, struct inode *arr[]);
-
-int ocfs_write_dirnode(ocfs_super * osb, struct buffer_head *bhs[], struct inode *hdr_inode);
-
-int ocfs_read_dirnode(ocfs_super * osb, __u64 off,int sync, struct buffer_head *bhs[], struct inode *hdr_inode);
-
-
void ocfs_end_buffer_io_sync (struct buffer_head *bh,
int uptodate);
@@ -71,6 +61,7 @@
#define OCFS_BH_COND_CACHED 2
#define OCFS_BH_CONCURRENT_WRITE 4 /* This should only be used by ocfs_worker */
#define OCFS_BH_IGNORE_JBD 8 /* This should only be used by ocfs_checkpoint_handle! */
+#define OCFS_BH_READAHEAD 16 /* use this to pass READA down to submit_bh */
#define OCFS_NONCACHED(osb,off) ((off) < (osb)->vol_layout.data_start_off)
@@ -293,8 +284,7 @@
#define OCFS_DO_HEX_DUMP(bh) \
do { \
- printk("bh->b_blocknr = %llu, bh->b_data:\n", \
- (unsigned long long)bh->b_blocknr); \
+ printk("bh->b_blocknr = %lu, bh->b_data:\n", bh->b_blocknr); \
for(i = 0; i < 512; i++) { \
printk("%03x ", bh->b_data[i]); \
if ( ((i+1) % 16) == 0 ) \
@@ -303,50 +293,6 @@
printk("\n"); \
} while (0)
-/* we should take this out later */
-static inline int check_rootdir_overwrite(struct buffer_head *bh)
-{
- int i;
-
- if (bh->b_blocknr >= 4720 && bh->b_blocknr < (4720+256)) {
- ocfs_dir_node *dir = (ocfs_dir_node *)bh->b_data;
- ocfs_file_entry *fe = (ocfs_file_entry *)bh->b_data;
-
- if (strncmp("DIRNV20", dir->signature, strlen("DIRNV20"))==0) {
- if (dir->node_disk_off >> 9 != 4720) {
- OCFS_DO_HEX_DUMP(bh);
- printk("uh oh! dirnode disk off is incorrect! %u\n",(__u32)(dir->node_disk_off>>9));
- BUG();
- } else if (bh->b_blocknr != 4720) {
- OCFS_DO_HEX_DUMP(bh);
- printk("uh oh! dirnode is being written at blocknr=%llu!\n", (unsigned long long)bh->b_blocknr);
- BUG();
- }
- } else if (strncmp("FIL", fe->signature, strlen("FIL"))==0) {
- if (fe->this_sector >> 9 != bh->b_blocknr) {
- OCFS_DO_HEX_DUMP(bh);
- printk("uh oh! fe->this_sector (%u) != blocknr (%llu)\n",
- (__u32)(fe->this_sector>>9),
- (unsigned long long)bh->b_blocknr);
- BUG();
- } else if (fe->u.child_dirnode >> 9 == 4720) {
- OCFS_DO_HEX_DUMP(bh);
- printk("uh oh! fe->child_dirnode recurses!!!\n");
- BUG();
- }
- } else if (bh->b_blocknr == 4720) {
- OCFS_DO_HEX_DUMP(bh);
- printk("uh oh! invalid type being written to dirnode!\n");
- printk("signature: '%c%c%c%c%c%c%c'\n",
- dir->signature[0], dir->signature[1], dir->signature[2],
- dir->signature[3], dir->signature[4], dir->signature[5], dir->signature[6]);
- printk("fooblydoo flippity floppety floo. supercalafragilicousexpialdizzle\n");
- BUG();
- }
- }
- return 0;
-}
-
static inline int ocfs_write_bh (ocfs_super * osb, struct buffer_head *bh,
int flags, struct inode *inode)
{
Modified: branches/new-dir-format/src/inc/ocfs.h
===================================================================
--- branches/new-dir-format/src/inc/ocfs.h 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/inc/ocfs.h 2004-05-24 21:34:48 UTC (rev 932)
@@ -262,6 +262,8 @@
#define OCFS_DEFAULT_DIR_NODE_SIZE (512 * OCFS_DEFAULT_DIR_NODE_SECTS)
#define OCFS_DEFAULT_FILE_NODE_SIZE (512)
+#define OCFS_DEFAULT_INODE_SIZE (512)
+
/*
** The following flag values reflect the operation to be performed
** by ocfs_create_modify_file
@@ -284,8 +286,8 @@
#define FLAG_FAST_PATH_LOCK 0x00004000
#define FLAG_FILE_UNUSED5 0x00008000
#define FLAG_FILE_UNUSED6 0x00010000
-#define FLAG_DEL_NAME 0x00020000
-#define FLAG_DEL_INODE 0x00040000
+//#define FLAG_DEL_NAME 0x00020000
+//#define FLAG_DEL_INODE 0x00040000
#define FLAG_FILE_UNUSED7 0x00080000
#define FLAG_FILE_UNUSED8 0x00100000
#define FLAG_FILE_UNUSED9 0x00200000
@@ -432,10 +434,6 @@
#define OCFS_FLAG_MEM_LISTS_INITIALIZED (0x00000002)
#define OCFS_FLAG_SHUTDOWN_VOL_THREAD (0x00000004)
-/* ocfs_dir_node->dir_node_flags flags */
-#define DIR_NODE_FLAG_ROOT 0x01
-#define DIR_NODE_FLAG_ORPHAN 0x02
-
/*
** Information on Publish sector of each node
*/
@@ -476,9 +474,7 @@
#define OCFS_ATTRIB_SYMLINK (0x100)
#define OCFS_ATTRIB_SOCKET (0x200)
-#define INVALID_DIR_NODE_INDEX -1
#define INVALID_NODE_POINTER -1
-#define OCFS_DIR_NODE_SIGNATURE "DIRNV20"
#define OCFS_FILE_ENTRY_SIGNATURE "FIL"
#define OCFS_EXTENT_HEADER_SIGNATURE "EXTHDR2"
#define OCFS_EXTENT_DATA_SIGNATURE "EXTDAT1"
@@ -498,8 +494,8 @@
#define EWARNING 998
#define OCFS_MAGIC 0xa156f7eb
-#define OCFS_ROOT_INODE_NUMBER 2
-#define OCFS_ROOT_INODE_FE_OFF 1536
+#define OCFS_ROOT_INODE_NUMBER 3
+#define OCFS_ROOT_INODE_FE_OFF(osb) (OCFS_ROOT_INODE_NUMBER << osb->sb->s_blocksize_bits)
#define OCFS_LINUX_MAX_FILE_SIZE 9223372036854775807LL
#define INITIAL_EXTENT_MAP_SIZE 10
@@ -536,10 +532,6 @@
#ifndef _OCFSDEF_H_
#define _OCFSDEF_H_
-#define IS_VALID_DIR_NODE(ptr) \
- (!strncmp((ptr)->signature, OCFS_DIR_NODE_SIGNATURE, \
- strlen(OCFS_DIR_NODE_SIGNATURE)))
-
/* sm - ocfs 1.0 fails to set fe->sig for dirs */
#define IS_VALID_FILE_ENTRY(ptr) \
(((ptr)->attribs & OCFS_ATTRIB_DIRECTORY) || \
@@ -757,58 +749,7 @@
#endif
-/* ofile macros */
-#ifdef OCFS_MEM_DBG
-#define ocfs_allocate_ofile(flag) ((ocfs_file *)({ \
- ocfs_file *of = NULL; \
- of = ocfs_dbg_slab_alloc(OcfsGlobalCtxt.ofile_cache, __FILE__, __LINE__); \
- if (of != NULL) { \
- memset (of, 0, sizeof (ocfs_file)); \
- of->obj_id.type = OCFS_TYPE_OFILE; \
- of->obj_id.size = sizeof (ocfs_file); \
- if (flag==OCFS_ATTRIB_DIRECTORY) { \
- int sz = OCFS_DEFAULT_DIR_NODE_SECTS * sizeof(struct buffer_head *); \
- of->curr_dir_buf = ocfs_malloc(sz); \
- if (of->curr_dir_buf == NULL) { \
- ocfs_safefree(of); \
- of = NULL; \
- } else \
- memset(of->curr_dir_buf, 0, sz); \
- } \
- } \
- of; }))
-#define ocfs_release_ofile(of) ({ \
- OCFS_ASSERT (of); \
- ocfs_safefree (of->curr_dir_buf); \
- ocfs_dbg_slab_free (OcfsGlobalCtxt.ofile_cache, of); })
-#else /* !OCFS_MEM_DBG */
-#define ocfs_allocate_ofile(flag) ((ocfs_file *)({ \
- ocfs_file *of = NULL; \
- of = kmem_cache_alloc (OcfsGlobalCtxt.ofile_cache, GFP_NOFS); \
- if (of != NULL) { \
- memset (of, 0, sizeof (ocfs_file)); \
- of->obj_id.type = OCFS_TYPE_OFILE; \
- of->obj_id.size = sizeof (ocfs_file); \
- if (flag==OCFS_ATTRIB_DIRECTORY) { \
- int sz = OCFS_DEFAULT_DIR_NODE_SECTS * sizeof(struct buffer_head *); \
- of->curr_dir_buf = ocfs_malloc(sz); \
- if (of->curr_dir_buf == NULL) { \
- ocfs_safefree(of); \
- of = NULL; \
- } else \
- memset(of->curr_dir_buf, 0, sz); \
- } \
- } \
- of; }))
-
-#define ocfs_release_ofile(of) ({ \
- OCFS_ASSERT (of); \
- ocfs_safefree (of->curr_dir_buf); \
- kmem_cache_free (OcfsGlobalCtxt.ofile_cache, of); })
-#endif
-
-
/* file entry macros */
#ifdef OCFS_MEM_DBG
#define ocfs_allocate_file_entry() ((ocfs_file_entry *)({ \
@@ -1616,6 +1557,7 @@
} u;
ocfs_lock_res i_lockres;
+ __u32 i_dir_start_lookup;
} ocfs_inode_private;
/* Eventually, the 'flags' and 'oin_flags' fields need to be
@@ -1635,7 +1577,7 @@
/* set on init_private, cleared on clear_inode */
#define OCFS_INODE_INITIALIZED 0x00000004
/* is this a system file? */
-#define OCFS_INODE_SYSFILE 0x00000008
+#define OCFS_INODE_SYSTEM_FILE 0x00000008
#define GET_INODE_CLEAN_SEQ(i) (atomic_t *)(&(OCFS_I(i)->i_clean_buffer_seq))
@@ -1656,6 +1598,19 @@
#define GET_INODE_FEOFF(i) OCFS_I(i)->feoff
+static inline unsigned long ino_from_fe_off(struct inode *inode)
+{
+ return (unsigned long)((GET_INODE_FEOFF(inode) >>
+ inode->i_sb->s_blocksize_bits) & (__u64)ULONG_MAX);
+}
+
+static inline unsigned long ino_from_off(struct super_block *sb, __u64 off)
+{
+ return (unsigned long)((off >> sb->s_blocksize_bits) & (__u64)ULONG_MAX);
+}
+
+
+
#warning take this out when all the lockres stuff checks out
#define GET_INODE_LOCKRES(i) ({ if (i==NULL) BUG(); (&(OCFS_I(i)->i_lockres)); })
@@ -1768,6 +1723,18 @@
atomic_t ext_extends;
} ocfs_alloc_stats;
+enum {
+ GLOBAL_BITMAP_SYSTEM_INODE = 0,
+ FILE_ALLOC_BITMAP_SYSTEM_INODE,
+ INODE_ALLOC_BITMAP_SYSTEM_INODE,
+ JOURNAL_SYSTEM_INODE,
+#if 0
+ DIR_ALLOC_BITMAP_SYSTEM_INODE,
+#endif
+ NUM_SYSTEM_INODES
+};
+
+
/*
* ocfs_super
*
@@ -1788,6 +1755,7 @@
struct list_head cache_lock_list;
struct super_block *sb;
struct inode *root_inode;
+ struct inode *system_inodes[NUM_SYSTEM_INODES];
ocfs_vol_layout vol_layout;
ocfs_vol_node_map vol_node_map;
struct semaphore cfg_lock;
@@ -1804,6 +1772,8 @@
__u32 cluster_size_bits;
__u32 dir_alloc_bits;
__u32 file_alloc_bits;
+ __u32 inode_alloc_bits;
+ __u32 inode_size;
int needs_flush;
ocfs_alloc_bm cluster_bitmap;
@@ -1872,11 +1842,9 @@
struct semaphore global_res;
struct list_head osb_next; /* List of all volumes */
kmem_cache_t *inode_cache;
- kmem_cache_t *ofile_cache;
kmem_cache_t *fe_cache;
kmem_cache_t *extent_cache;
kmem_cache_t *bh_sem_cache;
- kmem_cache_t *inum_cache;
__u32 flags;
__u32 pref_node_num; /* preferred... osb has the real one */
ocfs_guid guid; /* uniquely identifies a node */
@@ -2027,8 +1995,10 @@
__u32 used_bits;
__u32 total_bits;
} bitinfo;
- } u;
-/* sizeof(fe) = 496 bytes */
+ } u;
+ __u64 alloc_file_off; // NUMBER RANGE(0,ULONG_LONG_MAX)
+ __u32 alloc_node; // NUMBER RANGE(0,31)
+/* sizeof(fe) = 508 bytes */
}
ocfs_file_entry; // END CLASS
@@ -2063,50 +2033,7 @@
OCFS_GCC_ATTR_PACKED
ocfs_index_hdr;
-/* not sizeof-safe across platforms */
-typedef struct _ocfs_dir_node // CLASS
-{
- ocfs_disk_lock disk_lock; // DISKLOCK
- __u8 signature[8]; // CHAR[8]
- __u64 alloc_file_off; // NUMBER RANGE(0,ULONG_LONG_MAX)
- __u32 alloc_node; // NUMBER RANGE(0,31)
- __u64 free_node_ptr; /* Used in topmost dirnode,
- * points to last dirnode in
- * chain, or -1 if only
- * one. */
- __u64 node_disk_off; // DISKPTR
- __s64 next_node_ptr; // DISKPTR
- __s64 indx_node_ptr; // DISKPTR
- __s64 next_del_ent_node; /* Used in non-topmost
- * dirnodes, continues the
- * chain of dirnodes which
- * have had fe's deleted
- * from. -1 means end of list. */
- __s64 head_del_ent_node; /* Used in topmost dirnode,
- * points to head of a list
- * of dirnodes which we've
- * deleted from. -1 if never
- * deleted, or we've only
- * got one dirnode. */
- __u8 first_del; // DIRNODEINDEX
- __u8 num_del; // NUMBER RANGE(0,254)
- __u8 num_ents; // NUMBER RANGE(0,254)
- __u8 depth; // UNUSED
- __u8 num_ent_used; // NUMBER RANGE(0,254)
- __u8 dir_node_flags; // DIRFLAG
- __u8 sync_flags; // SYNCFLAG
- __u8 index[256]; // DIRINDEX
- __u8 index_dirty; // NUMBER RANGE(0,1)
- __u8 bad_off; // NUMBER RANGE(0,254)
- __u8 reserved[127]; // UNUSED
- __u8 file_ent[1]; // UNUSED
-}
-OCFS_GCC_ATTR_PACKALGN
-ocfs_dir_node; // END CLASS
-
-
-
typedef struct _ocfs_extent_group // CLASS
{
__u8 signature[8]; // CHAR ARRAY[8]
@@ -2296,9 +2223,12 @@
/* these three used as 'type' in ocfs_bitmap_update */
+#if 0
#define DISK_ALLOC_DIR_NODE 1
+#endif
#define DISK_ALLOC_EXTENT_NODE 2
#define DISK_ALLOC_VOLUME 3
+#define DISK_ALLOC_INODE 4
/* a bitmap update, currently used for freeing bits */
typedef struct ocfs_bitmap_update
@@ -2450,9 +2380,58 @@
char nodename[255]; /* node name */
};
+/*
+ * ocfs directory file types. Only the low 3 bits are used. The
+ * other bits are reserved for now.
+ */
+#define OCFS_FT_UNKNOWN 0
+#define OCFS_FT_REG_FILE 1
+#define OCFS_FT_DIR 2
+#define OCFS_FT_CHRDEV 3
+#define OCFS_FT_BLKDEV 4
+#define OCFS_FT_FIFO 5
+#define OCFS_FT_SOCK 6
+#define OCFS_FT_SYMLINK 7
+#define OCFS_FT_MAX 8
+/*
+ * OCFS_DIR_PAD defines the directory entries boundaries
+ *
+ * NOTE: It must be a multiple of 4
+ */
+#define OCFS_DIR_PAD 4
+#define OCFS_DIR_ROUND (OCFS_DIR_PAD - 1)
+#define OCFS_DIR_REC_LEN(name_len) (((name_len) + 12 + OCFS_DIR_ROUND) & \
+ ~OCFS_DIR_ROUND)
+#define OCFS_LINK_MAX 32000
+
+struct ocfs2_dir_entry {
+ __u64 inode; /* Inode number */
+ __u16 rec_len; /* Directory entry length */
+ __u8 name_len; /* Name length */
+ __u8 file_type;
+ char name[OCFS_MAX_FILENAME_LENGTH]; /* File name */
+};
+
+#define S_SHIFT 12
+static unsigned char ocfs_type_by_mode[S_IFMT >> S_SHIFT] = {
+ [S_IFREG >> S_SHIFT] OCFS_FT_REG_FILE,
+ [S_IFDIR >> S_SHIFT] OCFS_FT_DIR,
+ [S_IFCHR >> S_SHIFT] OCFS_FT_CHRDEV,
+ [S_IFBLK >> S_SHIFT] OCFS_FT_BLKDEV,
+ [S_IFIFO >> S_SHIFT] OCFS_FT_FIFO,
+ [S_IFSOCK >> S_SHIFT] OCFS_FT_SOCK,
+ [S_IFLNK >> S_SHIFT] OCFS_FT_SYMLINK,
+};
+
+static inline void ocfs_set_de_type(struct super_block *sb, struct ocfs2_dir_entry *de, umode_t mode) {
+ de->file_type = ocfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
+}
+
+
+
typedef struct _ocfs_find_inode_args
{
__u64 feoff;
@@ -2472,7 +2451,12 @@
}
ocfs_timeout;
+#define NAMEI_RA_CHUNKS 2
+#define NAMEI_RA_BLOCKS 4
+#define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
+#define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
+
#define __ocfs_wait(wq, condition, timeo, ret) \
do { \
ocfs_timeout __to; \
@@ -2539,17 +2523,6 @@
})
-static inline int ocfs_get_max_dir_index(ocfs_dir_node *dir)
-{
- int i;
- int ret = -1;
- for (i=0; i<dir->num_ent_used; i++)
- if ((int)dir->index[i] > ret)
- ret = (int)dir->index[i];
-
- return ret;
-}
-
static inline int ocfs_is_local_cache_lock(ocfs_super *osb, struct inode *inode)
{
ocfs_lock_res *lockres = GET_INODE_LOCKRES(inode);
Modified: branches/new-dir-format/src/inc/proto.h
===================================================================
--- branches/new-dir-format/src/inc/proto.h 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/inc/proto.h 2004-05-24 21:34:48 UTC (rev 932)
@@ -33,7 +33,6 @@
int ocfs_get_leaf_extent (ocfs_super * osb, ocfs_file_entry * FileEntry, __s64 Vbo, struct buffer_head **data_extent_bh, struct inode *inode);
int ocfs_find_contiguous_space_from_bitmap (ocfs_super * osb, __u64 file_size, __u64 * cluster_off, __u64 * cluster_count,int sysfile, struct buffer_head *lock_bh, struct inode *bitmap_inode);
int ocfs_alloc_node_block (ocfs_super * osb, __u64 FileSize, __u64 * DiskOffset, __u64 * file_off, __u32 NodeNum, __u32 Type, ocfs_journal_handle *handle);
-int ocfs_free_directory_block (ocfs_super * osb, ocfs_file_entry * fe, ocfs_journal_handle *handle, struct inode *inode);
int ocfs_free_file_extents (ocfs_super * osb, struct buffer_head *fe_bh, ocfs_journal_handle *handle, struct inode *inode);
int ocfs_lookup_obj_for_proc (ocfs_vote_obj *obj, ocfs_vote_obj_lookup_data *data);
@@ -90,6 +89,8 @@
void ocfs_clear_inode (struct inode *inode);
int ocfs_block_symlink (struct inode *inode, const char *symname, int len);
ssize_t ocfs_rw_direct (int rw, struct file *filp, char *buf, size_t size, loff_t * offp);
+struct buffer_head *ocfs_bread(ocfs_journal_handle *handle, struct inode * inode,
+ int block, int create, int *err, int reada);
int ocfs_submit_vol_metadata(ocfs_super *osb, ocfs_offset_map *map_buf, __u32 num);
@@ -197,7 +198,6 @@
int ocfs_get_system_file_size (ocfs_super * osb, __u32 FileId, __u64 * Length, __u64 * AllocSize);
__u64 ocfs_file_to_disk_off (ocfs_super * osb, __u32 FileId, __u64 Offset);
-void ocfs_initialize_dir_node (ocfs_super * osb, ocfs_dir_node * dir_node, __u64 bitmap_off, __u64 file_off, __u32 node);
int ocfs_compare_qstr (struct qstr * s1, struct qstr * s2);
void ocfs_truncate_inode_pages(struct inode *inode, loff_t off);
@@ -233,12 +233,9 @@
int ocfs_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry);
int ocfs_symlink (struct inode *dir, struct dentry *dentry, const char *symname);
-int ocfs_find_files_on_disk (ocfs_super * osb, struct qstr * file_name, struct buffer_head ** fe_bh, ocfs_file * ofile, struct inode *inode, int take_lock);
+int ocfs_find_files_on_disk (ocfs_super * osb, struct dentry * dentry, struct buffer_head ** fe_bh, struct inode *inode, struct inode *file_inode, int take_lock, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent);
int ocfs_write_force_dir_node (ocfs_super * osb, struct buffer_head *bhs[], __s32 idx);
-int ocfs_insert_file (ocfs_super * osb, ocfs_file_entry * InsertEntry, struct buffer_head **insert_bh, ocfs_journal_handle * handle, struct inode *dir_inode, struct inode *file_inode);
-int ocfs_reindex_dir_node (ocfs_super * osb, __u64 DirNodeOffset, struct buffer_head *bhs[], ocfs_journal_handle *handle, struct inode *dir_inode);
int ocfs_recover_dir_node (ocfs_super * osb, __u64 OrigDirNodeOffset, __u64 SavedDirNodeOffset);
-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);
@@ -260,20 +257,8 @@
void ocfs_end_buffer_io_sync(struct buffer_head *bh, int uptodate);
-int ocfs_inode_hash_init(ocfs_super *osb);
-void ocfs_inode_hash_destroy(ocfs_inode_hash *h);
-unsigned long ocfs_inode_hash_insert(ocfs_super *osb,
- __u64 offset);
-void ocfs_inode_hash_bind(ocfs_super *osb, __u64 feoff, struct inode *inode);
-void ocfs_inode_hash_remove(ocfs_inode_hash *h, __u64 off);
-int ocfs_inode_rehash(ocfs_inode_hash *h,
- __u64 oldoff,
- __u64 newoff);
struct inode *ocfs_iget(ocfs_super *osb, __u64 feoff,
struct buffer_head *fe_bh);
-struct inode *ocfs_inode_hash_lookup(ocfs_super *osb,
- __u64 offset);
-ino_t ocfs_inode_hash_lookup_ino(ocfs_super *osb, __u64 off);
void ocfs_init_timeout(ocfs_timeout *to);
void ocfs_set_timeout(ocfs_timeout *to, __u32 timeout);
@@ -285,4 +270,10 @@
int ocfs_inode_revalidate(struct dentry *dentry);
+struct buffer_head * ocfs_find_entry (struct dentry *dentry, struct ocfs2_dir_entry ** res_dir);
+int ocfs_check_dir_entry (struct inode * dir, struct ocfs2_dir_entry * de, struct buffer_head * bh, unsigned long offset);
+int empty_dir (struct inode * inode);
+int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode);
+int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode);
+
#endif /* _PROTO_H_ */
Modified: branches/new-dir-format/src/inode.c
===================================================================
--- branches/new-dir-format/src/inode.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/inode.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -162,7 +162,7 @@
/* Shortcut: if they ask for the root dirnode, just return
* it. */
- if (feoff == OCFS_ROOT_INODE_FE_OFF) {
+ if (feoff == OCFS_ROOT_INODE_FE_OFF(osb)) {
LOG_TRACE_ARGS("Asked for root dirnode (%llu)\n",
feoff);
@@ -216,42 +216,33 @@
if (feoff < osb->vol_layout.root_start_off)
flags |= OCFS_FIND_INODE_FLAG_SYSFILE;
- inode = ocfs_inode_hash_lookup(osb, feoff);
- if (!inode) {
- /* we should put this guy in the hash now... */
- LOG_TRACE_STR("calling iget4");
+ args.feoff = feoff;
+ args.fe_bh = fe_bh;
+ args.flags = flags;
+ args.ino = ino_from_off(sb, feoff);
- args.feoff = feoff;
- args.fe_bh = fe_bh;
- args.flags = flags;
-
- /* alright, allocate a new inode number for this guy
- * and insert it into the hash. It's not bound yet --
- * read_inode2 binds the actual inode to it. */
- args.ino = ocfs_inode_hash_insert(osb, feoff);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- inode = iget5_locked (sb, args.ino, ocfs_find_actor,
- ocfs_init_locked_inode, &args);
+ inode = iget5_locked (sb, args.ino, ocfs_find_actor,
+ ocfs_init_locked_inode, &args);
#else
- inode = iget4 (sb, args.ino, ocfs_find_inode, &args);
+ inode = iget4 (sb, args.ino, ocfs_find_inode, &args);
#endif
- if (inode == NULL) {
- LOG_ERROR_STR("access error");
- inode = NULL;
- goto bail;
- }
- if (is_bad_inode (inode)) {
- LOG_ERROR_STR("access error (bad inode)");
- iput (inode);
- inode = NULL;
- goto bail;
- }
+ if (inode == NULL) {
+ LOG_ERROR_STR("access error");
+ inode = NULL;
+ goto bail;
}
+ if (is_bad_inode (inode)) {
+ LOG_ERROR_STR("access error (bad inode)");
+ iput (inode);
+ inode = NULL;
+ goto bail;
+ }
bail:
if (inode) {
- LOG_TRACE_ARGS("returning inode with number %lu\n",
- inode->i_ino);
+ LOG_TRACE_ARGS("returning inode with number %llu\n",
+ GET_INODE_FEOFF(inode));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
/* inode was *not* in the inode cache. 2.6.x requires
* us to do our own read_inode call and unlock it
@@ -299,9 +290,6 @@
args = (ocfs_find_inode_args *) opaque;
- if (ino != inode->i_ino)
- goto bail;
-
if (GET_INODE_FEOFF(inode) != args->feoff) {
LOG_ERROR_STATUS(-EINVAL);
goto bail;
@@ -361,7 +349,6 @@
struct super_block *sb;
ocfs_super *osb;
__u64 offset;
- unsigned long uniq_ino;
LOG_ENTRY_ARGS ("(0x%p, %u, size:%llu)\n", inode, mode, fe->file_size);
@@ -406,15 +393,15 @@
if (fe->attribs & OCFS_ATTRIB_DIRECTORY)
OCFS_I(inode)->oin_flags |= OCFS_OIN_DIRECTORY;
- if (create_ino) {
- uniq_ino = ocfs_inode_hash_insert(osb, offset);
- inode->i_ino = uniq_ino;
- /* caller needs to know to call inode_hash_bind! */
- }
+ if (create_ino)
+ inode->i_ino = ino_from_off(inode->i_sb, offset);
+
LOG_TRACE_ARGS("offset = %llu, ino = %lu, create_ino = %s\n",
- offset, inode->i_ino,
+ offset, inode->i_ino,
create_ino ? "true" : "false");
+ printk("populate inode: setting nlink from %d to %d for %llu\n", inode->i_nlink, fe->link_cnt, offset);
+ inode->i_nlink = fe->link_cnt;
switch (inode->i_mode & S_IFMT) {
case S_IFREG:
atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
@@ -423,10 +410,15 @@
inode->i_size = fe->file_size;
break;
case S_IFDIR:
+ if (inode->i_nlink < 2) {
+ LOG_ERROR_ARGS("inlink=%d for %llu\n", inode->i_nlink,
+ offset);
+ inode->i_nlink = 2;
+ }
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;
+ inode->i_size = fe->file_size;
break;
case S_IFLNK:
atomic_set(GET_INODE_CLEAN_SEQ(inode), atomic_read(&osb->clean_buffer_seq));
@@ -561,10 +553,8 @@
BUG();
if (sysfile)
- OCFS_SET_FLAG(OCFS_I(inode)->flags, OCFS_INODE_SYSFILE);
+ OCFS_SET_FLAG(OCFS_I(inode)->flags, OCFS_INODE_SYSTEM_FILE);
- ocfs_inode_hash_bind(osb, feoff, inode);
-
ocfs_init_lockres (osb, inode);
bail:
@@ -597,7 +587,7 @@
int ret = 0;
ocfs_file_entry *fe = NULL;
- LOG_ENTRY_ARGS ("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque);
+ LOG_ENTRY_ARGS ("(0x%p, %lu, %llu, 0x%p)\n", inode, inode->i_ino, GET_INODE_FEOFF(inode), opaque);
if (inode == NULL)
goto bail;
@@ -649,26 +639,9 @@
{
ocfs_super *osb;
- LOG_ENTRY_ARGS ("(0x%p, inode_i_ino=%lu)\n", inode, inode->i_ino);
+ LOG_ENTRY_ARGS ("(0x%p, i_ino=%llu)\n", inode, GET_INODE_FEOFF(inode));
LOG_TRACE_ARGS ("put_inode: count=%d\n", atomic_read(&inode->i_count));
osb = OCFS_SB(inode->i_sb);
-
- /* Ok, if after this iput we would be the last holder of the
- * root inode, then we know we're unmounting so just dump it
- * now. */
- if ((inode->i_ino == OCFS_ROOT_INODE_NUMBER)
- && (atomic_read(&inode->i_count) == 2)) {
- LOG_TRACE_STR("Oop, iputing the root inode!");
- /* this is fun. Bring up the refcount for our call to
- * hash_remove so the iput inside of that function
- * doesn't throw us into recursion :) */
- if (ocfs_inc_icount(inode) < 0)
- BUG();
- ocfs_inode_hash_remove(&osb->inode_hash,
- GET_INODE_FEOFF(inode));
- atomic_dec(&inode->i_count);
- }
-
LOG_EXIT ();
return;
} /* ocfs_put_inode */
@@ -697,14 +670,14 @@
if (!inode)
goto bail;
- LOG_TRACE_ARGS("Clearing inode %lu feoff: %llu)\n", inode->i_ino,
+ LOG_TRACE_ARGS("Clearing inode feoff: %llu)\n",
GET_INODE_FEOFF(inode));
/* we should not really be using osb in this context. */
osb = OCFS_SB(inode->i_sb);
if (!inode->u.generic_ip) {
- LOG_ERROR_ARGS("inode %lu has no generic_ip!\n", inode->i_ino);
+ LOG_ERROR_ARGS("inode %llu has no generic_ip!\n", GET_INODE_FEOFF(inode));
goto bail;
}
@@ -721,7 +694,7 @@
goto bail;
}
- if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+ if (inode == osb->root_inode) {
LOG_TRACE_STR("this is the root inode, doing cleanup now!");
ocfs_sync_blockdev(inode->i_sb);
LOG_TRACE_STR ("syncing past root inode");
@@ -841,8 +814,8 @@
__u64 entryOffset;
struct buffer_head *bh = NULL;
- LOG_ENTRY_ARGS ("(0x%p, %llu, 0x%p, %d)\n", inode,
- (unsigned long long)iblock, bh_result, create);
+ LOG_ENTRY_ARGS ("(0x%p, %ld, 0x%p, %d)\n", inode, iblock, bh_result,
+ create);
if (!inode) {
LOG_ERROR_STR ("bad inode");
@@ -852,8 +825,7 @@
osb = OCFS_SB(inode->i_sb);
if ((iblock << 9) > PATH_MAX + 1) {
- LOG_ERROR_ARGS ("file offset > PATH_MAX: %llu",
- (unsigned long long)iblock << 9);
+ LOG_ERROR_ARGS ("file offset > PATH_MAX: %lu", iblock << 9);
goto bail;
}
@@ -874,8 +846,8 @@
if ((iblock << 9) >= (__s64)fe->alloc_size) {
OCFS_BH_PUT_DATA(bh);
- LOG_ERROR_ARGS ("file offset is outside the allocated size: %llu",
- (unsigned long long)iblock << 9);
+ LOG_ERROR_ARGS ("file offset is outside the allocated size: %lu",
+ iblock << 9);
goto bail;
}
@@ -892,6 +864,85 @@
return err;
} /* ocfs_symlink_get_block */
+
+/* TODO: this should probably be merged into ocfs_get_block */
+struct buffer_head *ocfs_bread(ocfs_journal_handle *handle, struct inode * inode,
+ int block, int create, int *err, int reada)
+{
+ struct buffer_head * bh = NULL;
+ int fatal = 0, tmperr = 0, new = 0;
+ ocfs_super *osb = NULL;
+ __s64 vbo = 0LL, lbo = 0LL;
+ int readflags = OCFS_BH_CACHED;
+
+ osb = OCFS_SB(inode->i_sb);
+ vbo = (__s64) block << inode->i_sb->s_blocksize_bits;
+
+ OCFS_ASSERT(!create || handle);
+
+#warning only turn this on if we know we can deal with read_bh returning nothing
+#if 0
+ if (reada)
+ readflags |= OCFS_BH_READAHEAD;
+#endif
+
+ if (vbo >= inode->i_size) {
+ if (!create) {
+ *err = -ENOSPC;
+ return NULL;
+ }
+ new = 1;
+ }
+
+ // ???: do we need priv_sem? should have i_sem i think
+ if (vbo >= OCFS_I(inode)->alloc_size) {
+ *err = ocfs_extend_file(osb, vbo + 512LL, GET_INODE_FEOFF(inode),
+ handle, inode, NULL);
+ if (*err < 0) {
+ *err = -ENOSPC;
+ return NULL;
+ }
+ // fe->file_size will be vbo+512 here, and alloc_size will be whatever
+ // i_size will be changed by caller (ocfs_add_entry) if we return !NULL
+ }
+
+ // do we need extend sem? no extend dlm message for dirs
+ tmperr = ocfs_lookup_file_allocation(osb, vbo, &lbo, 1, NULL, inode);
+ if (tmperr < 0)
+ goto fail;
+
+ tmperr = ocfs_read_bh(osb, lbo, &bh, readflags, inode);
+ if (tmperr < 0)
+ goto fail;
+
+ tmperr = 0;
+ if (new) {
+ fatal = ocfs_journal_access(handle, bh,
+ OCFS_JOURNAL_ACCESS_CREATE);
+ if (!fatal) {
+ char *buf = OCFS_BH_GET_DATA_WRITE(bh); /* write */
+ memset(buf, 0, osb->sect_size);
+ set_buffer_uptodate(bh);
+ OCFS_BH_PUT_DATA(bh);
+ fatal = ocfs_journal_dirty(handle, bh);
+ }
+ }
+
+ if (fatal)
+ goto fail;
+
+ *err = 0;
+ return bh;
+
+fail:
+ if (bh) {
+ brelse (bh);
+ bh = NULL;
+ }
+ *err = -EIO;
+ return NULL;
+}
+
/*
* ocfs_get_block()
*
@@ -905,8 +956,8 @@
__u32 len;
int oin_locked = 0;
- LOG_ENTRY_ARGS ("(0x%p, %llu, 0x%p, %d)\n", inode,
- (unsigned long long)iblock, bh_result, create);
+ LOG_ENTRY_ARGS ("(0x%p, %ld, 0x%p, %d)\n", inode, iblock, bh_result,
+ create);
if (S_ISLNK (inode->i_mode)) {
err = ocfs_symlink_get_block (inode, iblock, bh_result, create);
@@ -982,7 +1033,7 @@
int err = 0;
struct inode *inode = mapping->host;
- LOG_ENTRY_ARGS("(block = %llu)\n", (unsigned long long)block);
+ LOG_ENTRY_ARGS("(block = %lu)\n", block);
if (!inode) {
LOG_ERROR_STR ("bmap: bad inode");
@@ -1657,8 +1708,8 @@
int needs_trunc;
ocfs_super *osb;
- LOG_ENTRY_ARGS("(inode = 0x%p, ino = %lu)\n", inode,
- inode ? inode->i_ino : 0);
+ LOG_ENTRY_ARGS("(inode = 0x%p, ino = %llu)\n", inode,
+ inode ? GET_INODE_FEOFF(inode) : 0ULL);
if (!inode) {
LOG_TRACE_STR("eep, no inode!\n");
@@ -1733,14 +1784,14 @@
* in here! */
offset = GET_INODE_FEOFF(inode);
if (offset == 0) {
- LOG_ERROR_ARGS("inode %lu has zero offset\n", inode->i_ino);
+ LOG_ERROR_ARGS("inode %llu has zero offset\n", GET_INODE_FEOFF(inode));
status = -EINVAL;
goto leave;
}
if (INODE_DELETED(inode)) {
- LOG_TRACE_ARGS("Inode %lu was marked as deleted!",
- inode->i_ino);
+ LOG_TRACE_ARGS("Inode %llu was marked as deleted!",
+ GET_INODE_FEOFF(inode));
status = -ENOENT;
goto leave;
}
@@ -1769,6 +1820,7 @@
goto leave;
}
+#if 0
disk_len = strlen(fe->filename);
status = -ENOENT;
@@ -1787,12 +1839,15 @@
LOG_TRACE_STR ("file entry name did not match inode");
goto leave;
}
+#endif
if ((OCFS_I(inode)->alloc_size != (__s64) fe->alloc_size) ||
(inode->i_size != (__s64) fe->file_size) ||
(OCFS_I(inode)->chng_seq_num != DISK_LOCK_SEQNUM (fe)) ||
inode->i_uid != fe->uid ||
- inode->i_gid != fe->gid || inode->i_mode != fe->prot_bits){
+ inode->i_gid != fe->gid ||
+ inode->i_mode != fe->prot_bits ||
+ inode->i_nlink != fe->link_cnt){
if (OCFS_I(inode)->alloc_size > (__s64)fe->alloc_size){
ocfs_extent_map_destroy (&OCFS_I(inode)->map);
@@ -1802,8 +1857,9 @@
LOG_TRACE_STR("Allocsize, filesize or seq no did not match");
OCFS_I(inode)->alloc_size = fe->alloc_size;
inode->i_size = fe->file_size;
+printk("verifyupdate: setting nlink from %d to %d for %llu\n", inode->i_nlink, fe->link_cnt, GET_INODE_FEOFF(inode));
+ inode->i_nlink = fe->link_cnt;
OCFS_I(inode)->chng_seq_num = DISK_LOCK_SEQNUM (fe);
-
inode->i_blocks = (inode->i_size + osb->sect_size) >> osb->sect_size_bits;
inode->i_uid = fe->uid;
inode->i_gid = fe->gid;
@@ -1821,8 +1877,6 @@
switch (fe->attribs) {
case OCFS_ATTRIB_DIRECTORY:
- inode->i_size = OCFS_DEFAULT_DIR_NODE_SIZE;
- inode->i_blocks = (inode->i_size + osb->sect_size) >> osb->sect_size_bits;
inode->i_mode |= S_IFDIR;
break;
case OCFS_ATTRIB_SYMLINK:
Modified: branches/new-dir-format/src/io.c
===================================================================
--- branches/new-dir-format/src/io.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/io.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -28,448 +28,7 @@
#define OCFS_DEBUG_CONTEXT OCFS_DEBUG_CONTEXT_IO
-static int ocfs_read_bhs_iarr (ocfs_super * osb, __u64 off, __u64 len,
- struct buffer_head *bhs[], int flags,
- struct inode *inodes[]);
-static int ocfs_write_bhs_iarr (ocfs_super * osb, struct buffer_head *bhs[],
- int nr, int flags, struct inode *inodes[]);
-
-void ocfs_put_fileent_inode(int idx, struct inode **arr)
-{
- switch (idx) {
- case 0:
- case 255:
- break;
- default:
- /* release the ref from the get */
- if (arr[idx]) {
- struct inode *i = arr[idx];
- if (i->i_state == I_CLEAR ||
- atomic_read(&i->i_count)==0) {
- LOG_ERROR_ARGS("about to iput inode (%lu,%d,%s) one too many times!\n",
- i->i_ino, atomic_read(&i->i_count),
- i->i_state == I_CLEAR ? "clear" : "not clear");
- BUG();
- }
- iput(i);
- }
- break;
- }
-}
-
-struct inode * ocfs_get_fileent_inode(ocfs_super *osb, int idx, struct buffer_head *bhs[],
- struct inode *parent)
-{
- unsigned long top = bhs[0]->b_blocknr;
- struct inode *retval = NULL;
-
- switch (idx) {
- case 0:
- case 255:
- retval = parent;
- break;
- default:
- /* this will iget() the inode if non-NULL */
- retval = ocfs_inode_hash_lookup(osb, (top+idx) << 9);
- break;
- }
- return retval;
-}
-
-/* caching for dirnodes is now straighforward */
-/* if there is an inode for a given offset, use its seqnum to determine caching */
-/* if there is no inode, then it is definitely a sync read (barring buffer_jbd) */
-
-int ocfs_write_dirnode(ocfs_super * osb, struct buffer_head *bhs[],
- struct inode *hdr_inode)
-{
- int status, i;
- struct inode **arr = NULL;
-
- LOG_ENTRY();
-
- arr = (struct inode **) ocfs_malloc (256 * sizeof(struct inode *));
- if (!arr) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto bail;
- }
-
- for (i=0; i< 256; i++)
- arr[i] = ocfs_get_fileent_inode(osb, i, bhs, hdr_inode);
-
- status = ocfs_write_bhs_iarr (osb, bhs, 256, 0, arr);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- for (i=0; i<256; i++)
- ocfs_put_fileent_inode(i, arr);
- ocfs_safefree(arr);
-
-bail:
- LOG_EXIT_STATUS(status);
- return status;
-}
-
-int ocfs_read_dirnode(ocfs_super * osb, __u64 off, int sync,
- struct buffer_head *bhs[], struct inode *hdr_inode)
-{
- int status, i, max, total=1;
- struct inode **arr = NULL;
- ocfs_dir_node *dir;
- unsigned long blk;
-
- LOG_ENTRY();
-
- if (sync) {
- status = ocfs_read_bhs (osb, off, osb->vol_layout.dir_node_size,
- bhs, 0, hdr_inode);
- if (status < 0)
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
-
- status = ocfs_read_bh (osb, off, &bhs[0], OCFS_BH_CACHED, hdr_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- dir = (ocfs_dir_node *) OCFS_BH_GET_DATA_READ(bhs[0]);
- max = ocfs_get_max_dir_index(dir);
- max++; // zero-indexed
- OCFS_BH_PUT_DATA(bhs[0]);
-
- if (max > 0) {
- total = max+1;
- arr = (struct inode **) ocfs_malloc (total * sizeof(struct inode *));
- if (!arr) {
- LOG_ERROR_STATUS(status = -ENOMEM);
- goto bail;
- }
-
- for (i=0; i<total; i++) {
- arr[i] = ocfs_get_fileent_inode(osb, i, bhs, hdr_inode);
- }
-
- /* read only as many blocks as maximum of dir index */
- status = ocfs_read_bhs_iarr (osb,
- off + 512ULL,
- max << 9,
- &bhs[1],
- OCFS_BH_CACHED,
- &arr[1]);
- if (status < 0)
- LOG_ERROR_STATUS(status);
-
- for (i=0; i<total; i++)
- ocfs_put_fileent_inode(i, arr);
-
- ocfs_safefree(arr);
- } else {
- total = 1;
- }
-
- /* fill in the remainder of the blocks not read from disk */
- for (i=total, blk = ((unsigned long)(off >> 9) + total); i<256; i++, blk++) {
- bhs[i] = getblk (OCFS_GET_BLOCKDEV(osb->sb), blk, 512);
- if (!buffer_uptodate(bhs[i]) && !buffer_jbd(bhs[i])
- && !buffer_dirty(bhs[i]))
- memset(bhs[i]->b_data, 'P', 512);
- }
-bail:
- LOG_EXIT_STATUS(status);
- return status;
-}
-
-
-static int ocfs_write_bhs_iarr (ocfs_super * osb, struct buffer_head *bhs[],
- int nr, int flags, struct inode *inodes[])
-{
- int status = 0;
- int i;
- struct super_block *sb;
- ocfs_blockdev dev;
- struct buffer_head *bh;
-
-#ifdef OCFS_DBG_TIMING
- my_timing_t begin, end;
-#endif
-
- LOG_ENTRY_ARGS("(bh[0]->b_blocknr = %llu, nr=%d, flags=%u, inodes=%p)\n",
- (unsigned long long)bhs[0]->b_blocknr, nr, flags, inodes);
-#ifdef OCFS_DBG_TIMING
- rdtsc (begin.lohi[0], begin.lohi[1]);
-#endif
-
- if (osb == NULL || osb->sb == NULL || bhs == NULL) {
- LOG_TRACE_STR("osb == NULL || osb->sb == NULL || bhs == "
- "NULL");
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- if (nr > 256)
- LOG_TRACE_ARGS ("Getting write for %d blocks\n", nr);
-
- sb = osb->sb;
- dev = OCFS_GET_BLOCKDEV(sb);
-
- /* we don't ever want cached writes -- those should go to the
- * journal so we can control when they actually hit disk and
- * so we can make sure they never get overwritten by a
- * subsequent read. */
- if ((flags & OCFS_BH_CACHED) || (flags & OCFS_BH_COND_CACHED)) {
- LOG_TRACE_STR("asking for a cached write!");
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- for (i = 0 ; i < nr ; i++) {
- bh = bhs[i];
- if (bh == NULL) {
- LOG_TRACE_STR("bh == NULL");
- status = -EIO;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- check_rootdir_overwrite(bh);
-
- if (check_block_zero_write(bh) < 0) {
- status = -EIO;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- if (flags & OCFS_BH_CONCURRENT_WRITE)
- goto skip_modified_check;
-
- /* Make sure the buffer is locked for modify, and
- * we're the ones with the write lock on this
- * buffer. */
- if (!buffer_modified(bh)) {
- printk("ocfs2: modified bit is NOT set on buffer "
- "(bh->b_blocknr = %llu)!\n",
- (unsigned long long)bh->b_blocknr);
- BUG();
- }
- if (ocfs_bh_sem_lock_modify(bh) == OCFS_BH_SEM_WAIT_ON_MODIFY){
- printk("ocfs2: someone else owns this buffer"
- "(bh->b_blocknr = %llu)!\n",
- (unsigned long long)bh->b_blocknr);
- BUG();
- }
- ocfs_bh_sem_unlock(bh);
-
-skip_modified_check:
- if (!(flags & OCFS_BH_IGNORE_JBD) && buffer_jbd(bh)) {
-#ifdef VERBOSE_BH_JBD_TRACE
- LOG_TRACE_ARGS("trying to write a jbd managed bh "
- "(blocknr = %llu), nr=%d\n",
- (unsigned long long)bh->b_blocknr, nr);
-#endif
- continue;
- }
-
- lock_buffer(bh);
- set_buffer_uptodate(bh);
-
- /* remove from dirty list before I/O. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- /*
- * mark_buffer_clean() doesn't exist in 2.6.x kernels.
- * Not many places actually used mark_buffer_clean, but
- * at least reiserfs uses clear_buffer_dirty() as
- * a replacment.
- */
- clear_buffer_dirty(bh);
-#else
- mark_buffer_clean(bh);
-#endif
-
- bh->b_end_io = ocfs_end_buffer_io_sync;
- submit_bh(WRITE, bh);
- }
-
- for (i = (nr-1) ; i >= 0; i--) {
- bh = bhs[i];
-
- wait_on_buffer(bh);
-
- if (inodes[i])
- SET_BH_SEQNUM(inodes[i], bh);
- else
- CLEAR_BH_SEQNUM(bh);
-
- if (!(flags & OCFS_BH_CONCURRENT_WRITE))
- ocfs_clear_buffer_modified(bh);
- }
-
-bail:
-
-#ifdef OCFS_DBG_TIMING
- IO_FUNC_TIMING_PRINT("ocfs_write_bhs_iarr", status);
-#endif
-
- LOG_EXIT_STATUS(status);
- return status;
-}
-
-/*
- * ocfs_read_bhs_iarr()
- *
- */
-static int ocfs_read_bhs_iarr (ocfs_super * osb, __u64 off, __u64 len,
- struct buffer_head *bhs[], int flags,
- struct inode *inodes[])
-{
- int status = 0;
- struct super_block *sb;
- int nr, i, ignore_cache = 0;
- __u64 blocknum;
- ocfs_blockdev dev;
- struct buffer_head *bh;
-
-#ifdef OCFS_DBG_TIMING
- my_timing_t begin, end;
-#endif
- LOG_ENTRY_ARGS("(off=(%llu), len=(%llu), flags=%d, inodes=%p)\n", off,
- len, flags, inodes);
-#ifdef OCFS_DBG_TIMING
- rdtsc (begin.lohi[0], begin.lohi[1]);
-#endif
-
- if (len % 512) {
- LOG_TRACE_ARGS("len %% 512 (len=%llu)\n", len);
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- if (osb == NULL || osb->sb == NULL || bhs == NULL) {
- LOG_TRACE_STR("osb == NULL || osb->sb == NULL || bhs == NULL "
- "|| num == NULL");
- status = -EINVAL;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- if ((flags & OCFS_BH_COND_CACHED) &&
- (off >= osb->vol_layout.bitmap_off))
- flags |= OCFS_BH_CACHED;
-
- if (OCFS_NONCACHED(osb, off)) {
- if (flags & OCFS_BH_CACHED)
- LOG_TRACE_STR("hey bozo you are trying to write "
- "a system thingy cached!");
- flags &= ~OCFS_BH_CACHED;
- }
-
- sb = osb->sb;
- dev = OCFS_GET_BLOCKDEV(sb);
- blocknum = off >> sb->s_blocksize_bits;
-
- nr = (len + 511) >> 9;
- if (nr == 0) {
- LOG_TRACE_STR("No buffers will be read!!!");
- LOG_TRACE_ARGS("Len=%llu Off=%llu numbuffers=%u "
- "blocknum=%llu\n", len, off,
- nr, blocknum);
- status = 0;
- goto bail;
- }
-
- for (i = 0 ; i < nr ; i++) {
- if (bhs[i] == NULL) {
- bhs[i] = getblk (dev, blocknum++, sb->s_blocksize);
- if (bhs[i] == NULL) {
- LOG_TRACE_STR("bh == NULL");
- status = -EIO;
- LOG_ERROR_STATUS(status);
- goto bail;
- }
- }
- bh = bhs[i];
- ignore_cache = 0;
-
- /* Lock everyone else out of this bh */
- OCFS_BH_GET_DATA_READ(bh);
-
- if (!inodes[i]) {
- ignore_cache = 1;
- } else if (flags & OCFS_BH_CACHED && !TEST_BH_SEQNUM(inodes[i], bh)) {
-#ifdef VERBOSE_BH_SEQNUM_TRACE
- LOG_TRACE_ARGS("(read) bh (%llu) seqnum (%lu) does not "
- "match inode (%u)\n",
- (unsigned long long)bh->b_blocknr,
- (bh->b_state & STATE_BIT_MASK) >> 19,
- atomic_read(GET_INODE_CLEAN_SEQ(inodes[i])));
-#endif
- ignore_cache = 1;
- }
-
- if ((flags & OCFS_BH_CACHED) && (!buffer_uptodate(bh)))
- ignore_cache = 1;
-
- if (buffer_jbd(bh)) {
-#ifdef VERBOSE_BH_JBD_TRACE
- if (!(flags & OCFS_BH_CACHED) || ignore_cache)
- LOG_TRACE_ARGS("trying to sync read a jbd "
- "managed bh (blocknr = %llu)\n",
- (unsigned long long)bh->b_blocknr);
-#endif
- continue;
- }
-
- if (!(flags & OCFS_BH_CACHED) || ignore_cache) {
- if (buffer_dirty(bh)) {
- /* This should probably be a BUG, or
- * at least return an error. */
- LOG_TRACE_ARGS("asking me to sync read a "
- "dirty buffer! (blocknr = %llu)\n",
- (unsigned long long)bh->b_blocknr);
- continue;
- }
-
- lock_buffer(bh);
- clear_buffer_uptodate(bh);
- bh->b_end_io = ocfs_end_buffer_io_sync;
- submit_bh(READ, bh);
- continue;
- }
- }
-
- status = 0;
-
- for (i = (nr-1); i >= 0; i--) {
- bh = bhs[i];
-
- wait_on_buffer(bh);
-
- if (inodes[i])
- SET_BH_SEQNUM(inodes[i], bh);
- else
- CLEAR_BH_SEQNUM(bh);
-
- OCFS_BH_PUT_DATA(bh);
- }
- LOG_TRACE_ARGS("off=(%llu), len=(%llu), cached=%s\n", off, len,
- (!(flags & OCFS_BH_CACHED) || ignore_cache) ? "no" : "yes");
-
-bail:
-
-#ifdef OCFS_DBG_TIMING
- IO_FUNC_TIMING_PRINT("ocfs_read_bhs_iarr", status);
-#endif
-
- LOG_EXIT_STATUS(status);
- return status;
-}
-
int ocfs_write_bhs (ocfs_super * osb, struct buffer_head *bhs[],
int nr, int flags, struct inode *inode)
{
@@ -483,8 +42,8 @@
my_timing_t begin, end;
#endif
- LOG_ENTRY_ARGS("(bh[0]->b_blocknr = %llu, nr=%d, flags=%u, inode=%p)\n",
- (unsigned long long)bhs[0]->b_blocknr, nr, flags, inode);
+ LOG_ENTRY_ARGS("(bh[0]->b_blocknr = %lu, nr=%d, flags=%u, inode=%p)\n",
+ bhs[0]->b_blocknr, nr, flags, inode);
#ifdef OCFS_DBG_TIMING
rdtsc (begin.lohi[0], begin.lohi[1]);
#endif
@@ -523,8 +82,6 @@
goto bail;
}
- check_rootdir_overwrite(bh);
-
if (check_block_zero_write(bh) < 0) {
status = -EIO;
LOG_ERROR_STATUS(status);
@@ -539,14 +96,12 @@
* buffer. */
if (!buffer_modified(bh)) {
printk("ocfs2: modified bit is NOT set on buffer "
- "(bh->b_blocknr = %llu)!\n",
- (unsigned long long)bh->b_blocknr);
+ "(bh->b_blocknr = %lu)!\n", bh->b_blocknr);
BUG();
}
if (ocfs_bh_sem_lock_modify(bh) == OCFS_BH_SEM_WAIT_ON_MODIFY){
printk("ocfs2: someone else owns this buffer"
- "(bh->b_blocknr = %llu)!\n",
- (unsigned long long)bh->b_blocknr);
+ "(bh->b_blocknr = %lu)!\n", bh->b_blocknr);
BUG();
}
ocfs_bh_sem_unlock(bh);
@@ -555,8 +110,8 @@
if (!(flags & OCFS_BH_IGNORE_JBD) && buffer_jbd(bh)) {
#ifdef VERBOSE_BH_JBD_TRACE
LOG_TRACE_ARGS("trying to write a jbd managed bh "
- "(blocknr = %llu), nr=%d\n",
- (unsigned long long)bh->b_blocknr, nr);
+ "(blocknr = %lu), nr=%d\n",
+ bh->b_blocknr, nr);
#endif
continue;
}
@@ -689,9 +244,8 @@
if (flags & OCFS_BH_CACHED && inode &&
!TEST_BH_SEQNUM(inode, bh)) {
#ifdef VERBOSE_BH_SEQNUM_TRACE
- LOG_TRACE_ARGS("(read) bh (%llu) seqnum (%lu) does not "
- "match inode (%u)\n",
- (unsigned long long)bh->b_blocknr,
+ LOG_TRACE_ARGS("(read) bh (%lu) seqnum (%lu) does not "
+ "match inode (%u)\n", bh->b_blocknr,
(bh->b_state & STATE_BIT_MASK) >> 19,
atomic_read(GET_INODE_CLEAN_SEQ(inode)));
#endif
@@ -705,8 +259,8 @@
#ifdef VERBOSE_BH_JBD_TRACE
if (!(flags & OCFS_BH_CACHED) || ignore_cache)
LOG_TRACE_ARGS("trying to sync read a jbd "
- "managed bh (blocknr = %llu)\n",
- (unsigned long long)bh->b_blocknr);
+ "managed bh (blocknr = %lu)\n",
+ bh->b_blocknr);
#endif
continue;
}
@@ -716,15 +270,18 @@
/* This should probably be a BUG, or
* at least return an error. */
LOG_TRACE_ARGS("asking me to sync read a "
- "dirty buffer! (blocknr = %llu)\n",
- (unsigned long long)bh->b_blocknr);
+ "dirty buffer! (blocknr = %lu)\n",
+ bh->b_blocknr);
continue;
}
lock_buffer(bh);
clear_buffer_uptodate(bh);
bh->b_end_io = ocfs_end_buffer_io_sync;
- submit_bh(READ, bh);
+ if (flags & OCFS_BH_READAHEAD)
+ submit_bh(READA, bh);
+ else
+ submit_bh(READ, bh);
continue;
}
}
Modified: branches/new-dir-format/src/journal.c
===================================================================
--- branches/new-dir-format/src/journal.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/journal.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -365,9 +365,6 @@
else
kern_handle->h_sync = 0;
- for(i = 0; i < handle->num_buffs; i++)
- check_rootdir_overwrite(handle->buffs[i]);
-
/* actually stop the transaction. if we've set h_sync,
* it'll have been commited when we return */
retval = journal_stop(kern_handle);
@@ -536,9 +533,9 @@
CLEAR_BH_SEQNUM(bh);
if (buffer_jbd(bh))
- LOG_ERROR_ARGS("Buffer %llu has JBD bit set "
+ LOG_ERROR_ARGS("Buffer %lu has JBD bit set "
"after a journal_forget!\n",
- (unsigned long long)bh->b_blocknr);
+ bh->b_blocknr);
lock_buffer(bh);
clear_buffer_uptodate(bh);
@@ -638,9 +635,9 @@
int i;
int found = 0;
- LOG_ENTRY_ARGS("(bh->b_blocknr=%llu, type=%d (\"%s\"), "
+ LOG_ENTRY_ARGS("(bh->b_blocknr=%lu, type=%d (\"%s\"), "
"bh->b_size = %hu)\n",
- (unsigned long long)bh->b_blocknr, type,
+ bh->b_blocknr, type,
(type == OCFS_JOURNAL_ACCESS_CREATE) ?
"OCFS_JOURNAL_ACCESS_CREATE" :
"OCFS_JOURNAL_ACCESS_WRITE", bh->b_size);
@@ -648,8 +645,7 @@
/* we can safely remove this assertion after testing. */
if (!buffer_uptodate(bh)) {
printk("ocfs2: giving me a buffer that's not uptodate!\n");
- printk("ocfs2: b_blocknr=%llu\n",
- (unsigned long long)bh->b_blocknr);
+ printk("ocfs2: b_blocknr=%lu\n", bh->b_blocknr);
BUG();
}
/* by taking a "read" lock, we prevent anyone from doing any
@@ -684,15 +680,13 @@
*
* Otherwise, we make a copy of the data in the buffer. */
if (!buffer_jbd(bh) && type == OCFS_JOURNAL_ACCESS_CREATE) {
- LOG_TRACE_ARGS("Making block (%llu) a forget block at "
- "position %d\n",
- (unsigned long long)bh->b_blocknr, i);
+ LOG_TRACE_ARGS("Making block (%lu) a forget block at "
+ "position %d\n", bh->b_blocknr, i);
handle->co_buffs[i].data = NULL;
handle->co_buffs[i].forget = 1;
} else {
- LOG_TRACE_ARGS("Copying block (%llu) out to position"
- "%d\n",
- (unsigned long long)bh->b_blocknr, i);
+ LOG_TRACE_ARGS("Copying block (%lu) out to position"
+ "%d\n", bh->b_blocknr, i);
/* This malloc should just be a slab. */
handle->co_buffs[i].data = ocfs_malloc(bh->b_size);
if (handle->co_buffs[i].data == NULL) {
@@ -743,8 +737,7 @@
int status = -1;
int i;
- LOG_ENTRY_ARGS("(bh->b_blocknr=%llu)\n",
- (unsigned long long)bh->b_blocknr);
+ 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!");
@@ -757,9 +750,8 @@
*/
for(i = 0; i < handle->num_buffs; i++) {
if (handle->buffs[i] == bh) {
- LOG_TRACE_ARGS("block (%llu) already added to dirty "
- "list!\n",
- (unsigned long long)bh->b_blocknr);
+ LOG_TRACE_ARGS("block (%lu) already added to dirty " \
+ "list!\n", bh->b_blocknr);
goto call_jbd;
}
}
@@ -778,8 +770,7 @@
status = journal_dirty_metadata(handle->k_handle, bh);
if (status < 0) {
LOG_ERROR_ARGS("Could not dirty metadata buffer. "
- "(bh->b_blocknr=%llu)\n",
- (unsigned long long)bh->b_blocknr);
+ "(bh->b_blocknr=%lu)\n", bh->b_blocknr);
LOG_TRACE_ARGS("Setting handle->buffs[%d] = NULL\n", i);
brelse(bh);
handle->buffs[i] = NULL;
@@ -787,8 +778,6 @@
goto done;
}
- check_rootdir_overwrite(bh);
-
status = 0;
done:
LOG_EXIT_STATUS(status);
@@ -804,8 +793,7 @@
{
ocfs_journal_lock *lock;
- LOG_ENTRY_ARGS("(id=%llu, type=%u, flags=%u, bh=%p)\n",
- (unsigned long long)bh->b_blocknr, type, flags, bh);
+ LOG_ENTRY_ARGS("(id=%lu, type=%u, flags=%u, bh=%p)\n", bh->b_blocknr, type, flags, bh);
lock = ocfs_malloc(sizeof(ocfs_journal_lock));
if (lock == NULL) {
Modified: branches/new-dir-format/src/lockres.c
===================================================================
--- branches/new-dir-format/src/lockres.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/lockres.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -49,7 +49,7 @@
struct buffer_head *tmpbh = NULL, **b = NULL;
ocfs_file_entry *fe;
int flags;
- ocfs_lock_res *lockres = GET_INODE_LOCKRES(inode);
+ ocfs_lock_res *lockres = GET_INODE_LOCKRES(inode);;
LOG_ENTRY_ARGS ("(0x%p, %llu, 0x%p, 0x%p, 0x%p)\n", osb,
lock_id, lockres, bh, updated);
Modified: branches/new-dir-format/src/namei.c
===================================================================
--- branches/new-dir-format/src/namei.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/namei.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -30,9 +30,16 @@
extern spinlock_t oin_num_ext_lock;
-static int ocfs_fe_smash (ocfs_super * osb, __u32 flags, ocfs_journal_handle *passed_handle, struct dentry *dentry, struct inode *parent_inode);
-static int ocfs_rename_file (ocfs_super * osb, ocfs_journal_handle *handle,
-struct dentry *dentry, __u64 file_off, struct inode *dir_inode);
+static int inline search_dirblock(struct buffer_head * bh, struct inode *dir, struct dentry *dentry, unsigned long offset, struct ocfs2_dir_entry ** res_dir);
+static int ocfs_delete_entry (ocfs_journal_handle *handle, struct inode * dir, struct ocfs2_dir_entry * de_del, struct buffer_head * bh);
+static int ocfs_add_entry (ocfs_journal_handle *handle, struct dentry *dentry, struct inode *inode, __u64 inode_off);
+static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de);
+
+
+
+
+static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir, struct dentry *dentry, int mode, ocfs_dev dev, struct buffer_head **new_fe_bh, ocfs_journal_handle *handle, struct inode *inode);
+
static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir,
struct dentry *dentry, int mode,
ocfs_dev dev,
@@ -46,10 +53,6 @@
__u64 id2, __u32 type2, __u32 flags2,
struct buffer_head **bh2,
struct inode *inode2);
-static int ocfs_fix_extent_pointers(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct buffer_head *fe_bh,
- struct inode *inode);
static struct dentry_operations ocfs_dentry_ops = {
.d_revalidate = ocfs_dentry_revalidate // let's test it out!
@@ -67,11 +70,12 @@
{
int status;
ocfs_file_entry *fe = NULL;
- struct buffer_head *fe_bh = NULL;
+ struct buffer_head *fe_bh = NULL, *dirent_bh = NULL;
struct inode *inode = NULL;
struct super_block *sb = dir->i_sb;
struct dentry *ret;
ocfs_super *osb = OCFS_SB(sb);
+ struct ocfs2_dir_entry *dirent = NULL;
LOG_ENTRY_ARGS ("(0x%p, 0x%p, '%*s')\n", dir, dentry,
dentry->d_name.len, dentry->d_name.name);
@@ -85,8 +89,8 @@
LOG_TRACE_ARGS("about to call find_files_on_disk with inode=%p\n",
dir);
- status = ocfs_find_files_on_disk (osb, &(dentry->d_name),
- &fe_bh, NULL, dir, 1);
+ inode = NULL; // no inode yet
+ status = ocfs_find_files_on_disk (osb, dentry, &fe_bh, dir, inode, 1, &dirent_bh, &dirent);
if (status < 0)
goto bail_add;
@@ -114,6 +118,8 @@
bail:
if (fe_bh)
brelse(fe_bh);
+ if (dirent_bh)
+ brelse(dirent_bh);
LOG_EXIT_PTR (ret);
return ret;
@@ -124,8 +130,7 @@
{
int status = 0;
struct buffer_head *parent_fe_bh = NULL;
- __u64 parent_off;
- __u64 file_off = 0;
+ __u64 parent_off, file_off;
ocfs_journal_handle *handle = NULL;
ocfs_super *osb;
ocfs_file_entry *fe = NULL;
@@ -194,12 +199,10 @@
fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(new_fe_bh); /* read */
- file_off = fe->this_sector;
-
ocfs_populate_inode (inode, fe, mode, 1);
insert_inode_hash (inode);
- ocfs_inode_hash_bind(osb, GET_INODE_FEOFF(inode), inode);
+ file_off = fe->this_sector;
handle->new_file_lockid = fe->this_sector;
OCFS_BH_PUT_DATA(new_fe_bh);
fe = NULL;
@@ -209,6 +212,61 @@
status = ocfs_update_lockres (osb, GET_INODE_FEOFF(inode),
&new_fe_bh, NULL, 0, inode, 0, 0);
+ if (S_ISDIR (mode)) {
+ struct buffer_head *newdirbh = NULL;
+ int retval = 0;
+ struct ocfs2_dir_entry *de = NULL;
+
+ newdirbh = ocfs_bread (handle, inode, 0, 1, &retval, 0);
+ if (!newdirbh) {
+ LOG_ERROR_STATUS(status = retval);
+ goto leave;
+ }
+ status = ocfs_journal_access(handle, newdirbh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ brelse(newdirbh);
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ de = (struct ocfs2_dir_entry *) OCFS_BH_GET_DATA_WRITE(newdirbh); /* write */
+ de->inode = cpu_to_le64(file_off);
+ de->name_len = 1;
+ de->rec_len = cpu_to_le16(OCFS_DIR_REC_LEN(de->name_len));
+ strcpy (de->name, ".");
+ ocfs_set_de_type(dir->i_sb, de, S_IFDIR);
+ de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+ de->inode = cpu_to_le64(parent_off);
+ de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-OCFS_DIR_REC_LEN(1));
+ de->name_len = 2;
+ strcpy (de->name, "..");
+ ocfs_set_de_type(dir->i_sb, de, S_IFDIR);
+ inode->i_nlink = 2;
+ OCFS_BH_PUT_DATA(newdirbh);
+ status = ocfs_journal_dirty(handle, newdirbh);
+ brelse (newdirbh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ inode->i_size = inode->i_sb->s_blocksize;
+
+ status = ocfs_journal_access(handle, parent_fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(parent_fe_bh); /* write */
+ fe->link_cnt++;
+ OCFS_BH_PUT_DATA(parent_fe_bh);
+ fe = NULL;
+ status = ocfs_journal_dirty(handle, parent_fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ dir->i_nlink++;
+ }
+
d_instantiate (dentry, inode);
ocfs_commit_trans(handle);
@@ -249,29 +307,46 @@
*/
static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir,
struct dentry *dentry, int mode,
- ocfs_dev dev,
- struct buffer_head **new_fe_bh,
+ ocfs_dev dev, struct buffer_head **new_fe_bh,
ocfs_journal_handle *handle,
struct inode *inode)
{
int status = 0;
ocfs_file_entry *fe = NULL;
- struct buffer_head *fe_bh = NULL;
- int i;
- unsigned long blk;
+ __u64 bitmapOffset = 0;
+ __u64 fileOffset = 0;
LOG_ENTRY_ARGS ("(0x%p, 0x%p, %d, %d, '%*s')\n", dir, dentry, mode,
dev, dentry->d_name.len, dentry->d_name.name);
- if (new_fe_bh)
- *new_fe_bh = NULL;
+ OCFS_ASSERT(new_fe_bh);
+ *new_fe_bh = NULL;
- if ((fe = ocfs_allocate_file_entry ()) == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
+ down(&osb->node_alloc_sem);
+ status = ocfs_alloc_node_block (osb, osb->inode_size,
+ &bitmapOffset, &fileOffset, osb->node_num,
+ DISK_ALLOC_INODE, handle);
+ up(&osb->node_alloc_sem);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
goto leave;
}
+
+ status = ocfs_read_bh(osb, bitmapOffset, new_fe_bh,
+ OCFS_BH_CACHED, inode);
- memset (fe, 0, sizeof (ocfs_file_entry));
+ status = ocfs_journal_access(handle, *new_fe_bh, OCFS_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+
+ fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(*new_fe_bh); /* write */
+ memset (fe, 0, osb->sect_size);
+ inode->i_ino = ino_from_off(osb->sb, bitmapOffset);
+ fe->this_sector = bitmapOffset;
+ fe->alloc_file_off = fileOffset;
+ fe->alloc_node = osb->node_num;
fe->uid = current->fsuid;
fe->gid = current->fsgid;
fe->prot_bits = mode & 0007777;
@@ -283,9 +358,8 @@
fe->dev_minor = MINOR (dir->i_sb->s_dev);
}
- if (S_ISLNK (mode) || S_ISDIR (mode) || S_ISREG (mode)) {
+ 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;
@@ -302,9 +376,11 @@
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;
+ if (S_ISDIR (mode))
+ fe->link_cnt = 2;
+ else
+ fe->link_cnt = 1;
+
fe->local_ext = 1;
fe->granularity = -1;
fe->next_free_ext = 0;
@@ -318,103 +394,34 @@
DISK_LOCK_READER_NODE (fe) = osb->node_num;
DISK_LOCK_WRITER_NODE (fe) = osb->node_num;
DISK_LOCK_OIN_MAP(fe) = (1 << osb->node_num);
-
fe->create_time = fe->modify_time = OCFS_CURRENT_TIME;
+ fe->dir_node_ptr = GET_INODE_FEOFF(dir);
+ OCFS_BH_PUT_DATA(*new_fe_bh);
+ fe = NULL;
- 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 >> osb->sect_size_bits;
- 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 */
- down(&osb->node_alloc_sem);
- status = ocfs_alloc_node_block (osb, osb->vol_layout.dir_node_size, &bitmapOffset, &fileOffset, osb->node_num, DISK_ALLOC_DIR_NODE, handle);
- up(&osb->node_alloc_sem);
- 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->u.child_dirnode = bitmapOffset;
- fe->file_size = osb->vol_layout.dir_node_size;
- fe->next_del = INVALID_DIR_NODE_INDEX;
-
- blk = (unsigned long)(bitmapOffset >> osb->sect_size_bits);
- for (i = 0; i < numblks; i++) {
- dirbhs[i] = getblk (OCFS_GET_BLOCKDEV(osb->sb),
- blk++, osb->sb->s_blocksize);
-
- set_buffer_uptodate(dirbhs[i]);
- status = ocfs_journal_access(handle, dirbhs[i],
- OCFS_JOURNAL_ACCESS_CREATE);
- if (status < 0) {
- while (i >= 0)
- brelse(dirbhs[i--]);
- ocfs_safefree(dirbhs);
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- tmp = OCFS_BH_GET_DATA_WRITE(dirbhs[i]); /* write */
- memset(tmp, 0, osb->sect_size);
- OCFS_BH_PUT_DATA(dirbhs[i]);
- status = ocfs_journal_dirty(handle, dirbhs[i]);
- if (status < 0) {
- while (i >= 0)
- brelse(dirbhs[i--]);
- ocfs_safefree(dirbhs);
- LOG_ERROR_STATUS(status);
- goto leave;
- }
-
- }
-
- new_dir = (ocfs_dir_node *) OCFS_BH_GET_DATA_WRITE(dirbhs[0]); /* write */
- 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;
-
- /* cleanup after ourselves */
- for(i=0; i < numblks; i++)
- brelse(dirbhs[i]);
-
- ocfs_safefree (dirbhs);
+ status = ocfs_journal_dirty(handle, *new_fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
}
- status = ocfs_insert_file (osb, fe, &fe_bh, handle, dir, inode);
+ status = ocfs_add_entry (handle, dentry, inode, bitmapOffset);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto leave;
}
- if (new_fe_bh)
- *new_fe_bh = fe_bh;
-
- SET_BH_SEQNUM(inode, fe_bh);
+ SET_BH_SEQNUM(inode, *new_fe_bh);
leave:
- ocfs_release_file_entry(fe);
-
+ if (fe) {
+ OCFS_BH_PUT_DATA(*new_fe_bh);
+ fe = NULL;
+ }
+
+ if (status < 0 && *new_fe_bh) {
+ brelse(*new_fe_bh);
+ *new_fe_bh = NULL;
+ }
LOG_EXIT_STATUS (status);
return status;
} /* ocfs_mknod_locked */
@@ -475,92 +482,252 @@
*/
int ocfs_unlink (struct inode *dir, struct dentry *dentry)
{
- int status;
- struct inode *inode;
+ int status, tmpstat;
+ int got_parent = 0, got_file = 0;
+ struct inode *inode = dentry->d_inode;
int retval = -EBUSY;
- ocfs_super *osb = NULL;
- __u64 fileOff;
- int do_release = 0;
+ ocfs_super *osb = OCFS_SB(dir->i_sb);
+ __u64 fileOff = GET_INODE_FEOFF(inode);
struct inode *parentInode = dentry->d_parent->d_inode;
+ ocfs_file_entry *fe = NULL;
+ __u32 lockFlags = (S_ISDIR (inode->i_mode) ? (FLAG_FILE_DELETE | FLAG_DIR) : FLAG_FILE_DELETE);
+ struct buffer_head *fe_bh = NULL;
+ struct buffer_head *parent_node_bh = NULL; /* parent locknode */
+ ocfs_journal_handle *handle = NULL;
+ __u64 parent_off = GET_INODE_FEOFF(parentInode);
+ __u64 parent_dirnode_off = OCFS_I(parentInode)->u.child_dirnode;
+ struct ocfs2_dir_entry *dirent = NULL;
+ struct buffer_head *dirent_bh = NULL;
+ int drop_inode = 0, dec_parent = 0;
+
LOG_ENTRY_ARGS ("(0x%p, 0x%p, '%*s')\n", dir, dentry,
dentry->d_name.len, dentry->d_name.name);
- inode = dentry->d_inode;
- osb = OCFS_SB(dir->i_sb);
+ LOG_TRACE_ARGS("ino = %llu\n", fileOff);
- fileOff = GET_INODE_FEOFF(inode);
- if (fileOff == -1)
- BUG();
-
- LOG_TRACE_ARGS("fileOff = %llu, ino = %lu\n", fileOff, inode->i_ino);
-
status = -EBUSY;
- if (!ocfs_empty(dentry)) {
+ if (!empty_dir(inode)) {
LOG_TRACE_STR ("dentry is not empty, cannot delete");
+ goto bail;
} else if (OCFS_I(inode)->open_hndl_cnt > 0) {
LOG_TRACE_ARGS ("Cannot remove an open file (open_hndl_cnt = %u, fileOff = %llu, d_count=%u)\n", OCFS_I(inode)->open_hndl_cnt, fileOff, atomic_read(&dentry->d_count));
- } else if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+ goto bail;
+ } else if (inode == osb->root_inode) {
LOG_TRACE_STR ("Cannot delete the root directory");
status = -EPERM;
- } else if (OCFS_I(inode)->oin_flags & OCFS_OIN_DELETE_ON_CLOSE) {
- LOG_TRACE_STR ("OCFS_OIN_DELETE_ON_CLOSE set");
- status = 0;
- do_release = 1;
- } else {
- status = -EFAIL;
- do_release = 1;
+ goto bail;
+ }
+ status = -EFAIL;
- spin_lock(&oin_num_ext_lock);
- if (OCFS_I(inode)->num_extends) {
- LOG_ERROR_ARGS ("Cannot remove a file with = "
- "%u, pending extends (fileOff "
- "= %llu)\n",
- OCFS_I(inode)->num_extends,
- fileOff);
- spin_unlock(&oin_num_ext_lock);
- status = -EBUSY;
- goto bail;
- }
+ spin_lock(&oin_num_ext_lock);
+ if (OCFS_I(inode)->num_extends) {
+ LOG_ERROR_ARGS ("Cannot remove a file with = "
+ "%u, pending extends (fileOff "
+ "= %llu)\n",
+ OCFS_I(inode)->num_extends,
+ fileOff);
spin_unlock(&oin_num_ext_lock);
+ status = -EBUSY;
+ goto bail;
+ }
+ spin_unlock(&oin_num_ext_lock);
- down (&(OCFS_I(inode)->priv_sem));
- OCFS_SET_FLAG (OCFS_I(inode)->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
- up (&(OCFS_I(inode)->priv_sem));
+ handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
+ if (handle == NULL) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto leave;
+ }
- status = ocfs_fe_smash (osb, 0, NULL, dentry, parentInode);
+ /* lock parent directory, yes we use FLAG_FILE_CREATE even
+ * though we're deleting ;) */
+ status = ocfs_acquire_lock(osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE|FLAG_DIR, NULL,
+ parentInode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ got_parent = 1;
+ /* this will re-read the directory now with the EXCLUSIVE */
+ /* lock already held; it will also return the fe_bh to us */
+ status = ocfs_find_files_on_disk (osb, dentry, &fe_bh, parentInode,
+ inode, 0, &dirent_bh, &dirent);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ status = ocfs_acquire_lock (osb, fileOff, OCFS_DLM_EXCLUSIVE_LOCK,
+ lockFlags, &fe_bh, inode);
+ if (status < 0) {
+ if (status != -EINTR)
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+ got_file = 1;
+
+ if (S_ISDIR (inode->i_mode)) {
+ if (!empty_dir(inode)) {
+ status = -ENOTEMPTY;
+ goto leave;
+ } else if (inode->i_nlink != 2) {
+ status = -ENOTEMPTY;
+ goto leave;
+ }
+ }
+
+ status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+
+ /* need to preserve locking order, so take a 'write' lock on
+ * the dirnode sector first. it won't get passed to
+ * journal_dirty until ocfs_remove_file so clean up the write
+ * lock on errors before that */
+ status = ocfs_read_bh(osb, parent_dirnode_off, &parent_node_bh,
+ OCFS_BH_CACHED, parentInode);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+ OCFS_BH_GET_DATA_WRITE(parent_node_bh);
+ OCFS_BH_PUT_DATA(parent_node_bh);
+
+ /* we call ocfs_clear_buffer_modified in several error cases
+ * here if we set the modify bit on this buffer, but haven't
+ * journal_dirtied it yet. Otherwise, it'll stay modified even
+ * after the abort_trans. */
+ fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(fe_bh); /* write */
+ if (S_ISDIR (inode->i_mode))
+ fe->link_cnt = 0;
+ else
+ fe->link_cnt--;
+ if (!fe->link_cnt) {
+ drop_inode = 1;
+ 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);
+
+ if (drop_inode) {
+ /* Free up all the bits in the bitmap. */
+ /* mark all the extents (and extent metadata) for
+ * this file so we can remove them after commit. */
+ /* TODO: delay this. see orphan comment below */
+ status = ocfs_free_file_extents (osb, fe_bh, handle, inode);
if (status < 0) {
- if (status != -ENOTEMPTY && status != -EPERM &&
- status != -EBUSY && status != -EINTR)
+ ocfs_clear_buffer_modified(fe_bh);
+ ocfs_clear_buffer_modified(parent_node_bh);
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+
+ /* delete the name from the parent dir */
+ status = ocfs_delete_entry (handle, parentInode, dirent, dirent_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ /*
+ * TODO: we should link this entry into the local orphan dir after
+ * deleting the name from the parent. do NOT do the free_file_extents
+ * in this function. delay it until triggered by orphan_del (by
+ * delete_inode, truncate or similar)
+ */
+ if (S_ISDIR (inode->i_mode)) {
+ ocfs_file_entry *dirfe;
+ status = ocfs_journal_access(handle, parent_node_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ dirfe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(parent_node_bh);
+ dirfe->link_cnt--;
+ OCFS_BH_PUT_DATA(parent_node_bh);
+ status = ocfs_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ dec_parent=1;
+ }
+ }
- down (&(OCFS_I(inode)->priv_sem));
- OCFS_CLEAR_FLAG (OCFS_I(inode)->oin_flags, OCFS_OIN_DELETE_ON_CLOSE);
- up (&(OCFS_I(inode)->priv_sem));
- goto bail;
- }
+ status = ocfs_journal_dirty(handle, fe_bh);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+
+leave:
+ if (handle) {
+ if (status < 0)
+ ocfs_abort_trans(handle);
+ else
+ ocfs_commit_trans(handle);
}
- if (do_release)
- {
- inode->i_nlink--;
- retval = 0;
+ /* need this to alert dentry-owners on other nodes */
+ /* Release the file lock if we acquired it */
+ if (got_file) {
+ tmpstat = ocfs_release_lock(osb, fileOff,
+ OCFS_DLM_EXCLUSIVE_LOCK,
+ lockFlags, fe_bh, inode);
+ if (tmpstat < 0)
+ LOG_ERROR_STATUS(tmpstat);
+
}
+ if (got_parent) {
+ tmpstat = ocfs_release_lock(osb, parent_off,
+ OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE|FLAG_DIR,
+ NULL, parentInode);
+ if (tmpstat < 0)
+ LOG_ERROR_STATUS(tmpstat);
+
+ }
+
+ if (status >= 0) {
+ // already checked to make sure dir has nlink==2
+ if (S_ISDIR (inode->i_mode))
+ inode->i_nlink = 0;
+ else
+ inode->i_nlink--;
+ if (dec_parent)
+ dir->i_nlink--;
+#warning is INODE_DELETED needed anymore?
+ if (drop_inode)
+ SET_INODE_DELETED(inode);
+ }
bail:
if (status < 0 && status != -ENOTEMPTY &&
- status != -EPERM && status != -EBUSY)
+ status != -EPERM && status != -EBUSY && status != -EINTR) {
+ LOG_ERROR_STATUS(status);
retval = -EBUSY;
- else
+ } else
retval = status;
+ if (fe_bh)
+ brelse(fe_bh);
+
+ if (dirent_bh)
+ brelse(dirent_bh);
+
+ if (parent_node_bh)
+ brelse(parent_node_bh);
+
+
#ifndef BH_SEM_LEAK_CHECKING
if (retval < 0)
#endif
ocfs_bh_sem_hash_cleanup_pid(ocfs_getpid());
+
LOG_EXIT_INT (retval);
return retval;
} /* ocfs_unlink */
@@ -657,135 +824,11 @@
return(status);
} /* ocfs_double_lock */
-/*
- * ocfs_fix_extent_pointers
- *
- * If you move a file entry from one directory to another, the files
- * offset changes (obviously). This function updates all the
- * up_hdr_node_ptr's on any extents hanging off that file entry.
- */
-static int ocfs_fix_extent_pointers(ocfs_super *osb,
- ocfs_journal_handle *handle,
- struct buffer_head *fe_bh,
- struct inode *inode)
-{
- int status = 0;
- ocfs_file_entry *fe = NULL;
- __u64 new_ptr;
- struct buffer_head *extent_bh = NULL;
- ocfs_extent_group *extent = NULL;
- int i;
- LOG_ENTRY();
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(fe_bh);
-
- if (!IS_VALID_FILE_ENTRY(fe)) {
- LOG_ERROR_STATUS(status = -EINVAL);
- goto bail;
- }
-
- LOG_TRACE_ARGS("fe->this_sector = %llu, fe->local_ext = %s, "
- "fe->next_free_ext = %u\n",
- fe->this_sector,
- (fe->local_ext) ? "true" : "false",
- fe->next_free_ext);
-
- /* If we have local extents, then don't even worry about
- * this. Directories, by definition, always have local_ext
- * true, so we don't need a seperate check for them. */
- if (fe->local_ext)
- goto bail;
-
-
- new_ptr = fe->this_sector;
-
- for(i = 0; i < fe->next_free_ext; i++) {
- status = ocfs_read_bh(osb, fe->extents[i].disk_off, &extent_bh,
- OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- status = ocfs_journal_access(handle, extent_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- extent = (ocfs_extent_group *) OCFS_BH_GET_DATA_WRITE(extent_bh);
- if ((!IS_VALID_EXTENT_HEADER(extent))
- && (!IS_VALID_EXTENT_DATA(extent))) {
- LOG_ERROR_STATUS(status = -EINVAL);
- OCFS_BH_PUT_DATA(extent_bh);
- ocfs_clear_buffer_modified(extent_bh);
- goto bail;
- }
-
- /* this next line does the real work of the function. */
- extent->up_hdr_node_ptr = new_ptr;
-
- OCFS_BH_PUT_DATA(extent_bh);
- extent = NULL;
-
- status = ocfs_journal_dirty(handle, extent_bh);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
- }
-
- brelse(extent_bh);
- extent_bh = NULL;
- }
-bail:
- if (fe)
- OCFS_BH_PUT_DATA(fe_bh);
-
- if (extent_bh) {
- if (extent)
- OCFS_BH_PUT_DATA(extent_bh);
- brelse(extent_bh);
- }
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
-static int ocfs_ugly_rename_thingy(ocfs_super *osb, __u64 oldoff, __u64 newoff);
-
-static int ocfs_ugly_rename_thingy(ocfs_super *osb, __u64 oldoff, __u64 newoff)
-{
- int status = 0;
- ocfs_journal *journal = &osb->journal;
- ocfs_journal_handle *handle=NULL;
- ocfs_journal_lock *j_lock;
- struct list_head *tmp1, *tmp2;
-
- LOG_ENTRY();
-
- /* and now for an ugly journal hack! */
- down(&journal->commit_sem);
- list_for_each(tmp1, &(journal->commited)) {
- handle = list_entry(tmp1, ocfs_journal_handle, h_list);
-
- list_for_each(tmp2, &handle->locks) {
- j_lock = list_entry(tmp2, ocfs_journal_lock,
- lock_list);
- if (j_lock->bh) {
- brelse(j_lock->bh);
- j_lock->bh = NULL;
- }
- }
-
- }
-
- up(&journal->commit_sem);
-
- LOG_EXIT_STATUS(status);
- return(status);
-}
-
+#define PARENT_INO(buffer) \
+ ((struct ocfs2_dir_entry *) ((char *) buffer + \
+ le16_to_cpu(((struct ocfs2_dir_entry *) buffer)->rec_len)))->inode
/*
* ocfs_rename()
*
@@ -802,21 +845,22 @@
ocfs_file_entry *tmpfe = NULL;
ocfs_super *osb = NULL;
__u64 oldOffset, newDirOff, oldDirOff;
- __u64 tmpoff = 0;
- int kill_newfe = 0;
- int delete_target_oin = 0;
- ocfs_bitmap_free_head *free_head = NULL;
+ __u64 newfe_lockid = 0;
ocfs_journal_handle *handle = NULL;
__u32 dir_lock_flags = FLAG_FILE_CREATE | FLAG_DIR;
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;
- int needs_trunc = 0;
+ int needs_trunc = 0, drop_inode = 0;
int got_oldlock = 0, got_newlock = 0;
-
+ struct ocfs2_dir_entry *old_de = NULL, *new_de = NULL; // dirent for old_dentry
+ // and new_dentry
+ struct buffer_head *new_de_bh = NULL, *old_de_bh = NULL; // bhs for above
+ struct buffer_head *old_inode_de_bh = NULL; // if old_dentry is a dir,
+ // this is the 1st dirent bh
+ nlink_t old_dir_nlink = old_dir->i_nlink, new_dir_nlink = new_dir->i_nlink;
+
LOG_ENTRY_ARGS ("(0x%p, 0x%p, 0x%p, 0x%p, from='%*s' to='%*s')\n",
old_dir, old_dentry, new_dir, new_dentry,
old_dentry->d_name.len, old_dentry->d_name.name,
@@ -832,6 +876,7 @@
/* new parent dir offset */
newDirOff = GET_INODE_FEOFF(new_dir);
+
if (new_inode) {
if (ocfs_inc_icount(new_inode) < 0)
@@ -847,7 +892,7 @@
}
if (new_inode && S_ISDIR (old_inode->i_mode) &&
- !ocfs_empty (new_dentry)) {
+ !empty_dir (new_inode)) {
status = -ENOTEMPTY;
LOG_TRACE_STR ("New (directory) dentry NOT empty!");
goto bail;
@@ -869,16 +914,12 @@
/* Locking hierarchy will be broken */
if (new_inode) {
- if (!(OCFS_I(new_inode)->oin_flags & OCFS_OIN_DELETE_ON_CLOSE)) {
- /* OIN exists and it's not marked for deletion! */
- down (&(OCFS_I(new_inode)->priv_sem));
- status = ocfs_verify_update_inode (osb, new_inode,
- &needs_trunc, 0);
- up (&(OCFS_I(new_inode)->priv_sem));
- delete_target_oin = 1;
- if (needs_trunc)
- ocfs_truncate_inode_pages(new_inode, 0);
- }
+ down (&(OCFS_I(new_inode)->priv_sem));
+ status = ocfs_verify_update_inode (osb, new_inode,
+ &needs_trunc, 0);
+ up (&(OCFS_I(new_inode)->priv_sem));
+ if (needs_trunc)
+ ocfs_truncate_inode_pages(new_inode, 0);
}
/* start our transaction */
@@ -909,14 +950,13 @@
if (S_ISDIR(old_inode->i_mode))
oldfe_flags = FLAG_DIR;
- oldfe_lockid = GET_INODE_FEOFF(old_inode);
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,
+ status = ocfs_acquire_lock(osb, oldOffset, OCFS_DLM_EXCLUSIVE_LOCK,
oldfe_flags, NULL, old_inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -924,11 +964,38 @@
}
got_oldlock = 1;
+ if (S_ISDIR(old_inode->i_mode)) {
+ status = -EIO;
+ old_inode_de_bh = ocfs_bread (handle, old_inode, 0, 0, &status, 0);
+ if (!old_inode_de_bh)
+ goto finally;
+ if (le64_to_cpu(PARENT_INO(old_inode_de_bh->b_data)) !=
+ GET_INODE_FEOFF(old_dir))
+ goto finally;
+ status = -EMLINK;
+ if (!new_inode && new_dir!=old_dir &&
+ new_dir->i_nlink >= OCFS_LINK_MAX)
+ goto finally;
+ }
+
+ status = -ENOENT;
+ old_de_bh = ocfs_find_entry (old_dentry, &old_de);
+ if (!old_de_bh)
+ goto finally;
+
+ /*
+ * Check for inode number is _not_ due to possible IO errors.
+ * We might rmdir the source, keep it as pwd of some process
+ * and merrily kill the link to whatever was created under the
+ * same name. Goodbye sticky bit ;-<
+ */
+ if (le64_to_cpu(old_de->inode) != GET_INODE_FEOFF(old_inode))
+ goto finally;
+
/* check if the target already exists (in which case we need
* to delete it */
- status = ocfs_find_files_on_disk(osb, &(new_dentry->d_name),
- &newfe_bh, NULL, new_dir, 0);
-
+ status = ocfs_find_files_on_disk(osb, new_dentry, &newfe_bh,
+ new_dir, new_inode, 0, &new_de_bh, &new_de);
/* The only error we allow here is -ENOENT because the new
* file not existing is perfectly valid. */
if ((status < 0) && (status != -ENOENT)) {
@@ -938,12 +1005,10 @@
goto finally;
}
- if (status == 0)
- kill_newfe = 1;
-
/* In case we need to overwrite an existing file, we blow it
* away first */
- if (kill_newfe) {
+ if (new_de) {
+ /* TODO: change this block to the ext3-style orphan model */
newfe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(newfe_bh); /* read */
if (newfe->attribs & OCFS_ATTRIB_DIRECTORY)
newfe_flags = FLAG_DIR;
@@ -951,13 +1016,11 @@
newfe_lockid = 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, NULL,
+ newfe_flags, &newfe_bh,
new_inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -965,161 +1028,159 @@
}
got_newlock = 1;
- status = ocfs_fe_smash (osb, 0, handle, new_dentry,
- new_dir);
+ status = ocfs_journal_access(handle, newfe_bh, OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto finally;
}
- }
+
+ /* need to preserve locking order, so take a 'write' lock on
+ * the dirnode sector first. it won't get passed to
+ * journal_dirty until ocfs_remove_file so clean up the write
+ * lock on errors before that */
+ OCFS_BH_GET_DATA_WRITE(new_dir_bh);
+ OCFS_BH_PUT_DATA(new_dir_bh);
-
- /* 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, FLAG_DEL_NAME | FLAG_DEL_INODE,
- handle, old_dentry, old_dir);
- if (status < 0) {
- if (status != -ENOTEMPTY && status != -EINTR &&
- status != -EBUSY)
- LOG_ERROR_STATUS (status);
+ /* we call ocfs_clear_buffer_modified in several error cases
+ * here if we set the modify bit on this buffer, but haven't
+ * journal_dirtied it yet. Otherwise, it'll stay modified even
+ * after the abort_trans. */
+ newfe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(newfe_bh); /* write */
+ if (S_ISDIR (new_inode->i_mode) && !empty_dir(new_inode)) {
+ status = -ENOTEMPTY;
+ OCFS_BH_PUT_DATA(newfe_bh);
+ ocfs_clear_buffer_modified(new_dir_bh);
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;
+ if (S_ISDIR (new_inode->i_mode))
+ newfe->link_cnt = 0;
+ else
+ newfe->link_cnt--;
+ if (!newfe->link_cnt) {
+ OCFS_SET_FLAG (newfe->sync_flags, OCFS_SYNC_FLAG_MARK_FOR_DELETION);
+ newfe->sync_flags &= (~OCFS_SYNC_FLAG_VALID);
+ drop_inode = 1;
}
+ OCFS_BH_PUT_DATA(newfe_bh);
- status = ocfs_read_bh(osb, oldOffset, &oldfe_bh,
- OCFS_BH_CACHED, old_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
+ if (drop_inode) {
+ /* Free up all the bits in the bitmap. */
+ /* mark all the extents (and extent metadata) for
+ * this file so we can remove them after commit. */
+ /* TODO: delay this. see orphan comment below */
+ status = ocfs_free_file_extents (osb, newfe_bh, handle, new_inode);
+ if (status < 0) {
+ ocfs_clear_buffer_modified(newfe_bh);
+ ocfs_clear_buffer_modified(new_dir_bh);
+ LOG_ERROR_STATUS (status);
+ goto finally;
+ }
+
+ /*
+ * TODO: we should link this entry into the local orphan dir after
+ * deleting the name from the parent. do NOT do the free_file_extents
+ * in this function. delay it until triggered by orphan_del (by
+ * delete_inode, truncate or similar)
+ */
+ status = ocfs_journal_dirty(handle, newfe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto finally;
+ }
}
- oldfe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(oldfe_bh); /* read */
- 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;
- DISK_LOCK_CURRENT_MASTER (tmpfe) = osb->node_num;
- DISK_LOCK_FILE_LOCK (tmpfe) = OCFS_DLM_ENABLE_CACHE_LOCK;
- DISK_LOCK_READER_NODE (tmpfe) = osb->node_num;
- DISK_LOCK_WRITER_NODE (tmpfe) = osb->node_num;
- DISK_LOCK_OIN_MAP(tmpfe) = (1 << osb->node_num);
- tmpfe->modify_time = OCFS_CURRENT_TIME;
-
- tmpoff = tmpfe->this_sector;
-
- down(&old_inode->i_sem);
- /* we take oin->priv_sem because we want to lock out
- * verify_update_oin, which reads fe_off from the
- * inode, but doesn't always have i_sem. */
- down(&OCFS_I(old_inode)->priv_sem);
-
- status = ocfs_insert_file(osb, tmpfe, &insert_bh,
- handle, new_dir, old_inode);
+ /* change the dirent to point to the correct inode */
+ status = ocfs_journal_access(handle, new_de_bh, OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
- up(&OCFS_I(old_inode)->priv_sem);
- up(&old_inode->i_sem);
LOG_ERROR_STATUS (status);
goto finally;
}
-
- status = ocfs_fix_extent_pointers(osb, handle, insert_bh,
- old_inode);
+ new_de->inode = le64_to_cpu(GET_INODE_FEOFF(old_inode));
+ new_de->file_type = old_de->file_type;
+ new_dir->i_version = ++event;
+ status = ocfs_journal_dirty(handle, new_de_bh);
if (status < 0) {
- up(&OCFS_I(old_inode)->priv_sem);
- up(&old_inode->i_sem);
- LOG_ERROR_STATUS (status);
+ LOG_ERROR_STATUS(status);
goto finally;
}
- LOG_TRACE_ARGS("(after) tmpfe->this_sector = %llu\n",
- tmpfe->this_sector);
- /* move the inode offset over to the new entry */
- status = ocfs_ugly_rename_thingy(osb,
- GET_INODE_FEOFF(old_inode),
- tmpfe->this_sector);
- if (status < 0) {
- up(&OCFS_I(old_inode)->priv_sem);
- up(&old_inode->i_sem);
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
- SET_INODE_FEOFF(old_inode, tmpfe->this_sector);
- OCFS_I(old_inode)->u.fe_private = tmpfe->u.fe_private;
- ocfs_inode_rehash(&osb->inode_hash, tmpoff,
- tmpfe->this_sector);
-
- up(&OCFS_I(old_inode)->priv_sem);
- up(&old_inode->i_sem);
} 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, new_dentry, oldOffset,
- new_dir);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- }
+ /* if the name was not found in new_dir, add it now */
+ status = ocfs_add_entry (handle, new_dentry, old_inode, oldOffset);
+ }
+
finally:
if (status < 0) {
ocfs_abort_trans(handle);
goto bail;
- } else {
- /* commit_trans */
- ocfs_commit_trans(handle);
+ }
- /* 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);
- }
+ old_inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty(old_inode);
- if (new_inode)
- fsync_inode_buffers(old_inode);
+ /* now that the name has been added to new_dir, remove the old name */
+ status = ocfs_delete_entry(handle, old_dir, old_de, old_de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto finally;
}
- old_inode->i_nlink++;
if (new_inode) {
- new_dir->i_mtime = new_dir->i_ctime = CURRENT_TIME;
- if (S_ISDIR (old_inode->i_mode))
+ new_inode->i_nlink--;
+ new_inode->i_ctime = CURRENT_TIME;
+ }
+ old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+ if (old_inode_de_bh) {
+ status = ocfs_journal_access(handle, old_inode_de_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ // BAD
+ goto bail;
+ }
+ PARENT_INO(old_inode_de_bh->b_data) = le64_to_cpu(GET_INODE_FEOFF(new_dir));
+ status = ocfs_journal_dirty(handle, old_inode_de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ // BAD
+ goto bail;
+ }
+ old_dir->i_nlink--;
+ if (new_inode) {
new_inode->i_nlink--;
- new_inode->i_nlink--;
- } else {
- if (S_ISDIR (old_inode->i_mode))
+ } else {
new_dir->i_nlink++;
+ mark_inode_dirty(new_dir);
+ }
}
- old_inode->i_nlink--;
- if (S_ISDIR (old_inode->i_mode)) {
- new_dir->i_mtime = new_dir->i_ctime = CURRENT_TIME;
- old_dir->i_nlink--;
+ mark_inode_dirty(old_dir);
+ if (new_inode) {
+ mark_inode_dirty(new_inode);
+ if (!new_inode->i_nlink)
+ ocfs_orphan_add(handle, new_inode);
}
+ if (old_dir != new_dir) {
+ if (new_dir_nlink != new_dir->i_nlink)
+ LOG_ERROR_ARGS("need to change nlink for new dir %llu from %d to %d\n",
+ GET_INODE_FEOFF(new_dir), new_dir_nlink, new_dir->i_nlink);
+ }
+ if (old_dir_nlink != old_dir->i_nlink)
+ LOG_ERROR_ARGS("need to change nlink for old dir %llu from %d to %d\n",
+ GET_INODE_FEOFF(old_dir), old_dir_nlink, old_dir->i_nlink);
+
+ /* commit_trans */
+ ocfs_commit_trans(handle);
+
+ if (new_inode)
+ fsync_inode_buffers(old_inode);
+
+ status = 0;
+
bail:
if (got_oldlock) {
- ocfs_release_lock(osb, oldfe_lockid,
+ ocfs_release_lock(osb, oldOffset,
OCFS_DLM_EXCLUSIVE_LOCK,
oldfe_flags, NULL, old_inode);
}
@@ -1151,8 +1212,12 @@
brelse(old_dir_bh);
if (new_dir_bh)
brelse(new_dir_bh);
- if (free_head)
- ocfs_free_bitmap_free_head(free_head);
+ if (new_de_bh)
+ brelse(new_de_bh);
+ if (old_de_bh)
+ brelse(old_de_bh);
+ if (old_inode_de_bh)
+ brelse(old_inode_de_bh);
#ifndef BH_SEM_LEAK_CHECKING
if (status < 0)
@@ -1269,7 +1334,6 @@
}
insert_inode_hash (inode);
- ocfs_inode_hash_bind(osb, GET_INODE_FEOFF(inode), inode);
d_instantiate (dentry, inode);
abort_trans:
@@ -1309,409 +1373,469 @@
} /* ocfs_symlink */
-/* ocfs_rename_file()
- *
- */
-static int ocfs_rename_file (ocfs_super * osb, ocfs_journal_handle *handle, struct dentry *dentry, __u64 file_off, struct inode *dir_inode)
+
+int ocfs_check_dir_entry (struct inode * dir, struct ocfs2_dir_entry * de, struct buffer_head * bh, unsigned long offset)
{
- int status = 0;
- ocfs_dir_node *pLockNode = NULL;
- ocfs_file_entry *fe = NULL;
- __u32 index;
- struct buffer_head *fe_bh = NULL, *dirbh = NULL;
- int cache_lock = 0, needs_reindex = 0;
- __u64 dir_node_ptr = 0;
- int flags = 0;
- struct qstr *file_name = &(dentry->d_name);
- struct inode *inode = dentry->d_inode;
+ const char * error_msg = NULL;
+ const int rlen = le16_to_cpu(de->rec_len);
+
+ if (rlen < OCFS_DIR_REC_LEN(1))
+ error_msg = "rec_len is smaller than minimal";
+ else if (rlen % 4 != 0)
+ error_msg = "rec_len % 4 != 0";
+ else if (rlen < OCFS_DIR_REC_LEN(de->name_len))
+ error_msg = "rec_len is too small for name_len";
+ else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
+ error_msg = "directory entry across blocks";
+
+ if (error_msg != NULL)
+ LOG_ERROR_ARGS("bad entry in directory #%llu: %s - "
+ "offset=%lu, inode=%llu, rec_len=%d, name_len=%d",
+ GET_INODE_FEOFF(dir), error_msg, offset,
+ le64_to_cpu(de->inode),
+ rlen, de->name_len);
+ return error_msg == NULL ? 1 : 0;
+}
- LOG_ENTRY ();
+static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de)
+{
+ if (len != de->name_len)
+ return 0;
+ if (!de->inode)
+ return 0;
+ return !memcmp(name, de->name, len);
+}
- 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;
- }
- fe = (ocfs_file_entry *)OCFS_BH_GET_DATA_READ(fe_bh); /* read */
- if (!IS_VALID_FILE_ENTRY(fe))
- BUG();
- dir_node_ptr = fe->dir_node_ptr;
- OCFS_BH_PUT_DATA(fe_bh);
- fe = NULL;
+static int ocfs_add_entry (ocfs_journal_handle *handle, struct dentry *dentry, struct inode *inode, __u64 inode_off)
+{
+ struct inode *dir = dentry->d_parent->d_inode;
+ const char *name = dentry->d_name.name;
+ int namelen = dentry->d_name.len;
+ unsigned long offset;
+ unsigned short rec_len;
+ struct buffer_head * bh;
+ struct ocfs2_dir_entry * de, * de1;
+ struct super_block * sb;
+ int retval, status;
+ char *buf = NULL;
- status = ocfs_read_bh (osb, dir_node_ptr, &dirbh, OCFS_BH_CACHED,
- inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
+ sb = dir->i_sb;
- status = ocfs_journal_access(handle, dirbh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- 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;
- }
+ if (!namelen)
+ return -EINVAL;
+ bh = ocfs_bread (handle, dir, 0, 0, &retval, 0);
+ if (!bh)
+ return retval;
+ rec_len = OCFS_DIR_REC_LEN(namelen);
+ offset = 0;
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ while (1) {
+ if ((char *)de >= sb->s_blocksize + bh->b_data) {
+ brelse (bh);
+ bh = NULL;
+ bh = ocfs_bread (handle, dir, offset >> sb->s_blocksize_bits, 1, &retval, 0);
+ if (!bh)
+ return retval;
+ if (dir->i_size <= offset) {
+ if (dir->i_size == 0) {
+ brelse(bh);
+ return -ENOENT;
+ }
- /* preserve bh lock ordering so grab the write on dirbh 1st. */
- pLockNode = (ocfs_dir_node *)OCFS_BH_GET_DATA_WRITE(dirbh); /* write */
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(fe_bh); /* write */
+ /* create next block */
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (buf) {
+#warning removemelater
+ LOG_ERROR_ARGS("oops. block=%lu\n", bh->b_blocknr);
+ BUG();
+ }
+ buf = OCFS_BH_GET_DATA_WRITE(bh); /* write */
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ de->inode = 0;
+ de->rec_len = le16_to_cpu(sb->s_blocksize);
+ dir->i_size = offset + sb->s_blocksize;
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ } else {
+ /* move to next block */
+ buf = OCFS_BH_GET_DATA_READ(bh); /* read */
+ de = (struct ocfs2_dir_entry *) bh->b_data;
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ }
+
+ }
+ if (buf) {
+#warning removemelater
+ LOG_ERROR_ARGS("oops. block=%lu\n", bh->b_blocknr);
+ BUG();
+ }
+ buf = OCFS_BH_GET_DATA_READ(bh); /* read */
+ if (!ocfs_check_dir_entry (dir, de, bh, offset)) {
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ brelse (bh);
+ return -ENOENT;
+ }
+ if (ocfs_match (namelen, name, de)) {
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ brelse (bh);
+ return -EEXIST;
+ }
+ if ((le64_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) ||
+ (le16_to_cpu(de->rec_len) >= OCFS_DIR_REC_LEN(de->name_len) + rec_len)) {
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ buf = OCFS_BH_GET_DATA_WRITE(bh); /* write */
+ /* By now the buffer is marked for journaling */
+ offset += le16_to_cpu(de->rec_len);
+ if (le64_to_cpu(de->inode)) {
+ de1 = (struct ocfs2_dir_entry *) ((char *) de +
+ OCFS_DIR_REC_LEN(de->name_len));
+ de1->rec_len =
+ cpu_to_le16(le16_to_cpu(de->rec_len) -
+ OCFS_DIR_REC_LEN(de->name_len));
+ de->rec_len = cpu_to_le16(OCFS_DIR_REC_LEN(de->name_len));
+ de = de1;
+ }
+ de->file_type = OCFS_FT_UNKNOWN;
+ if (inode_off) {
+ de->inode = cpu_to_le64(inode_off);
+ ocfs_set_de_type(dir->i_sb, de, inode->i_mode);
+ } else
+ de->inode = 0;
+ de->name_len = namelen;
+ memcpy (de->name, name, namelen);
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
- if (!IS_VALID_DIR_NODE(pLockNode))
- BUG();
-
- /* Change the actual name now */
- fe->filename[0] = '\0';
- strncpy (fe->filename, file_name->name, file_name->len);
- fe->filename[file_name->len] = '\0';
- DISK_LOCK_SEQNUM (fe) = 0;
- SET_VALID_BIT (fe->sync_flags);
- fe->sync_flags &= ~(OCFS_SYNC_FLAG_CHANGE);
-
- /* mark the dirnode as dirty */
- pLockNode->index_dirty = 1;
- pLockNode->bad_off = (fe->this_sector - dir_node_ptr) >> osb->sect_size_bits;
- 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) {
- 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;
+ dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+ dir->i_version = ++event;
+ status = ocfs_journal_dirty(handle, bh);
+ brelse(bh);
+ return 0;
}
+ offset += le16_to_cpu(de->rec_len);
+ de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
}
+ if (buf)
+ OCFS_BH_PUT_DATA(bh);
+ buf = NULL;
+ brelse (bh);
+ return -ENOSPC;
+}
-leave:
- if (fe != NULL)
- OCFS_BH_PUT_DATA(fe_bh);
- if (fe_bh)
- brelse(fe_bh);
- if (dirbh)
- brelse(dirbh);
-
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_rename_file */
-
-/* This is broken as it only checks the 1st dir node, and doesn't even
- * check the right field. Also, it will change with the new directory
- * structures. Return a negative value on error, 0 on empty or a positive
- * value on not empty. */
-static int ocfs_is_dir_empty(ocfs_super *osb, struct inode *dir_inode, __u64 dir_node_off)
+/*
+ * ocfs_delete_entry deletes a directory entry by merging it with the
+ * previous entry
+ */
+static int ocfs_delete_entry (ocfs_journal_handle *handle, struct inode * dir, struct ocfs2_dir_entry * de_del, struct buffer_head * bh)
{
- int status;
- struct buffer_head *dir_node_bh = NULL;
- __u8 numused;
- ocfs_dir_node *dirnode;
+ struct ocfs2_dir_entry * de, * pde;
+ int i, status = -ENOENT;
- LOG_ENTRY_ARGS("(dir_node_off == %llu)\n", dir_node_off);
-
- status = ocfs_read_bh(osb, dir_node_off, &dir_node_bh, OCFS_BH_CACHED,
- dir_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto bail;
+ i = 0;
+ pde = NULL;
+ de = (struct ocfs2_dir_entry *) OCFS_BH_GET_DATA_READ(bh); /* read */
+ while (i < bh->b_size) {
+ if (!ocfs_check_dir_entry(dir, de, bh, i)) {
+ OCFS_BH_PUT_DATA(bh);
+ status = -EIO;
+ goto bail;
+ }
+ if (de == de_del) {
+ OCFS_BH_PUT_DATA(bh);
+ status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ status = -EIO;
+ goto bail;
+ }
+ OCFS_BH_GET_DATA_WRITE(bh); /* write */
+ if (pde)
+ pde->rec_len = cpu_to_le16(le16_to_cpu(pde->rec_len) +
+ le16_to_cpu(de->rec_len));
+ else
+ de->inode = 0;
+ OCFS_BH_PUT_DATA(bh);
+ dir->i_version = ++event;
+ status = ocfs_journal_dirty(handle, bh);
+ goto bail;
+ }
+ i += le16_to_cpu(de->rec_len);
+ pde = de;
+ de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len));
}
-
- dirnode = (ocfs_dir_node *)OCFS_BH_GET_DATA_READ(dir_node_bh);/* read */
- if (!IS_VALID_DIR_NODE(dirnode)) {
- OCFS_BH_PUT_DATA(dir_node_bh);
- status = -EIO;
- LOG_TRACE_STR("Uhoh, invalid dirnode found!");
- goto bail;
- }
-
- numused = dirnode->num_ent_used;
- OCFS_BH_PUT_DATA(dir_node_bh);
-
- status = (int) numused;
+ OCFS_BH_PUT_DATA(bh);
bail:
- if (dir_node_bh)
- brelse(dir_node_bh);
-
- LOG_EXIT_STATUS(status);
- return(status);
+ return status;
}
-/* 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.
- *
- * FLAG_DEL_INODE - Do not remove the inode from our inode hash.
- *
- * 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)
- *
+/*
+ * Returns 0 if not found, -1 on failure, and 1 on success
*/
-static int ocfs_fe_smash (ocfs_super * osb, __u32 flags, ocfs_journal_handle *passed_handle, struct dentry *dentry, struct inode *parent_inode)
+static int inline search_dirblock(struct buffer_head * bh,
+ struct inode *dir,
+ struct dentry *dentry,
+ unsigned long offset,
+ struct ocfs2_dir_entry ** res_dir)
{
- int status = 0;
- int tmpstat;
- ocfs_file_entry *fe = NULL;
- __u32 lockFlags = 0;
- int local_handle = 0, is_dir;
- struct buffer_head *fe_bh = NULL;
- struct buffer_head *parent_node_bh = NULL; /* parent locknode */
- ocfs_journal_handle *handle = NULL;
- struct inode *inode = dentry->d_inode;
- int got_parent = 0, got_file = 0;
- __u64 file_off = GET_INODE_FEOFF(inode);
- __u64 parent_off = GET_INODE_FEOFF(parent_inode);
- __u64 parent_dirnode_off = OCFS_I(parent_inode)->u.child_dirnode;
+ struct ocfs2_dir_entry * de;
+ char * dlimit;
+ int de_len;
+ const char *name = dentry->d_name.name;
+ int namelen = dentry->d_name.len;
+ int ret = 0;
- LOG_ENTRY ();
+ de = (struct ocfs2_dir_entry *) OCFS_BH_GET_DATA_READ(bh); /* read */
+ dlimit = (char *)de + dir->i_sb->s_blocksize;
+ while ((char *) de < dlimit) {
+ /* this code is executed quadratically often */
+ /* do minimal checking `by hand' */
- if (passed_handle) {
- status = ocfs_read_bh (osb, file_off, &fe_bh, OCFS_BH_CACHED, inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
+ if ((char *) de + namelen <= dlimit &&
+ ocfs_match (namelen, name, de)) {
+ /* found a match - just to be sure, do a full check */
+ if (!ocfs_check_dir_entry(dir, de, bh, offset)) {
+ ret = -1;
+ goto bail;
+ }
+ *res_dir = de;
+ ret = 1;
+ goto bail;
}
- handle = passed_handle;
- goto skip_lock;
+ /* prevent looping on a bad block */
+ de_len = le16_to_cpu(de->rec_len);
+ if (de_len <= 0) {
+ ret = -1;
+ goto bail;
+ }
+ offset += de_len;
+ de = (struct ocfs2_dir_entry *) ((char *) de + de_len);
}
+bail:
+ OCFS_BH_PUT_DATA(bh);
+ return ret;
+}
- handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
- if (handle == NULL) {
- LOG_ERROR_STATUS (status = -ENOMEM);
- goto leave;
- }
- local_handle = 1;
- /* lock parent directory, yes we use FLAG_FILE_CREATE even
- * though we're deleting ;) */
- status = ocfs_acquire_lock(osb, parent_off, OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_DIR, NULL,
- parent_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- got_parent = 1;
- /* this will re-read the directory now with the EXCLUSIVE */
- /* lock already held; it will also return the fe_bh to us */
- status = ocfs_find_files_on_disk (osb, &(dentry->d_name), &fe_bh, NULL,
- parent_inode, 0);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
+struct buffer_head * ocfs_find_entry (struct dentry *dentry,
+ struct ocfs2_dir_entry ** res_dir)
+{
+ struct super_block * sb;
+ struct buffer_head * bh_use[NAMEI_RA_SIZE];
+ struct buffer_head * bh, *ret = NULL;
+ unsigned long start, block, b;
+ int ra_max = 0; /* Number of bh's in the readahead
+ buffer, bh_use[] */
+ int ra_ptr = 0; /* Current index into readahead
+ buffer */
+ int num = 0;
+ int nblocks, i, err;
+ struct inode *dir = dentry->d_parent->d_inode;
- if (S_ISDIR (inode->i_mode))
- lockFlags = (FLAG_FILE_DELETE | FLAG_DIR);
- else
- lockFlags = (FLAG_FILE_DELETE);
+ *res_dir = NULL;
+ sb = dir->i_sb;
- status = ocfs_acquire_lock (osb, file_off, OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, &fe_bh, inode);
- if (status < 0) {
- if (status != -EINTR)
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- got_file = 1;
+ nblocks = dir->i_size >> OCFS_SB(sb)->sect_size_bits;
+ start = OCFS_I(dir)->i_dir_start_lookup;
+ if (start >= nblocks)
+ start = 0;
+ block = start;
+restart:
+ do {
+ /*
+ * We deal with the read-ahead logic here.
+ */
+ if (ra_ptr >= ra_max) {
+ /* Refill the readahead buffer */
+ ra_ptr = 0;
+ b = block;
+ for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
+ /*
+ * Terminate if we reach the end of the
+ * directory and must wrap, or if our
+ * search has finished at this block.
+ */
+ if (b >= nblocks || (num && block == start)) {
+ bh_use[ra_max] = NULL;
+ break;
+ }
+ num++;
+
+#warning questionable readahead stuff here
+ bh = ocfs_bread(NULL, dir, b++, 0, &err, 1);
+ bh_use[ra_max] = bh;
+#if 0 // ???
+ if (bh)
+ ll_rw_block(READ, 1, &bh);
+#endif
+ }
+ }
+ if ((bh = bh_use[ra_ptr++]) == NULL)
+ goto next;
+ wait_on_buffer(bh);
+ if (!buffer_uptodate(bh)) {
+ /* read error, skip block & hope for the best */
+ brelse(bh);
+ goto next;
+ }
+ i = search_dirblock(bh, dir, dentry,
+ block << OCFS_SB(sb)->sect_size_bits, res_dir);
+ if (i == 1) {
+ OCFS_I(dir)->i_dir_start_lookup = block;
+ ret = bh;
+ goto cleanup_and_exit;
+ } else {
+ brelse(bh);
+ if (i < 0)
+ goto cleanup_and_exit;
+ }
+ next:
+ if (++block >= nblocks)
+ block = 0;
+ } while (block != start);
-skip_lock:
- status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
+ /*
+ * If the directory has grown while we were searching, then
+ * search the last part of the directory before giving up.
+ */
+ block = nblocks;
+ nblocks = dir->i_size >> OCFS_SB(sb)->sect_size_bits;
+ if (block < nblocks) {
+ start = 0;
+ goto restart;
}
+
+cleanup_and_exit:
+ /* Clean up the read-ahead blocks */
+ for (; ra_ptr < ra_max; ra_ptr++)
+ brelse (bh_use[ra_ptr]);
+ return ret;
+}
- /* need to preserve locking order, so take a 'write' lock on
- * the dirnode sector first. it won't get passed to
- * journal_dirty until ocfs_remove_file so clean up the write
- * lock on errors before that */
- status = ocfs_read_bh(osb, parent_dirnode_off, &parent_node_bh,
- OCFS_BH_CACHED, parent_inode);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto leave;
- }
- OCFS_BH_GET_DATA_WRITE(parent_node_bh);
- OCFS_BH_PUT_DATA(parent_node_bh);
- /* we call ocfs_clear_buffer_modified in several error cases
- * here if we set the modify bit on this buffer, but haven't
- * journal_dirtied it yet. Otherwise, it'll stay modified even
- * after the abort_trans. */
- fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(fe_bh); /* write */
- is_dir = S_ISDIR (inode->i_mode);
- if (fe->attribs & OCFS_ATTRIB_DIRECTORY && !is_dir)
- BUG();
+int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode)
+{
+ LOG_ERROR_ARGS("need to add %llu to orphan dir, i_nlink=%d\n",
+ GET_INODE_FEOFF(inode), inode->i_nlink);
+ return 0;
+}
- if (is_dir && !(flags & FLAG_DEL_NAME)) {
- int numused;
+int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode)
+{
+ return 0;
+}
- numused = ocfs_is_dir_empty(osb, inode, fe->u.child_dirnode);
- if (numused) {
- if (numused > 0)
- status = -ENOTEMPTY;
- else {
- status = numused;
- LOG_ERROR_STATUS(status);
- }
- OCFS_BH_PUT_DATA(fe_bh);
- ocfs_clear_buffer_modified(parent_node_bh);
- goto leave;
- }
- }
+#if 0
+static int ocfs_link (struct dentry * old_dentry,
+ struct inode * dir, struct dentry *dentry)
+{
+ ocfs_journal_handle *handle = NULL;
+ struct inode *inode = old_dentry->d_inode;
+ int err;
+ __u64 parent_off=0ULL, fe_off=0ULL;
+ int tmpstat;
+ struct buffer_head *bh = NULL;
+ ocfs_file_entry *fe = NULL;
- 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);
- ocfs_clear_buffer_modified(parent_node_bh);
- goto delete_entry;
- }
+ if (S_ISDIR(inode->i_mode))
+ return -EPERM;
- 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);
+ if (inode->i_nlink >= OCFS_LINK_MAX)
+ return -EMLINK;
- /* 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_READ(fe_bh); /* read */
- status = ocfs_free_directory_block (osb, fe, handle, inode);
- OCFS_BH_PUT_DATA(fe_bh);
- if (status < 0) {
- OCFS_BH_PUT_DATA(fe_bh);
- ocfs_clear_buffer_modified(parent_node_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, handle, inode);
- if (status < 0) {
- ocfs_clear_buffer_modified(fe_bh);
- ocfs_clear_buffer_modified(parent_node_bh);
- LOG_ERROR_STATUS (status);
- goto leave;
- }
+#define OCFS_DATA_TRANS_BLOCKS (3 * 8 - 2)
+ handle = ocfs_start_trans(osb, OCFS_DATA_TRANS_BLOCKS);
+ if (handle == NULL) {
+ return -ENOMEM;
}
+
+ /* lock the parent directory */
+ parent_off = GET_INODE_FEOFF(dir);
+ err = ocfs_acquire_lock (osb, parent_off,
+ OCFS_DLM_ENABLE_CACHE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR,
+ NULL, dir);
+ if (err < 0) {
+ parent_off = 0ULL;
+ if (err != -EINTR)
+ LOG_ERROR_STATUS (err);
+ goto bail;
+ }
-delete_entry:
- /* remove the fe from the dirnode.*/
- status = ocfs_remove_file(osb, fe_bh, parent_node_bh, handle,
- parent_inode, inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
+ /* lock the file entry */
+ fe_off = GET_INODE_FEOFF(inode);
+ err = ocfs_acquire_lock (osb, fe_off,
+ OCFS_DLM_ENABLE_CACHE_LOCK,
+ FLAG_FILE_CREATE,
+ &bh, inode);
+ if (err < 0) {
+ fe_off = 0ULL;
+ if (err != -EINTR)
+ LOG_ERROR_STATUS (err);
+ goto bail;
}
- status = ocfs_journal_dirty(handle, fe_bh);
- if (status < 0)
- LOG_ERROR_STATUS(status);
+ err = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (err < 0)
+ goto bail;
-leave:
+ fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_WRITE(bh);
+ fe->link_cnt++;
+ inode->i_nlink = fe->link_cnt;
+ inode->i_ctime = CURRENT_TIME;
+ atomic_inc(&inode->i_count);
+ OCFS_BH_PUT_DATA(bh);
- if (inode && status == 0 && !(flags & FLAG_DEL_INODE)) {
- SET_INODE_DELETED(inode);
-// printk("ocfs2: removing inode %lu, voteoff = %llu, "
-// "feoff = %llu, count = %u\n", inode->i_ino,
-// GET_INODE_VOTEOFF(inode),
-// GET_INODE_FEOFF(inode),
-// atomic_read(&inode->i_count));
- ocfs_inode_hash_remove(&osb->inode_hash,
- GET_INODE_FEOFF(inode));
+ err = ocfs_journal_dirty(handle, bh);
+ if (err < 0) {
+ inode->i_nlink--;
+ goto bail;
}
- if (local_handle && handle && (status < 0))
+ err = ocfs_add_entry(handle, dentry, inode);
+ if (err)
+ inode->i_nlink--;
+ else
+ d_instantiate(dentry, inode);
+bail:
+ if (err < 0)
ocfs_abort_trans(handle);
- else if (local_handle && handle)
+ else
ocfs_commit_trans(handle);
- /* 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 (got_file) {
- tmpstat = ocfs_release_lock(osb, file_off,
- OCFS_DLM_EXCLUSIVE_LOCK,
- lockFlags, fe_bh, inode);
+ if (parent_off) {
+ tmpstat = ocfs_release_lock (osb, parent_off,
+ OCFS_DLM_ENABLE_CACHE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR,
+ NULL, dir);
if (tmpstat < 0)
- LOG_ERROR_STATUS(tmpstat);
-
+ LOG_ERROR_STATUS (tmpstat);
}
-
- if (got_parent) {
- tmpstat = ocfs_release_lock(osb, parent_off,
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE|FLAG_DIR,
- NULL, parent_inode);
+ if (fe_off) {
+ tmpstat = ocfs_release_lock (osb, fe_off,
+ OCFS_DLM_ENABLE_CACHE_LOCK,
+ FLAG_FILE_CREATE,
+ bh, inode);
if (tmpstat < 0)
- LOG_ERROR_STATUS(tmpstat);
-
+ LOG_ERROR_STATUS (tmpstat);
}
- if (fe_bh)
- brelse(fe_bh);
+ if (bh)
+ brelse(bh);
- if (parent_node_bh)
- brelse(parent_node_bh);
+ // is this right?!
+ if (err)
+ iput(inode);
- LOG_EXIT_STATUS (status);
- return status;
-} /* ocfs_fe_smash */
+ return err;
+}
+#endif
Modified: branches/new-dir-format/src/nm.c
===================================================================
--- branches/new-dir-format/src/nm.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/nm.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -814,15 +814,14 @@
}
/* If the inode exists and we we're going to
- * vote yes on the delete, then lets remove it
- * from the hash now. It will retain a single
+ * vote yes on the delete, then lets mark it
+ * deleted now. It will retain a single
* reference for the rest of this function (we
* can sync it and change nlink) which we iput
* before exit. */
if (inode && vote_response == FLAG_VOTE_NODE) {
+#warning is this needed anymore?
SET_INODE_DELETED(inode);
- ocfs_inode_hash_remove(&osb->inode_hash,
- GET_INODE_FEOFF(inode));
}
if (!lockres) {
@@ -982,7 +981,7 @@
}
fe = (ocfs_file_entry *) OCFS_BH_GET_DATA_READ(fe_bh); /* read */
- is_dir = IS_VALID_DIR_NODE(fe);
+ is_dir = fe->attribs & OCFS_ATTRIB_DIRECTORY;
is_locked = DISK_LOCK_FILE_LOCK (fe) > OCFS_DLM_NO_LOCK;
if (vote_type == CHANGE_MASTER) {
OCFS_BH_PUT_DATA(fe_bh);
Modified: branches/new-dir-format/src/osb.c
===================================================================
--- branches/new-dir-format/src/osb.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/osb.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -143,19 +143,23 @@
if (vol_layout->file_node_size == 0)
vol_layout->file_node_size = OCFS_DEFAULT_FILE_NODE_SIZE;
+ osb->inode_size = OCFS_DEFAULT_INODE_SIZE;
+
/* get some pseudo constants for >> bits */
osb->sect_size_bits = ocfs_get_right_shift_bits(sect_size);
osb->cluster_size_bits = ocfs_get_right_shift_bits(vol_layout->cluster_size);
osb->dir_alloc_bits = ocfs_get_right_shift_bits(vol_layout->dir_node_size);
osb->file_alloc_bits = ocfs_get_right_shift_bits(vol_layout->file_node_size);
- printk("sectbits=%d, clusterbits=%d, dirbits=%d, filebits=%d\n",
+ osb->inode_alloc_bits = ocfs_get_right_shift_bits(osb->inode_size);
+ printk("sectbits=%d, clusterbits=%d, dirbits=%d, filebits=%d, inodebits=%d\n",
osb->sect_size_bits, osb->cluster_size_bits,
- osb->dir_alloc_bits, osb->file_alloc_bits);
+ osb->dir_alloc_bits, osb->file_alloc_bits, osb->inode_alloc_bits);
OCFS_ASSERT(osb->sect_size_bits);
OCFS_ASSERT(osb->cluster_size_bits);
OCFS_ASSERT(osb->dir_alloc_bits);
OCFS_ASSERT(osb->file_alloc_bits);
+ OCFS_ASSERT(osb->inode_alloc_bits);
osb->max_dir_node_ent = (__u32) (vol_layout->dir_node_size >> osb->sect_size_bits) - 2;
@@ -224,13 +228,6 @@
for(i = 0; i < OCFS_MAXIMUM_NODES; i++)
osb->last_publ_seq_num[i] = (__u64) (-1);
- /* init the inode hash */
- status = ocfs_inode_hash_init(osb);
- if (status < 0) {
- LOG_ERROR_STATUS (status);
- goto finally;
- }
-
/* 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 */
Modified: branches/new-dir-format/src/proc.c
===================================================================
--- branches/new-dir-format/src/proc.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/proc.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -170,9 +170,7 @@
item = list_entry (iter, alloc_item, list);
switch (item->type) {
case SLAB_ITEM:
- if (item->u.slab == OcfsGlobalCtxt.ofile_cache)
- slabname = "ofile";
- else if (item->u.slab == OcfsGlobalCtxt.fe_cache)
+ if (item->u.slab == OcfsGlobalCtxt.fe_cache)
slabname = "fe";
else
slabname = "unknown";
Modified: branches/new-dir-format/src/super.c
===================================================================
--- branches/new-dir-format/src/super.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/super.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -142,6 +142,7 @@
#endif
static int ocfs_init_system_inodes(ocfs_super *osb);
+static int ocfs_release_system_inodes(ocfs_super *osb);
static struct super_operations ocfs_sops = {
.statfs = ocfs_statfs,
@@ -190,10 +191,6 @@
LOG_ENTRY();
- /* Why the iputs below? Because we get an extra reference
- * which we don't need (the purpose of this function is to
- * just get the system inodes in the inode hash) */
-
/* the vol bitmap */
sys_off = OCFS_BITMAP_LOCK_OFFSET;
new = ocfs_iget(osb, sys_off, NULL);
@@ -202,7 +199,7 @@
LOG_ERROR_STATUS(status);
goto bail;
}
- iput(new);
+ osb->system_inodes[GLOBAL_BITMAP_SYSTEM_INODE] = new;
/* file alloc bitmap */
sys_off = osb->vol_layout.root_int_off +
@@ -214,8 +211,9 @@
LOG_ERROR_STATUS(status);
goto bail;
}
- iput(new);
+ osb->system_inodes[FILE_ALLOC_BITMAP_SYSTEM_INODE] = new;
+#if 0
/* dir alloc bitmap */
sys_off = osb->vol_layout.root_int_off +
((OCFS_FILE_DIR_ALLOC_BITMAP + osb->node_num)
@@ -226,8 +224,21 @@
LOG_ERROR_STATUS(status);
goto bail;
}
- iput(new);
+ osb->system_inodes[DIR_ALLOC_BITMAP_SYSTEM_INODE] = new;
+#endif
+ /* inode alloc bitmap */
+ sys_off = osb->vol_layout.root_int_off +
+ ((OCFS_INODE_BITMAP + osb->node_num)
+ * osb->sect_size);
+ new = ocfs_iget(osb, sys_off, NULL);
+ if (!new) {
+ status = -EINVAL;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ osb->system_inodes[INODE_ALLOC_BITMAP_SYSTEM_INODE] = new;
+
/* journal file */
sys_off = osb->vol_layout.root_int_off +
((OCFS_JOURNAL_FILE + osb->node_num) * osb->sect_size);
@@ -237,14 +248,31 @@
LOG_ERROR_STATUS(status);
goto bail;
}
- iput(new);
+ osb->system_inodes[JOURNAL_SYSTEM_INODE] = new;
bail:
LOG_EXIT_STATUS(status);
return(status);
} /* ocfs_init_system_inodes */
+
/*
+ * ocfs_release_system_inodes()
+ */
+static int ocfs_release_system_inodes(ocfs_super *osb)
+{
+ int status = 0, i;
+
+ LOG_ENTRY();
+
+ for (i=0; i<NUM_SYSTEM_INODES; i++) {
+ iput(osb->system_inodes[i]);
+ }
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_release_system_inodes */
+
+/*
* __ocfs_read_super()
*
*/
@@ -476,7 +504,7 @@
init_MUTEX (&(OcfsGlobalCtxt.global_res));
OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_GLBL_CTXT_RESOURCE_INITIALIZED);
- /* Initialize the memory slabs for oin, ofile, and file entry */
+ /* Initialize the memory slabs for oin and file entry */
status = ocfs_initialize_mem_lists ();
if (status < 0) {
LOG_ERROR_STATUS (status);
@@ -791,10 +819,6 @@
sizeof(ocfs_inode_private), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
NULL, NULL);
- OcfsGlobalCtxt.ofile_cache = kmem_cache_create ("ocfs2_ofile",
- sizeof (ocfs_file) + OCFS_POINTER_SIZE, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
OcfsGlobalCtxt.fe_cache = kmem_cache_create ("ocfs2_fileentry",
512, 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN, NULL, NULL);
@@ -806,10 +830,6 @@
sizeof(ocfs_bh_sem), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
NULL, NULL);
- OcfsGlobalCtxt.inum_cache = kmem_cache_create("ocfs2_inum",
- sizeof(ocfs_inode_num), 0, SLAB_NO_REAP | SLAB_HWCACHE_ALIGN,
- NULL, NULL);
-
OCFS_SET_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
return 0;
@@ -822,11 +842,9 @@
static void ocfs_free_mem_lists (void)
{
kmem_cache_destroy (OcfsGlobalCtxt.inode_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.ofile_cache);
kmem_cache_destroy (OcfsGlobalCtxt.fe_cache);
kmem_cache_destroy (OcfsGlobalCtxt.extent_cache);
kmem_cache_destroy (OcfsGlobalCtxt.bh_sem_cache);
- kmem_cache_destroy (OcfsGlobalCtxt.inum_cache);
OCFS_CLEAR_FLAG (OcfsGlobalCtxt.flags, OCFS_FLAG_MEM_LISTS_INITIALIZED);
} /* ocfs_free_mem_lists */
@@ -1005,7 +1023,7 @@
osb->vol_state = VOLUME_ENABLED;
up (&(osb->osb_res));
- inode = ocfs_iget(osb, OCFS_ROOT_INODE_FE_OFF, NULL);
+ inode = ocfs_iget(osb, OCFS_ROOT_INODE_FE_OFF(osb), NULL);
if (!inode) {
status = -EIO;
LOG_ERROR_STATUS (status);
@@ -1152,9 +1170,6 @@
// list_del(&osb->osb_next); /* this has been moved into ocfs_delete_osb */
up (&(OcfsGlobalCtxt.global_res));
- /* destroy the inode hash */
- ocfs_inode_hash_destroy(&osb->inode_hash);
-
osb->vol_state = VOLUME_DISMOUNTED;
if (AcquiredOSB) {
up (&(osb->osb_res));
@@ -1173,6 +1188,8 @@
ocfs_safefree (p);
}
+ ocfs_release_system_inodes(osb);
+
ocfs_delete_osb (osb);
ocfs_safefree (osb);
sb->s_dev = 0;
Modified: branches/new-dir-format/src/util.c
===================================================================
--- branches/new-dir-format/src/util.c 2004-05-24 21:26:32 UTC (rev 931)
+++ branches/new-dir-format/src/util.c 2004-05-24 21:34:48 UTC (rev 932)
@@ -326,7 +326,8 @@
void ocfs_truncate_inode_pages(struct inode *inode, loff_t off)
{
- LOG_TRACE_ARGS ("truncating pages for inode %lu (%p) from offset %llu\n", inode->i_ino, inode, off);
+ LOG_TRACE_ARGS ("truncating pages for inode %llu (%p) from offset %llu\n",
+ GET_INODE_FEOFF(inode), inode, off);
truncate_inode_pages(&inode->i_data, off);
} /* ocfs_truncate_inode_pages */
More information about the Ocfs2-commits
mailing list