[Ocfs2-commits] mfasheh commits r1491 - branches/dlm-changes/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Fri Sep 24 18:42:25 CDT 2004
Author: mfasheh
Date: 2004-09-24 18:42:23 -0500 (Fri, 24 Sep 2004)
New Revision: 1491
Modified:
branches/dlm-changes/src/namei.c
branches/dlm-changes/src/namei.h
Log:
* move ocfs_match into namei.h as dir.c wants it now.
* take directory locks outside of transactions. We do this with a prepare /
insert api. Prepare is responsible for finding a spot (and extending to
create a new one if need be) and insert actually makes the changes.
Modified: branches/dlm-changes/src/namei.c
===================================================================
--- branches/dlm-changes/src/namei.c 2004-09-24 23:39:22 UTC (rev 1490)
+++ branches/dlm-changes/src/namei.c 2004-09-24 23:42:23 UTC (rev 1491)
@@ -58,6 +58,7 @@
#include "inode.h"
#include "lockres.h"
#include "namei.h"
+#include "suballoc.h"
#include "util.h"
#include "vote.h"
@@ -71,26 +72,35 @@
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 blkno,
- 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_add_entry (ocfs_journal_handle *handle, struct inode *dir,
+ const char *name, int namelen,
+ struct inode *inode, u64 blkno,
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh);
+
static int ocfs_mknod_locked(ocfs_super *osb, struct inode *dir,
struct dentry *dentry, int mode,
dev_t dev,
struct buffer_head **new_fe_bh,
struct buffer_head *parent_fe_bh,
ocfs_journal_handle *handle,
- struct inode *inode);
+ struct inode *inode,
+ ocfs2_alloc_context *inode_ac,
+ struct buffer_head *de_bh);
+static int ocfs_fill_new_dir(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *parent,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ ocfs2_alloc_context *data_ac);
+
static int ocfs_double_lock(ocfs_super *osb,
ocfs_journal_handle *handle,
__u32 type1, __u32 flags1,
@@ -100,8 +110,15 @@
struct buffer_head **bh2,
struct inode *inode2);
+static int ocfs_prepare_orphan_dir(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *inode,
+ char **ret_name,
+ struct buffer_head **de_bh);
+
static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
- struct inode *inode, ocfs2_dinode *fe);
+ struct inode *inode, ocfs2_dinode *fe,
+ char *name, struct buffer_head *de_bh);
static int ocfs_create_symlink_data(ocfs_super *osb,
ocfs_journal_handle *handle,
@@ -111,11 +128,12 @@
static inline int ocfs_add_entry(ocfs_journal_handle *handle,
struct dentry *dentry,
struct inode *inode, u64 blkno,
- struct buffer_head *parent_fe_bh)
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh)
{
return(__ocfs_add_entry(handle, dentry->d_parent->d_inode,
dentry->d_name.name, dentry->d_name.len,
- inode, blkno, parent_fe_bh));
+ inode, blkno, parent_fe_bh, insert_bh));
}
/*
@@ -169,13 +187,82 @@
bail:
if (dirent_bh)
brelse(dirent_bh);
-
+
LOG_EXIT_PTR (ret);
LOG_CLEAR_CONTEXT();
return ret;
} /* ocfs_lookup */
+static int ocfs_fill_new_dir(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *parent,
+ struct inode *inode,
+ struct buffer_head *fe_bh,
+ ocfs2_alloc_context *data_ac)
+{
+ int status;
+ struct buffer_head *new_bh = NULL;
+ struct ocfs2_dir_entry *de = NULL;
+
+ LOG_ENTRY();
+
+ status = ocfs_do_extend_dir(osb->sb, handle, inode, fe_bh,
+ data_ac, NULL, &new_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ set_buffer_uptodate(new_bh);
+ SET_BH_SEQNUM(inode, new_bh);
+ status = ocfs_journal_access(handle, new_bh,
+ OCFS_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ memset(new_bh->b_data, 0, osb->sb->s_blocksize);
+
+ de = (struct ocfs2_dir_entry *) new_bh->b_data;
+ de->inode = cpu_to_le64(OCFS_I(inode)->ip_blkno);
+ de->name_len = 1;
+ de->rec_len =
+ cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
+ strcpy (de->name, ".");
+ ocfs_set_de_type(de, S_IFDIR);
+ de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
+ de->inode = cpu_to_le64(OCFS_I(parent)->ip_blkno);
+ de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
+ OCFS2_DIR_REC_LEN(1));
+ de->name_len = 2;
+ strcpy (de->name, "..");
+ ocfs_set_de_type(de, S_IFDIR);
+
+ status = ocfs_journal_dirty(handle, new_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ inode->i_size = inode->i_sb->s_blocksize;
+ inode->i_nlink = 2;
+ inode->i_blocks = 1;
+ status = ocfs_mark_inode_dirty(handle, inode, fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ status = 0;
+bail:
+ if (new_bh)
+ brelse(new_bh);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
static int ocfs_mknod(struct inode *dir, struct dentry *dentry,
int mode, dev_t dev)
{
@@ -187,7 +274,10 @@
ocfs2_dinode *fe = NULL;
ocfs2_dinode *dirfe;
struct buffer_head *new_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
struct inode *inode = NULL;
+ ocfs2_alloc_context *inode_ac = NULL;
+ ocfs2_alloc_context *data_ac = NULL;
LOG_SET_CONTEXT(MKNOD);
@@ -251,6 +341,32 @@
goto leave;
}
+ /* get a spot inside the dir. */
+ status = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto leave;
+ }
+
+ /* reserve an inode spot */
+ status = ocfs_reserve_new_inode(osb, handle, &inode_ac);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto leave;
+ }
+
+ /* are we making a directory? If so, reserve a cluster for his
+ * 1st extent. */
+ if (S_ISDIR(mode)) {
+ status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+ }
+
handle = ocfs_start_trans(osb, handle, OCFS_MKNOD_CREDITS);
if (handle == NULL) {
LOG_ERROR_STATUS (status = -ENOMEM);
@@ -259,7 +375,8 @@
/* do the real work now. */
status = ocfs_mknod_locked(osb, dir, dentry, mode, dev,
- &new_fe_bh, parent_fe_bh, handle, inode);
+ &new_fe_bh, parent_fe_bh, handle,
+ inode, inode_ac, de_bh);
if (status < 0) {
if (status != -EINTR)
LOG_ERROR_STATUS(status);
@@ -283,50 +400,19 @@
status = ocfs_update_lockres(osb, new_fe_bh, inode, 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);
+ status = ocfs_fill_new_dir(osb, handle, dir, inode,
+ new_fe_bh, data_ac);
if (status < 0) {
- brelse(newdirbh);
LOG_ERROR_STATUS(status);
goto leave;
}
- de = (struct ocfs2_dir_entry *) newdirbh->b_data;
- de->inode = cpu_to_le64(fe->i_blkno);
- fe = NULL;
- de->name_len = 1;
- de->rec_len =
- cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
- strcpy (de->name, ".");
- ocfs_set_de_type(de, S_IFDIR);
- de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
- de->inode = cpu_to_le64(OCFS_I(dir)->ip_blkno);
- de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize -
- OCFS2_DIR_REC_LEN(1));
- de->name_len = 2;
- strcpy (de->name, "..");
- ocfs_set_de_type(de, S_IFDIR);
- inode->i_nlink = 2;
- status = ocfs_journal_dirty(handle, newdirbh);
- brelse (newdirbh);
+
+ status = ocfs_journal_access(handle, parent_fe_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
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 = (ocfs2_dinode *) parent_fe_bh->b_data;
fe->i_links_count++;
fe = NULL;
@@ -355,12 +441,21 @@
if (new_fe_bh)
brelse(new_fe_bh);
+ if (de_bh)
+ brelse(de_bh);
+
if (parent_fe_bh != NULL)
brelse(parent_fe_bh);
if ((status < 0) && inode)
iput(inode);
+ if (inode_ac)
+ ocfs_free_alloc_context(inode_ac);
+
+ if (data_ac)
+ ocfs_free_alloc_context(data_ac);
+
LOG_EXIT_STATUS(status);
LOG_CLEAR_CONTEXT();
@@ -377,30 +472,28 @@
struct buffer_head **new_fe_bh,
struct buffer_head *parent_fe_bh,
ocfs_journal_handle *handle,
- struct inode *inode)
+ struct inode *inode,
+ ocfs2_alloc_context *inode_ac,
+ struct buffer_head *de_bh)
{
int status = 0;
ocfs2_dinode *fe = NULL;
ocfs2_extent_list *fel;
- __u64 disk_off = 0;
u64 fe_blkno = 0;
- __u64 fileOffset = 0;
+ u16 suballoc_bit;
LOG_ENTRY_ARGS ("(0x%p, 0x%p, %d, %lu, '%*s')\n", dir, dentry, mode,
(unsigned long)dev, dentry->d_name.len, dentry->d_name.name);
OCFS_ASSERT(new_fe_bh);
*new_fe_bh = NULL;
-
- status = ocfs_alloc_node_block(osb, osb->sb->s_blocksize,
- &disk_off, &fileOffset,
- osb->node_num, DISK_ALLOC_INODE,
- handle);
+
+ status = ocfs_claim_new_inode(osb, handle, inode_ac, &suballoc_bit,
+ &fe_blkno);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto leave;
}
- fe_blkno = disk_off >> osb->sb->s_blocksize_bits;
*new_fe_bh = sb_getblk(osb->sb, fe_blkno);
if (!*new_fe_bh) {
@@ -433,7 +526,7 @@
spin_unlock(&osb->s_next_gen_lock);
fe->i_generation = cpu_to_le32(inode->i_generation);
fe->i_blkno = fe_blkno;
- fe->i_suballoc_blkno = fileOffset >> osb->sb->s_blocksize_bits;
+ fe->i_suballoc_bit = suballoc_bit;
fe->i_suballoc_node = osb->node_num;
fe->i_uid = current->fsuid;
if (dir->i_mode & S_ISGID) {
@@ -480,7 +573,7 @@
inode->i_mode = mode;
status = ocfs_add_entry(handle, dentry, inode, fe_blkno,
- parent_fe_bh);
+ parent_fe_bh, de_bh);
if (status < 0) {
LOG_ERROR_STATUS (status);
goto leave;
@@ -547,6 +640,7 @@
int err;
struct buffer_head *fe_bh = NULL;
struct buffer_head *parent_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
ocfs2_dinode *fe = NULL;
ocfs_super *osb = OCFS_SB(dir->i_sb);
@@ -584,6 +678,14 @@
ocfs_handle_add_lock(handle, OCFS_LKM_EXMODE, 0, dir);
ocfs_handle_add_inode(handle, dir);
+ err = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (err < 0) {
+ LOG_ERROR_STATUS (err);
+ goto bail;
+ }
+
err = ocfs_acquire_lock (osb, OCFS_LKM_EXMODE, 0, &fe_bh, inode);
if (err < 0) {
if (err != -EINTR)
@@ -627,8 +729,8 @@
goto bail;
}
- err = ocfs_add_entry(handle, dentry, inode,
- OCFS_I(inode)->ip_blkno, parent_fe_bh);
+ err = ocfs_add_entry(handle, dentry, inode, OCFS_I(inode)->ip_blkno,
+ parent_fe_bh, de_bh);
if (err) {
fe->i_links_count--;
inode->i_nlink--;
@@ -641,7 +743,8 @@
bail:
if (handle)
ocfs_commit_trans(handle);
-
+ if (de_bh)
+ brelse(de_bh);
if (fe_bh)
brelse(fe_bh);
if (parent_fe_bh)
@@ -670,6 +773,8 @@
ocfs_journal_handle *handle = NULL;
struct ocfs2_dir_entry *dirent = NULL;
struct buffer_head *dirent_bh = NULL;
+ char *orphan_name;
+ struct buffer_head *orphan_entry_bh = NULL;
LOG_SET_CONTEXT(UNLINK);
@@ -738,6 +843,16 @@
}
}
+ if (S_ISDIR(inode->i_mode) || (inode->i_nlink == 1)) {
+ status = ocfs_prepare_orphan_dir(osb, handle, inode,
+ &orphan_name,
+ &orphan_entry_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto leave;
+ }
+ }
+
handle = ocfs_start_trans(osb, handle, OCFS_FILE_DELETE_CREDITS);
if (handle == NULL) {
LOG_ERROR_STATUS (status = -ENOMEM);
@@ -763,7 +878,8 @@
else
fe->i_links_count--;
if (!fe->i_links_count) {
- status = ocfs_orphan_add(osb, handle, inode, fe);
+ status = ocfs_orphan_add(osb, handle, inode, fe, orphan_name,
+ orphan_entry_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto leave;
@@ -832,6 +948,12 @@
if (parent_node_bh)
brelse(parent_node_bh);
+ if (orphan_entry_bh)
+ brelse(orphan_entry_bh);
+
+ if (orphan_name)
+ kfree(orphan_name);
+
LOG_EXIT_INT (retval);
LOG_CLEAR_CONTEXT();
@@ -924,17 +1046,22 @@
#define PARENT_INO(buffer) \
((struct ocfs2_dir_entry *) ((char *) buffer + \
le16_to_cpu(((struct ocfs2_dir_entry *) buffer)->rec_len)))->inode
+
/*
* ocfs_rename()
*
*/
static int ocfs_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry)
{
+#warning "this needs to be split up into seperate functions."
int status = 0;
struct inode *old_inode = old_dentry->d_inode;
struct inode *new_inode = new_dentry->d_inode;
ocfs2_dinode *newfe = NULL;
+ char *orphan_name;
+ struct buffer_head *orphan_entry_bh = NULL;
struct buffer_head *newfe_bh = NULL;
+ struct buffer_head *insert_entry_bh = NULL;
ocfs_super *osb = NULL;
u64 newfe_blkno;
ocfs_journal_handle *handle = NULL;
@@ -1023,7 +1150,7 @@
ocfs_handle_add_inode(handle, old_inode);
status = -EIO;
- old_inode_de_bh = ocfs_bread (handle, old_inode, 0, 0, &status, 0);
+ old_inode_de_bh = ocfs_bread (old_inode, 0, &status, 0);
if (!old_inode_de_bh)
goto finally;
@@ -1044,7 +1171,7 @@
goto finally;
}
}
-
+
status = -ENOENT;
old_de_bh = ocfs_find_entry(old_dentry->d_name.name,
old_dentry->d_name.len,
@@ -1111,6 +1238,27 @@
"new_blkno=%llu newfebh=%p bhblocknr=%llu\n",
new_de, newfe_blkno, newfe_bh, newfe_bh ?
(unsigned long long)newfe_bh->b_blocknr : 0ULL);
+
+ if (S_ISDIR(new_inode->i_mode) || (new_inode->i_nlink == 1)) {
+ status = ocfs_prepare_orphan_dir(osb, handle,
+ new_inode,
+ &orphan_name,
+ &orphan_entry_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto finally;
+ }
+ }
+ } else {
+ OCFS_ASSERT(new_dentry->d_parent->d_inode == new_dir);
+ status = ocfs_prepare_dir_for_insert(osb, new_dir, new_dir_bh,
+ new_dentry->d_name.name,
+ new_dentry->d_name.len,
+ &insert_entry_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status);
+ goto finally;
+ }
}
handle = ocfs_start_trans(osb, handle, OCFS_FILE_RENAME_CREDITS);
@@ -1141,7 +1289,8 @@
if (!newfe->i_links_count) {
status = ocfs_orphan_add(osb, handle, new_inode,
- newfe);
+ newfe, orphan_name,
+ orphan_entry_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto finally;
@@ -1174,7 +1323,7 @@
/* if the name was not found in new_dir, add it now */
status = ocfs_add_entry (handle, new_dentry, old_inode,
OCFS_I(old_inode)->ip_blkno,
- new_dir_bh);
+ new_dir_bh, insert_entry_bh);
}
finally:
@@ -1279,7 +1428,14 @@
brelse(old_de_bh);
if (old_inode_de_bh)
brelse(old_inode_de_bh);
+ if (orphan_entry_bh)
+ brelse(orphan_entry_bh);
+ if (insert_entry_bh)
+ brelse(insert_entry_bh);
+ if (orphan_name)
+ kfree(orphan_name);
+
LOG_EXIT_STATUS(status);
LOG_CLEAR_CONTEXT();
@@ -1411,11 +1567,14 @@
struct super_block *sb;
int l;
struct buffer_head *new_fe_bh = NULL;
+ struct buffer_head *de_bh = NULL;
struct buffer_head *parent_fe_bh = NULL;
ocfs2_dinode *fe = NULL;
ocfs2_dinode *dirfe;
ocfs_journal_handle *handle = NULL;
int credits;
+ ocfs2_alloc_context *inode_ac = NULL;
+ ocfs2_alloc_context *data_ac = NULL;
LOG_SET_CONTEXT(SYMLINK);
@@ -1444,7 +1603,7 @@
l = strlen (symname) + 1;
newsize = l - 1;
- credits = ocfs_calc_symlink_credits(sb, newsize);
+ credits = ocfs_calc_symlink_credits(sb);
handle = ocfs_alloc_handle(osb);
if (handle == NULL) {
@@ -1470,6 +1629,26 @@
goto abort_trans;
}
+ status = ocfs_prepare_dir_for_insert(osb, dir, parent_fe_bh,
+ dentry->d_name.name,
+ dentry->d_name.len, &de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto abort_trans;
+ }
+
+ status = ocfs_reserve_new_inode(osb, handle, &inode_ac);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto abort_trans;
+ }
+
+ status = ocfs_reserve_bits(osb, handle, 1, &data_ac);
+ if (status < 0) {
+ LOG_ERROR_STATUS (status = -ENOMEM);
+ goto abort_trans;
+ }
+
handle = ocfs_start_trans(osb, handle, credits);
if (handle == NULL) {
LOG_ERROR_STATUS (status = -ENOMEM);
@@ -1479,14 +1658,14 @@
status = ocfs_mknod_locked(osb, dir, dentry,
S_IFLNK | S_IRWXUGO, 0,
&new_fe_bh, parent_fe_bh, handle,
- inode);
+ inode, inode_ac, de_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto abort_trans;
}
fe = (ocfs2_dinode *) new_fe_bh->b_data;
-
+
if (ocfs_populate_inode (inode, fe, 1) < 0) {
LOG_ERROR_ARGS("populate inode failed! bh->b_blocknr=%llu, "
"i_blkno=%llu, i_ino=%lu\n",
@@ -1501,8 +1680,8 @@
if (status < 0)
LOG_ERROR_STATUS(status);
- status = ocfs_extend_file(osb, newsize, handle, inode, NULL, 0,
- new_fe_bh);
+ status = ocfs_extend_allocation(osb, inode, 1, new_fe_bh, handle,
+ data_ac, NULL, NULL);
if (status < 0) {
if (status != -ENOSPC && status != -EINTR) {
LOG_ERROR_ARGS ("Failed to extend file to %llu", newsize);
@@ -1515,6 +1694,12 @@
inode->i_size = newsize;
inode->i_blocks = (newsize + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+ status = ocfs_mark_inode_dirty(handle, inode, new_fe_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto abort_trans;
+ }
+
status = ocfs_inode_fill_ext_map(osb, new_fe_bh, inode);
if (status < 0) {
LOG_ERROR_STATUS(status);
@@ -1540,6 +1725,10 @@
brelse(new_fe_bh);
if (parent_fe_bh)
brelse(parent_fe_bh);
+ if (de_bh)
+ brelse(de_bh);
+ if (inode_ac)
+ ocfs_free_alloc_context(inode_ac);
LOG_EXIT_STATUS (status);
@@ -1572,75 +1761,41 @@
return error_msg == NULL ? 1 : 0;
}
-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);
-}
-
/* we don't always have a dentry for what we want to add, so people
- * like orphan dir can call this instead. */
+ * like orphan dir can call this instead.
+ *
+ * If you pass me insert_bh, I'll skip the search of the other dir
+ * blocks and put the record in there.
+*/
static int __ocfs_add_entry (ocfs_journal_handle *handle, struct inode *dir,
const char *name, int namelen,
struct inode *inode, u64 blkno,
- struct buffer_head *parent_fe_bh)
+ struct buffer_head *parent_fe_bh,
+ struct buffer_head *insert_bh)
{
unsigned long offset;
unsigned short rec_len;
- struct buffer_head * bh;
struct ocfs2_dir_entry * de, * de1;
struct super_block * sb;
int retval, status;
- ocfs2_dinode *fe = NULL;
LOG_ENTRY();
+ OCFS_ASSERT(insert_bh);
sb = dir->i_sb;
if (!namelen)
return -EINVAL;
- bh = ocfs_bread (handle, dir, 0, 0, &retval, 0);
- if (!bh)
- return retval;
+
rec_len = OCFS2_DIR_REC_LEN(namelen);
offset = 0;
- de = (struct ocfs2_dir_entry *) bh->b_data;
+ de = (struct ocfs2_dir_entry *) insert_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)
- goto bail;
- if (dir->i_size <= offset) {
- if (dir->i_size == 0) {
- retval = -ENOENT;
- goto bail;
- }
-
- /* create next block */
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_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;
- status = ocfs_journal_dirty(handle, bh);
-
- /* update the parent file entry file size */
- status = ocfs_journal_access(handle, parent_fe_bh, OCFS_JOURNAL_ACCESS_WRITE);
- fe = (ocfs2_dinode *) parent_fe_bh->b_data;
- fe->i_size = dir->i_size;
- status = ocfs_journal_dirty(handle, parent_fe_bh);
- } else {
- /* move to next block */
- de = (struct ocfs2_dir_entry *) bh->b_data;
- }
-
- }
- if (!ocfs_check_dir_entry (dir, de, bh, offset)) {
+ OCFS_ASSERT((char *)de < sb->s_blocksize + insert_bh->b_data);
+ /* These checks should've already been passed by the
+ * prepare function, but I guess we can leave them
+ * here anyway. */
+ if (!ocfs_check_dir_entry (dir, de, insert_bh, offset)) {
retval = -ENOENT;
goto bail;
}
@@ -1652,7 +1807,8 @@
(le16_to_cpu(de->rec_len) >= rec_len)) ||
(le16_to_cpu(de->rec_len) >=
(OCFS2_DIR_REC_LEN(de->name_len) + rec_len))) {
- status = ocfs_journal_access(handle, bh, OCFS_JOURNAL_ACCESS_WRITE);
+ status = ocfs_journal_access(handle, insert_bh,
+ OCFS_JOURNAL_ACCESS_WRITE);
/* By now the buffer is marked for journaling */
offset += le16_to_cpu(de->rec_len);
if (le64_to_cpu(de->inode)) {
@@ -1675,7 +1831,7 @@
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
dir->i_version++;
- status = ocfs_journal_dirty(handle, bh);
+ status = ocfs_journal_dirty(handle, insert_bh);
retval = 0;
goto bail;
}
@@ -1683,9 +1839,10 @@
de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
}
+ /* when you think about it, the assert above should prevent us
+ * from ever getting here. */
retval = -ENOSPC;
bail:
- brelse (bh);
LOG_EXIT_STATUS(retval);
return retval;
@@ -1832,7 +1989,7 @@
num++;
#warning questionable readahead stuff here
- bh = ocfs_bread(NULL, dir, b++, 0, &err, 1);
+ bh = ocfs_bread(dir, b++, &err, 1);
bh_use[ra_max] = bh;
#if 0 // ???
if (bh)
@@ -1884,44 +2041,62 @@
return ret;
}
-/*
- * ocfs_orphan_add()
- *
- */
-static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
- struct inode *inode, ocfs2_dinode *fe)
+static int ocfs_blkno_stringify(u64 blkno, char **retval)
{
- 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);
+ LOG_ENTRY();
- /* create a unique name here. */
+ *retval = NULL;
name = kmalloc(OCFS2_MAX_FILENAME_LENGTH+1, GFP_KERNEL);
if (!name) {
- status = -EFAIL;
- LOG_ERROR_STATUS(status);
- goto leave;
+ namelen = -ENOMEM;
+ LOG_ERROR_STATUS(namelen);
+ goto bail;
}
namelen = snprintf(name, OCFS2_MAX_FILENAME_LENGTH+1, "%llu",
- OCFS_I(inode)->ip_blkno);
+ blkno);
if (namelen <= 0) {
- if (namelen)
- status = namelen;
- else
- status = -EFAIL;
+ kfree(name);
+ if (!namelen)
+ namelen = -EFAULT;
+ LOG_ERROR_STATUS(namelen);
+ goto bail;
+ }
+
+ LOG_TRACE_ARGS("built filename '%s' for orphan dir (len=%d)\n", name,
+ namelen);
+
+ *retval = name;
+bail:
+ LOG_EXIT_STATUS(namelen);
+ return(namelen);
+}
+
+static int ocfs_prepare_orphan_dir(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *inode,
+ char **ret_name,
+ struct buffer_head **de_bh)
+{
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ int status = 0;
+ char *name = NULL;
+ int namelen;
+
+ *ret_name = NULL;
+
+ /* create a unique name here. */
+ namelen = ocfs_blkno_stringify(OCFS_I(inode)->ip_blkno, &name);
+ if (namelen < 0) {
+ status = namelen;
LOG_ERROR_STATUS(status);
goto leave;
}
- LOG_TRACE_ARGS("adding filename '%s' to orphan dir (len=%d)\n", name,
- namelen);
-
orphan_dir_inode = ocfs_get_system_file_inode(osb,
ORPHAN_DIR_SYSTEM_INODE,
-1);
@@ -1942,9 +2117,65 @@
orphan_dir_inode);
ocfs_handle_add_inode(handle, orphan_dir_inode);
+ status = ocfs_prepare_dir_for_insert(osb, orphan_dir_inode,
+ orphan_dir_bh, name, namelen,
+ de_bh);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ *ret_name = name;
+leave:
+ if (orphan_dir_inode)
+ iput(orphan_dir_inode);
+
+ if ((status < 0) && name)
+ kfree(name);
+
+ if (orphan_dir_bh)
+ brelse(orphan_dir_bh);
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+}
+
+/*
+ * ocfs_orphan_add()
+ *
+ */
+static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
+ struct inode *inode, ocfs2_dinode *fe,
+ char *name, struct buffer_head *de_bh)
+{
+ struct inode *orphan_dir_inode = NULL;
+ struct buffer_head *orphan_dir_bh = NULL;
+ int status = 0;
+ int namelen;
+ ocfs2_dinode *orphan_fe;
+
+ LOG_ENTRY_ARGS("(inode->i_ino = %lu)\n", inode->i_ino);
+
+ namelen = strlen(name);
+
+ orphan_dir_inode = ocfs_get_system_file_inode(osb,
+ ORPHAN_DIR_SYSTEM_INODE,
+ -1);
+ if (!orphan_dir_inode) {
+ status = -EFAIL;
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
+ status = ocfs_read_bh(osb, OCFS_I(orphan_dir_inode)->ip_blkno << osb->sb->s_blocksize_bits, &orphan_dir_bh, OCFS_BH_CACHED, orphan_dir_inode);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto leave;
+ }
+
status = __ocfs_add_entry(handle, orphan_dir_inode, name, namelen,
inode, OCFS_I(inode)->ip_blkno,
- orphan_dir_bh);
+ orphan_dir_bh, de_bh);
if (status < 0) {
LOG_ERROR_STATUS(status);
goto leave;
@@ -1970,16 +2201,11 @@
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);
Modified: branches/dlm-changes/src/namei.h
===================================================================
--- branches/dlm-changes/src/namei.h 2004-09-24 23:39:22 UTC (rev 1490)
+++ branches/dlm-changes/src/namei.h 2004-09-24 23:42:23 UTC (rev 1491)
@@ -40,5 +40,13 @@
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);
+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);
+}
#endif /* OCFS2_NAMEI_H */
More information about the Ocfs2-commits
mailing list