/* * Lookup file info. If it doesn't exist, create a file info struct * and open a (VFS) file for the given inode. * * FIXME: * Note that we open the file O_RDONLY even when creating write locks. * This is not quite right, but for now, we assume the client performs * the proper R/W checking. */ __be32 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result, struct nfs_fh *f) { struct hlist_node *pos; struct nlm_file *file; unsigned int hash; __be32 nfserr; nlm_debug_print_fh("nlm_lookup_file", f); hash = file_hash(f); /* Lock file table */ mutex_lock(&nlm_file_mutex); hlist_for_each_entry(file, pos, &nlm_files[hash], f_list) if (!nfs_compare_fh(&file->f_handle, f)) goto found; nlm_debug_print_fh("creating file for", f); nfserr = nlm_lck_denied_nolocks; file = kzalloc(sizeof(*file), GFP_KERNEL); if (!file) goto out_unlock; memcpy(&file->f_handle, f, sizeof(struct nfs_fh)); mutex_init(&file->f_mutex); INIT_HLIST_NODE(&file->f_list); INIT_LIST_HEAD(&file->f_blocks); /* Open the file. Note that this must not sleep for too long, else * we would lock up lockd:-) So no NFS re-exports, folks. * * We have to make sure we have the right credential to open * the file. */ if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) { dprintk("lockd: open failed (error %d)\n", nfserr); goto out_free; } hlist_add_head(&file->f_list, &nlm_files[hash]); found: dprintk("lockd: found file %p (count %d)\n", file, file->f_count); *result = file; file->f_count++; nfserr = 0; out_unlock: mutex_unlock(&nlm_file_mutex); return nfserr; out_free: kfree(file); goto out_unlock; }
/* * In NFSv3 we can have 64bit inode numbers. In order to support * this, and re-exported directories (also seen in NFSv2) * we are forced to allow 2 different inodes to have the same * i_ino. */ static int nfs_find_actor(struct inode *inode, void *opaque) { struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; struct nfs_fh *fh = desc->fh; struct nfs_fattr *fattr = desc->fattr; if (NFS_FILEID(inode) != fattr->fileid) return 0; if (nfs_compare_fh(NFS_FH(inode), fh)) return 0; if (is_bad_inode(inode) || NFS_STALE(inode)) return 0; return 1; }