[Ocfs2-commits] mfasheh commits r1203 - trunk/src
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Wed Jun 23 20:01:43 CDT 2004
Author: mfasheh
Date: 2004-06-23 19:01:42 -0500 (Wed, 23 Jun 2004)
New Revision: 1203
Modified:
trunk/src/inode.c
trunk/src/inode.h
trunk/src/namei.c
trunk/src/ocfs_journal.h
Log:
* revamp symlink data handling somewhat. We now journal it, albeit in
a slightly different way than other JBD file systems as we don't do
data journalling.
* As a result, our symlink bug (symlink data wasn't hitting disk
properly) is fixed :)
Modified: trunk/src/inode.c
===================================================================
--- trunk/src/inode.c 2004-06-23 21:00:46 UTC (rev 1202)
+++ trunk/src/inode.c 2004-06-24 00:01:42 UTC (rev 1203)
@@ -822,43 +822,7 @@
return ret;
} /* ocfs_commit_write */
-
/*
- * ocfs_block_symlink()
- *
- */
-int ocfs_block_symlink (struct inode *inode, const char *symname, int len)
-{
- struct address_space *mapping = inode->i_mapping;
- struct page *page = grab_cache_page (mapping, 0);
- int err = -ENOMEM;
- char *kaddr;
-
- if (!page)
- goto fail;
- err = mapping->a_ops->prepare_write (NULL, page, 0, len - 1);
- if (err)
- goto fail_map;
- kaddr = page_address (page);
- memset (kaddr, 0, PAGE_CACHE_SIZE);
- memcpy (kaddr, symname, len - 1);
- mapping->a_ops->commit_write (NULL, page, 0, len - 1);
- err = mapping->a_ops->readpage (NULL, page);
- wait_on_page_locked (page);
- page_cache_release (page);
- if (err < 0)
- goto fail;
- mark_inode_dirty (inode);
- return 0;
-
-fail_map:
- unlock_page (page);
- page_cache_release (page);
-fail:
- return err;
-} /* ocfs_block_symlink */
-
-/*
* ocfs_symlink_get_block()
*
*/
Modified: trunk/src/inode.h
===================================================================
--- trunk/src/inode.h 2004-06-23 21:00:46 UTC (rev 1202)
+++ trunk/src/inode.h 2004-06-24 00:01:42 UTC (rev 1203)
@@ -29,8 +29,6 @@
#ifndef OCFS2_INODE_H
#define OCFS2_INODE_H
-int ocfs_block_symlink(struct inode *inode, const char *symname,
- int len);
struct buffer_head *ocfs_bread(ocfs_journal_handle *handle,
struct inode * inode, int block,
int create, int *err, int reada);
Modified: trunk/src/namei.c
===================================================================
--- trunk/src/namei.c 2004-06-23 21:00:46 UTC (rev 1202)
+++ trunk/src/namei.c 2004-06-24 00:01:42 UTC (rev 1203)
@@ -90,6 +90,7 @@
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,
__u32 type1, __u32 flags1,
@@ -102,6 +103,11 @@
static int ocfs_orphan_add(ocfs_super *osb, ocfs_journal_handle *handle,
struct inode *inode, ocfs2_dinode *fe);
+static int ocfs_create_symlink_data(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *inode,
+ const char *symname);
+
static inline int ocfs_add_entry(ocfs_journal_handle *handle,
struct dentry *dentry,
struct inode *inode, u64 blkno,
@@ -1365,6 +1371,118 @@
return status;
} /* ocfs_rename */
+/*
+ * ocfs_create_symlink_data()
+ *
+ * we expect i_size = strlen(symname). Copy symname into the file
+ * data, including the null terminator.
+ */
+static int ocfs_create_symlink_data(ocfs_super *osb,
+ ocfs_journal_handle *handle,
+ struct inode *inode,
+ const char *symname)
+{
+ struct buffer_head **bhs = NULL;
+ const char *c;
+ struct super_block *sb = osb->sb;
+ s64 logical, contig;
+ int virtual, blocks, status, i, bytes_left;
+
+ bytes_left = inode->i_size + 1;
+ /* we can't trust i_blocks because we're actually going to
+ * write i_size + 1 bytes. */
+ blocks = (bytes_left + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
+
+ LOG_ENTRY_ARGS("i_blocks = %lu, i_size = %llu, blocks = %d\n",
+ inode->i_blocks, inode->i_size, blocks);
+
+ /* Sanity check -- make sure we're going to fit. */
+ if (bytes_left > OCFS_I(inode)->ip_alloc_size) {
+ status = -EIO;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ bhs = ocfs_malloc(sizeof(struct buffer_head *) * blocks);
+ if (!bhs) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+ memset(bhs, 0, sizeof(struct buffer_head *) * blocks);
+
+ status = ocfs_lookup_file_allocation(osb, 0, &logical, 1, &contig,
+ inode, 1);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ LOG_TRACE_ARGS("logical = %lld, contig = %lld\n", logical, contig);
+
+ /* links can never be larger than one cluster so we know this
+ * is all going to be contiguous, but do a sanity check
+ * anyway. */
+ if (contig < bytes_left) {
+ status = -EIO;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ /* right now lookup_file_allocation returns bytes, but that
+ * changes soon so shift back to blocks. */
+ logical = logical >> sb->s_blocksize_bits;
+ virtual = 0;
+ while(bytes_left > 0) {
+ c = &symname[virtual * sb->s_blocksize];
+
+ bhs[virtual] = sb_getblk(sb, logical);
+ if (!bhs[virtual]) {
+ status = -ENOMEM;
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ set_buffer_uptodate(bhs[virtual]);
+ SET_BH_SEQNUM(inode, bhs[virtual]);
+ status = ocfs_journal_access(handle, bhs[virtual],
+ OCFS_JOURNAL_ACCESS_CREATE);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ memset(bhs[virtual]->b_data, 0, sb->s_blocksize);
+
+ memcpy(bhs[virtual]->b_data, c,
+ (bytes_left > sb->s_blocksize) ? sb->s_blocksize :
+ bytes_left);
+
+ status = ocfs_journal_dirty(handle, bhs[virtual]);
+ if (status < 0) {
+ LOG_ERROR_STATUS(status);
+ goto bail;
+ }
+
+ virtual++;
+ logical++;
+ bytes_left -= sb->s_blocksize;
+ }
+
+ status = 0;
+bail:
+
+ if (bhs) {
+ for(i = 0; i < blocks; i++)
+ if (bhs[i])
+ brelse(bhs[i]);
+ kfree(bhs);
+ }
+
+ LOG_EXIT_STATUS(status);
+ return(status);
+} /* ocfs_create_symlink_data */
+
/*
* ocfs_symlink()
*
@@ -1382,6 +1500,7 @@
ocfs2_dinode *fe = NULL;
ocfs_journal_handle *handle = NULL;
int got_lock = 0;
+ int credits;
LOG_SET_CONTEXT(SYMLINK);
@@ -1412,8 +1531,10 @@
l = strlen (symname) + 1;
newsize = l - 1;
+ credits = ocfs_calc_symlink_credits(sb, newsize);
+
/* start the transaction */
- handle = ocfs_start_trans(osb, OCFS_SYMLINK_CREDITS);
+ handle = ocfs_start_trans(osb, credits);
if (handle == NULL) {
LOG_ERROR_STATUS (status = -ENOMEM);
goto bail;
@@ -1471,6 +1592,9 @@
goto abort_trans;
}
+ status = ocfs_create_symlink_data(osb, handle, inode, symname);
+ if (status < 0)
+ LOG_ERROR_STATUS(status);
abort_trans:
if (status < 0) {
@@ -1480,9 +1604,6 @@
d_instantiate (dentry, inode);
ocfs_commit_trans(handle);
- status = ocfs_block_symlink (inode, symname, l);
- if (status < 0)
- LOG_ERROR_STATUS(status);
}
if (got_lock) {
Modified: trunk/src/ocfs_journal.h
===================================================================
--- trunk/src/ocfs_journal.h 2004-06-23 21:00:46 UTC (rev 1202)
+++ trunk/src/ocfs_journal.h 2004-06-24 00:01:42 UTC (rev 1203)
@@ -364,19 +364,25 @@
return (bitmap_blocks + sysfile_bitmap_blocks + OCFS_FILE_EXTEND_CREDITS);
}
+static inline int ocfs_calc_symlink_credits(struct super_block *sb,
+ int size)
+{
+ /* get our fuzz from mknod and extend credits. */
+ int blocks = OCFS_MKNOD_CREDITS + 1;
+
+ blocks += ocfs_calc_extend_credits(sb, size);
+
+ blocks += size >> sb->s_blocksize_bits;
+
+ return(blocks);
+}
+
/* fe, anything along new 'edge' of tree + fuzz*/
#define OCFS_FILE_TRUNCATE_CREDITS (1 + 4 + OCFS_JOURNAL_FUZZ_CREDITS)
/* the file entry + the locknode + possibily the parent dirnode + fuzz */
#define OCFS_FILE_DELETE_CREDITS (1 + 1 + 1 + OCFS_JOURNAL_FUZZ_CREDITS)
-/* need to create a new file and extend it to hold the info for the
- * symlink we add one for a potential write of the main bitmap. Since
- * we wind up with twice the fuzz because we reuse some macros so we
- * subtract one.*/
-#define OCFS_SYMLINK_CREDITS (OCFS_MKNOD_CREDITS + OCFS_FILE_EXTEND_CREDITS \
- + 1 - OCFS_JOURNAL_FUZZ_CREDITS)
-
/* fe change, locknode change, dirnode head, times two plus a possible
* delete, plus a possible dirnode addition in insert_file, and fuzz */
#define OCFS_FILE_RENAME_CREDITS (2 * (1 + 1 + 1) + OCFS_FILE_DELETE_CREDITS \
More information about the Ocfs2-commits
mailing list