[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