pramfs: dir operations
PATCH v4 9/16 pramfs: dir operations
From: Marco Stornelli <[email protected]>
File operations for directories.
---
fs/pramfs/dir.c +215 -0
@@ -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, +};
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)
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