file.h revision 284443
1193240Ssam/*- 2193240Ssam * Copyright (c) 2010 Isilon Systems, Inc. 3193240Ssam * Copyright (c) 2010 iX Systems, Inc. 4193240Ssam * Copyright (c) 2010 Panasas, Inc. 5193240Ssam * Copyright (c) 2013 Mellanox Technologies, Ltd. 6193240Ssam * All rights reserved. 7193240Ssam * 8193240Ssam * Redistribution and use in source and binary forms, with or without 9193240Ssam * modification, are permitted provided that the following conditions 10193240Ssam * are met: 11193240Ssam * 1. Redistributions of source code must retain the above copyright 12193240Ssam * notice unmodified, this list of conditions, and the following 13193240Ssam * disclaimer. 14193240Ssam * 2. Redistributions in binary form must reproduce the above copyright 15193240Ssam * notice, this list of conditions and the following disclaimer in the 16193240Ssam * documentation and/or other materials provided with the distribution. 17193240Ssam * 18193240Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19193240Ssam * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20193240Ssam * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21193240Ssam * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22193240Ssam * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23193240Ssam * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24193240Ssam * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25193240Ssam * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26193240Ssam * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27193240Ssam * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28193240Ssam */ 29193240Ssam#ifndef _LINUX_FILE_H_ 30193240Ssam#define _LINUX_FILE_H_ 31193240Ssam 32193240Ssam#include <sys/param.h> 33193240Ssam#include <sys/file.h> 34193240Ssam#include <sys/filedesc.h> 35193240Ssam#include <sys/refcount.h> 36234866Suqs#include <sys/capsicum.h> 37193240Ssam#include <sys/proc.h> 38193240Ssam 39193240Ssam#include <linux/fs.h> 40193240Ssam 41193240Ssamstruct linux_file; 42 43#undef file 44 45extern struct fileops linuxfileops; 46 47static inline struct linux_file * 48linux_fget(unsigned int fd) 49{ 50 cap_rights_t rights; 51 struct file *file; 52 53 if (fget_unlocked(curthread->td_proc->p_fd, fd, 54 cap_rights_init(&rights), &file, NULL) != 0) { 55 return (NULL); 56 } 57 return (struct linux_file *)file->f_data; 58} 59 60static inline void 61fput(struct linux_file *filp) 62{ 63 if (filp->_file == NULL) { 64 kfree(filp); 65 return; 66 } 67 if (refcount_release(&filp->_file->f_count)) { 68 _fdrop(filp->_file, curthread); 69 kfree(filp); 70 } 71} 72 73static inline void 74put_unused_fd(unsigned int fd) 75{ 76 cap_rights_t rights; 77 struct file *file; 78 79 if (fget_unlocked(curthread->td_proc->p_fd, fd, 80 cap_rights_init(&rights), &file, NULL) != 0) { 81 return; 82 } 83 /* 84 * NOTE: We should only get here when the "fd" has not been 85 * installed, so no need to free the associated Linux file 86 * structure. 87 */ 88 fdclose(curthread, file, fd); 89 90 /* drop extra reference */ 91 fdrop(file, curthread); 92} 93 94static inline void 95fd_install(unsigned int fd, struct linux_file *filp) 96{ 97 cap_rights_t rights; 98 struct file *file; 99 100 if (fget_unlocked(curthread->td_proc->p_fd, fd, 101 cap_rights_init(&rights), &file, NULL) != 0) { 102 file = NULL; 103 } 104 filp->_file = file; 105 finit(file, filp->f_mode, DTYPE_DEV, filp, &linuxfileops); 106 107 /* drop the extra reference */ 108 fput(filp); 109} 110 111static inline int 112get_unused_fd(void) 113{ 114 struct file *file; 115 int error; 116 int fd; 117 118 error = falloc(curthread, &file, &fd, 0); 119 if (error) 120 return -error; 121 /* drop the extra reference */ 122 fdrop(file, curthread); 123 return fd; 124} 125 126static inline struct linux_file * 127alloc_file(int mode, const struct file_operations *fops) 128{ 129 struct linux_file *filp; 130 131 filp = kzalloc(sizeof(*filp), GFP_KERNEL); 132 if (filp == NULL) 133 return (NULL); 134 filp->f_op = fops; 135 filp->f_mode = mode; 136 137 return filp; 138} 139 140struct fd { 141 struct linux_file *linux_file; 142}; 143 144static inline void fdput(struct fd fd) 145{ 146 fput(fd.linux_file); 147} 148 149static inline struct fd fdget(unsigned int fd) 150{ 151 struct linux_file *f = linux_fget(fd); 152 return (struct fd){f}; 153} 154 155#define file linux_file 156#define fget linux_fget 157 158#endif /* _LINUX_FILE_H_ */ 159