📄 namei.c
字号:
/* * FILE NAME fs/pramfs/namei.c * * BRIEF DESCRIPTION * * Inode operations for directories. * * Author: Steve Longerbeam <stevel@mvista.com, or source@mvista.com> * * Copyright 2003 Sony Corporation * Copyright 2003 Matsushita Electric Industrial Co., Ltd. * 2003-2004 (c) MontaVista Software, Inc. 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/pram_fs.h>#include <linux/pagemap.h>/* * Couple of helper functions - make the code slightly cleaner. */static inline void pram_inc_count(struct inode *inode){ inode->i_nlink++; pram_write_inode_sync(inode);}static inline void pram_dec_count(struct inode *inode){ if (inode->i_nlink) { inode->i_nlink--; pram_write_inode_sync(inode); }}static inline int pram_add_nondir(struct inode * dir, struct dentry * dentry, struct inode * inode){ int err = pram_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); return 0; } pram_dec_count(inode); iput(inode); return err;}/* * Methods themselves. */static ino_tpram_inode_by_name(struct inode * dir, struct dentry * dentry){ struct pram_inode * pi; ino_t ino; int namelen; pi = pram_get_inode(dir->i_sb, dir->i_ino); ino = pi->i_type.dir.head; while (ino) { pi = pram_get_inode(dir->i_sb, ino); if (pi->i_links_count) { namelen = strlen(pi->i_d.d_name); if (namelen == dentry->d_name.len && !memcmp(dentry->d_name.name, pi->i_d.d_name, namelen)) break; } ino = pi->i_d.d_next; } return ino;}static struct dentry *pram_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd){ struct inode * inode = NULL; ino_t ino; if (dentry->d_name.len > PRAM_NAME_LEN) return ERR_PTR(-ENAMETOOLONG); ino = pram_inode_by_name(dir, dentry); if (ino) { struct pram_inode * pi = pram_get_inode(dir->i_sb, ino); inode = pram_fill_new_inode(dir->i_sb, pi); if (!inode) return ERR_PTR(-EACCES); } d_add(dentry, inode); return NULL;}/* * By the time this is called, we already have created * the directory cache entry for the new file, but it * is so far negative - it has no inode. * * If the create succeeds, we fill in the inode information * with d_instantiate(). */static int pram_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd){ struct inode * inode; int err; pram_lock_failsafe(dir->i_sb, PRAM_FAILSAFE_OP_CREATE, dir->i_ino, mode, 0); inode = pram_new_inode (dir, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { inode->i_op = &pram_file_inode_operations; inode->i_fop = &pram_file_operations; inode->i_mapping->a_ops = &pram_aops; err = pram_add_nondir(dir, dentry, inode); } pram_unlock_failsafe(dir->i_sb); return err;}static int pram_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev){ struct inode * inode; int err; pram_lock_failsafe(dir->i_sb, PRAM_FAILSAFE_OP_MKNOD, dir->i_ino, mode, rdev); inode = pram_new_inode (dir, mode); err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); pram_write_inode_sync(inode); /* update rdev */ err = pram_add_nondir(dir, dentry, inode); } pram_unlock_failsafe(dir->i_sb); return err;}static int pram_symlink (struct inode * dir, struct dentry * dentry, const char * symname){ struct super_block * sb = dir->i_sb; int err = -ENAMETOOLONG; unsigned len = strlen(symname); struct inode * inode; pram_lock_failsafe(sb, PRAM_FAILSAFE_OP_SYMLINK, dir->i_ino, 0, 0); if (len+1 > sb->s_blocksize) goto out; inode = pram_new_inode (dir, S_IFLNK | S_IRWXUGO); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out; inode->i_op = &pram_symlink_inode_operations; inode->i_mapping->a_ops = &pram_aops; err = pram_block_symlink(inode, symname, len); if (err) goto out_fail; inode->i_size = len; pram_write_inode_sync(inode); err = pram_add_nondir(dir, dentry, inode);out: pram_unlock_failsafe(sb); return err;out_fail: pram_dec_count(inode); iput (inode); goto out;}static int pram_link (struct dentry * dest_dentry, struct inode * dir, struct dentry * dentry){ pram_dbg ("hard links not supported\n"); return -ENOSYS;}static int pram_unlink(struct inode * dir, struct dentry *dentry){ struct inode * inode = dentry->d_inode; inode->i_ctime = dir->i_ctime; pram_lock_failsafe(dir->i_sb, PRAM_FAILSAFE_OP_UNLINK, inode->i_ino, dir->i_ino, 0); pram_dec_count(inode); pram_unlock_failsafe(dir->i_sb); return 0;}static int pram_mkdir(struct inode * dir, struct dentry * dentry, int mode){ struct inode * inode; struct pram_inode * pi; int err = -EMLINK; pram_lock_failsafe(dir->i_sb, PRAM_FAILSAFE_OP_MKDIR, dir->i_ino, mode, 0); if (dir->i_nlink >= PRAM_LINK_MAX) goto out; pram_inc_count(dir); inode = pram_new_inode (dir, S_IFDIR | mode); err = PTR_ERR(inode); if (IS_ERR(inode)) goto out_dir; inode->i_op = &pram_dir_inode_operations; inode->i_fop = &pram_dir_operations; inode->i_mapping->a_ops = &pram_aops; pram_inc_count(inode); // make the new directory empty pi = pram_get_inode(dir->i_sb, inode->i_ino); pram_lock_inode(dir->i_sb, pi); pi->i_type.dir.head = pi->i_type.dir.tail = 0; pram_unlock_inode(dir->i_sb, pi); err = pram_add_link(dentry, inode); if (err) goto out_fail; d_instantiate(dentry, inode);out: pram_unlock_failsafe(dir->i_sb); return err;out_fail: pram_dec_count(inode); pram_dec_count(inode); iput(inode);out_dir: pram_dec_count(dir); goto out;}static int pram_rmdir (struct inode * dir, struct dentry *dentry){ struct inode * inode = dentry->d_inode; struct pram_inode * pi; int err = -ENOTEMPTY; if (!inode) return -ENOENT; pram_lock_failsafe(dir->i_sb, PRAM_FAILSAFE_OP_RMDIR, inode->i_ino, dir->i_ino, 0); pi = pram_get_inode(dir->i_sb, inode->i_ino); // directory to delete is empty? if (pi->i_type.dir.tail == 0) { inode->i_ctime = dir->i_ctime; inode->i_size = 0; inode->i_nlink = 0; pram_write_inode_sync(inode); pram_dec_count(dir); err = 0; } else { pram_dbg("dir not empty\n"); } pram_unlock_failsafe(dir->i_sb); return err;}static int pram_rename (struct inode * old_dir, struct dentry * old_dentry, struct inode * new_dir, struct dentry * new_dentry){ struct inode * old_inode = old_dentry->d_inode; struct inode * new_inode = new_dentry->d_inode; struct pram_inode * pi_new; int err = -ENOENT; pram_lock_failsafe(old_dir->i_sb, PRAM_FAILSAFE_OP_RENAME, 0, 0, 0); if (new_inode) { err = -ENOTEMPTY; pi_new = pram_get_inode(new_dir->i_sb, new_inode->i_ino); if (S_ISDIR(old_inode->i_mode)) { if (pi_new->i_type.dir.tail != 0) goto out; if (new_inode->i_nlink) new_inode->i_nlink--; } new_inode->i_ctime = CURRENT_TIME; pram_dec_count(new_inode); } else { if (S_ISDIR(old_inode->i_mode)) { err = -EMLINK; if (new_dir->i_nlink >= PRAM_LINK_MAX) goto out; pram_dec_count(old_dir); pram_inc_count(new_dir); } } /* unlink the inode from the old directory ... */ if ((err = pram_remove_link(old_inode))) { goto out; } /* and link it into the new directory. */ if ((err = pram_add_link(new_dentry, old_inode))) { goto out; } err = 0; out: pram_unlock_failsafe(old_dir->i_sb); return err;}const struct inode_operations pram_dir_inode_operations = { .create = pram_create, .lookup = pram_lookup, .link = pram_link, .unlink = pram_unlink, .symlink = pram_symlink, .mkdir = pram_mkdir, .rmdir = pram_rmdir, .mknod = pram_mknod, .rename = pram_rename,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -