Skip to contentSkip to conversation

pramfs: dir operations

PATCH Superseded Marco Stornelli 2 participants 3 messages Nov 20, 2010 – Nov 24, 2010 VFS

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v4 9/16 pramfs: dir operations

From: Marco Stornelli <[email protected]>

File operations for directories.

---

fs/pramfs/dir.c +215 -0
diff -Nurp linux-2.6.36-orig/fs/pramfs/dir.c linux-2.6.36/fs/pramfs/dir.c
@@ -0,0 +1,215 @@
+/*
+ * FILE NAME fs/pramfs/dir.c
+ *
+ * BRIEF DESCRIPTION
+ *
+ * File operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli <[email protected]>
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include "pram.h"
+
+/*
+ *	Parent is locked.
+ */
+int pram_add_link(struct dentry *dentry, struct inode *inode)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct pram_inode *pidir, *pi, *pitail = NULL;
+	u64 tail_ino, prev_ino;
+
+	const char *name = dentry->d_name.name;
+
+	int namelen = dentry->d_name.len > PRAM_NAME_LEN ?
+		PRAM_NAME_LEN : dentry->d_name.len;
+
+	pidir = pram_get_inode(dir->i_sb, dir->i_ino);
+	pi = pram_get_inode(dir->i_sb, inode->i_ino);
+
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
+
+	tail_ino = be64_to_cpu(pidir->i_type.dir.tail);
+	if (tail_ino != 0) {
+		pitail = pram_get_inode(dir->i_sb, tail_ino);
+		pram_memunlock_inode(pitail);
+		pitail->i_d.d_next = cpu_to_be64(inode->i_ino);
+		pram_memlock_inode(pitail);
+
+		prev_ino = tail_ino;
+
+		pram_memunlock_inode(pidir);
+		pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
+		pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
+		pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
+		pram_memlock_inode(pidir);
+	} else {
+		/* the directory is empty */
+		prev_ino = 0;
+
+		pram_memunlock_inode(pidir);
+		pidir->i_type.dir.tail = cpu_to_be64(inode->i_ino);
+		pidir->i_type.dir.head = cpu_to_be64(inode->i_ino);
+		pidir->i_mtime = cpu_to_be32(dir->i_mtime.tv_sec);
+		pidir->i_ctime = cpu_to_be32(dir->i_ctime.tv_sec);
+		pram_memlock_inode(pidir);
+	}
+
+
+	pram_memunlock_inode(pi);
+	pi->i_d.d_prev = cpu_to_be64(prev_ino);
+	pi->i_d.d_parent = cpu_to_be64(dir->i_ino);
+	memcpy(pi->i_d.d_name, name, namelen);
+	pi->i_d.d_name[namelen] = '\0';
+	pram_memlock_inode(pi);
+	return 0;
+}
+
+int pram_remove_link(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	struct pram_inode *prev = NULL;
+	struct pram_inode *next = NULL;
+	struct pram_inode *pidir, *pi;
+
+	pi = pram_get_inode(sb, inode->i_ino);
+	pidir = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_parent));
+	if (!pidir)
+		return -EACCES;
+
+	if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.head)) {
+		/* first inode in directory */
+		next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
+
+		if (next) {
+			pram_memunlock_inode(next);
+			next->i_d.d_prev = 0;
+			pram_memlock_inode(next);
+
+			pram_memunlock_inode(pidir);
+			pidir->i_type.dir.head = pi->i_d.d_next;
+		} else {
+			pram_memunlock_inode(pidir);
+			pidir->i_type.dir.head = 0;
+			pidir->i_type.dir.tail = 0;
+		}
+		pram_memlock_inode(pidir);
+	} else if (inode->i_ino == be64_to_cpu(pidir->i_type.dir.tail)) {
+		/* last inode in directory */
+		prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
+
+		pram_memunlock_inode(prev);
+		prev->i_d.d_next = 0;
+		pram_memlock_inode(prev);
+
+		pram_memunlock_inode(pidir);
+		pidir->i_type.dir.tail = pi->i_d.d_prev;
+		pram_memlock_inode(pidir);
+	} else {
+		/* somewhere in the middle */
+		prev = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_prev));
+		next = pram_get_inode(sb, be64_to_cpu(pi->i_d.d_next));
+
+		if (prev && next) {
+			pram_memunlock_inode(prev);
+			prev->i_d.d_next = pi->i_d.d_next;
+			pram_memlock_inode(prev);
+
+			pram_memunlock_inode(next);
+			next->i_d.d_prev = pi->i_d.d_prev;
+			pram_memlock_inode(next);
+		}
+	}
+
+	pram_memunlock_inode(pi);
+	pi->i_d.d_next = 0;
+	pi->i_d.d_prev = 0;
+	pi->i_d.d_parent = 0;
+	pram_memlock_inode(pi);
+
+	return 0;
+}
+
+#define S_SHIFT 12
+static unsigned int dtype_by_mode[S_IFMT >> S_SHIFT] = {
+	[S_IFREG >> S_SHIFT]    DT_REG,
+	[S_IFDIR >> S_SHIFT]    DT_DIR,
+	[S_IFCHR >> S_SHIFT]    DT_CHR,
+	[S_IFBLK >> S_SHIFT]    DT_BLK,
+	[S_IFIFO >> S_SHIFT]    DT_FIFO,
+	[S_IFSOCK >> S_SHIFT]   DT_SOCK,
+	[S_IFLNK >> S_SHIFT]    DT_LNK,
+};
+
+static int pram_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	struct pram_inode *pi;
+	int namelen, ret = 0;
+	char *name;
+	ino_t ino;
+
+	pi = pram_get_inode(sb, inode->i_ino);
+
+	switch ((unsigned long)filp->f_pos) {
+	case 0:
+		ret = filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR);
+		filp->f_pos++;
+		return ret;
+	case 1:
+		ret = filldir(dirent, "..", 2, 1, be64_to_cpu(pi->i_d.d_parent), DT_DIR);
+		ino = be64_to_cpu(pi->i_type.dir.head);
+		filp->f_pos = ino ? ino : 2;
+		return ret;
+	case 2:
+		ino = be64_to_cpu(pi->i_type.dir.head);
+		if (ino) {
+			filp->f_pos = ino;
+			pi = pram_get_inode(sb, ino);
+			break;
+		} else {
+			/* the directory is empty */
+			filp->f_pos = 2;
+			return 0;
+		}
+	case 3:
+		return 0;
+	default:
+		ino = filp->f_pos;
+		pi = pram_get_inode(sb, ino);
+		break;
+	}
+
+	while (pi && !be16_to_cpu(pi->i_links_count)) {
+		ino = filp->f_pos = be64_to_cpu(pi->i_d.d_next);
+		pi = pram_get_inode(sb, ino);
+	}
+
+	if (pi) {
+		name = pi->i_d.d_name;
+		namelen = strlen(name);
+
+		ret = filldir(dirent, name, namelen,
+			      filp->f_pos, ino,
+			      dtype_by_mode[(be16_to_cpu(pi->i_mode) & S_IFMT)>>S_SHIFT]);
+		filp->f_pos = pi->i_d.d_next ? be64_to_cpu(pi->i_d.d_next) : 3;
+	} else
+		filp->f_pos = 3;
+
+	return ret;
+}
+
+struct file_operations pram_dir_operations = {
+	.read		= generic_read_dir,
+	.readdir	= pram_readdir,
+	.fsync		= noop_fsync,
+};
#1 lore raw

