All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 09/16 v5] pramfs: dir operations
@ 2010-12-16 18:01 Marco Stornelli
  0 siblings, 0 replies; only message in thread
From: Marco Stornelli @ 2010-12-16 18:01 UTC (permalink / raw)
  To: Linux Kernel; +Cc: Linux Embedded, Linux FS Devel, Tim Bird, Andrew Morton

From: Marco Stornelli <marco.stornelli@gmail.com>

File operations for directories.

Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
---
diff -Nurp linux-2.6.36-orig/fs/pramfs/dir.c linux-2.6.36/fs/pramfs/dir.c
--- linux-2.6.36-orig/fs/pramfs/dir.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.36/fs/pramfs/dir.c	2010-11-28 10:31:01.000000000 +0100
@@ -0,0 +1,204 @@
+/*
+ * BRIEF DESCRIPTION
+ *
+ * File operations for directories.
+ *
+ * Copyright 2009-2010 Marco Stornelli <marco.stornelli@gmail.com>
+ * 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 = min_t(unsigned int, dentry->d_name.len, PRAM_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(dir->i_sb, pitail);
+		pitail->i_d.d_next = cpu_to_be64(inode->i_ino);
+		pram_memlock_inode(dir->i_sb, pitail);
+
+		prev_ino = tail_ino;
+
+		pram_memunlock_inode(dir->i_sb, 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(dir->i_sb, pidir);
+	} else {
+		/* the directory is empty */
+		prev_ino = 0;
+
+		pram_memunlock_inode(dir->i_sb, 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(dir->i_sb, pidir);
+	}
+
+
+	pram_memunlock_inode(dir->i_sb, 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(dir->i_sb, 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(sb, next);
+			next->i_d.d_prev = 0;
+			pram_memlock_inode(sb, next);
+
+			pram_memunlock_inode(sb, pidir);
+			pidir->i_type.dir.head = pi->i_d.d_next;
+		} else {
+			pram_memunlock_inode(sb, pidir);
+			pidir->i_type.dir.head = 0;
+			pidir->i_type.dir.tail = 0;
+		}
+		pram_memlock_inode(sb, 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(sb, prev);
+		prev->i_d.d_next = 0;
+		pram_memlock_inode(sb, prev);
+
+		pram_memunlock_inode(sb, pidir);
+		pidir->i_type.dir.tail = pi->i_d.d_prev;
+		pram_memlock_inode(sb, 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(sb, prev);
+			prev->i_d.d_next = pi->i_d.d_next;
+			pram_memlock_inode(sb, prev);
+
+			pram_memunlock_inode(sb, next);
+			next->i_d.d_prev = pi->i_d.d_prev;
+			pram_memlock_inode(sb, next);
+		}
+	}
+
+	pram_memunlock_inode(sb, pi);
+	pi->i_d.d_next = 0;
+	pi->i_d.d_prev = 0;
+	pi->i_d.d_parent = 0;
+	pram_memlock_inode(sb, pi);
+
+	return 0;
+}
+
+#define DT2IF(dt) (((dt) << 12) & S_IFMT)
+#define IF2DT(sif) (((sif) & S_IFMT) >> 12)
+
+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,
+			      IF2DT(be16_to_cpu(pi->i_mode)));
+		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,
+};

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2010-12-16 18:01 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-16 18:01 [PATCH 09/16 v5] pramfs: dir operations Marco Stornelli

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.