[Ocfs2-commits]
jlbec commits r1059 - in branches/format-changes: . src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Sat Jun 12 01:50:14 CDT 2004
Author: jlbec
Date: 2004-06-12 00:50:13 -0500 (Sat, 12 Jun 2004)
New Revision: 1059
Modified:
branches/format-changes/TODO
branches/format-changes/src/alloc.c
branches/format-changes/src/dir.c
branches/format-changes/src/dlm.c
branches/format-changes/src/dlm.h
branches/format-changes/src/file.c
branches/format-changes/src/inode.c
branches/format-changes/src/inode.h
branches/format-changes/src/journal.c
branches/format-changes/src/namei.c
branches/format-changes/src/namei.h
branches/format-changes/src/nm.c
branches/format-changes/src/ocfs.h
branches/format-changes/src/super.c
Log:
o Merged 1045:1056 from trunk:
- [1053] First orphan-dir pass
- [1053] mknod_locked and bread performance improvement
- [1053] Bugfix in ocfs_free_disk_bitmap
- [1056] Remove lock_id argument to ocfs_{acquire,release}_lock
Modified: branches/format-changes/TODO
===================================================================
--- branches/format-changes/TODO 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/TODO 2004-06-12 05:50:13 UTC (rev 1059)
@@ -34,9 +34,6 @@
different and / or special cased. In a related todo: Get rid of the
INODE_JOURNAL flag on our inodes and use the system file flag instead.
-* now that acquire_lock and release_lock take inodes, get rid of the lock_id
- and other redundant arguments in the prototype.
-
* Go through the code and remove every spot where we look inside a bh for a
value which is right there on an inode (like, whether it's a directory or
not, fe / vote offsets, lock flags, etc). This includes passing redundant
Modified: branches/format-changes/src/alloc.c
===================================================================
--- branches/format-changes/src/alloc.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/alloc.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -356,8 +356,8 @@
}
down(&OCFS_I(extnode_inode[i])->ip_io_sem);
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock (osb,
+ OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
&ugly_hack_bh,
extnode_inode[i]);
@@ -385,10 +385,9 @@
}
down(&OCFS_I(vol_inode)->ip_io_sem);
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET(osb),
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE,
- &globalbh, vol_inode);
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE,
+ &globalbh, vol_inode);
if (status < 0) {
up(&OCFS_I(vol_inode)->ip_io_sem);
iput(vol_inode);
@@ -399,8 +398,6 @@
goto abort;
}
ocfs_ugly_hack(handle, globalbh);
- brelse(ugly_hack_bh);
- ugly_hack_bh = NULL;
}
@@ -449,10 +446,9 @@
ocfs_abort_trans(handle);
if (free_vol_bits) {
- status = ocfs_release_lock (osb, OCFS_BITMAP_LOCK_OFFSET(osb),
- OCFS_DLM_EXCLUSIVE_LOCK,
- FLAG_FILE_CREATE, globalbh,
- vol_inode);
+ status = ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE, globalbh,
+ vol_inode);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto finally;
@@ -463,7 +459,7 @@
osb->vol_layout.root_int_off;
for (i = 0; i < osb->max_nodes; i++, lock_id += osb->sect_size) {
if (free_ext_node[i] != NULL) {
- status = ocfs_release_lock (osb, lock_id,
+ status = ocfs_release_lock (osb,
OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
NULL, extnode_inode[i]);
@@ -2924,9 +2920,8 @@
ocfs_handle_add_inode(handle, bitmap_inode);
/* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET(osb),
- OCFS_DLM_EXCLUSIVE_LOCK, 0,
- &bh, bitmap_inode);
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ 0, &bh, bitmap_inode);
if (status < 0) {
if (status != -EINTR)
LOG_ERROR_STATUS (status);
@@ -3081,7 +3076,6 @@
int startbh, numblocks;
__u64 fileSize = 0;
__u64 offset = 0;
- __u64 lockId = 0;
__u64 numBytes = 0;
__u64 allocSize = 0;
__u64 prevFileSize = 0;
@@ -3138,14 +3132,7 @@
BUG();
}
- /* Get a lock on the file */
- lockId = (bm_file * osb->sect_size) + osb->vol_layout.root_int_off;
- if (lockId != GET_INODE_FEOFF(inode)) {
- LOG_TRACE_ARGS("lockId = %llu, offset = %llu\n", lockId,
- GET_INODE_FEOFF(inode));
- BUG();
- }
- status = ocfs_acquire_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE, &bh, inode);
if (status < 0) {
LOG_ERROR_STATUS (status);
@@ -3768,10 +3755,9 @@
ocfs_handle_add_inode(handle, main_bm_inode);
/* Get the allocation lock here */
- status = ocfs_acquire_lock (osb, OCFS_BITMAP_LOCK_OFFSET(osb),
- OCFS_DLM_EXCLUSIVE_LOCK, 0,
- &main_bm_bh,
- main_bm_inode);
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ 0, &main_bm_bh,
+ main_bm_inode);
if (status < 0) {
main_bm_bh = NULL;
if (status != -EINTR)
Modified: branches/format-changes/src/dir.c
===================================================================
--- branches/format-changes/src/dir.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/dir.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -196,14 +196,13 @@
int lock_acq = 0;
struct buffer_head *bh = NULL;
__u32 lock_type = OCFS_DLM_ENABLE_CACHE_LOCK;
- __u64 parent_off = GET_INODE_FEOFF(inode);
-
- LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, name='%*s', fe_off=%p, inode=%p)\n",
- osb, parent_off, namelen, name, fe_off, inode);
+ LOG_ENTRY_ARGS ("(osb=%p, parent=%llu, name='%*s', fe_off=%p, inode=%p)\n",
+ osb, GET_INODE_FEOFF(inode), namelen, name, fe_off, inode);
+
if (take_lock) {
/* Get a lock on the directory... */
- status = ocfs_acquire_lock (osb, parent_off, lock_type, FLAG_DIR|FLAG_READDIR,
+ status = ocfs_acquire_lock (osb, lock_type, FLAG_DIR|FLAG_READDIR,
&bh, inode);
if (status < 0) {
/* Volume should be disabled in this case */
@@ -226,7 +225,7 @@
if (take_lock && lock_acq)
{
- tmpstat = ocfs_release_lock (osb, parent_off, lock_type,
+ tmpstat = ocfs_release_lock (osb, lock_type,
FLAG_DIR|FLAG_READDIR, bh, inode);
if (tmpstat < 0) {
LOG_ERROR_STATUS (tmpstat);
Modified: branches/format-changes/src/dlm.c
===================================================================
--- branches/format-changes/src/dlm.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/dlm.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -687,9 +687,8 @@
/* no need to alert master for these cases */
if (S_ISDIR (inode->i_mode) ||
lockres->master_node_num == OCFS_INVALID_NODE_NUM ||
- (!(lockres->lock_state & FLAG_ALWAYS_UPDATE_OPEN) &&
ocfs_node_is_alive(&lockres->oin_openmap,
- osb->node_num))) {
+ osb->node_num)) {
status = 0;
goto bail;
}
@@ -772,7 +771,7 @@
* ocfs_acquire_lock()
* inode is definitely non NULL
*/
-int ocfs_acquire_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type,
+int ocfs_acquire_lock (ocfs_super * osb, __u32 lock_type,
__u32 flags, struct buffer_head **bh, struct inode *inode)
{
int status = -EFAIL;
@@ -786,14 +785,17 @@
int disk_vote = 0;
int no_owner = 0, owner_dead = 0, wait_on_recovery = 0;
__u32 extra_lock_flags = 0;
+ __u64 lock_id;
- LOG_ENTRY_ARGS ("(0x%p, %llu, %u, %u, 0x%p)\n",
- osb, lock_id, lock_type, flags, bh);
+ LOG_ENTRY_ARGS ("(0x%p, %u, %u, 0x%p)\n",
+ osb, lock_type, flags, bh);
OCFS_ASSERT(lock_type != OCFS_DLM_NO_LOCK);
OCFS_ASSERT(inode);
- OCFS_ASSERT(GET_INODE_FEOFF(inode) == lock_id);
+ lock_id = GET_INODE_FEOFF(inode);
+ LOG_TRACE_ARGS("lock_id = %llu\n", lock_id);
+
if (bh != NULL)
b = bh;
else
@@ -915,7 +917,8 @@
if (lockres->master_node_num != osb->node_num &&
(wait_on_recovery || no_owner || owner_dead)) {
extra_lock_flags = FLAG_REMASTER;
- } else if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) {
+ } else if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME
+ | FLAG_RELEASE_DENTRY)) {
if (ocfs_journal_new_file_search(osb, lock_id)!=0) {
extra_lock_flags = 0;
} else if (lockres->lock_type == OCFS_DLM_ENABLE_CACHE_LOCK)
@@ -1061,7 +1064,8 @@
#if 0
/* publish_map & openmap for operations that dont need broadcast */
if (!(flags & (FLAG_FILE_RENAME | FLAG_FILE_DELETE |
- FLAG_FILE_TRUNCATE | FLAG_FILE_EXTEND)))
+ FLAG_FILE_RELEASE_DENTRY | FLAG_FILE_TRUNCATE |
+ FLAG_FILE_EXTEND)))
ocfs_node_map_and(&votemap, &openmap);
#endif
@@ -1069,7 +1073,7 @@
if (ocfs_node_map_is_empty(&votemap))
goto finally;
- if (!(flags & FLAG_FILE_UPDATE_OIN) && !(flags & FLAG_FILE_DELETE))
+ if (!(flags & FLAG_FILE_UPDATE_OIN))
goto finally;
status = -EAGAIN;
@@ -1170,17 +1174,21 @@
* ocfs_release_lock()
* inode is definitely non NULL
*/
-int ocfs_release_lock (ocfs_super * osb, __u64 lock_id, __u32 lock_type, __u32 flags, struct buffer_head *bh, struct inode *inode)
+int ocfs_release_lock (ocfs_super * osb, __u32 lock_type, __u32 flags, struct buffer_head *bh, struct inode *inode)
{
int status = 0;
int tries = 0;
ocfs_lock_res *lockres = GET_INODE_LOCKRES(inode);
+ __u64 lock_id;
- LOG_ENTRY_ARGS ("(0x%p, %llu, %u, %u, 0x%p)\n",
- osb, lock_id, lock_type, flags, lockres);
+ LOG_ENTRY_ARGS ("(0x%p, %u, %u, 0x%p)\n",
+ osb, lock_type, flags, lockres);
OCFS_ASSERT(inode);
+ lock_id = GET_INODE_FEOFF(inode);
+ LOG_TRACE_ARGS("lock_id = %llu", lock_id);
+
flags |= FLAG_RELEASE_LOCK;
again:
@@ -1219,7 +1227,7 @@
}
lockres->lock_type = OCFS_DLM_NO_LOCK;
- if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RELEASE_MASTER))
+ if (flags & FLAG_FILE_RELEASE_MASTER)
lockres->master_node_num = OCFS_INVALID_NODE_NUM;
status = ocfs_disk_release_lock (osb, lock_id, lock_type, flags, bh, inode);
@@ -1329,7 +1337,9 @@
ocfs_node_map_init(osb, &open_map);
/* figure out who to vote with */
- if (flags & (FLAG_REMASTER | FLAG_FILE_DELETE | FLAG_FILE_RENAME | FLAG_DROP_READONLY)) {
+ if (flags & (FLAG_REMASTER | FLAG_FILE_DELETE |
+ FLAG_FILE_RENAME | FLAG_DROP_READONLY |
+ FLAG_RELEASE_DENTRY)) {
ocfs_node_map_dup(osb, &vote_map, &osb->publ_map); /* broadcast */
/* only nodes that see this is readonly */
if (flags & FLAG_DROP_READONLY)
Modified: branches/format-changes/src/dlm.h
===================================================================
--- branches/format-changes/src/dlm.h 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/dlm.h 2004-06-12 05:50:13 UTC (rev 1059)
@@ -30,14 +30,14 @@
int new_lock_function(ocfs_super *osb, __u32 requested_lock,
__u32 flags, struct buffer_head *bh,
int *disk_vote, struct inode *inode);
-int ocfs_acquire_lock(ocfs_super *osb, __u64 lock_id, __u32 lock_type,
+int ocfs_acquire_lock(ocfs_super *osb, __u32 lock_type,
__u32 flags, struct buffer_head **bh,
struct inode *inode);
int ocfs_break_cache_lock_zap_buffers(ocfs_super *osb,
struct inode *inode);
void ocfs_compute_dlm_stats(int status, int vote_status,
ocfs_dlm_stats *stats);
-int ocfs_release_lock(ocfs_super *osb, __u64 lock_id, __u32 lock_type,
+int ocfs_release_lock(ocfs_super *osb, __u32 lock_type,
__u32 flags, struct buffer_head *bh,
struct inode *inode);
int ocfs_update_disk_lock(ocfs_super *osb, __u32 flags,
Modified: branches/format-changes/src/file.c
===================================================================
--- branches/format-changes/src/file.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/file.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -375,12 +375,6 @@
if (OCFS_I(inode)->oin_flags & OCFS_OIN_OPEN_FOR_DIRECTIO)
OCFS_CLEAR_FLAG(OCFS_I(inode)->oin_flags, OCFS_OIN_OPEN_FOR_DIRECTIO);
- if (OCFS_I(inode)->oin_flags & OCFS_OIN_NEEDS_DELETION) {
- up (&(OCFS_I(inode)->priv_sem));
- LOG_ERROR_STR("Not deleting lockrse on a last close! eek!");
- goto bail;
- }
-
/* we might still be holding inode_extend_sem on
* behalf of another node, so release it here. */
down(&recovery_list_sem);
@@ -584,7 +578,6 @@
int tmpstat;
ocfs2_dinode *fileEntry = NULL;
int have_disk_lock = 0;
- __u64 lockId = 0;
__u32 lockFlags = 0, locktype = 0;
struct buffer_head *bh = NULL;
ocfs_journal_handle *handle = NULL;
@@ -613,7 +606,6 @@
locktype = OCFS_DLM_EXCLUSIVE_LOCK;
/* now we always take an UPDATE lock */
- lockId = fileEntry->i_blkno << osb->sb->s_blocksize_bits;
lockFlags = FLAG_FILE_UPDATE;
OCFS_BH_PUT_DATA(bh);
@@ -627,7 +619,7 @@
ocfs_handle_set_checkpoint(handle, 0);
ocfs_handle_set_sync(handle, 0);
- status = ocfs_acquire_lock (osb, lockId, locktype, lockFlags,
+ status = ocfs_acquire_lock (osb, locktype, lockFlags,
&bh, inode);
if (status < 0) {
if (status != -EINTR)
@@ -651,7 +643,6 @@
/* Set the valid bit here */
fileEntry->i_flags |= OCFS2_VALID_FL;
- fileEntry->i_flags &= ~(OCFS2_CHANGE_FL);
OCFS_BH_PUT_DATA(bh);
@@ -676,7 +667,7 @@
}
}
if (have_disk_lock) {
- tmpstat = ocfs_release_lock (osb, lockId, locktype,
+ tmpstat = ocfs_release_lock (osb, locktype,
lockFlags, bh, inode);
if (tmpstat < 0)
LOG_ERROR_STATUS (tmpstat);
@@ -944,7 +935,6 @@
{
int status = 0, tmpstat;
ocfs2_dinode *fe = NULL;
- __u64 lockId = 0;
__u32 lockFlags = 0, locktype = 0;
int have_disk_lock = 0;
__u64 new_alloc_size;
@@ -980,7 +970,6 @@
goto leave;
}
- lockId = fe->i_blkno << osb->sb->s_blocksize_bits;
lockFlags = FLAG_FILE_TRUNCATE;
if ((DISK_LOCK(fe)->dl_level == OCFS_DLM_ENABLE_CACHE_LOCK)
@@ -992,7 +981,7 @@
OCFS_BH_PUT_DATA(bh);
- status = ocfs_acquire_lock (osb, lockId, locktype, lockFlags,
+ status = ocfs_acquire_lock (osb, locktype, lockFlags,
&bh, inode);
if (status < 0) {
if (status != -EINTR)
@@ -1040,7 +1029,6 @@
DISK_LOCK(fe)->dl_seq_num = 0;
fe->i_flags |= OCFS2_VALID_FL;
- fe->i_flags &= ~(OCFS2_CHANGE_FL);
fe->i_mtime = OCFS_CURRENT_TIME;
OCFS_BH_PUT_DATA(bh);
@@ -1065,7 +1053,7 @@
if (have_disk_lock) {
lockFlags |= FLAG_FILE_UPDATE_OIN;
- tmpstat = ocfs_release_lock (osb, lockId, locktype,
+ tmpstat = ocfs_release_lock (osb, locktype,
lockFlags, bh, inode);
if (tmpstat < 0)
LOG_ERROR_STATUS (tmpstat);
@@ -1096,7 +1084,6 @@
__u64 alloc_size = 0;
__u64 bitmapOffset = 0;
__u64 numClustersAlloc = 0;
- __u64 lockId = 0;
__u32 lockFlags = 0;
__u32 locktype = OCFS_DLM_ENABLE_CACHE_LOCK;
int have_disk_lock = 0;
@@ -1156,14 +1143,13 @@
fe = OCFS_BH_GET_DATA_READ(bh);
/* now we always take an EXTEND lock */
- lockId = fe->i_blkno << osb->sb->s_blocksize_bits;
lockFlags = FLAG_FILE_EXTEND;
OCFS_BH_PUT_DATA(bh);
brelse(bh);
bh = NULL;
- status = ocfs_acquire_lock (osb, lockId, locktype, lockFlags, &bh, inode);
+ status = ocfs_acquire_lock (osb, locktype, lockFlags, &bh, inode);
if (status < 0) {
if (status != -EINTR)
LOG_ERROR_STATUS (status);
@@ -1281,7 +1267,6 @@
ocfs_fe_set_attributes(fe, attr);
/* Set the Valid bit and reset the change bit here... TODO */
fe->i_flags |= OCFS2_VALID_FL;
- fe->i_flags &= ~(OCFS2_CHANGE_FL);
fe->i_mtime = OCFS_CURRENT_TIME;
tempOffset = fe->i_blkno << osb->sb->s_blocksize_bits;
@@ -1314,7 +1299,7 @@
if (have_disk_lock) {
lockFlags |= FLAG_FILE_UPDATE_OIN;
- tmpstat = ocfs_release_lock (osb, lockId, OCFS_DLM_EXCLUSIVE_LOCK,
+ tmpstat = ocfs_release_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
lockFlags, bh, inode);
if (tmpstat < 0)
LOG_ERROR_STATUS (tmpstat);
Modified: branches/format-changes/src/inode.c
===================================================================
--- branches/format-changes/src/inode.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/inode.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
+#include <linux/smp_lock.h>
#include <asm/byteorder.h>
@@ -39,6 +40,7 @@
#include "alloc.h"
#include "dir.h"
+#include "dlm.h"
#include "extmap.h"
#include "file.h"
#include "hash.h"
@@ -655,6 +657,175 @@
}
/*
+ * ocfs_delete_inode()
+ *
+ */
+void ocfs_delete_inode(struct inode *inode)
+{
+ struct inode *orphan_dir_inode = NULL;
+ ocfs_journal_handle *handle = NULL;
+ ocfs_super *osb = OCFS_SB(inode->i_sb);
+ int status = 0;
+ int release_disk_lock = 0;
+ struct buffer_head *orphan_dir_bh = NULL;
+ struct buffer_head *fe_bh = NULL;
+ __u32 lock_flags = FLAG_FILE_DELETE;
+ ocfs2_dinode *fe;
+
+ LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
+
+ if (OCFS_I(inode)->flags & OCFS_INODE_SYSTEM_FILE) {
+ LOG_TRACE_STR("Skipping system file delete.");
+ goto clear_inode;
+ }
+
+ if (inode->i_ino == OCFS_ROOT_INODE_NUMBER) {
+ LOG_TRACE_STR("Skipping root inode delete.");
+ goto clear_inode;
+ }
+
+ if (OCFS_I(inode)->flags & OCFS_INODE_SKIP_DELETE) {
+ LOG_TRACE_ARGS("Skipping delete of %lu because another node "
+ "has done this for us.\n", inode->i_ino);
+ goto clear_inode;
+ }
+
+ /* If we're coming from process_vote we can't go into our own
+ * voting [hello, deadlock city!], so unforuntately we just
+ * have to skip deleting this guy. That's OK though because
+ * the node who's doing the actual deleting should handle it
+ * anyway. */
+ if (osb->voting_ino == inode->i_ino) {
+ LOG_TRACE_ARGS("Skipping delete of %lu because we're currently"
+ "in process_vote\n", inode->i_ino);
+ goto clear_inode;
+ }
+
+ orphan_dir_inode = igrab(osb->system_inodes[ORPHAN_DIR_SYSTEM_INODE]);
+ if (!orphan_dir_inode) {
+ LOG_ERROR_STATUS(-EFAIL);
+ goto clear_inode;
+ }
+
+ lock_kernel();
+
+ /* Oop, lets be carefull of lock / trans ordering here... */
+ handle = ocfs_start_trans(osb, OCFS_FILE_DELETE_CREDITS);
+ if (handle == NULL) {
+ unlock_kernel();
+ LOG_ERROR_STATUS(-ENOMEM);
+ goto clear_inode;
+ }
+
+ ocfs_handle_add_inode(handle, orphan_dir_inode);
+
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR,
+ &orphan_dir_bh, orphan_dir_inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+ ocfs_handle_add_lock(handle, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR, orphan_dir_bh,
+ orphan_dir_inode, 1);
+
+ /* take ip_io_sem on the inode, only to avoid a warning in
+ * acquire_lockres. We can get rid of it when we get rid of
+ * acquire_lockres */
+ down(&OCFS_I(inode)->ip_io_sem);
+ if (S_ISDIR(inode->i_mode))
+ lock_flags |= FLAG_DIR;
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK, lock_flags,
+ &fe_bh, inode);
+ up(&OCFS_I(inode)->ip_io_sem);
+ if (status < 0) {
+ /* EBUSY here is assumed to mean that other nodes are
+ * still using the inode. We're done here though, so
+ * avoid doing anything on disk and let them worry
+ * about deleting it. */
+ if (status != -EBUSY)
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+ release_disk_lock = 1;
+
+ /* check OCFS_SYNC_FLAG_ORPHANED */
+ fe = OCFS_BH_GET_DATA_READ(fe_bh);
+ if (!(fe->i_flags & OCFS2_ORPHANED_FL)) {
+ OCFS_BH_PUT_DATA(fe_bh);
+ /* for lack of a better error? */
+ status = -EEXIST;
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+
+ /* has someone already deleted us?! baaad... */
+ if (fe->i_dtime) {
+ OCFS_BH_PUT_DATA(fe_bh);
+
+ status = -EEXIST;
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+ OCFS_BH_PUT_DATA(fe_bh);
+
+ status = ocfs_orphan_del(osb, handle, orphan_dir_inode, inode,
+ orphan_dir_bh);
+
+ /* set the inodes dtime */
+ status = ocfs_journal_access(handle, fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+
+ fe = OCFS_BH_GET_DATA_WRITE(fe_bh);
+ fe->i_dtime = OCFS_CURRENT_TIME;
+ fe->i_flags &= (~(OCFS2_VALID_FL | OCFS2_ORPHANED_FL));
+ OCFS_BH_PUT_DATA(fe_bh);
+
+ status = ocfs_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail_locked;
+ }
+
+ /* actually delete the data and the inode */
+ status = ocfs_free_file_extents(osb, fe_bh, handle, inode);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+
+bail_locked:
+ if (handle && (status == 0))
+ ocfs_commit_trans(handle);
+ else if (handle)
+ ocfs_abort_trans(handle);
+
+ if (release_disk_lock) {
+ down(&OCFS_I(inode)->ip_io_sem);
+ status = ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ lock_flags, fe_bh, inode);
+ up(&OCFS_I(inode)->ip_io_sem);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
+ }
+
+ unlock_kernel();
+
+ if (orphan_dir_bh)
+ brelse(orphan_dir_bh);
+ if (fe_bh)
+ brelse(fe_bh);
+
+ iput(orphan_dir_inode);
+clear_inode:
+ /* we must clear inode. */
+ clear_inode(inode);
+ LOG_EXIT();
+} /* ocfs_delete_inode */
+
+/*
* ocfs_clear_inode()
*
*/
@@ -668,8 +839,8 @@
if (!inode)
goto bail;
- LOG_TRACE_ARGS("Clearing inode feoff: %llu)\n",
- GET_INODE_FEOFF(inode));
+ LOG_TRACE_ARGS("Clearing inode feoff: %llu, nlink = %u)\n",
+ GET_INODE_FEOFF(inode), inode->i_nlink);
/* we should not really be using osb in this context. */
osb = OCFS_SB(inode->i_sb);
@@ -905,25 +1076,35 @@
if (tmperr < 0)
goto fail;
- tmperr = ocfs_read_bh(osb, lbo, &bh, readflags, inode);
- if (tmperr < 0)
- goto fail;
+ if (new) {
+ bh = getblk(OCFS_GET_BLOCKDEV(osb->sb),
+ lbo >> osb->sb->s_blocksize_bits,
+ osb->sb->s_blocksize);
+ if (!bh) {
+ tmperr = -EIO;
+ goto fail;
+ }
+ set_buffer_uptodate(bh);
+ SET_BH_SEQNUM(inode, bh);
- tmperr = 0;
- if (new) {
fatal = ocfs_journal_access(handle, bh,
OCFS_JOURNAL_ACCESS_CREATE);
- if (!fatal) {
- char *buf = OCFS_BH_GET_DATA_WRITE(bh);
- 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;
+
+ char *buf = OCFS_BH_GET_DATA_WRITE(bh);
+ memset(buf, 0, osb->sect_size);
+ OCFS_BH_PUT_DATA(bh);
+ fatal = ocfs_journal_dirty(handle, bh);
+ if (fatal)
+ goto fail;
+ } else {
+ tmperr = ocfs_read_bh(osb, lbo, &bh, readflags, inode);
+ if (tmperr < 0)
+ goto fail;
}
- if (fatal)
- goto fail;
+ tmperr = 0;
*err = 0;
return bh;
@@ -1800,14 +1981,13 @@
goto leave;
/* Add checks as needed */
- if ((fe->i_flags & OCFS2_MARK_FOR_DELETION_FL) ||
- (!(fe->i_flags & OCFS2_VALID_FL))) {
- if (fe->i_flags & OCFS2_MARK_FOR_DELETION_FL) {
- LOG_TRACE_STR
- ("File Entry is marked for deletion");
- } else {
+ if ((fe->i_dtime) || (!(fe->i_flags & OCFS2_VALID_FL))) {
+ if (fe->i_dtime)
+ LOG_ERROR_ARGS("Inode %lu has dtime = %llu\n",
+ inode->i_ino, fe->i_dtime);
+ else
LOG_TRACE_STR ("File Entry is invalid");
- }
+
status = -ENOENT;
goto leave;
}
Modified: branches/format-changes/src/inode.h
===================================================================
--- branches/format-changes/src/inode.h 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/inode.h 2004-06-12 05:50:13 UTC (rev 1059)
@@ -33,6 +33,7 @@
struct inode * inode, int block,
int create, int *err, int reada);
void ocfs_clear_inode(struct inode *inode);
+void ocfs_delete_inode(struct inode *inode);
struct inode *ocfs_iget(ocfs_super *osb, __u64 feoff);
int ocfs_inode_init_private(struct inode *inode);
int ocfs_inode_revalidate(struct dentry *dentry);
Modified: branches/format-changes/src/journal.c
===================================================================
--- branches/format-changes/src/journal.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/journal.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -282,7 +282,6 @@
if (!INODE_DELETED(lock->inode)) {
tmpstat = ocfs_release_lock(osb,
- GET_INODE_FEOFF(lock->inode),
lock->type,
lock->flags,
(action == TRANS_ABORT
@@ -909,7 +908,7 @@
SET_INODE_JOURNAL(inode);
/* TODO: Use another type of lock. */
- status = ocfs_acquire_lock (osb, lock_id, OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE, &bh, inode);
if (status < 0) {
up(&OCFS_I(inode)->ip_io_sem);
@@ -1070,8 +1069,7 @@
down(&OCFS_I(inode)->ip_io_sem);
/* unlock our journal */
- status = ocfs_release_lock (osb, journal->lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_release_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE,
journal->lockbh, inode);
up(&OCFS_I(inode)->ip_io_sem);
@@ -1366,8 +1364,7 @@
if (osb->node_num == node_num)
BUG();
- status = ocfs_acquire_lock (osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE|FLAG_FILE_RECOVERY,
&bh, inode);
@@ -1474,8 +1471,7 @@
if (got_lock) {
down(&OCFS_I(inode)->ip_io_sem);
- status = ocfs_release_lock(osb, lock_id,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE|FLAG_FILE_RECOVERY,
bh, inode);
up(&OCFS_I(inode)->ip_io_sem);
Modified: branches/format-changes/src/namei.c
===================================================================
--- branches/format-changes/src/namei.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/namei.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -53,29 +53,56 @@
extern spinlock_t oin_num_ext_lock;
-static int inline search_dirblock(struct buffer_head * bh, struct inode *dir, const char *name, int namelen, 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, struct buffer_head *parent_fe_bh);
-static inline int ocfs_match (int len, const char * const name, struct ocfs2_dir_entry * de);
+static int inline search_dirblock(struct buffer_head *bh,
+ struct inode *dir,
+ const char *name, int namelen,
+ 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 inode *dir,
+ const char *name, int namelen,
+ struct inode *inode, __u64 inode_off,
+ struct buffer_head *parent_fe_bh);
+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_dev dev,
+ struct buffer_head **new_fe_bh,
struct buffer_head *parent_fe_bh,
ocfs_journal_handle *handle,
struct inode *inode);
-static int ocfs_double_lock(ocfs_super *osb, ocfs_journal_handle *handle,
- __u64 id1, __u32 type1, __u32 flags1,
+static int ocfs_double_lock(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ __u32 type1, __u32 flags1,
struct buffer_head **bh1,
struct inode *inode1,
- __u64 id2, __u32 type2, __u32 flags2,
+ __u32 type2, __u32 flags2,
struct buffer_head **bh2,
struct inode *inode2);
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
+ struct inode *inode, ocfs2_dinode *fe);
+
static struct dentry_operations ocfs_dentry_ops = {
.d_revalidate = ocfs_dentry_revalidate // let's test it out!
};
+static inline int ocfs_add_entry(ocfs_journal_handle *handle,
+ struct dentry *dentry,
+ struct inode *inode, __u64 inode_off,
+ struct buffer_head *parent_fe_bh)
+{
+ return(__ocfs_add_entry(handle, dentry->d_parent->d_inode,
+ dentry->d_name.name, dentry->d_name.len,
+ inode, inode_off, parent_fe_bh));
+}
+
/*
* ocfs_lookup()
*
@@ -141,7 +168,7 @@
{
int status = 0;
struct buffer_head *parent_fe_bh = NULL;
- __u64 parent_off, file_off;
+ __u64 file_off;
ocfs_journal_handle *handle = NULL;
ocfs_super *osb;
ocfs2_dinode *fe = NULL;
@@ -173,9 +200,6 @@
goto leave;
}
- /* need the offset of our parent directory to lock it */
- parent_off = GET_INODE_FEOFF(dir);
-
/* start the transaction */
handle = ocfs_start_trans(osb, OCFS_MKNOD_CREDITS);
if (handle == NULL) {
@@ -187,8 +211,7 @@
ocfs_handle_set_sync(handle, 0);
/* lock the parent directory */
- status = ocfs_acquire_lock (osb, parent_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE | FLAG_DIR,
&parent_fe_bh, dir);
if (status < 0) {
@@ -250,7 +273,7 @@
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->inode = cpu_to_le64(GET_INODE_FEOFF(dir));
de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-OCFS_DIR_REC_LEN(1));
de->name_len = 2;
strcpy (de->name, "..");
@@ -324,7 +347,8 @@
*/
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,
struct buffer_head *parent_fe_bh,
ocfs_journal_handle *handle,
struct inode *inode)
@@ -363,8 +387,16 @@
goto leave;
}
- status = ocfs_read_bh(osb, disk_off, new_fe_bh,
- OCFS_BH_CACHED, inode);
+ *new_fe_bh = getblk(OCFS_GET_BLOCKDEV(osb->sb),
+ disk_off >> osb->sb->s_blocksize_bits,
+ osb->sb->s_blocksize);
+ if (!*new_fe_bh) {
+ status = -EIO;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ set_buffer_uptodate(*new_fe_bh);
+ SET_BH_SEQNUM(inode, *new_fe_bh);
status = ocfs_journal_access(handle, *new_fe_bh, OCFS_JOURNAL_ACCESS_CREATE);
if (status < 0) {
@@ -401,7 +433,6 @@
fe->i_last_eb_blk = 0;
strcpy (fe->i_signature, OCFS2_FILE_ENTRY_SIGNATURE);
fe->i_flags |= OCFS2_VALID_FL;
- fe->i_flags &= ~(OCFS2_CHANGE_FL);
DISK_LOCK(fe)->dl_seq_num = 0;
DISK_LOCK(fe)->dl_master = osb->node_num;
DISK_LOCK(fe)->dl_level = OCFS_DLM_ENABLE_CACHE_LOCK;
@@ -516,16 +547,14 @@
__u64 fe_off = GET_INODE_FEOFF(inode);
struct inode *parentInode = dentry->d_parent->d_inode;
ocfs2_dinode *fe = NULL;
- __u32 lockFlags = (S_ISDIR (inode->i_mode) ? (FLAG_FILE_DELETE | FLAG_DIR) : FLAG_FILE_DELETE);
+ __u32 lockFlags = (S_ISDIR (inode->i_mode) ? (FLAG_RELEASE_DENTRY | FLAG_DIR) : FLAG_RELEASE_DENTRY);
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);
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);
@@ -536,10 +565,9 @@
if (S_ISDIR (inode->i_mode) && !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, fe_off = %llu, d_count=%u)\n", OCFS_I(inode)->open_hndl_cnt, fe_off, atomic_read(&dentry->d_count));
- goto bail;
- } else if (inode == osb->root_inode) {
+ }
+
+ if (inode == osb->root_inode) {
LOG_TRACE_STR ("Cannot delete the root directory");
status = -EPERM;
goto bail;
@@ -570,7 +598,7 @@
/* 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,
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE|FLAG_DIR, NULL,
parentInode);
if (status < 0) {
@@ -599,7 +627,7 @@
goto leave;
}
- status = ocfs_acquire_lock (osb, fe_off, OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_EXCLUSIVE_LOCK,
lockFlags, &fe_bh, inode);
if (status < 0) {
if (status != -EINTR)
@@ -607,7 +635,7 @@
goto leave;
}
got_file = 1;
-
+
if (S_ISDIR (inode->i_mode)) {
if (!empty_dir(inode)) {
status = -ENOTEMPTY;
@@ -624,97 +652,84 @@
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_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_BH_GET_DATA_WRITE(fe_bh);
+ if (fe->i_links_count != inode->i_nlink) {
+ printk("ocfs_unlink: hmm, inode has nlink = %u, fe has link_cnt = %u. Setting inode from fe.\n",
+ inode->i_nlink, fe->i_links_count);
+ inode->i_nlink = fe->i_links_count;
+ }
+
if (S_ISDIR (inode->i_mode))
fe->i_links_count = 0;
- else
+ else
fe->i_links_count--;
if (!fe->i_links_count) {
- drop_inode = 1;
- OCFS_SET_FLAG(fe->i_flags, OCFS2_MARK_FOR_DELETION_FL);
- fe->i_flags &= (~OCFS2_VALID_FL);
+ status = ocfs_orphan_add(osb, handle, inode, fe);
+ if (status < 0) {
+ OCFS_BH_PUT_DATA(fe_bh);
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
}
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);
+ status = ocfs_journal_dirty(handle, fe_bh);
+ if (status < 0) {
+ 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;
+ }
+
+ if (S_ISDIR (inode->i_mode)) {
+ ocfs2_dinode *dirfe;
+ status = ocfs_journal_access(handle, parent_node_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
- ocfs_clear_buffer_modified(fe_bh);
- ocfs_clear_buffer_modified(parent_node_bh);
- LOG_ERROR_STATUS (status);
+ LOG_ERROR_STATUS(status);
goto leave;
}
-
- /* delete the name from the parent dir */
- status = ocfs_delete_entry (handle, parentInode, dirent, dirent_bh);
+ dirfe = OCFS_BH_GET_DATA_WRITE(parent_node_bh);
+ dirfe->i_links_count--;
+ OCFS_BH_PUT_DATA(parent_node_bh);
+ status = ocfs_journal_dirty(handle, fe_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)) {
- ocfs2_dinode *dirfe;
- status = ocfs_journal_access(handle, parent_node_bh,
- OCFS_JOURNAL_ACCESS_WRITE);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto leave;
- }
- dirfe = OCFS_BH_GET_DATA_WRITE(parent_node_bh);
- dirfe->i_links_count--;
- 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;
- }
}
- 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
+ else {
ocfs_commit_trans(handle);
+ // already checked to make sure dir has nlink==2
+ if (S_ISDIR (inode->i_mode)) {
+ inode->i_nlink = 0;
+ dir->i_nlink--;
+ } else
+ inode->i_nlink--;
+ }
}
/* 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, fe_off,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ tmpstat = ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
lockFlags, fe_bh, inode);
if (tmpstat < 0)
LOG_ERROR_STATUS(tmpstat);
@@ -722,8 +737,7 @@
}
if (got_parent) {
- tmpstat = ocfs_release_lock(osb, parent_off,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ tmpstat = ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
FLAG_FILE_CREATE|FLAG_DIR,
NULL, parentInode);
if (tmpstat < 0)
@@ -731,19 +745,6 @@
}
- 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);
- }
-
up(&OCFS_I(inode)->ip_io_sem);
up(&OCFS_I(dir)->ip_io_sem);
bail:
@@ -781,23 +782,26 @@
* if they have the same id, then the 1st one is the only one locked.
*/
static int ocfs_double_lock(ocfs_super *osb, ocfs_journal_handle *handle,
- __u64 id1, __u32 type1, __u32 flags1,
+ __u32 type1, __u32 flags1,
struct buffer_head **bh1,
struct inode *inode1,
- __u64 id2, __u32 type2, __u32 flags2,
+ __u32 type2, __u32 flags2,
struct buffer_head **bh2,
struct inode *inode2)
{
int status = 0;
int id2_locked = 0;
- __u64 tmpid;
+ __u64 tmpid, id1, id2;
__u32 tmptype, tmpflags;
struct buffer_head **tmpbh;
struct inode *tmpinode;
- LOG_ENTRY_ARGS("(lock_id1 = %llu, lock_id2 = %llu)\n", id1,
- id2);
+ LOG_ENTRY_ARGS("(lock_id1 = %llu, lock_id2 = %llu)\n",
+ GET_INODE_FEOFF(inode1), GET_INODE_FEOFF(inode2));
+ id1 = GET_INODE_FEOFF(inode1);
+ id2 = GET_INODE_FEOFF(inode2);
+
if (*bh1)
*bh1 = NULL;
if (*bh2)
@@ -829,7 +833,7 @@
inode1 = tmpinode;
}
/* lock id2 */
- status = ocfs_acquire_lock(osb, id2, type2, flags2, bh2, inode2);
+ status = ocfs_acquire_lock(osb, type2, flags2, bh2, inode2);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto bail;
@@ -837,7 +841,7 @@
id2_locked = 1;
}
/* lock id1 */
- status = ocfs_acquire_lock(osb, id1, type1, flags1,
+ status = ocfs_acquire_lock(osb, type1, flags1,
bh1, inode1);
if (status < 0) {
LOG_ERROR_STATUS (status);
@@ -847,7 +851,7 @@
bail:
if (status < 0) {
if (id2_locked) {
- status = ocfs_release_lock(osb, id2, type2, flags2,
+ status = ocfs_release_lock(osb, type2, flags2,
*bh2, inode2);
if (bh2) {
brelse(*bh2);
@@ -903,15 +907,15 @@
ocfs2_dinode *newfe = NULL;
struct buffer_head *newfe_bh = NULL;
ocfs_super *osb = NULL;
- __u64 oldOffset, newDirOff, oldDirOff;
+ __u64 oldfe_lockid;
__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 newfe_flags = 0;
- int needs_trunc = 0, drop_inode = 0;
+ __u32 oldfe_flags = FLAG_RELEASE_DENTRY | FLAG_FILE_RENAME;
+ __u32 newfe_flags = FLAG_RELEASE_DENTRY;
+ int needs_trunc = 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
@@ -927,15 +931,8 @@
osb = OCFS_SB(old_dir->i_sb);
- /* old parent dir offset */
- oldDirOff = GET_INODE_FEOFF(old_dir);
+ oldfe_lockid = GET_INODE_FEOFF(old_inode);
- /* old file offset */
- oldOffset = GET_INODE_FEOFF(old_inode);
-
- /* new parent dir offset */
- newDirOff = GET_INODE_FEOFF(new_dir);
-
double_down(&OCFS_I(old_dir)->ip_io_sem, &OCFS_I(new_dir)->ip_io_sem);
down(&OCFS_I(old_inode)->ip_io_sem);
@@ -972,18 +969,6 @@
}
spin_unlock(&oin_num_ext_lock);
- /* Don't ever take the main resource for the OIN before this as */
- /* Locking hierarchy will be broken */
-
- if (new_inode) {
- 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 */
handle = ocfs_start_trans(osb, OCFS_FILE_RENAME_CREDITS);
if (handle == NULL) {
@@ -991,18 +976,12 @@
goto bail;
}
- /* for the (possibly two) parent directory locks, we just put
- * them in the journal handle to be released by
- * commit/abort. For rename, this is only a convenience and if
- * it is a problem, we can move the release_locks into the
- * bottom of this function. */
-
/* if old and new are the same, this'll just do one lock. */
status = ocfs_double_lock(osb, handle,
- oldDirOff, OCFS_DLM_EXCLUSIVE_LOCK,
+ OCFS_DLM_EXCLUSIVE_LOCK,
dir_lock_flags,
&old_dir_bh, old_dir,
- newDirOff, OCFS_DLM_EXCLUSIVE_LOCK,
+ OCFS_DLM_EXCLUSIVE_LOCK,
dir_lock_flags,
&new_dir_bh, new_dir);
if (status < 0) {
@@ -1026,12 +1005,7 @@
if (S_ISDIR(old_inode->i_mode))
oldfe_flags = FLAG_DIR;
- if (old_dir != new_dir)
- oldfe_flags |= FLAG_FILE_DELETE;
- else
- oldfe_flags |= FLAG_FILE_RENAME;
-
- status = ocfs_acquire_lock(osb, oldOffset, OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
oldfe_flags, NULL, old_inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -1054,9 +1028,9 @@
}
status = -ENOENT;
- old_de_bh = ocfs_find_entry (old_dentry->d_name.name,
- old_dentry->d_name.len,
- old_dir, &old_de);
+ old_de_bh = ocfs_find_entry(old_dentry->d_name.name,
+ old_dentry->d_name.len,
+ old_dir, &old_de);
if (!old_de_bh)
goto finally;
@@ -1084,34 +1058,22 @@
goto finally;
}
+ if (!new_de && new_inode)
+ LOG_ERROR_ARGS("inode %lu does not exist in it's parent "
+ "directory!", new_inode->i_ino);
+
/* In case we need to overwrite an existing file, we blow it
* away first */
if (new_de) {
+ if (!new_inode)
+ BUG();
+
if (newfe_lockid != GET_INODE_FEOFF(new_inode))
BUG();
- status = ocfs_read_bh(osb, newfe_lockid, &newfe_bh,
- OCFS_BH_CACHED, new_inode);
- if (status < 0) {
- LOG_ERROR_STATUS(status);
- goto finally;
- }
-
- /* TODO: change this block to the ext3-style orphan model */
- newfe = OCFS_BH_GET_DATA_READ(newfe_bh);
- if (S_ISDIR(newfe->i_mode))
+ if (S_ISDIR(new_inode->i_mode))
newfe_flags = FLAG_DIR;
- newfe_flags |= FLAG_FILE_DELETE;
-
- if (newfe_lockid !=
- (newfe->i_blkno << osb->sb->s_blocksize_bits))
- BUG();
-
- OCFS_BH_PUT_DATA(newfe_bh);
- newfe = NULL;
-
- status = ocfs_acquire_lock(osb, newfe_lockid,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
newfe_flags, &newfe_bh,
new_inode);
if (status < 0) {
@@ -1119,77 +1081,64 @@
goto finally;
}
got_newlock = 1;
- LOG_ERROR_ARGS("aha rename over existing... new_de=%p newlockid=%llu newfebh=%p bhblocknr=%llu\n",
+
+ /* if our caching is working right, then after the
+ * verify_update_inode, newfe->i_nlink ==
+ * new_inode->i_nlink */
+ 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);
+
+ LOG_TRACE_ARGS("aha rename over existing... new_de=%p "
+ "newlockid=%llu newfebh=%p bhblocknr=%llu\n",
new_de, newfe_lockid, newfe_bh, newfe_bh ?
(unsigned long long)newfe_bh->b_blocknr : 0ULL);
- status = ocfs_journal_access(handle, newfe_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ 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);
- /* 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_BH_GET_DATA_WRITE(newfe_bh);
- if (S_ISDIR (new_inode->i_mode) && !empty_dir(new_inode)) {
- status = -ENOTEMPTY;
- OCFS_BH_PUT_DATA(newfe_bh);
- newfe = NULL;
- ocfs_clear_buffer_modified(new_dir_bh);
- goto finally;
+ if (S_ISDIR (new_inode->i_mode)) {
+ if (!empty_dir(new_inode) || new_inode->i_nlink != 2) {
+ status = -ENOTEMPTY;
+ goto finally;
+ }
}
+ newfe = OCFS_BH_GET_DATA_WRITE(newfe_bh);
if (S_ISDIR (new_inode->i_mode))
newfe->i_links_count = 0;
else
newfe->i_links_count--;
+
if (!newfe->i_links_count) {
- OCFS_SET_FLAG(newfe->i_flags,
- OCFS2_MARK_FOR_DELETION_FL);
- newfe->i_flags &= (~OCFS2_VALID_FL);
- drop_inode = 1;
+ status = ocfs_orphan_add(osb, handle, new_inode,
+ newfe);
+ if (status < 0) {
+ OCFS_BH_PUT_DATA(newfe_bh);
+ LOG_ERROR_STATUS(status);
+ goto finally;
+ }
}
+
OCFS_BH_PUT_DATA(newfe_bh);
newfe = NULL;
- 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;
- }
+ status = ocfs_journal_dirty(handle, newfe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto finally;
}
/* change the dirent to point to the correct inode */
- status = ocfs_journal_access(handle, new_de_bh, OCFS_JOURNAL_ACCESS_WRITE);
+ status = ocfs_journal_access(handle, new_de_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto finally;
@@ -1207,8 +1156,9 @@
} else {
/* if the name was not found in new_dir, add it now */
- status = ocfs_add_entry (handle, new_dentry, old_inode, oldOffset, new_dir_bh);
- }
+ status = ocfs_add_entry (handle, new_dentry, old_inode,
+ oldfe_lockid, new_dir_bh);
+ }
finally:
@@ -1224,7 +1174,7 @@
status = ocfs_delete_entry(handle, old_dir, old_de, old_de_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
- goto finally;
+ goto bail;
}
if (new_inode) {
@@ -1233,7 +1183,8 @@
}
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);
+ status = ocfs_journal_access(handle, old_inode_de_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
if (status < 0) {
LOG_ERROR_STATUS (status);
// BAD
@@ -1257,11 +1208,8 @@
}
}
mark_inode_dirty(old_dir);
- if (new_inode) {
+ 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)
@@ -1282,14 +1230,12 @@
bail:
if (got_oldlock) {
- ocfs_release_lock(osb, oldOffset,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
oldfe_flags, NULL, old_inode);
}
if (got_newlock) {
- ocfs_release_lock(osb, newfe_lockid,
- OCFS_DLM_EXCLUSIVE_LOCK,
+ ocfs_release_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
newfe_flags, NULL, new_inode);
}
@@ -1301,11 +1247,8 @@
iput(new_inode);
}
- if (newfe_bh) {
- if (newfe)
- OCFS_BH_PUT_DATA(newfe_bh);
+ if (newfe_bh)
brelse(newfe_bh);
- }
if (old_dir_bh)
brelse(old_dir_bh);
if (new_dir_bh)
@@ -1334,7 +1277,7 @@
{
ocfs_super *osb = NULL;
struct inode *inode = NULL;
- __u64 file_off, parent_off;
+ __u64 file_off;
__u64 newsize;
int status;
struct super_block *sb;
@@ -1381,9 +1324,7 @@
}
/* lock the parent directory */
- parent_off = GET_INODE_FEOFF(dir);
- status = ocfs_acquire_lock (osb, parent_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ status = ocfs_acquire_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE | FLAG_DIR,
&parent_fe_bh, dir);
if (status < 0) {
@@ -1453,8 +1394,7 @@
if (got_lock) {
int tmpstat;
- tmpstat = ocfs_release_lock (osb, parent_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ tmpstat = ocfs_release_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE | FLAG_DIR,
parent_fe_bh, dir);
if (tmpstat < 0)
@@ -1517,12 +1457,13 @@
return !memcmp(name, de->name, len);
}
-
-static int ocfs_add_entry (ocfs_journal_handle *handle, struct dentry *dentry, struct inode *inode, __u64 inode_off, struct buffer_head *parent_fe_bh)
+/* we don't always have a dentry for what we want to add, so people
+ * like orphan dir can call this instead. */
+static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
+ const char *name, int namelen,
+ struct inode *inode, __u64 inode_off,
+ struct buffer_head *parent_fe_bh)
{
- 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;
@@ -1733,8 +1674,9 @@
-struct buffer_head * ocfs_find_entry (const char *name, int namelen, struct inode *dir,
- struct ocfs2_dir_entry ** res_dir)
+struct buffer_head *ocfs_find_entry(const char *name, int namelen,
+ struct inode *dir,
+ struct ocfs2_dir_entry **res_dir)
{
struct super_block * sb;
struct buffer_head * bh_use[NAMEI_RA_SIZE];
@@ -1827,18 +1769,185 @@
return ret;
}
+/*
+ * ocfs_orphan_add()
+ *
+ */
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
+ struct inode *inode, ocfs2_dinode *fe)
+{
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ int status = 0;
+ char *name = NULL;
+ int namelen;
+ ocfs2_dinode *orphan_fe;
+ LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
-int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode)
+ /* create a unique name here. */
+ name = kmalloc(OCFS_MAX_FILENAME_LENGTH+1, GFP_KERNEL);
+ if (!name) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ namelen = snprintf(name, OCFS_MAX_FILENAME_LENGTH+1, "%llu",
+ GET_INODE_FEOFF(inode));
+ if (namelen <= 0) {
+ if (namelen)
+ status = namelen;
+ else
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ LOG_TRACE_ARGS("adding filename '%s' to orphan dir (len=%d)\n", name,
+ namelen);
+
+ orphan_dir_inode = igrab(osb->system_inodes[ORPHAN_DIR_SYSTEM_INODE]);
+ if (!orphan_dir_inode) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ ocfs_handle_add_inode(handle, orphan_dir_inode);
+
+ /* disk lock orphan dir here. */
+ status = ocfs_acquire_lock(osb, OCFS_DLM_EXCLUSIVE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR,
+ &orphan_dir_bh, orphan_dir_inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ ocfs_handle_add_lock(handle, OCFS_DLM_ENABLE_CACHE_LOCK,
+ FLAG_FILE_CREATE | FLAG_DIR, orphan_dir_bh,
+ orphan_dir_inode, 1);
+
+ status = __ocfs_add_entry(handle, orphan_dir_inode, name, namelen,
+ inode, GET_INODE_FEOFF(inode),
+ orphan_dir_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ status = ocfs_journal_access(handle, orphan_dir_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ /* we're a cluster, and nlink can change on disk from
+ * underneath us... */
+ orphan_fe = OCFS_BH_GET_DATA_WRITE(orphan_dir_bh);
+ if (S_ISDIR(inode->i_mode))
+ orphan_fe->i_links_count++;
+ orphan_dir_inode->i_nlink = orphan_fe->i_links_count;
+ OCFS_BH_PUT_DATA(orphan_dir_bh);
+
+ status = ocfs_journal_dirty(handle, orphan_dir_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+
+ fe->i_flags |= OCFS2_ORPHANED_FL;
+
+leave:
+ if (orphan_dir_inode)
+ iput(orphan_dir_inode);
+
+ if (name)
+ kfree(name);
+
+ if (orphan_dir_bh)
+ brelse(orphan_dir_bh);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_orphan_add */
+
+/* unlike orphan_add, we expect the orphan dir to already be locked here. */
+int ocfs_orphan_del(ocfs_super *osb, ocfs_journal_handle *handle,
+ struct inode *orphan_dir_inode, struct inode *inode,
+ struct buffer_head *orphan_dir_bh)
{
- LOG_ERROR_ARGS("need to add %llu to orphan dir, i_nlink=%d\n",
- GET_INODE_FEOFF(inode), inode->i_nlink);
- return 0;
-}
+ char *name = NULL;
+ int namelen;
+ ocfs2_dinode *orphan_fe;
+ int status = 0;
+ struct buffer_head *target_de_bh;
+ struct ocfs2_dir_entry *target_de = NULL;
-int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode)
-{
- return 0;
+ name = kmalloc(OCFS_MAX_FILENAME_LENGTH+1, GFP_KERNEL);
+ if (!name) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ namelen = snprintf(name, OCFS_MAX_FILENAME_LENGTH+1, "%llu",
+ GET_INODE_FEOFF(inode));
+ if (namelen <= 0) {
+ if (namelen)
+ status = namelen;
+ else
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ LOG_TRACE_ARGS("removing '%s' from orphan dir (len=%d)\n", name,
+ namelen);
+
+ /* find it's spot in the orphan directory */
+ target_de_bh = ocfs_find_entry(name, namelen, orphan_dir_inode,
+ &target_de);
+ if (!target_de_bh) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ /* remove it from the orphan directory */
+ status = ocfs_delete_entry(handle, orphan_dir_inode, target_de,
+ target_de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ status = ocfs_journal_access(handle, orphan_dir_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ /* do the i_nlink dance! :) */
+ orphan_fe = OCFS_BH_GET_DATA_WRITE(orphan_dir_bh);
+ if (S_ISDIR(inode->i_mode))
+ orphan_fe->i_links_count--;
+ orphan_dir_inode->i_nlink = orphan_fe->i_links_count;
+ OCFS_BH_PUT_DATA(orphan_dir_bh);
+
+ status = ocfs_journal_dirty(handle, orphan_dir_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+leave:
+ if (name)
+ kfree(name);
+
+ return status;
}
#if 0
@@ -1868,8 +1977,7 @@
/* lock the parent directory */
parent_off = GET_INODE_FEOFF(dir);
- err = ocfs_acquire_lock (osb, parent_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ err = ocfs_acquire_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE | FLAG_DIR,
&parent_fe_bh, dir);
if (err < 0) {
@@ -1881,8 +1989,7 @@
/* lock the file entry */
fe_off = GET_INODE_FEOFF(inode);
- err = ocfs_acquire_lock (osb, fe_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ err = ocfs_acquire_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE,
&bh, inode);
if (err < 0) {
@@ -1921,16 +2028,14 @@
ocfs_commit_trans(handle);
if (parent_off) {
- tmpstat = ocfs_release_lock (osb, parent_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ tmpstat = ocfs_release_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE | FLAG_DIR,
parent_fe_bh, dir);
if (tmpstat < 0)
LOG_ERROR_STATUS (tmpstat);
}
if (fe_off) {
- tmpstat = ocfs_release_lock (osb, fe_off,
- OCFS_DLM_ENABLE_CACHE_LOCK,
+ tmpstat = ocfs_release_lock (osb, OCFS_DLM_ENABLE_CACHE_LOCK,
FLAG_FILE_CREATE,
bh, inode);
if (tmpstat < 0)
Modified: branches/format-changes/src/namei.h
===================================================================
--- branches/format-changes/src/namei.h 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/namei.h 2004-06-12 05:50:13 UTC (rev 1059)
@@ -35,8 +35,9 @@
#else
int ocfs_create (struct inode *dir, struct dentry *dentry, int mode);
#endif
-struct buffer_head * ocfs_find_entry (const char *name, int namelen, struct inode *dir,
- struct ocfs2_dir_entry ** res_dir);
+struct buffer_head *ocfs_find_entry(const char *name, int namelen,
+ struct inode *dir,
+ struct ocfs2_dir_entry **res_dir);
int ocfs_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *dentry);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -53,9 +54,8 @@
int ocfs_symlink(struct inode *dir, struct dentry *dentry,
const char *symname);
int ocfs_unlink(struct inode *dir, struct dentry *dentry);
+int ocfs_orphan_del(ocfs_super *osb, ocfs_journal_handle *handle,
+ struct inode *orphan_dir_inode, struct inode *inode,
+ struct buffer_head *orphan_dir_bh);
-/* FIXME: only in namei.c */
-int ocfs_orphan_add(ocfs_journal_handle *handle, struct inode *inode);
-int ocfs_orphan_del(ocfs_journal_handle *handle, struct inode *inode);
-
#endif /* OCFS2_NAMEI_H */
Modified: branches/format-changes/src/nm.c
===================================================================
--- branches/format-changes/src/nm.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/nm.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -78,8 +78,8 @@
static const char *process_vote_strings[] = {
"INVALID_REQUEST", // reply with a NO vote
"UPDATE_OIN_INODE", // update both oin and inode
- "DELETE_RENAME_ACQUIRE",// delete or rename request
- "DELETE_RENAME_RELEASE",// delete or rename release request
+ "DELETE_ACQUIRE",// delete or rename request
+ "DELETE_RELEASE",// delete or rename release request
"RELEASE_CACHE", // release a cache lock I hold
"CHANGE_MASTER", // request to change master to requestor
"ADD_OIN_MAP", // add requestor into oin map
@@ -88,6 +88,7 @@
"REMASTER_REQUESTOR", // remaster lock to requestor
"DROP_READONLY", // RO cachelock needs to convert to RW
"READONLY",
+ "RELEASE_DENTRY"
};
#endif
@@ -525,10 +526,10 @@
my_node_wins = (node_num < osb->node_num);
}
-// if (flags & FLAG_DROP_LINK) {
-// vote_type = RELEASE_DENTRY;
-// goto done;
-// }
+ if (flags & (FLAG_RELEASE_DENTRY | FLAG_FILE_RENAME)) {
+ vote_type = RELEASE_DENTRY;
+ goto done;
+ }
if (flags & FLAG_DROP_READONLY) {
vote_type = DROP_READONLY;
@@ -542,11 +543,11 @@
goto done;
}
- if (flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) {
+ if (flags & FLAG_FILE_DELETE) {
if (flags & FLAG_RELEASE_LOCK)
- vote_type = DELETE_RENAME_RELEASE;
+ vote_type = DELETE_RELEASE;
else if (flags & FLAG_ACQUIRE_LOCK)
- vote_type = DELETE_RENAME_ACQUIRE;
+ vote_type = DELETE_ACQUIRE;
else
vote_type = INVALID_REQUEST;
} else if (flags & FLAG_FILE_RELEASE_CACHE)
@@ -571,7 +572,7 @@
vote_type = REMASTER_REQUESTOR;
}
- if (inode == NULL && vote_type != DELETE_RENAME_RELEASE)
+ if (inode == NULL && vote_type != DELETE_RELEASE)
vote_type = INVALID_REQUEST;
done:
LOG_EXIT_STATUS(vote_type);
@@ -632,7 +633,6 @@
ocfs_vote *vote = NULL;
struct buffer_head *fe_bh = NULL, *vote_bh = NULL;
int vote_type = INVALID_REQUEST, vote_response = 0;
- int oin_sem = 0;
struct inode *inode = NULL;
int master_alive = 1, is_dir = 0;
int is_locked, open_handle;
@@ -689,7 +689,7 @@
* look up the inode in the release case -- it should already
* be gone. Eventually what we'll really want to do is get it
* via the old offsets and set the new ones. */
- if ((flags & (FLAG_FILE_DELETE | FLAG_FILE_RENAME)) && (flags & FLAG_RELEASE_LOCK))
+ if ((flags & FLAG_FILE_DELETE) && (flags & FLAG_RELEASE_LOCK))
inode = NULL;
else {
inode = ocfs_iget(osb, lock_id);
@@ -702,6 +702,11 @@
goto leave;
}
+ /* ahh, so you find yourself asking "what the
+ * heck is this?"
+ * Please see the note in ocfs_delete_inode. */
+ osb->voting_ino = inode->i_ino;
+
down(&OCFS_I(inode)->ip_io_sem);
have_io_sem = 1;
@@ -778,137 +783,117 @@
vote_response = FLAG_VOTE_OIN_UPDATED;
break;
-#if 0
case RELEASE_DENTRY:
if (!inode)
BUG();
/* we always vote yes on this one. */
vote_response = FLAG_VOTE_NODE;
- printk("going to prune dentries for inode %lu\n",
- inode->i_ino);
+ /* do nothing in the release case... hmm,
+ * perhaps we should just do a verify_update
+ * or something in case the guy aborted... */
+ if (flags & FLAG_RELEASE_LOCK)
+ break;
+
d_prune_aliases (inode);
- inode->i_nlink--;
+
+ /* for rename, we don't drop link counts */
+ if (!(flags & FLAG_FILE_RENAME)) {
+ if (S_ISDIR(inode->i_mode))
+ inode->i_nlink = 0;
+ else
+ inode->i_nlink--;
+ }
+
+ LOG_TRACE_ARGS("pruned dentries for inode %lu, nlink "
+ "= %u\n", inode->i_ino, inode->i_nlink);
break;
-#endif
- case DELETE_RENAME_RELEASE:
+
+ case DELETE_RELEASE:
/* ACK and done */
vote_response = FLAG_VOTE_NODE;
break;
- case DELETE_RENAME_ACQUIRE:
- LOG_TRACE_STR("DELETE_RENAME");
+ case DELETE_ACQUIRE:
+ LOG_TRACE_STR("DELETE_ACQUIRE");
- /* all cases except open_hndl_cnt > 0 will vote YES */
- vote_response = FLAG_VOTE_NODE;
+ down (&(OCFS_I(inode)->priv_sem));
+ OCFS_I(inode)->needs_verification = 1;
+ tmpstat = ocfs_verify_update_inode(osb, inode,
+ &needs_trunc,
+ 1);
+ if (tmpstat < 0)
+ LOG_ERROR_STATUS (tmpstat);
- if (inode) {
- oin_sem = 1;
- down (&(OCFS_I(inode)->priv_sem));
- OCFS_I(inode)->needs_verification = 1;
- tmpstat = ocfs_verify_update_inode(osb, inode,
- &needs_trunc,
- 1);
- if (tmpstat < 0)
- LOG_ERROR_STATUS (tmpstat);
-
- if (needs_trunc) {
- ocfs_truncate_inode_pages(inode, 0);
- needs_trunc = 0;
- }
+ if (needs_trunc)
+ ocfs_truncate_inode_pages(inode, 0);
- if (OCFS_I(inode)->open_hndl_cnt > 0) {
- /* the NO vote for delete/rename */
- vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
- } else {
- spin_lock(&oin_num_ext_lock);
- if (OCFS_I(inode)->num_extends) {
- vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
- } else {
- OCFS_SET_FLAG (OCFS_I(inode)->oin_flags, OCFS_OIN_NEEDS_DELETION);
- up(&(OCFS_I(inode)->priv_sem));
- ocfs_release_lockres (lockres); // ocfs_process_vote
- lockres = NULL;
- oin_sem = 0;
- if (needs_trunc) {
- ocfs_truncate_inode_pages(inode, 0);
- needs_trunc = 0;
- }
- }
- spin_unlock(&oin_num_ext_lock);
- }
+ LOG_TRACE_ARGS("DELETE vote on inode %lu, read "
+ "lnk_cnt = %u\n", inode->i_ino,
+ inode->i_nlink);
+ /* verify_update_inode does a dirty read which
+ * might set i_nlink to an old value. */
+ if (inode->i_nlink) {
+ LOG_ERROR_ARGS("Orphaned inode %lu has link "
+ "count = %d!\n", inode->i_ino,
+ inode->i_nlink);
+ inode->i_nlink = 0;
}
- /* If the inode exists and we we're going to
- * 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);
+ /* vote no if the file is still open. */
+ if (OCFS_I(inode)->open_hndl_cnt > 0) {
+ vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
+ up(&(OCFS_I(inode)->priv_sem));
+ goto delete_vote_no;
}
+ up(&(OCFS_I(inode)->priv_sem));
- if (!lockres) {
- /* is there an inode to dump? */
- if (inode) {
- inode->i_nlink = 0;
- d_prune_aliases (inode);
+ /* vote no if someone's extending it. */
+ spin_lock(&oin_num_ext_lock);
+ if (OCFS_I(inode)->num_extends) {
+ spin_unlock(&oin_num_ext_lock);
+ vote_response = FLAG_VOTE_OIN_ALREADY_INUSE;
+ goto delete_vote_no;
+ }
+ spin_unlock(&oin_num_ext_lock);
+
+ vote_response = FLAG_VOTE_NODE;
+
+ SET_INODE_DELETED(inode);
+ /* if we vote yes, then we set the SKIP_DELETE
+ * flag on the inode so we don't try to delete
+ * it in delete_inode ourselves. */
+ OCFS_SET_FLAG(OCFS_I(inode)->flags,
+ OCFS_INODE_SKIP_DELETE);
+
+ inode->i_nlink = 0;
+ d_prune_aliases (inode);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- sync_mapping_buffers(inode->i_mapping);
+ sync_mapping_buffers(inode->i_mapping);
#else
- fsync_inode_buffers (inode);
+ fsync_inode_buffers (inode);
#endif
- up(&OCFS_I(inode)->ip_io_sem);
- have_io_sem = 0;
- }
- break;
- }
+ /* Alright, for the YES case, we're done here. */
+ break;
- if (inode) {
- up(&OCFS_I(inode)->ip_io_sem);
- have_io_sem = 0;
- }
-
- /* Set the always update master on open flag */
- lockres->lock_state |= FLAG_ALWAYS_UPDATE_OPEN;
+delete_vote_no:
lockres->last_upd_seq_num = seq_num;
- if (lockres->master_node_num == OCFS_INVALID_NODE_NUM || !master_alive)
+ /* (6/11/2004): the next two conditional are
+ * likely useless relics. If we don't hit
+ * those error messages then we can delete
+ * them.*/
+ if (lockres->master_node_num == OCFS_INVALID_NODE_NUM
+ || !master_alive) {
lockres->master_node_num = node_num;
-
- /* Change the master if there is no lock */
- if (lockres->master_node_num == osb->node_num &&
- lockres->lock_type < OCFS_DLM_EXCLUSIVE_LOCK) {
- /* Change the lock ownership to the node asking for vote */
- /* and write new master on the disk */
-
- status = ocfs_read_bh(osb, lock_id, &fe_bh, lockflags, inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- if (status >= 0) {
- fe = OCFS_BH_GET_DATA_WRITE(fe_bh);
- DISK_LOCK(fe)->dl_master = node_num;
- OCFS_BH_PUT_DATA(fe_bh);
- status = ocfs_write_bh(osb, fe_bh, 0, inode);
- if (status < 0)
- LOG_ERROR_STATUS (status);
- else
- lockres->master_node_num = node_num;
- brelse(fe_bh);
- }
+ LOG_ERROR_STR("Wowzers, how'd I hit this code:"
+ " master node is invalid!?!");
}
- if (oin_sem) {
- up(&(OCFS_I(inode)->priv_sem));
- oin_sem = 0;
+ if ((lockres->master_node_num == osb->node_num) &&
+ (lockres->lock_type < OCFS_DLM_EXCLUSIVE_LOCK)) {
+ LOG_ERROR_STR("Wowzers, how'd I hit this "
+ "code!?!");
}
-
- if (needs_trunc) {
- ocfs_truncate_inode_pages(inode, 0);
- needs_trunc = 0;
- }
-
break;
case READONLY:
@@ -1065,8 +1050,7 @@
}
fe = OCFS_BH_GET_DATA_READ(fe_bh);
- if ((fe->i_flags & OCFS2_NAME_DELETED_FL) ||
- (!(fe->i_flags & OCFS2_VALID_FL))) {
+ if (!(fe->i_flags & OCFS2_VALID_FL)) {
vote_response = FLAG_VOTE_FILE_DEL;
OCFS_BH_PUT_DATA(fe_bh);
} else {
@@ -1258,9 +1242,12 @@
ocfs_inc_inode_seq(osb, inode, 1);
if (have_io_sem)
up(&OCFS_I(inode)->ip_io_sem);
- iput(inode);
}
+ if (inode)
+ iput(inode);
+ osb->voting_ino = 0;
+
up(&osb->vote_sem);
LOG_EXIT_STATUS (status);
Modified: branches/format-changes/src/ocfs.h
===================================================================
--- branches/format-changes/src/ocfs.h 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/ocfs.h 2004-06-12 05:50:13 UTC (rev 1059)
@@ -97,8 +97,8 @@
enum {
INVALID_REQUEST, // reply with a NO vote
UPDATE_OIN_INODE, // update both oin and inode
- DELETE_RENAME_ACQUIRE,// delete or rename acquire request
- DELETE_RENAME_RELEASE,// delete or rename release request
+ DELETE_ACQUIRE,// delete or rename acquire request
+ DELETE_RELEASE,// delete or rename release request
RELEASE_CACHE, // release a cache lock I hold
CHANGE_MASTER, // request to change master to requestor
ADD_OIN_MAP, // add requestor into oin map
@@ -106,7 +106,8 @@
REMASTER_THIS, // remaster lock to me
REMASTER_REQUESTOR, // remaster lock to requestor
DROP_READONLY, // RO cachelock needs to convert to RW
- READONLY // a RW or RO cachelock, requesting RO
+ READONLY, // a RW or RO cachelock, requesting RO
+ RELEASE_DENTRY
};
#define OCFS_MAX_DLM_PKT_SIZE 256
@@ -166,7 +167,7 @@
#define FLAG_FILE_CREATE_DIR 0x00000040
#define FLAG_FILE_UPDATE_OIN 0x00000080
#define FLAG_FILE_RELEASE_MASTER 0x00000100
-#define FLAG_DROP_LINK 0x00000200
+#define FLAG_RELEASE_DENTRY 0x00000200
#define FLAG_CHANGE_MASTER 0x00000400
#define FLAG_ADD_OIN_MAP 0x00000800
#define FLAG_DIR 0x00001000
@@ -217,6 +218,7 @@
#define LOG_FILE_BASE_ID (OCFS_RECOVER_LOG_SYSFILE * OCFS_MAXIMUM_NODES) // unused in version 2
#define CLEANUP_FILE_BASE_ID (OCFS_CLEANUP_LOG_SYSFILE * OCFS_MAXIMUM_NODES) // unused in version 2
#define OCFS_LOCAL_ALLOC_FILE (OCFS_VOL_BM_SYSFILE * OCFS_MAXIMUM_NODES) // was OCFS_VOL_BITMAP_FILE
+#define OCFS_ORPHAN_DIR (OCFS_ORPHAN_DIR_SYSFILE * OCFS_MAXIMUM_NODES)
#define OCFS_JOURNAL_FILE (OCFS_JOURNAL_SYSFILE * OCFS_MAXIMUM_NODES)
#define OCFS_INODE_FILE (OCFS_INODE_SYSFILE * OCFS_MAXIMUM_NODES)
#define OCFS_INODE_BITMAP (OCFS_INODE_BM_SYSFILE * OCFS_MAXIMUM_NODES)
@@ -316,12 +318,13 @@
*/
/* OCFS2 file flags */
#define OCFS2_VALID_FL (0x01)
-#define OCFS2_CHANGE_FL (0x02)
-#define OCFS2_MARK_FOR_DELETION_FL (0x04)
-#define OCFS2_NAME_DELETED_FL (0x08)
+#define OCFS2_UNUSED2_FL (0x02)
+#define OCFS2_ORPHANED_FL (0x04)
+#define OCFS2_UNUSED3_FL (0x08)
#define OCFS2_SYSTEM_FL (0x10)
#define OCFS2_SUPER_FL (0x11)
#define OCFS2_ALLOC_FL (0x12)
+#define OCFS2_BITMAP_FL (0x14)
#define INVALID_NODE_POINTER -1
@@ -917,7 +920,7 @@
__u32 used_bits;
__u32 total_bits;
} ip_bitinfo;
- } u;
+ } u;
ocfs_lock_res i_lockres;
__u32 i_dir_start_lookup;
@@ -927,10 +930,8 @@
* merged. */
/* oin_flags flags */
#define OCFS_OIN_DIRECTORY (0x00000002)
-#define OCFS_OIN_DELETE_ON_CLOSE (0x00000008)
-#define OCFS_OIN_NEEDS_DELETION (0x00000010)
-#define OCFS_OIN_OPEN_FOR_DIRECTIO (0x00000100)
-#define OCFS_OIN_OPEN_FOR_WRITE (0x00000200)
+#define OCFS_OIN_OPEN_FOR_DIRECTIO (0x00000008)
+#define OCFS_OIN_OPEN_FOR_WRITE (0x00000010)
/* 'flags' flags. */
/* has this inode been deleted, either from this node or from another node. */
@@ -941,6 +942,8 @@
#define OCFS_INODE_INITIALIZED 0x00000004
/* is this a system file? */
#define OCFS_INODE_SYSTEM_FILE 0x00000008
+/* are we going to let another node deal with deletion of this inode? */
+#define OCFS_INODE_SKIP_DELETE 0x00000010
#define OCFS_I(i) ((ocfs_inode_private *)(i->u.generic_ip))
@@ -1183,6 +1186,7 @@
struct semaphore vote_sem; /* protects calls to ocfs_process_vote */
struct list_head vote_obj_queue;
spinlock_t vote_obj_queue_lock;
+ unsigned long voting_ino; /* only safe from the process_vote pid */
};
typedef struct _ocfs_comm_info
Modified: branches/format-changes/src/super.c
===================================================================
--- branches/format-changes/src/super.c 2004-06-11 23:43:59 UTC (rev 1058)
+++ branches/format-changes/src/super.c 2004-06-12 05:50:13 UTC (rev 1059)
@@ -191,7 +191,7 @@
.put_inode = ocfs_put_inode,
.clear_inode = ocfs_clear_inode,
//put_inode = force_delete,
- //delete_inode = ocfs_delete_inode,
+ .delete_inode = ocfs_delete_inode,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
.read_inode = ocfs_read_inode,
.read_inode2 = ocfs_read_inode2,
More information about the Ocfs2-commits
mailing list