📄 inode.c
字号:
OCFS2_I(inode)->ip_blkno, sync_data);#ifndef OCFS2_DELETE_INODE_WORKAROUND if (sync_data) write_inode_now(inode, 1); truncate_inode_pages(&inode->i_data, 0);#endif}void ocfs2_delete_inode(struct inode *inode){ int wipe, status; sigset_t blocked, oldset; struct buffer_head *di_bh = NULL; mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino); if (is_bad_inode(inode)) { mlog(0, "Skipping delete of bad inode\n"); goto bail; } if (!ocfs2_inode_is_valid_to_delete(inode)) { /* It's probably not necessary to truncate_inode_pages * here but we do it for safety anyway (it will most * likely be a no-op anyway) */ ocfs2_cleanup_delete_inode(inode, 0); goto bail; } /* We want to block signals in delete_inode as the lock and * messaging paths may return us -ERESTARTSYS. Which would * cause us to exit early, resulting in inodes being orphaned * forever. */ sigfillset(&blocked); status = sigprocmask(SIG_BLOCK, &blocked, &oldset); if (status < 0) { mlog_errno(status); ocfs2_cleanup_delete_inode(inode, 1); goto bail; } /* Lock down the inode. This gives us an up to date view of * it's metadata (for verification), and allows us to * serialize delete_inode votes. */ status = ocfs2_meta_lock(inode, NULL, &di_bh, 1); if (status < 0) { if (status != -ENOENT) mlog_errno(status); ocfs2_cleanup_delete_inode(inode, 0); goto bail_unblock; } /* Query the cluster. This will be the final decision made * before we go ahead and wipe the inode. */ status = ocfs2_query_inode_wipe(inode, di_bh, &wipe); if (!wipe || status < 0) { /* Error and inode busy vote both mean we won't be * removing the inode, so they take almost the same * path. */ if (status < 0) mlog_errno(status); /* Someone in the cluster has voted to not wipe this * inode, or it was never completely orphaned. Write * out the pages and exit now. */ ocfs2_cleanup_delete_inode(inode, 1); goto bail_unlock_inode; } ocfs2_cleanup_delete_inode(inode, 0); status = ocfs2_wipe_inode(inode, di_bh); if (status < 0) { if (status != -EDEADLK) mlog_errno(status); goto bail_unlock_inode; } /* Mark the inode as successfully deleted. This is important * for ocfs2_clear_inode as it will check this flag and skip * any checkpointing work */ OCFS2_I(inode)->ip_flags |= OCFS2_INODE_DELETED;bail_unlock_inode: ocfs2_meta_unlock(inode, 1); brelse(di_bh);bail_unblock: status = sigprocmask(SIG_SETMASK, &oldset, NULL); if (status < 0) mlog_errno(status);bail: clear_inode(inode); mlog_exit_void();}void ocfs2_clear_inode(struct inode *inode){ int status; struct ocfs2_inode_info *oi = OCFS2_I(inode); mlog_entry_void(); if (!inode) goto bail; mlog(0, "Clearing inode: %"MLFu64", nlink = %u\n", OCFS2_I(inode)->ip_blkno, inode->i_nlink); mlog_bug_on_msg(OCFS2_SB(inode->i_sb) == NULL, "Inode=%lu\n", inode->i_ino); /* Do these before all the other work so that we don't bounce * the vote thread while waiting to destroy the locks. */ ocfs2_mark_lockres_freeing(&oi->ip_meta_lockres); ocfs2_mark_lockres_freeing(&oi->ip_data_lockres); /* We very well may get a clear_inode before all an inodes * metadata has hit disk. Of course, we can't drop any cluster * locks until the journal has finished with it. The only * exception here are successfully wiped inodes - their * metadata can now be considered to be part of the system * inodes from which it came. */ if (!(OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED)) ocfs2_checkpoint_inode(inode); mlog_bug_on_msg(!list_empty(&oi->ip_io_markers), "Clear inode of %"MLFu64", inode has io markers\n", oi->ip_blkno); ocfs2_extent_map_drop(inode, 0); ocfs2_extent_map_init(inode); status = ocfs2_drop_inode_locks(inode); if (status < 0) mlog_errno(status); ocfs2_lock_res_free(&oi->ip_meta_lockres); ocfs2_lock_res_free(&oi->ip_data_lockres); ocfs2_metadata_cache_purge(inode); mlog_bug_on_msg(oi->ip_metadata_cache.ci_num_cached, "Clear inode of %"MLFu64", inode has %u cache items\n", oi->ip_blkno, oi->ip_metadata_cache.ci_num_cached); mlog_bug_on_msg(!(oi->ip_flags & OCFS2_INODE_CACHE_INLINE), "Clear inode of %"MLFu64", inode has a bad flag\n", oi->ip_blkno); mlog_bug_on_msg(spin_is_locked(&oi->ip_lock), "Clear inode of %"MLFu64", inode is locked\n", oi->ip_blkno); mlog_bug_on_msg(down_trylock(&oi->ip_io_sem), "Clear inode of %"MLFu64", io_sem is locked\n", oi->ip_blkno); up(&oi->ip_io_sem); /* * down_trylock() returns 0, down_write_trylock() returns 1 * kernel 1, world 0 */ mlog_bug_on_msg(!down_write_trylock(&oi->ip_alloc_sem), "Clear inode of %"MLFu64", alloc_sem is locked\n", oi->ip_blkno); up_write(&oi->ip_alloc_sem); mlog_bug_on_msg(oi->ip_open_count, "Clear inode of %"MLFu64" has open count %d\n", oi->ip_blkno, oi->ip_open_count); mlog_bug_on_msg(!list_empty(&oi->ip_handle_list), "Clear inode of %"MLFu64" has non empty handle list\n", oi->ip_blkno); mlog_bug_on_msg(oi->ip_handle, "Clear inode of %"MLFu64" has non empty handle pointer\n", oi->ip_blkno); /* Clear all other flags. */ oi->ip_flags = OCFS2_INODE_CACHE_INLINE; oi->ip_created_trans = 0; oi->ip_last_trans = 0; oi->ip_dir_start_lookup = 0; oi->ip_blkno = 0ULL;bail: mlog_exit_void();}/* Called under inode_lock, with no more references on the * struct inode, so it's safe here to check the flags field * and to manipulate i_nlink without any other locks. */void ocfs2_drop_inode(struct inode *inode){ struct ocfs2_inode_info *oi = OCFS2_I(inode); mlog_entry_void(); mlog(0, "Drop inode %"MLFu64", nlink = %u, ip_flags = 0x%x\n", oi->ip_blkno, inode->i_nlink, oi->ip_flags); /* Testing ip_orphaned_slot here wouldn't work because we may * not have gotten a delete_inode vote from any other nodes * yet. */ if (oi->ip_flags & OCFS2_INODE_MAYBE_ORPHANED) { mlog(0, "Inode was orphaned on another node, clearing nlink.\n"); inode->i_nlink = 0; } generic_drop_inode(inode); mlog_exit_void();}/* * TODO: this should probably be merged into ocfs2_get_block * * However, you now need to pay attention to the cont_prepare_write() * stuff in ocfs2_get_block (that is, ocfs2_get_block pretty much * expects never to extend). */struct buffer_head *ocfs2_bread(struct inode *inode, int block, int *err, int reada){ struct buffer_head *bh = NULL; int tmperr; u64 p_blkno; int readflags = OCFS2_BH_CACHED;#if 0 /* only turn this on if we know we can deal with read_block * returning nothing */ if (reada) readflags |= OCFS2_BH_READAHEAD;#endif if (((u64)block << inode->i_sb->s_blocksize_bits) >= i_size_read(inode)) { BUG_ON(!reada); return NULL; } down_read(&OCFS2_I(inode)->ip_alloc_sem); tmperr = ocfs2_extent_map_get_blocks(inode, block, 1, &p_blkno, NULL); up_read(&OCFS2_I(inode)->ip_alloc_sem); if (tmperr < 0) { mlog_errno(tmperr); goto fail; } tmperr = ocfs2_read_block(OCFS2_SB(inode->i_sb), p_blkno, &bh, readflags, inode); if (tmperr < 0) goto fail; tmperr = 0; *err = 0; return bh;fail: if (bh) { brelse(bh); bh = NULL; } *err = -EIO; return NULL;}/* * This is called from our getattr. */int ocfs2_inode_revalidate(struct dentry *dentry){ struct inode *inode = dentry->d_inode; int status = 0; mlog_entry("(inode = 0x%p, ino = %"MLFu64")\n", inode, inode ? OCFS2_I(inode)->ip_blkno : 0ULL); if (!inode) { mlog(0, "eep, no inode!\n"); status = -ENOENT; goto bail; } spin_lock(&OCFS2_I(inode)->ip_lock); if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&OCFS2_I(inode)->ip_lock); mlog(0, "inode deleted!\n"); status = -ENOENT; goto bail; } spin_unlock(&OCFS2_I(inode)->ip_lock); /* Let ocfs2_meta_lock do the work of updating our struct * inode for us. */ status = ocfs2_meta_lock(inode, NULL, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); goto bail; } ocfs2_meta_unlock(inode, 0);bail: mlog_exit(status); return status;}/* * Updates a disk inode from a * struct inode. * Only takes ip_lock. */int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, struct inode *inode, struct buffer_head *bh){ int status; struct ocfs2_dinode *fe = (struct ocfs2_dinode *) bh->b_data; mlog_entry("(inode %"MLFu64")\n", OCFS2_I(inode)->ip_blkno); status = ocfs2_journal_access(handle, inode, bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto leave; } spin_lock(&OCFS2_I(inode)->ip_lock); fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); spin_unlock(&OCFS2_I(inode)->ip_lock); fe->i_size = cpu_to_le64(i_size_read(inode)); fe->i_links_count = cpu_to_le16(inode->i_nlink); fe->i_uid = cpu_to_le32(inode->i_uid); fe->i_gid = cpu_to_le32(inode->i_gid); fe->i_mode = cpu_to_le16(inode->i_mode); fe->i_atime = cpu_to_le64(inode->i_atime.tv_sec); fe->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec); fe->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); fe->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); fe->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec); fe->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); status = ocfs2_journal_dirty(handle, bh); if (status < 0) mlog_errno(status); status = 0;leave: mlog_exit(status); return status;}/* * * Updates a struct inode from a disk inode. * does no i/o, only takes ip_lock. */void ocfs2_refresh_inode(struct inode *inode, struct ocfs2_dinode *fe){ spin_lock(&OCFS2_I(inode)->ip_lock); OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); i_size_write(inode, le64_to_cpu(fe->i_size)); if (S_ISREG(inode->i_mode)) { OCFS2_I(inode)->ip_mmu_private = i_size_read(inode); } inode->i_nlink = le16_to_cpu(fe->i_links_count); inode->i_uid = le32_to_cpu(fe->i_uid); inode->i_gid = le32_to_cpu(fe->i_gid); inode->i_mode = le16_to_cpu(fe->i_mode);#ifdef INODE_HAS_BLKSIZE inode->i_blksize = (u32) OCFS2_SB(inode->i_sb)->s_clustersize;#endif if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0) inode->i_blocks = 0; else inode->i_blocks = ocfs2_align_bytes_to_sectors(i_size_read(inode)); 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); spin_unlock(&OCFS2_I(inode)->ip_lock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -