static ssize_t ocfs2_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { int ret = 0; struct inode *inode = in->f_path.dentry->d_inode; mlog_entry("(0x%p, 0x%p, %u, '%.*s')\n", in, pipe, (unsigned int)len, in->f_path.dentry->d_name.len, in->f_path.dentry->d_name.name); /* * See the comment in ocfs2_file_aio_read() */ ret = ocfs2_meta_lock(inode, NULL, 0); if (ret < 0) { mlog_errno(ret); goto bail; } ocfs2_meta_unlock(inode, 0); ret = generic_file_splice_read(in, ppos, pipe, len, flags); bail: mlog_exit(ret); return ret; }
/* * NOTE: this should always be called with parent dir i_mutex taken. */ int ocfs2_find_files_on_disk(const char *name, int namelen, u64 *blkno, struct inode *inode, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent) { int status = -ENOENT; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); mlog_entry("(osb=%p, parent=%"MLFu64", name='%.*s', blkno=%p, " "inode=%p)\n", osb, OCFS2_I(inode)->ip_blkno, namelen, name, blkno, inode); *dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent); if (!*dirent_bh || !*dirent) { status = -ENOENT; goto leave; } *blkno = le64_to_cpu((*dirent)->inode); status = 0; leave: if (status < 0) { *dirent = NULL; if (*dirent_bh) { brelse(*dirent_bh); *dirent_bh = NULL; } } mlog_exit(status); return status; }
int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode = dentry->d_inode; struct super_block *sb = dentry->d_inode->i_sb; struct ocfs2_super *osb = sb->s_fs_info; int err; mlog_entry_void(); err = ocfs2_inode_revalidate(dentry); if (err) { if (err != -ENOENT) mlog_errno(err); goto bail; } generic_fillattr(inode, stat); /* We set the blksize from the cluster size for performance */ stat->blksize = osb->s_clustersize; bail: mlog_exit(err); return err; }
static char *ocfs2_fast_symlink_getlink(struct inode *inode, struct buffer_head **bh) { int status; char *link = NULL; struct ocfs2_dinode *fe; mlog_entry_void(); status = ocfs2_read_block(OCFS2_SB(inode->i_sb), OCFS2_I(inode)->ip_blkno, bh, OCFS2_BH_CACHED, inode); if (status < 0) { mlog_errno(status); link = ERR_PTR(status); goto bail; } fe = (struct ocfs2_dinode *) (*bh)->b_data; link = (char *) fe->id2.i_symlink; bail: mlog_exit(status); return link; }
static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct inode *inode, struct buffer_head *fe_bh) { int status = 0; struct ocfs2_dinode *fe; handle_t *handle = NULL; mlog_entry_void(); fe = (struct ocfs2_dinode *) fe_bh->b_data; /* * This check will also skip truncate of inodes with inline * data and fast symlinks. */ if (fe->i_clusters) { if (ocfs2_should_order_data(inode)) ocfs2_begin_ordered_truncate(inode, 0); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); handle = NULL; mlog_errno(status); goto out; } status = ocfs2_journal_access_di(handle, INODE_CACHE(inode), fe_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto out; } i_size_write(inode, 0); status = ocfs2_mark_inode_dirty(handle, inode, fe_bh); if (status < 0) { mlog_errno(status); goto out; } ocfs2_commit_trans(osb, handle); handle = NULL; status = ocfs2_commit_truncate(osb, inode, fe_bh); if (status < 0) { mlog_errno(status); goto out; } } out: if (handle) ocfs2_commit_trans(osb, handle); mlog_exit(status); return status; }
static int ocfs2_file_open(struct inode *inode, struct file *file) { int status; int mode = file->f_flags; struct ocfs2_inode_info *oi = OCFS2_I(inode); mlog_entry("(0x%p, 0x%p, '%.*s')\n", inode, file, file->f_path.dentry->d_name.len, file->f_path.dentry->d_name.name); spin_lock(&oi->ip_lock); /* Check that the inode hasn't been wiped from disk by another * node. If it hasn't then we're safe as long as we hold the * spin lock until our increment of open count. */ if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_DELETED) { spin_unlock(&oi->ip_lock); status = -ENOENT; goto leave; } if (mode & O_DIRECT) oi->ip_flags |= OCFS2_INODE_OPEN_DIRECT; oi->ip_open_count++; spin_unlock(&oi->ip_lock); status = 0; leave: mlog_exit(status); return status; }
/* * 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; static struct lock_class_key ocfs2_quota_ip_alloc_sem_key, ocfs2_file_ip_alloc_sem_key; mlog_entry("inode = %p, opaque = %p\n", inode, opaque); inode->i_ino = args->fi_ino; OCFS2_I(inode)->ip_blkno = args->fi_blkno; if (args->fi_sysfile_type != 0) lockdep_set_class(&inode->i_mutex, &ocfs2_sysfile_lock_key[args->fi_sysfile_type]); if (args->fi_sysfile_type == USER_QUOTA_SYSTEM_INODE || args->fi_sysfile_type == GROUP_QUOTA_SYSTEM_INODE || args->fi_sysfile_type == LOCAL_USER_QUOTA_SYSTEM_INODE || args->fi_sysfile_type == LOCAL_GROUP_QUOTA_SYSTEM_INODE) lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, &ocfs2_quota_ip_alloc_sem_key); else lockdep_set_class(&OCFS2_I(inode)->ip_alloc_sem, &ocfs2_file_ip_alloc_sem_key); mlog_exit(0); return 0; }
static int ocfs2_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; loff_t start = (loff_t)page->index << PAGE_CACHE_SHIFT; int ret, unlock = 1; mlog_entry("(0x%p, %lu)\n", file, (page ? page->index : 0)); ret = ocfs2_meta_lock_with_page(inode, NULL, 0, page); if (ret != 0) { if (ret == AOP_TRUNCATED_PAGE) unlock = 0; mlog_errno(ret); goto out; } if (down_read_trylock(&OCFS2_I(inode)->ip_alloc_sem) == 0) { ret = AOP_TRUNCATED_PAGE; goto out_meta_unlock; } /* * i_size might have just been updated as we grabed the meta lock. We * might now be discovering a truncate that hit on another node. * block_read_full_page->get_block freaks out if it is asked to read * beyond the end of a file, so we check here. Callers * (generic_file_read, vm_ops->fault) are clever enough to check i_size * and notice that the page they just read isn't needed. * * XXX sys_readahead() seems to get that wrong? */ if (start >= i_size_read(inode)) { zero_user_page(page, 0, PAGE_SIZE, KM_USER0); SetPageUptodate(page); ret = 0; goto out_alloc; } ret = ocfs2_data_lock_with_page(inode, 0, page); if (ret != 0) { if (ret == AOP_TRUNCATED_PAGE) unlock = 0; mlog_errno(ret); goto out_alloc; } ret = block_read_full_page(page, ocfs2_get_block); unlock = 0; ocfs2_data_unlock(inode, 0); out_alloc: up_read(&OCFS2_I(inode)->ip_alloc_sem); out_meta_unlock: ocfs2_meta_unlock(inode, 0); out: if (unlock) unlock_page(page); mlog_exit(ret); return ret; }
static int ocfs2_readlink(struct dentry *dentry, char __user *buffer, int buflen) { int ret; char *link; struct buffer_head *bh = NULL; struct inode *inode = dentry->d_inode; mlog_entry_void(); link = ocfs2_fast_symlink_getlink(inode, &bh); if (IS_ERR(link)) { ret = PTR_ERR(link); goto out; } /* * Without vfsmount we can't update atime now, * but we will update atime here ultimately. */ ret = vfs_readlink(dentry, buffer, buflen, link); brelse(bh); out: mlog_exit(ret); return ret; }
/* * NOTE: this should always be called with parent dir i_mutex taken. */ int ocfs2_find_files_on_disk(const char *name, int namelen, u64 *blkno, struct inode *inode, struct buffer_head **dirent_bh, struct ocfs2_dir_entry **dirent) { int status = -ENOENT; mlog_entry("(name=%.*s, blkno=%p, inode=%p, dirent_bh=%p, dirent=%p)\n", namelen, name, blkno, inode, dirent_bh, dirent); *dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent); if (!*dirent_bh || !*dirent) { status = -ENOENT; goto leave; } *blkno = le64_to_cpu((*dirent)->inode); status = 0; leave: if (status < 0) { *dirent = NULL; if (*dirent_bh) { brelse(*dirent_bh); *dirent_bh = NULL; } } mlog_exit(status); return status; }
int ocfs2_update_inode_atime(struct inode *inode, struct buffer_head *bh) { int ret; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); handle_t *handle; mlog_entry_void(); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (handle == NULL) { ret = -ENOMEM; mlog_errno(ret); goto out; } inode->i_atime = CURRENT_TIME; ret = ocfs2_mark_inode_dirty(handle, inode, bh); if (ret < 0) mlog_errno(ret); ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); out: mlog_exit(ret); return ret; }
static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len, int connectable) { struct inode *inode = dentry->d_inode; int len = *max_len; int type = 1; u64 blkno; u32 generation; __le32 *fh = (__force __le32 *) fh_in; mlog_entry("(0x%p, '%.*s', 0x%p, %d, %d)\n", dentry, dentry->d_name.len, dentry->d_name.name, fh, len, connectable); if (len < 3 || (connectable && len < 6)) { mlog(ML_ERROR, "fh buffer is too small for encoding\n"); type = 255; goto bail; } blkno = OCFS2_I(inode)->ip_blkno; generation = inode->i_generation; mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", (unsigned long long)blkno, generation); len = 3; fh[0] = cpu_to_le32((u32)(blkno >> 32)); fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff)); fh[2] = cpu_to_le32(generation); if (connectable && !S_ISDIR(inode->i_mode)) { struct inode *parent; spin_lock(&dentry->d_lock); parent = dentry->d_parent->d_inode; blkno = OCFS2_I(parent)->ip_blkno; generation = parent->i_generation; fh[3] = cpu_to_le32((u32)(blkno >> 32)); fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff)); fh[5] = cpu_to_le32(generation); spin_unlock(&dentry->d_lock); len = 6; type = 2; mlog(0, "Encoding parent: blkno: %llu, generation: %u\n", (unsigned long long)blkno, generation); } *max_len = len; bail: mlog_exit(type); return type; }
int ocfs2_claim_local_alloc_bits(struct ocfs2_super *osb, handle_t *handle, struct ocfs2_alloc_context *ac, u32 bits_wanted, u32 *bit_off, u32 *num_bits) { int status, start; struct inode *local_alloc_inode; void *bitmap; struct ocfs2_dinode *alloc; struct ocfs2_local_alloc *la; mlog_entry_void(); BUG_ON(ac->ac_which != OCFS2_AC_USE_LOCAL); local_alloc_inode = ac->ac_inode; alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); start = ocfs2_local_alloc_find_clear_bits(osb, alloc, bits_wanted); if (start == -1) { /* TODO: Shouldn't we just BUG here? */ status = -ENOSPC; mlog_errno(status); goto bail; } bitmap = la->la_bitmap; *bit_off = le32_to_cpu(la->la_bm_off) + start; /* local alloc is always contiguous by nature -- we never * delete bits from it! */ *num_bits = bits_wanted; status = ocfs2_journal_access_di(handle, INODE_CACHE(local_alloc_inode), osb->local_alloc_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto bail; } while(bits_wanted--) ocfs2_set_bit(start++, bitmap); le32_add_cpu(&alloc->id1.bitmap1.i_used, *num_bits); status = ocfs2_journal_dirty(handle, osb->local_alloc_bh); if (status < 0) { mlog_errno(status); goto bail; } status = 0; bail: mlog_exit(status); return status; }
int ocfs2_journal_access(handle_t *handle, struct inode *inode, struct buffer_head *bh, int type) { int status; BUG_ON(!inode); BUG_ON(!handle); BUG_ON(!bh); mlog_entry("bh->b_blocknr=%llu, type=%d (\"%s\"), bh->b_size = %zu\n", (unsigned long long)bh->b_blocknr, type, (type == OCFS2_JOURNAL_ACCESS_CREATE) ? "OCFS2_JOURNAL_ACCESS_CREATE" : "OCFS2_JOURNAL_ACCESS_WRITE", bh->b_size); /* we can safely remove this assertion after testing. */ if (!buffer_uptodate(bh)) { mlog(ML_ERROR, "giving me a buffer that's not uptodate!\n"); mlog(ML_ERROR, "b_blocknr=%llu\n", (unsigned long long)bh->b_blocknr); BUG(); } /* Set the current transaction information on the inode so * that the locking code knows whether it can drop it's locks * on this inode or not. We're protected from the commit * thread updating the current transaction id until * ocfs2_commit_trans() because ocfs2_start_trans() took * j_trans_barrier for us. */ ocfs2_set_inode_lock_trans(OCFS2_SB(inode->i_sb)->journal, inode); mutex_lock(&OCFS2_I(inode)->ip_io_mutex); switch (type) { case OCFS2_JOURNAL_ACCESS_CREATE: case OCFS2_JOURNAL_ACCESS_WRITE: status = journal_get_write_access(handle, bh); break; case OCFS2_JOURNAL_ACCESS_UNDO: status = journal_get_undo_access(handle, bh); break; default: status = -EINVAL; mlog(ML_ERROR, "Uknown access type!\n"); } mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); if (status < 0) mlog(ML_ERROR, "Error %d getting %d access to buffer!\n", status, type); mlog_exit(status); return status; }
static int ocfs2_local_alloc_find_clear_bits(struct ocfs2_super *osb, struct ocfs2_dinode *alloc, u32 numbits) { int numfound, bitoff, left, startoff, lastzero; void *bitmap = NULL; mlog_entry("(numbits wanted = %u)\n", numbits); if (!alloc->id1.bitmap1.i_total) { mlog(0, "No bits in my window!\n"); bitoff = -1; goto bail; } bitmap = OCFS2_LOCAL_ALLOC(alloc)->la_bitmap; numfound = bitoff = startoff = 0; lastzero = -1; left = le32_to_cpu(alloc->id1.bitmap1.i_total); while ((bitoff = ocfs2_find_next_zero_bit(bitmap, left, startoff)) != -1) { if (bitoff == left) { /* mlog(0, "bitoff (%d) == left", bitoff); */ break; } /* mlog(0, "Found a zero: bitoff = %d, startoff = %d, " "numfound = %d\n", bitoff, startoff, numfound);*/ /* Ok, we found a zero bit... is it contig. or do we * start over?*/ if (bitoff == startoff) { /* we found a zero */ numfound++; startoff++; } else { /* got a zero after some ones */ numfound = 1; startoff = bitoff+1; } /* we got everything we needed */ if (numfound == numbits) { /* mlog(0, "Found it all!\n"); */ break; } } mlog(0, "Exiting loop, bitoff = %d, numfound = %d\n", bitoff, numfound); if (numfound == numbits) bitoff = startoff - numfound; else bitoff = -1; bail: mlog_exit(bitoff); return bitoff; }
static int ocfs2_block_group_fill(handle_t *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, u64 group_blkno, u16 my_chain, struct ocfs2_chain_list *cl) { int status = 0; struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) bg_bh->b_data; struct super_block * sb = alloc_inode->i_sb; mlog_entry_void(); if (((unsigned long long) bg_bh->b_blocknr) != group_blkno) { ocfs2_error(alloc_inode->i_sb, "group block (%llu) != " "b_blocknr (%llu)", (unsigned long long)group_blkno, (unsigned long long) bg_bh->b_blocknr); status = -EIO; goto bail; } status = ocfs2_journal_access(handle, alloc_inode, bg_bh, OCFS2_JOURNAL_ACCESS_CREATE); if (status < 0) { mlog_errno(status); goto bail; } memset(bg, 0, sb->s_blocksize); strcpy(bg->bg_signature, OCFS2_GROUP_DESC_SIGNATURE); bg->bg_generation = cpu_to_le32(OCFS2_SB(sb)->fs_generation); bg->bg_size = cpu_to_le16(ocfs2_group_bitmap_size(sb)); bg->bg_bits = cpu_to_le16(ocfs2_bits_per_group(cl)); bg->bg_chain = cpu_to_le16(my_chain); bg->bg_next_group = cl->cl_recs[my_chain].c_blkno; bg->bg_parent_dinode = cpu_to_le64(OCFS2_I(alloc_inode)->ip_blkno); bg->bg_blkno = cpu_to_le64(group_blkno); /* set the 1st bit in the bitmap to account for the descriptor block */ ocfs2_set_bit(0, (unsigned long *)bg->bg_bitmap); bg->bg_free_bits_count = cpu_to_le16(le16_to_cpu(bg->bg_bits) - 1); status = ocfs2_journal_dirty(handle, bg_bh); if (status < 0) mlog_errno(status); /* There is no need to zero out or otherwise initialize the * other blocks in a group - All valid FS metadata in a block * group stores the superblock fs_generation value at * allocation time. */ bail: mlog_exit(status); return status; }
static int ocfs2_orphan_for_truncate(struct ocfs2_super *osb, struct inode *inode, struct buffer_head *fe_bh, u64 new_i_size) { int status; handle_t *handle; struct ocfs2_dinode *di; mlog_entry_void(); /* TODO: This needs to actually orphan the inode in this * transaction. */ handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); goto out; } status = ocfs2_journal_access(handle, inode, fe_bh, OCFS2_JOURNAL_ACCESS_WRITE); if (status < 0) { mlog_errno(status); goto out_commit; } /* * Do this before setting i_size. */ status = ocfs2_zero_tail_for_truncate(inode, handle, new_i_size); if (status) { mlog_errno(status); goto out_commit; } i_size_write(inode, new_i_size); inode->i_blocks = ocfs2_align_bytes_to_sectors(new_i_size); inode->i_ctime = inode->i_mtime = CURRENT_TIME; di = (struct ocfs2_dinode *) fe_bh->b_data; di->i_size = cpu_to_le64(new_i_size); di->i_ctime = di->i_mtime = cpu_to_le64(inode->i_ctime.tv_sec); di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); status = ocfs2_journal_dirty(handle, fe_bh); if (status < 0) mlog_errno(status); out_commit: ocfs2_commit_trans(osb, handle); out: mlog_exit(status); return status; }
/* Callers don't need to care which bitmap (local alloc or main) to * use so we figure it out for them, but unfortunately this clutters * things a bit. */ int ocfs2_reserve_clusters(struct ocfs2_super *osb, u32 bits_wanted, struct ocfs2_alloc_context **ac) { int status; mlog_entry_void(); *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = bits_wanted; status = -ENOSPC; if (ocfs2_alloc_should_use_local(osb, bits_wanted)) { status = ocfs2_reserve_local_alloc_bits(osb, bits_wanted, *ac); if ((status < 0) && (status != -ENOSPC)) { mlog_errno(status); goto bail; } else if (status == -ENOSPC) { /* reserve_local_bits will return enospc with * the local alloc inode still locked, so we * can change this safely here. */ mlog(0, "Disabling local alloc\n"); /* We set to OCFS2_LA_DISABLED so that umount * can clean up what's left of the local * allocation */ osb->local_alloc_state = OCFS2_LA_DISABLED; } } if (status == -ENOSPC) { status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } } status = 0; bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } mlog_exit(status); return status; }
/* Callers don't need to care which bitmap (local alloc or main) to * use so we figure it out for them, but unfortunately this clutters * things a bit. */ static int ocfs2_reserve_clusters_with_limit(struct ocfs2_super *osb, u32 bits_wanted, u64 max_block, int flags, struct ocfs2_alloc_context **ac) { int status; mlog_entry_void(); *ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL); if (!(*ac)) { status = -ENOMEM; mlog_errno(status); goto bail; } (*ac)->ac_bits_wanted = bits_wanted; (*ac)->ac_max_block = max_block; status = -ENOSPC; if (!(flags & ALLOC_GROUPS_FROM_GLOBAL) && ocfs2_alloc_should_use_local(osb, bits_wanted)) { status = ocfs2_reserve_local_alloc_bits(osb, bits_wanted, *ac); if (status == -EFBIG) { /* The local alloc window is outside ac_max_block. * use the main bitmap. */ status = -ENOSPC; } else if ((status < 0) && (status != -ENOSPC)) { mlog_errno(status); goto bail; } } if (status == -ENOSPC) { status = ocfs2_reserve_cluster_bitmap_bits(osb, *ac); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } } status = 0; bail: if ((status < 0) && *ac) { ocfs2_free_alloc_context(*ac); *ac = NULL; } mlog_exit(status); return status; }
/* Note: Because we don't support holes, our allocation has * already happened (allocation writes zeros to the file data) * so we don't have to worry about ordered writes in * ocfs2_writepage. * * ->writepage is called during the process of invalidating the page cache * during blocked lock processing. It can't block on any cluster locks * to during block mapping. It's relying on the fact that the block * mapping can't have disappeared under the dirty pages that it is * being asked to write back. */ static int ocfs2_writepage(struct page *page, struct writeback_control *wbc) { int ret; mlog_entry("(0x%p)\n", page); ret = block_write_full_page(page, ocfs2_get_block, wbc); 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; }
static inline int ocfs2_block_group_set_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, unsigned int bit_off, unsigned int num_bits) { int status; void *bitmap = bg->bg_bitmap; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; mlog_entry_void(); if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); status = -EIO; goto bail; } BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off, num_bits); if (ocfs2_is_cluster_bitmap(alloc_inode)) journal_type = OCFS2_JOURNAL_ACCESS_UNDO; status = ocfs2_journal_access(handle, alloc_inode, group_bh, journal_type); if (status < 0) { mlog_errno(status); goto bail; } le16_add_cpu(&bg->bg_free_bits_count, -num_bits); while(num_bits--) ocfs2_set_bit(bit_off++, bitmap); status = ocfs2_journal_dirty(handle, group_bh); if (status < 0) { mlog_errno(status); goto bail; } bail: mlog_exit(status); return status; }
/* * pass it the bitmap lock in lock_bh if you have it. */ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, struct ocfs2_journal_handle *handle, struct ocfs2_alloc_context *ac) { int status = 0; u32 cluster_off, cluster_count; struct ocfs2_dinode *alloc = NULL; struct ocfs2_local_alloc *la; mlog_entry_void(); alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data; la = OCFS2_LOCAL_ALLOC(alloc); if (alloc->id1.bitmap1.i_total) mlog(0, "asking me to alloc a new window over a non-empty " "one\n"); mlog(0, "Allocating %u clusters for a new window.\n", ocfs2_local_alloc_window_bits(osb)); /* we used the generic suballoc reserve function, but we set * everything up nicely, so there's no reason why we can't use * the more specific cluster api to claim bits. */ status = ocfs2_claim_clusters(osb, handle, ac, ocfs2_local_alloc_window_bits(osb), &cluster_off, &cluster_count); if (status < 0) { if (status != -ENOSPC) mlog_errno(status); goto bail; } la->la_bm_off = cpu_to_le32(cluster_off); alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count); /* just in case... In the future when we find space ourselves, * we don't have to get all contiguous -- but we'll have to * set all previously used bits in bitmap and update * la_bits_set before setting the bits in the main bitmap. */ alloc->id1.bitmap1.i_used = 0; memset(OCFS2_LOCAL_ALLOC(alloc)->la_bitmap, 0, le16_to_cpu(la->la_size)); mlog(0, "New window allocated:\n"); mlog(0, "window la_bm_off = %u\n", OCFS2_LOCAL_ALLOC(alloc)->la_bm_off); mlog(0, "window bits = %u\n", le32_to_cpu(alloc->id1.bitmap1.i_total)); bail: mlog_exit(status); return status; }
static int ocfs2_write_remove_suid(struct inode *inode) { int ret; struct buffer_head *bh = NULL; struct ocfs2_inode_info *oi = OCFS2_I(inode); handle_t *handle; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); struct ocfs2_dinode *di; mlog_entry("(Inode %llu, mode 0%o)\n", (unsigned long long)oi->ip_blkno, inode->i_mode); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (handle == NULL) { ret = -ENOMEM; mlog_errno(ret); goto out; } ret = ocfs2_read_block(osb, oi->ip_blkno, &bh, OCFS2_BH_CACHED, inode); if (ret < 0) { mlog_errno(ret); goto out_trans; } ret = ocfs2_journal_access(handle, inode, bh, OCFS2_JOURNAL_ACCESS_WRITE); if (ret < 0) { mlog_errno(ret); goto out_bh; } inode->i_mode &= ~S_ISUID; if ((inode->i_mode & S_ISGID) && (inode->i_mode & S_IXGRP)) inode->i_mode &= ~S_ISGID; di = (struct ocfs2_dinode *) bh->b_data; di->i_mode = cpu_to_le16(inode->i_mode); ret = ocfs2_journal_dirty(handle, bh); if (ret < 0) mlog_errno(ret); out_bh: brelse(bh); out_trans: ocfs2_commit_trans(osb, handle); out: mlog_exit(ret); return ret; }
/* * JBD Might read a cached version of another nodes journal file. We * don't want this as this file changes often and we get no * notification on those changes. The only way to be sure that we've * got the most up to date version of those blocks then is to force * read them off disk. Just searching through the buffer cache won't * work as there may be pages backing this file which are still marked * up to date. We know things can't change on this file underneath us * as we have the lock by now :) */ static int ocfs2_force_read_journal(struct inode *inode) { int status = 0; int i; u64 v_blkno, p_blkno, p_blocks, num_blocks; #define CONCURRENT_JOURNAL_FILL 32ULL struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; mlog_entry_void(); memset(bhs, 0, sizeof(struct buffer_head *) * CONCURRENT_JOURNAL_FILL); num_blocks = ocfs2_blocks_for_bytes(inode->i_sb, inode->i_size); v_blkno = 0; while (v_blkno < num_blocks) { status = ocfs2_extent_map_get_blocks(inode, v_blkno, &p_blkno, &p_blocks, NULL); if (status < 0) { mlog_errno(status); goto bail; } if (p_blocks > CONCURRENT_JOURNAL_FILL) p_blocks = CONCURRENT_JOURNAL_FILL; /* We are reading journal data which should not * be put in the uptodate cache */ status = ocfs2_read_blocks(OCFS2_SB(inode->i_sb), p_blkno, p_blocks, bhs, 0, NULL); if (status < 0) { mlog_errno(status); goto bail; } for(i = 0; i < p_blocks; i++) { brelse(bhs[i]); bhs[i] = NULL; } v_blkno += p_blocks; } bail: for(i = 0; i < CONCURRENT_JOURNAL_FILL; i++) if (bhs[i]) brelse(bhs[i]); mlog_exit(status); return status; }
static inline int ocfs2_block_group_set_bits(handle_t *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, struct buffer_head *group_bh, unsigned int bit_off, unsigned int num_bits) { int status; void *bitmap = bg->bg_bitmap; int journal_type = OCFS2_JOURNAL_ACCESS_WRITE; mlog_entry_void(); /* All callers get the descriptor via * ocfs2_read_group_descriptor(). Any corruption is a code bug. */ BUG_ON(!OCFS2_IS_VALID_GROUP_DESC(bg)); BUG_ON(le16_to_cpu(bg->bg_free_bits_count) < num_bits); mlog(0, "block_group_set_bits: off = %u, num = %u\n", bit_off, num_bits); if (ocfs2_is_cluster_bitmap(alloc_inode)) journal_type = OCFS2_JOURNAL_ACCESS_UNDO; status = ocfs2_journal_access_gd(handle, INODE_CACHE(alloc_inode), group_bh, journal_type); if (status < 0) { mlog_errno(status); goto bail; } le16_add_cpu(&bg->bg_free_bits_count, -num_bits); while(num_bits--) ocfs2_set_bit(bit_off++, bitmap); status = ocfs2_journal_dirty(handle, group_bh); if (status < 0) { mlog_errno(status); goto bail; } bail: mlog_exit(status); return status; }
/* * 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; if (args->fi_sysfile_type != 0) lockdep_set_class(&inode->i_mutex, &ocfs2_sysfile_lock_key[args->fi_sysfile_type]); mlog_exit(0); return 0; }
int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, struct inode *inode) { int ret = 0; mlog_entry("(bh->b_blocknr = %llu, inode=%p)\n", (unsigned long long)bh->b_blocknr, inode); BUG_ON(bh->b_blocknr < OCFS2_SUPER_BLOCK_BLKNO); BUG_ON(buffer_jbd(bh)); /* No need to check for a soft readonly file system here. non * journalled writes are only ever done on system files which * can get modified during recovery even if read-only. */ if (ocfs2_is_hard_readonly(osb)) { ret = -EROFS; goto out; } mutex_lock(&OCFS2_I(inode)->ip_io_mutex); lock_buffer(bh); set_buffer_uptodate(bh); /* remove from dirty list before I/O. */ clear_buffer_dirty(bh); get_bh(bh); /* for end_buffer_write_sync() */ bh->b_end_io = end_buffer_write_sync; submit_bh(WRITE, bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) { ocfs2_set_buffer_uptodate(inode, bh); } else { /* We don't need to remove the clustered uptodate * information for this bh as it's not marked locally * uptodate. */ ret = -EIO; put_bh(bh); } mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); out: mlog_exit(ret); return ret; }
static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) { int status; status = ocfs2_inode_lock(inode, NULL, 0); if (status < 0) { mlog_errno(status); return status; } ocfs2_get_inode_flags(OCFS2_I(inode)); *flags = OCFS2_I(inode)->ip_attr; ocfs2_inode_unlock(inode, 0); mlog_exit(status); return status; }
static u32 ocfs2_local_alloc_count_bits(struct ocfs2_dinode *alloc) { int i; u8 *buffer; u32 count = 0; struct ocfs2_local_alloc *la = OCFS2_LOCAL_ALLOC(alloc); mlog_entry_void(); buffer = la->la_bitmap; for (i = 0; i < le16_to_cpu(la->la_size); i++) count += hweight8(buffer[i]); mlog_exit(count); return count; }