lk: implement mkfifo

Alex Chiang achiang at hp.com
Thu Apr 17 19:26:48 PDT 2008


Implement mkfifo.

For POSIX compliance, we need to update the directory's ctime and
mtime when the FIFO is created, so add a crfs_change_cinode
stanza to the metadata change set.

We can also move the call to inode_inc_link_count up, and change
it to a plain old inc_nlink before we commit our changes.

Leaving it as inode_inc_link_count results in a deadlock since
the following will happen:

	mark_inode_dirty 
	 crfs_dirty_inode
	  crfs_meta_change_prepare
	   __lock_pages
	    /* ruh roh */

This patch allows crfs to pass 100 / 105 (95%) of the POSIX FIFO
tests.

[The remaining 5 failures are a generic mknod issue with removing
very long filenames.]

Signed-off-by: Alex Chiang <achiang at hp.com>
---
diff -r 809dabc38617 -r fb4148080e26 lk/inode.c
--- a/lk/inode.c	Fri Apr 11 14:57:48 2008 -0600
+++ b/lk/inode.c	Thu Apr 17 20:11:47 2008 -0600
@@ -90,6 +90,10 @@ int crfs_populate_inode(struct inode *in
 	    case S_IFLNK:
 		    inode->i_op = &crfs_symlink_iops;
 		    break;
+	    case S_IFIFO:
+		    inode->i_op = &crfs_special_iops;
+		    init_special_inode(inode, inode->i_mode, inode->i_rdev);
+		    break;
 	    default:
 		    BUG();
 		    break;
diff -r 809dabc38617 -r fb4148080e26 lk/namei.c
--- a/lk/namei.c	Fri Apr 11 14:57:48 2008 -0600
+++ b/lk/namei.c	Thu Apr 17 20:11:47 2008 -0600
@@ -401,6 +401,24 @@ static void rewind_last_inode(struct crf
 	spin_unlock(&info->last_lock);
 }
 
+/*
+ * We just update everything that all callers could want us to..
+ */
+static s16 crfs_change_cinode(struct crfs_change_func_args *args,
+			      void *data, u16 before, u16 size)
+{
+	struct crfs_inode *cinode = data;
+	struct inode *inode = args->vfs_inode;
+
+	cinode->ctime.sec = cpu_to_le64(inode->i_ctime.tv_sec);
+	cinode->ctime.nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
+	cinode->mtime.sec = cpu_to_le64(inode->i_mtime.tv_sec);
+	cinode->mtime.nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
+	cinode->nlink = cpu_to_le32(inode->i_nlink);
+
+	return size;
+}
+
 static int crfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 		      dev_t dev)
 {
@@ -437,11 +455,19 @@ static int crfs_mknod(struct inode *dir,
 	}
 	
 	/* inode, dirents, and maybe . and .. dirents for a new dir */
-	set = crfs_meta_change_alloc(info, 7);
+	set = crfs_meta_change_alloc(info, 8);
 	if (set == NULL) {
 		ret = -ENOMEM;
 		goto out;
 	}
+
+	/* update the dir's time stamps */
+	change = crfs_meta_change_next(set);
+	change->func = crfs_change_cinode;
+	change->args.vfs_inode = dir;
+	crfs_key_set(&change->key, dir->i_ino, CRFS_INODE_ITEM_KEY, 0);
+	change->bytes = sizeof(struct crfs_inode);
+	change->ret_if_missing = -EIO;
 
 	/* build a new crfs inode and sync it with our allocated inode */ 
 	change = crfs_meta_change_next(set);
@@ -509,15 +535,19 @@ static int crfs_mknod(struct inode *dir,
 	}
 
 	ret = crfs_meta_change_prepare(info, set);
-	if (ret == 0)
-		crfs_meta_change_commit(info, set, NULL);
+	if (ret)
+		goto out;
+
+	/* update the vfs structures */
+	dir->i_mtime = CURRENT_TIME;
+	dir->i_ctime = dir->i_mtime;
+	if (S_ISDIR(mode))
+		inc_nlink(dir);
+
+	crfs_meta_change_commit(info, set, NULL);
 	crfs_meta_change_free(set);
 
 out:
-	/* XXX it sure seems like this should be expressed in a change */
-	if (ret == 0 && S_ISDIR(mode))
-		inode_inc_link_count(dir);
-
 	if (ret == 0) {
 		insert_inode_hash(inode);
 		/* XXX set dentry->d_op? */
@@ -539,24 +569,6 @@ static int crfs_mkdir(struct inode *dir,
 static int crfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	return crfs_mknod(dir, dentry, mode | S_IFDIR, 0);
-}
-
-/*
- * We just update everything that all callers could want us to..
- */
-static s16 crfs_change_cinode(struct crfs_change_func_args *args,
-			      void *data, u16 before, u16 size)
-{
-	struct crfs_inode *cinode = data;
-	struct inode *inode = args->vfs_inode;
-
-	cinode->ctime.sec = cpu_to_le64(inode->i_ctime.tv_sec);
-	cinode->ctime.nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
-	cinode->mtime.sec = cpu_to_le64(inode->i_mtime.tv_sec);
-	cinode->mtime.nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
-	cinode->nlink = cpu_to_le32(inode->i_nlink);
-
-	return size;
 }
 
 /*
@@ -982,3 +994,10 @@ struct inode_operations crfs_dir_iops = 
 //	.link		= crfs_link,
 	.symlink	= crfs_symlink,
 };
+
+/*
+ * Empty for now
+ */
+struct inode_operations crfs_special_iops = {
+
+};
diff -r 809dabc38617 -r fb4148080e26 lk/namei.h
--- a/lk/namei.h	Fri Apr 11 14:57:48 2008 -0600
+++ b/lk/namei.h	Thu Apr 17 20:11:47 2008 -0600
@@ -20,6 +20,7 @@
 
 extern struct inode_operations crfs_dir_iops;
 extern struct inode_operations crfs_symlink_iops;
+extern struct inode_operations crfs_special_iops;
 
 /* XXX should these be in their own file? */
 struct crfs_change_func_args;



More information about the crfs-devel mailing list