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