fs/pramfs/dir.c line 34

Quoted 11 lines · Marco Stornelli
fs/pramfs/dir.c +11 -0
+int pram_add_link(struct dentry *dentry, struct inode *inode)
+{
+	struct inode *dir = dentry->d_parent->d_inode;
+	struct pram_inode *pidir, *pi, *pitail = NULL;
+	u64 tail_ino, prev_ino;
+
+	const char *name = dentry->d_name.name;
+
+	int namelen = dentry->d_name.len > PRAM_NAME_LEN ?
+		PRAM_NAME_LEN : dentry->d_name.len;
+
	namelen = min_t(unsigned int, dentry->d_name.len, PRAM_NAME_LEN);

?

Quoted 13 lines
fs/pramfs/dir.c +13 -0
+#define S_SHIFT 12
+static unsigned int dtype_by_mode[S_IFMT >> S_SHIFT] = {
+	[S_IFREG >> S_SHIFT]    DT_REG,
+	[S_IFDIR >> S_SHIFT]    DT_DIR,
+	[S_IFCHR >> S_SHIFT]    DT_CHR,
+	[S_IFBLK >> S_SHIFT]    DT_BLK,
+	[S_IFIFO >> S_SHIFT]    DT_FIFO,
+	[S_IFSOCK >> S_SHIFT]   DT_SOCK,
+	[S_IFLNK >> S_SHIFT]    DT_LNK,
+};
+
+static int pram_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{

...

fs/pramfs/dir.c line 204

Quoted 4 lines
fs/pramfs/dir.c +4 -0
+		ret = filldir(dirent, name, namelen,
+			      filp->f_pos, ino,
+			      dtype_by_mode[(be16_to_cpu(pi->i_mode) & S_IFMT)>>S_SHIFT]);
+		filp->f_pos = pi->i_d.d_next ? be64_to_cpu(pi->i_d.d_next) : 3;

You might try to provide some generic helpers for this, at least GFS2 also does the same thing:

include/linux/gfs2_ondisk.h:#define DT2IF(dt) (((dt) << 12) & S_IFMT) include/linux/gfs2_ondisk.h:#define IF2DT(sif) (((sif) & S_IFMT) >> 12)

#2 lore raw

2010/11/24 Paul Mundt <[email protected]>:

Quoted 15 lines · Marco Stornelli

fs/pramfs/dir.c line 34

Quoted 11 lines
fs/pramfs/dir.c +11 -0
+int pram_add_link(struct dentry *dentry, struct inode *inode)
+{
+     struct inode *dir = dentry->d_parent->d_inode;
+     struct pram_inode *pidir, *pi, *pitail = NULL;
+     u64 tail_ino, prev_ino;
+
+     const char *name = dentry->d_name.name;
+
+     int namelen = dentry->d_name.len > PRAM_NAME_LEN ?
+             PRAM_NAME_LEN : dentry->d_name.len;
+

       namelen = min_t(unsigned int, dentry->d_name.len, PRAM_NAME_LEN);

Quoted 1 line

?

Ok, I can use it, I have to check the type.

Quoted 20 lines
Quoted 14 lines
fs/pramfs/dir.c +13 -0
+#define S_SHIFT 12
+static unsigned int dtype_by_mode[S_IFMT >> S_SHIFT] = {
+     [S_IFREG >> S_SHIFT]    DT_REG,
+     [S_IFDIR >> S_SHIFT]    DT_DIR,
+     [S_IFCHR >> S_SHIFT]    DT_CHR,
+     [S_IFBLK >> S_SHIFT]    DT_BLK,
+     [S_IFIFO >> S_SHIFT]    DT_FIFO,
+     [S_IFSOCK >> S_SHIFT]   DT_SOCK,
+     [S_IFLNK >> S_SHIFT]    DT_LNK,
+};
+
+static int pram_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{

...

Quoted 4 lines

+             ret = filldir(dirent, name, namelen,
+                           filp->f_pos, ino,
+                           dtype_by_mode[(be16_to_cpu(pi->i_mode) & S_IFMT)>>S_SHIFT]);
+             filp->f_pos = pi->i_d.d_next ? be64_to_cpu(pi->i_d.d_next) : 3;

Quoted 6 lines

You might try to provide some generic helpers for this, at least GFS2 also does the same thing:

include/linux/gfs2_ondisk.h:#define DT2IF(dt) (((dt) << 12) & S_IFMT) include/linux/gfs2_ondisk.h:#define IF2DT(sif) (((sif) & S_IFMT) >> 12)

I'll look at it.

Marco
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html