📄 inode.c
字号:
/* -*- mode: c; c-basic-offset: 8; -*- * vim: noexpandtab sw=8 ts=8 sts=0: * * inode.c * * vfs' aops, fops, dops and iops * * Copyright (C) 2002, 2004 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */#include <linux/fs.h>#include <linux/types.h>#include <linux/slab.h>#include <linux/highmem.h>#include <linux/pagemap.h>#include <linux/smp_lock.h>#include <asm/byteorder.h>#define MLOG_MASK_PREFIX ML_INODE#include <cluster/masklog.h>#include "ocfs2.h"#include "alloc.h"#include "dlmglue.h"#include "extent_map.h"#include "file.h"#include "heartbeat.h"#include "inode.h"#include "journal.h"#include "namei.h"#include "suballoc.h"#include "super.h"#include "symlink.h"#include "sysfile.h"#include "uptodate.h"#include "vote.h"#include "buffer_head_io.h"#define OCFS2_FI_FLAG_NOWAIT 0x1#define OCFS2_FI_FLAG_DELETE 0x2struct ocfs2_find_inode_args{ u64 fi_blkno; unsigned long fi_ino; unsigned int fi_flags;};static int ocfs2_read_locked_inode(struct inode *inode, struct ocfs2_find_inode_args *args);static int ocfs2_init_locked_inode(struct inode *inode, void *opaque);static int ocfs2_find_actor(struct inode *inode, void *opaque);static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct inode *inode, struct buffer_head *fe_bh);struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, u64 blkno, int delete_vote){ struct ocfs2_find_inode_args args; /* ocfs2_ilookup_for_vote should *only* be called from the * vote thread */ BUG_ON(current != osb->vote_task); args.fi_blkno = blkno; args.fi_flags = OCFS2_FI_FLAG_NOWAIT; if (delete_vote) args.fi_flags |= OCFS2_FI_FLAG_DELETE; args.fi_ino = ino_from_blkno(osb->sb, blkno); return ilookup5(osb->sb, args.fi_ino, ocfs2_find_actor, &args);}struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno){ struct inode *inode = NULL; struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; mlog_entry("(blkno = %"MLFu64")\n", blkno); /* Ok. By now we've either got the offsets passed to us by the * caller, or we just pulled them off the bh. Lets do some * sanity checks to make sure they're OK. */ if (blkno == 0) { inode = ERR_PTR(-EINVAL); mlog_errno(PTR_ERR(inode)); goto bail; } args.fi_blkno = blkno; args.fi_flags = 0; args.fi_ino = ino_from_blkno(sb, blkno); inode = iget5_locked(sb, args.fi_ino, ocfs2_find_actor, ocfs2_init_locked_inode, &args); /* inode was *not* in the inode cache. 2.6.x requires * us to do our own read_inode call and unlock it * afterwards. */ if (inode && inode->i_state & I_NEW) { mlog(0, "Inode was not in inode cache, reading it.\n"); ocfs2_read_locked_inode(inode, &args); unlock_new_inode(inode); } if (inode == NULL) { inode = ERR_PTR(-ENOMEM); mlog_errno(PTR_ERR(inode)); goto bail; } if (is_bad_inode(inode)) { iput(inode); inode = ERR_PTR(-ESTALE); goto bail; }bail: if (!IS_ERR(inode)) { mlog(0, "returning inode with number %"MLFu64"\n", OCFS2_I(inode)->ip_blkno); mlog_exit_ptr(inode); } return inode;}/* * here's how inodes get read from disk: * iget5_locked -> find_actor -> OCFS2_FIND_ACTOR * found? : return the in-memory inode * not found? : get_new_inode -> OCFS2_INIT_LOCKED_INODE */static int ocfs2_find_actor(struct inode *inode, void *opaque){ struct ocfs2_find_inode_args *args = NULL; struct ocfs2_inode_info *oi = OCFS2_I(inode); int ret = 0; mlog_entry("(0x%p, %lu, 0x%p)\n", inode, inode->i_ino, opaque); args = opaque; mlog_bug_on_msg(!inode, "No inode in find actor!\n"); if (oi->ip_blkno != args->fi_blkno) goto bail; /* OCFS2_FI_FLAG_NOWAIT is *only* set from * ocfs2_ilookup_for_vote which won't create an inode for one * that isn't found. The vote thread which doesn't want to get * an inode which is in the process of going away - otherwise * the call to __wait_on_freeing_inode in find_inode_fast will * cause it to deadlock on an inode which may be waiting on a * vote (or lock release) in delete_inode */ if ((args->fi_flags & OCFS2_FI_FLAG_NOWAIT) && (inode->i_state & (I_FREEING|I_CLEAR))) { /* As stated above, we're not going to return an * inode. In the case of a delete vote, the voting * code is going to signal the other node to go * ahead. Mark that state here, so this freeing inode * has the state when it gets to delete_inode. */ if (args->fi_flags & OCFS2_FI_FLAG_DELETE) { spin_lock(&oi->ip_lock); ocfs2_mark_inode_remotely_deleted(inode, O2NM_INVALID_NODE_NUM); spin_unlock(&oi->ip_lock); } goto bail; } ret = 1;bail: mlog_exit(ret); return ret;}/* * initialize the new inode, but don't do anything that would cause * us to sleep. * return 0 on success, 1 on failure */static int ocfs2_init_locked_inode(struct inode *inode, void *opaque){ struct ocfs2_find_inode_args *args = opaque; mlog_entry("inode = %p, opaque = %p\n", inode, opaque); inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; mlog_exit(0); return 0;}int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, int create_ino){ struct super_block *sb; struct ocfs2_super *osb; int status = -EINVAL; mlog_entry("(0x%p, size:%"MLFu64")\n", inode, fe->i_size); sb = inode->i_sb; osb = OCFS2_SB(sb); /* this means that read_inode cannot create a superblock inode * today. change if needed. */ if (!OCFS2_IS_VALID_DINODE(fe) || !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL))) { mlog(0, "Invalid dinode: i_ino=%lu, i_blkno=%"MLFu64", " "signature = %.*s, flags = 0x%x\n", inode->i_ino, le64_to_cpu(fe->i_blkno), 7, fe->i_signature, le32_to_cpu(fe->i_flags)); goto bail; } if (le32_to_cpu(fe->i_fs_generation) != osb->fs_generation) { mlog(ML_ERROR, "file entry generation does not match " "superblock! osb->fs_generation=%x, " "fe->i_fs_generation=%x\n", osb->fs_generation, le32_to_cpu(fe->i_fs_generation)); goto bail; } inode->i_version = 1; inode->i_generation = le32_to_cpu(fe->i_generation); inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); inode->i_mode = le16_to_cpu(fe->i_mode); inode->i_uid = le32_to_cpu(fe->i_uid); inode->i_gid = le32_to_cpu(fe->i_gid);#ifdef INODE_HAS_BLKSIZE inode->i_blksize = (u32)osb->s_clustersize;#endif /* Fast symlinks will have i_size but no allocated clusters. */ if (S_ISLNK(inode->i_mode) && !fe->i_clusters) inode->i_blocks = 0; else inode->i_blocks = ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); inode->i_mapping->a_ops = &ocfs2_aops; inode->i_flags |= S_NOATIME; inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); inode->i_mtime.tv_nsec = le32_to_cpu(fe->i_mtime_nsec); inode->i_ctime.tv_sec = le64_to_cpu(fe->i_ctime); inode->i_ctime.tv_nsec = le32_to_cpu(fe->i_ctime_nsec); if (OCFS2_I(inode)->ip_blkno != le64_to_cpu(fe->i_blkno)) mlog(ML_ERROR, "ip_blkno %"MLFu64" != i_blkno %"MLFu64"!\n", OCFS2_I(inode)->ip_blkno, fe->i_blkno); OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; OCFS2_I(inode)->ip_deleting_node = O2NM_INVALID_NODE_NUM; if (create_ino) inode->i_ino = ino_from_blkno(inode->i_sb, le64_to_cpu(fe->i_blkno)); mlog(0, "blkno = %"MLFu64", ino = %lu, create_ino = %s\n", fe->i_blkno, inode->i_ino, create_ino ? "true" : "false"); inode->i_nlink = le16_to_cpu(fe->i_links_count); if (fe->i_flags & cpu_to_le32(OCFS2_LOCAL_ALLOC_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; mlog(0, "local alloc inode: i_ino=%lu\n", inode->i_ino); } else if (fe->i_flags & cpu_to_le32(OCFS2_BITMAP_FL)) { OCFS2_I(inode)->ip_flags |= OCFS2_INODE_BITMAP; } else if (fe->i_flags & cpu_to_le32(OCFS2_SUPER_BLOCK_FL)) { mlog(0, "superblock inode: i_ino=%lu\n", inode->i_ino); /* we can't actually hit this as read_inode can't * handle superblocks today ;-) */ BUG(); } switch (inode->i_mode & S_IFMT) { case S_IFREG: inode->i_fop = &ocfs2_fops; inode->i_op = &ocfs2_file_iops; i_size_write(inode, le64_to_cpu(fe->i_size)); OCFS2_I(inode)->ip_mmu_private = inode->i_size; break; case S_IFDIR: inode->i_op = &ocfs2_dir_iops; inode->i_fop = &ocfs2_dops; i_size_write(inode, le64_to_cpu(fe->i_size)); break; case S_IFLNK: if (ocfs2_inode_is_fast_symlink(inode)) inode->i_op = &ocfs2_fast_symlink_inode_operations; else inode->i_op = &ocfs2_symlink_inode_operations; i_size_write(inode, le64_to_cpu(fe->i_size)); break; default: inode->i_op = &ocfs2_special_file_iops; init_special_inode(inode, inode->i_mode, inode->i_rdev); break; } ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_meta_lockres, OCFS2_LOCK_TYPE_META, inode); ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, OCFS2_LOCK_TYPE_DATA, inode); status = 0;bail: mlog_exit(status); return status;}static int ocfs2_read_locked_inode(struct inode *inode, struct ocfs2_find_inode_args *args){ struct super_block *sb; struct ocfs2_super *osb; struct ocfs2_dinode *fe; struct buffer_head *bh = NULL; int status; int sysfile = 0; mlog_entry("(0x%p, 0x%p)\n", inode, args); status = -EINVAL; if (inode == NULL || inode->i_sb == NULL) { mlog(ML_ERROR, "bad inode\n"); goto bail; } sb = inode->i_sb; osb = OCFS2_SB(sb); if (!args) { mlog(ML_ERROR, "bad inode args\n"); make_bad_inode(inode); goto bail; } /* Read the FE off disk. This is safe because the kernel only * does one read_inode2 for a new inode, and if it doesn't * exist yet then nobody can be working on it! */ status = ocfs2_read_block(osb, args->fi_blkno, &bh, 0, NULL); if (status < 0) { mlog_errno(status); make_bad_inode(inode); goto bail; } fe = (struct ocfs2_dinode *) bh->b_data; if (!OCFS2_IS_VALID_DINODE(fe)) { mlog(ML_ERROR, "Invalid dinode #%"MLFu64": signature = %.*s\n", fe->i_blkno, 7, fe->i_signature); make_bad_inode(inode); goto bail; } if (fe->i_flags & cpu_to_le32(OCFS2_SYSTEM_FL)) sysfile = 1; if (S_ISCHR(le16_to_cpu(fe->i_mode)) || S_ISBLK(le16_to_cpu(fe->i_mode))) inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); status = -EINVAL; if (ocfs2_populate_inode(inode, fe, 0) < 0) { make_bad_inode(inode); goto bail; } BUG_ON(args->fi_blkno != le64_to_cpu(fe->i_blkno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -