static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) { sigset_t blocked, oldset; int error, ret; mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); /* The best way to deal with signals in this path is * to block them upfront, rather than allowing the * locking paths to return -ERESTARTSYS. */ sigfillset(&blocked); /* We should technically never get a bad ret return * from sigprocmask */ error = sigprocmask(SIG_BLOCK, &blocked, &oldset); if (ret < 0) { mlog_errno(error); ret = VM_FAULT_SIGBUS; goto out; } ret = filemap_fault(area, vmf); error = sigprocmask(SIG_SETMASK, &oldset, NULL); if (error < 0) mlog_errno(error); out: mlog_exit_ptr(vmf->page); return ret; }
static struct dentry *ocfs2_get_dentry(struct super_block *sb, struct ocfs2_inode_handle *handle) { struct inode *inode; struct dentry *result; mlog_entry("(0x%p, 0x%p)\n", sb, handle); if (handle->ih_blkno == 0) { mlog_errno(-ESTALE); return ERR_PTR(-ESTALE); } inode = ocfs2_iget(OCFS2_SB(sb), handle->ih_blkno, 0, 0); if (IS_ERR(inode)) return (void *)inode; if (handle->ih_generation != inode->i_generation) { iput(inode); return ERR_PTR(-ESTALE); } result = d_alloc_anon(inode); if (!result) { iput(inode); mlog_errno(-ENOMEM); return ERR_PTR(-ENOMEM); } result->d_op = &ocfs2_dentry_ops; mlog_exit_ptr(result); return result; }
static struct page *ocfs2_nopage(struct vm_area_struct * area, unsigned long address, int *type) { struct page *page = NOPAGE_SIGBUS; sigset_t blocked, oldset; int ret; mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address, type); /* The best way to deal with signals in this path is * to block them upfront, rather than allowing the * locking paths to return -ERESTARTSYS. */ sigfillset(&blocked); /* We should technically never get a bad ret return * from sigprocmask */ ret = sigprocmask(SIG_BLOCK, &blocked, &oldset); if (ret < 0) { mlog_errno(ret); goto out; } page = filemap_nopage(area, address, type); ret = sigprocmask(SIG_SETMASK, &oldset, NULL); if (ret < 0) mlog_errno(ret); out: mlog_exit_ptr(page); return page; }
static struct dentry *ocfs2_get_parent(struct dentry *child) { int status; u64 blkno; struct dentry *parent; struct inode *inode; struct inode *dir = child->d_inode; struct buffer_head *dirent_bh = NULL; struct ocfs2_dir_entry *dirent; mlog_entry("(0x%p, '%.*s')\n", child, child->d_name.len, child->d_name.name); mlog(0, "find parent of directory %llu\n", (unsigned long long)OCFS2_I(dir)->ip_blkno); status = ocfs2_meta_lock(dir, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); parent = ERR_PTR(status); goto bail; } status = ocfs2_find_files_on_disk("..", 2, &blkno, dir, &dirent_bh, &dirent); if (status < 0) { parent = ERR_PTR(-ENOENT); goto bail_unlock; } inode = ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0); if (IS_ERR(inode)) { mlog(ML_ERROR, "Unable to create inode %llu\n", (unsigned long long)blkno); parent = ERR_PTR(-EACCES); goto bail_unlock; } parent = d_alloc_anon(inode); if (!parent) { iput(inode); parent = ERR_PTR(-ENOMEM); } parent->d_op = &ocfs2_dentry_ops; bail_unlock: ocfs2_meta_unlock(dir, 0); if (dirent_bh) brelse(dirent_bh); bail: mlog_exit_ptr(parent); return parent; }
struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags, int sysfile_type) { struct inode *inode = NULL; struct super_block *sb = osb->sb; struct ocfs2_find_inode_args args; mlog_entry("(blkno = %llu)\n", (unsigned long long)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 = flags; args.fi_ino = ino_from_blkno(sb, blkno); args.fi_sysfile_type = sysfile_type; 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 %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); mlog_exit_ptr(inode); } return inode; }
static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) { sigset_t oldset; int ret; mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); ocfs2_block_signals(&oldset); ret = filemap_fault(area, vmf); ocfs2_unblock_signals(&oldset); mlog_exit_ptr(vmf->page); return ret; }
static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in, int fh_len, int fileid_type, int (*acceptable)(void *context, struct dentry *de), void *context) { struct ocfs2_inode_handle handle, parent; struct dentry *ret = NULL; __le32 *fh = (__force __le32 *) fh_in; mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n", sb, fh, fh_len, fileid_type, acceptable, context); if (fh_len < 3 || fileid_type > 2) goto bail; if (fileid_type == 2) { if (fh_len < 6) goto bail; parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32; parent.ih_blkno |= (u64)le32_to_cpu(fh[4]); parent.ih_generation = le32_to_cpu(fh[5]); mlog(0, "Decoding parent: blkno: %llu, generation: %u\n", (unsigned long long)parent.ih_blkno, parent.ih_generation); } handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32; handle.ih_blkno |= (u64)le32_to_cpu(fh[1]); handle.ih_generation = le32_to_cpu(fh[2]); mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", (unsigned long long)handle.ih_blkno, handle.ih_generation); ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent, acceptable, context); bail: mlog_exit_ptr(ret); return ret; }
static struct dentry *ocfs2_get_parent(struct dentry *child) { int status; u64 blkno; struct dentry *parent; struct inode *dir = child->d_inode; mlog_entry("(0x%p, '%.*s')\n", child, child->d_name.len, child->d_name.name); mlog(0, "find parent of directory %llu\n", (unsigned long long)OCFS2_I(dir)->ip_blkno); status = ocfs2_inode_lock(dir, NULL, 0); if (status < 0) { if (status != -ENOENT) mlog_errno(status); parent = ERR_PTR(status); goto bail; } status = ocfs2_lookup_ino_from_name(dir, "..", 2, &blkno); if (status < 0) { parent = ERR_PTR(-ENOENT); goto bail_unlock; } parent = d_obtain_alias(ocfs2_iget(OCFS2_SB(dir->i_sb), blkno, 0, 0)); if (!IS_ERR(parent)) parent->d_op = &ocfs2_dentry_ops; bail_unlock: ocfs2_inode_unlock(dir, 0); bail: mlog_exit_ptr(parent); return parent; }
static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) { sigset_t blocked, oldset; int error, ret; mlog_entry("(area=%p, page offset=%lu)\n", area, vmf->pgoff); error = ocfs2_vm_op_block_sigs(&blocked, &oldset); if (error < 0) { mlog_errno(error); ret = VM_FAULT_SIGBUS; goto out; } ret = filemap_fault(area, vmf); error = ocfs2_vm_op_unblock_sigs(&oldset); if (error < 0) mlog_errno(error); out: mlog_exit_ptr(vmf->page); return ret; }
static struct dentry *ocfs2_get_dentry(struct super_block *sb, struct ocfs2_inode_handle *handle) { struct inode *inode; struct ocfs2_super *osb = OCFS2_SB(sb); u64 blkno = handle->ih_blkno; int status, set; struct dentry *result; mlog_entry("(0x%p, 0x%p)\n", sb, handle); if (blkno == 0) { mlog(0, "nfs wants inode with blkno: 0\n"); result = ERR_PTR(-ESTALE); goto bail; } inode = ocfs2_ilookup(sb, blkno); /* * If the inode exists in memory, we only need to check it's * generation number */ if (inode) goto check_gen; /* * This will synchronize us against ocfs2_delete_inode() on * all nodes */ status = ocfs2_nfs_sync_lock(osb, 1); if (status < 0) { mlog(ML_ERROR, "getting nfs sync lock(EX) failed %d\n", status); goto check_err; } status = ocfs2_test_inode_bit(osb, blkno, &set); if (status < 0) { if (status == -EINVAL) { /* * The blkno NFS gave us doesn't even show up * as an inode, we return -ESTALE to be * nice */ mlog(0, "test inode bit failed %d\n", status); status = -ESTALE; } else { mlog(ML_ERROR, "test inode bit failed %d\n", status); } goto unlock_nfs_sync; } /* If the inode allocator bit is clear, this inode must be stale */ if (!set) { mlog(0, "inode %llu suballoc bit is clear\n", (unsigned long long)blkno); status = -ESTALE; goto unlock_nfs_sync; } inode = ocfs2_iget(osb, blkno, 0, 0); unlock_nfs_sync: ocfs2_nfs_sync_unlock(osb, 1); check_err: if (status < 0) { if (status == -ESTALE) { mlog(0, "stale inode ino: %llu generation: %u\n", (unsigned long long)blkno, handle->ih_generation); } result = ERR_PTR(status); goto bail; } if (IS_ERR(inode)) { mlog_errno(PTR_ERR(inode)); result = (void *)inode; goto bail; } check_gen: if (handle->ih_generation != inode->i_generation) { iput(inode); mlog(0, "stale inode ino: %llu generation: %u\n", (unsigned long long)blkno, handle->ih_generation); result = ERR_PTR(-ESTALE); goto bail; } result = d_obtain_alias(inode); if (!IS_ERR(result)) result->d_op = &ocfs2_dentry_ops; else mlog_errno(PTR_ERR(result)); bail: mlog_exit_ptr(result); return result; }