/* cnode related routines for the coda kernel code (C) 1996 Peter Braam */ #include #include #include #include #include #include #include "coda_linux.h" static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) { return memcmp(fid1, fid2, sizeof(*fid1)) == 0; } static const struct inode_operations coda_symlink_inode_operations = { .get_link = page_get_link, .setattr = coda_setattr, }; /* cnode.c */ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) { coda_vattr_to_iattr(inode, attr); if (S_ISREG(inode->i_mode)) { inode->i_op = &coda_file_inode_operations; inode->i_fop = &coda_file_operations; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &coda_dir_inode_operations; inode->i_fop = &coda_dir_operations; } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &coda_symlink_inode_operations; inode_nohighmem(inode); inode->i_data.a_ops = &coda_symlink_aops; inode->i_mapping = &inode->i_data; } else init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev)); } static int coda_test_inode(struct inode *inode, void *data) { struct CodaFid *fid = (struct CodaFid *)data; struct coda_inode_info *cii = ITOC(inode); return coda_fideq(&cii->c_fid, fid); } static int coda_set_inode(struct inode *inode, void *data) { struct CodaFid *fid = (struct CodaFid *)data; struct coda_inode_info *cii = ITOC(inode); cii->c_fid = *fid; return 0; } struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid, struct coda_vattr * attr) { struct inode *inode; struct coda_inode_info *cii; unsigned long hash = coda_f2i(fid); inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); if (!inode) return ERR_PTR(-ENOMEM); if (inode->i_state & I_NEW) { cii = ITOC(inode); /* we still need to set i_ino for things like stat(2) */ inode->i_ino = hash; /* inode is locked and unique, no need to grab cii->c_lock */ cii->c_mapcount = 0; unlock_new_inode(inode); } /* always replace the attributes, type might have changed */ coda_fill_inode(inode, attr); return inode; } /* this is effectively coda_iget: - get attributes (might be cached) - get the inode for the fid using vfs iget - link the two up if this is needed - fill in the attributes */ struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb) { struct coda_vattr attr; struct inode *inode; int error; /* We get inode numbers from Venus -- see venus source */ error = venus_getattr(sb, fid, &attr); if (error) return ERR_PTR(error); inode = coda_iget(sb, fid, &attr); if (IS_ERR(inode)) pr_warn("%s: coda_iget failed\n", __func__); return inode; } /* Although we treat Coda file identifiers as immutable, there is one * special case for files created during a disconnection where they may * not be globally unique. When an identifier collision is detected we * first try to flush the cached inode from the kernel and finally * resort to renaming/rehashing in-place. Userspace remembers both old * and new values of the identifier to handle any in-flight upcalls. * The real solution is to use globally unique UUIDs as identifiers, but * retrofitting the existing userspace code for this is non-trivial. */ void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, struct CodaFid *newfid) { struct coda_inode_info *cii = ITOC(inode); unsigned long hash = coda_f2i(newfid); BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); /* replace fid and rehash inode */ /* XXX we probably need to hold some lock here! */ remove_inode_hash(inode); cii->c_fid = *newfid; inode->i_ino = hash; __insert_inode_hash(inode, hash); } /* convert a fid to an inode. */ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) { struct inode *inode; unsigned long hash = coda_f2i(fid); if ( !sb ) { pr_warn("%s: no sb!\n", __func__); return NULL; } inode = ilookup5(sb, hash, coda_test_inode, fid); if ( !inode ) return NULL; /* we should never see newly created inodes because we intentionally * fail in the initialization callback */ BUG_ON(inode->i_state & I_NEW); return inode; } /* the CONTROL inode is made without asking attributes from Venus */ struct inode *coda_cnode_makectl(struct super_block *sb) { struct inode *inode = new_inode(sb); if (inode) { inode->i_ino = CTL_INO; inode->i_op = &coda_ioctl_inode_operations; inode->i_fop = &coda_ioctl_operations; inode->i_mode = 0444; return inode; } return ERR_PTR(-ENOMEM); } fo' class='commit-info'> authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-02-03 17:10:28 +1100 committerMichael Ellerman <mpe@ellerman.id.au>2017-02-08 23:36:29 +1100 commitd7df2443cd5f67fc6ee7c05a88e4996e8177f91b (patch) tree098a7c0ca4fceb8a65cb1f693c9d71990388933d /sound/isa/opti9xx/opti92x-ad1848.c parenta0615a16f7d0ceb5804d295203c302d496d8ee91 (diff)
powerpc/mm: Fix spurrious segfaults on radix with autonuma
When autonuma (Automatic NUMA balancing) marks a PTE inaccessible it clears all the protection bits but leave the PTE valid. With the Radix MMU, an attempt at executing from such a PTE will take a fault with bit 35 of SRR1 set "SRR1_ISI_N_OR_G". It is thus incorrect to treat all such faults as errors. We should pass them to handle_mm_fault() for autonuma to deal with. The case of pages that are really not executable is handled by the existing test for VM_EXEC further down. That leaves us with catching the kernel attempts at executing user pages. We can catch that earlier, even before we do find_vma. It is never valid on powerpc for the kernel to take an exec fault to begin with. So fold that test with the existing test for the kernel faulting on kernel addresses to bail out early. Fixes: 1d18ad026844 ("powerpc/mm: Detect instruction fetch denied and report") Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Acked-by: Balbir Singh <bsingharora@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'sound/isa/opti9xx/opti92x-ad1848.c')