Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15 323 lines 7.5 kB view raw
1/* 2 * Copyright (C) 2005, 2006 3 * Avishay Traeger (avishay@gmail.com) 4 * Copyright (C) 2008, 2009 5 * Boaz Harrosh <ooo@electrozaur.com> 6 * 7 * Copyrights for code taken from ext2: 8 * Copyright (C) 1992, 1993, 1994, 1995 9 * Remy Card (card@masi.ibp.fr) 10 * Laboratoire MASI - Institut Blaise Pascal 11 * Universite Pierre et Marie Curie (Paris VI) 12 * from 13 * linux/fs/minix/inode.c 14 * Copyright (C) 1991, 1992 Linus Torvalds 15 * 16 * This file is part of exofs. 17 * 18 * exofs is free software; you can redistribute it and/or modify 19 * it under the terms of the GNU General Public License as published by 20 * the Free Software Foundation. Since it is based on ext2, and the only 21 * valid version of GPL for the Linux kernel is version 2, the only valid 22 * version of GPL for exofs is version 2. 23 * 24 * exofs is distributed in the hope that it will be useful, 25 * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * GNU General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with exofs; if not, write to the Free Software 31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 32 */ 33 34#include "exofs.h" 35 36static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode) 37{ 38 int err = exofs_add_link(dentry, inode); 39 if (!err) { 40 d_instantiate(dentry, inode); 41 return 0; 42 } 43 inode_dec_link_count(inode); 44 iput(inode); 45 return err; 46} 47 48static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry, 49 unsigned int flags) 50{ 51 struct inode *inode; 52 ino_t ino; 53 54 if (dentry->d_name.len > EXOFS_NAME_LEN) 55 return ERR_PTR(-ENAMETOOLONG); 56 57 ino = exofs_inode_by_name(dir, dentry); 58 inode = ino ? exofs_iget(dir->i_sb, ino) : NULL; 59 return d_splice_alias(inode, dentry); 60} 61 62static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode, 63 bool excl) 64{ 65 struct inode *inode = exofs_new_inode(dir, mode); 66 int err = PTR_ERR(inode); 67 if (!IS_ERR(inode)) { 68 inode->i_op = &exofs_file_inode_operations; 69 inode->i_fop = &exofs_file_operations; 70 inode->i_mapping->a_ops = &exofs_aops; 71 mark_inode_dirty(inode); 72 err = exofs_add_nondir(dentry, inode); 73 } 74 return err; 75} 76 77static int exofs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, 78 dev_t rdev) 79{ 80 struct inode *inode; 81 int err; 82 83 inode = exofs_new_inode(dir, mode); 84 err = PTR_ERR(inode); 85 if (!IS_ERR(inode)) { 86 init_special_inode(inode, inode->i_mode, rdev); 87 mark_inode_dirty(inode); 88 err = exofs_add_nondir(dentry, inode); 89 } 90 return err; 91} 92 93static int exofs_symlink(struct inode *dir, struct dentry *dentry, 94 const char *symname) 95{ 96 struct super_block *sb = dir->i_sb; 97 int err = -ENAMETOOLONG; 98 unsigned l = strlen(symname)+1; 99 struct inode *inode; 100 struct exofs_i_info *oi; 101 102 if (l > sb->s_blocksize) 103 goto out; 104 105 inode = exofs_new_inode(dir, S_IFLNK | S_IRWXUGO); 106 err = PTR_ERR(inode); 107 if (IS_ERR(inode)) 108 goto out; 109 110 oi = exofs_i(inode); 111 if (l > sizeof(oi->i_data)) { 112 /* slow symlink */ 113 inode->i_op = &page_symlink_inode_operations; 114 inode_nohighmem(inode); 115 inode->i_mapping->a_ops = &exofs_aops; 116 memset(oi->i_data, 0, sizeof(oi->i_data)); 117 118 err = page_symlink(inode, symname, l); 119 if (err) 120 goto out_fail; 121 } else { 122 /* fast symlink */ 123 inode->i_op = &simple_symlink_inode_operations; 124 inode->i_link = (char *)oi->i_data; 125 memcpy(oi->i_data, symname, l); 126 inode->i_size = l-1; 127 } 128 mark_inode_dirty(inode); 129 130 err = exofs_add_nondir(dentry, inode); 131out: 132 return err; 133 134out_fail: 135 inode_dec_link_count(inode); 136 iput(inode); 137 goto out; 138} 139 140static int exofs_link(struct dentry *old_dentry, struct inode *dir, 141 struct dentry *dentry) 142{ 143 struct inode *inode = d_inode(old_dentry); 144 145 inode->i_ctime = current_time(inode); 146 inode_inc_link_count(inode); 147 ihold(inode); 148 149 return exofs_add_nondir(dentry, inode); 150} 151 152static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 153{ 154 struct inode *inode; 155 int err; 156 157 inode_inc_link_count(dir); 158 159 inode = exofs_new_inode(dir, S_IFDIR | mode); 160 err = PTR_ERR(inode); 161 if (IS_ERR(inode)) 162 goto out_dir; 163 164 inode->i_op = &exofs_dir_inode_operations; 165 inode->i_fop = &exofs_dir_operations; 166 inode->i_mapping->a_ops = &exofs_aops; 167 168 inode_inc_link_count(inode); 169 170 err = exofs_make_empty(inode, dir); 171 if (err) 172 goto out_fail; 173 174 err = exofs_add_link(dentry, inode); 175 if (err) 176 goto out_fail; 177 178 d_instantiate(dentry, inode); 179out: 180 return err; 181 182out_fail: 183 inode_dec_link_count(inode); 184 inode_dec_link_count(inode); 185 iput(inode); 186out_dir: 187 inode_dec_link_count(dir); 188 goto out; 189} 190 191static int exofs_unlink(struct inode *dir, struct dentry *dentry) 192{ 193 struct inode *inode = d_inode(dentry); 194 struct exofs_dir_entry *de; 195 struct page *page; 196 int err = -ENOENT; 197 198 de = exofs_find_entry(dir, dentry, &page); 199 if (!de) 200 goto out; 201 202 err = exofs_delete_entry(de, page); 203 if (err) 204 goto out; 205 206 inode->i_ctime = dir->i_ctime; 207 inode_dec_link_count(inode); 208 err = 0; 209out: 210 return err; 211} 212 213static int exofs_rmdir(struct inode *dir, struct dentry *dentry) 214{ 215 struct inode *inode = d_inode(dentry); 216 int err = -ENOTEMPTY; 217 218 if (exofs_empty_dir(inode)) { 219 err = exofs_unlink(dir, dentry); 220 if (!err) { 221 inode->i_size = 0; 222 inode_dec_link_count(inode); 223 inode_dec_link_count(dir); 224 } 225 } 226 return err; 227} 228 229static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry, 230 struct inode *new_dir, struct dentry *new_dentry, 231 unsigned int flags) 232{ 233 struct inode *old_inode = d_inode(old_dentry); 234 struct inode *new_inode = d_inode(new_dentry); 235 struct page *dir_page = NULL; 236 struct exofs_dir_entry *dir_de = NULL; 237 struct page *old_page; 238 struct exofs_dir_entry *old_de; 239 int err = -ENOENT; 240 241 if (flags & ~RENAME_NOREPLACE) 242 return -EINVAL; 243 244 old_de = exofs_find_entry(old_dir, old_dentry, &old_page); 245 if (!old_de) 246 goto out; 247 248 if (S_ISDIR(old_inode->i_mode)) { 249 err = -EIO; 250 dir_de = exofs_dotdot(old_inode, &dir_page); 251 if (!dir_de) 252 goto out_old; 253 } 254 255 if (new_inode) { 256 struct page *new_page; 257 struct exofs_dir_entry *new_de; 258 259 err = -ENOTEMPTY; 260 if (dir_de && !exofs_empty_dir(new_inode)) 261 goto out_dir; 262 263 err = -ENOENT; 264 new_de = exofs_find_entry(new_dir, new_dentry, &new_page); 265 if (!new_de) 266 goto out_dir; 267 err = exofs_set_link(new_dir, new_de, new_page, old_inode); 268 new_inode->i_ctime = current_time(new_inode); 269 if (dir_de) 270 drop_nlink(new_inode); 271 inode_dec_link_count(new_inode); 272 if (err) 273 goto out_dir; 274 } else { 275 err = exofs_add_link(new_dentry, old_inode); 276 if (err) 277 goto out_dir; 278 if (dir_de) 279 inode_inc_link_count(new_dir); 280 } 281 282 old_inode->i_ctime = current_time(old_inode); 283 284 exofs_delete_entry(old_de, old_page); 285 mark_inode_dirty(old_inode); 286 287 if (dir_de) { 288 err = exofs_set_link(old_inode, dir_de, dir_page, new_dir); 289 inode_dec_link_count(old_dir); 290 if (err) 291 goto out_dir; 292 } 293 return 0; 294 295 296out_dir: 297 if (dir_de) { 298 kunmap(dir_page); 299 put_page(dir_page); 300 } 301out_old: 302 kunmap(old_page); 303 put_page(old_page); 304out: 305 return err; 306} 307 308const struct inode_operations exofs_dir_inode_operations = { 309 .create = exofs_create, 310 .lookup = exofs_lookup, 311 .link = exofs_link, 312 .unlink = exofs_unlink, 313 .symlink = exofs_symlink, 314 .mkdir = exofs_mkdir, 315 .rmdir = exofs_rmdir, 316 .mknod = exofs_mknod, 317 .rename = exofs_rename, 318 .setattr = exofs_setattr, 319}; 320 321const struct inode_operations exofs_special_inode_operations = { 322 .setattr = exofs_setattr, 323};