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.2-rc1 321 lines 7.4 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 if (!new_valid_dev(rdev)) 84 return -EINVAL; 85 86 inode = exofs_new_inode(dir, mode); 87 err = PTR_ERR(inode); 88 if (!IS_ERR(inode)) { 89 init_special_inode(inode, inode->i_mode, rdev); 90 mark_inode_dirty(inode); 91 err = exofs_add_nondir(dentry, inode); 92 } 93 return err; 94} 95 96static int exofs_symlink(struct inode *dir, struct dentry *dentry, 97 const char *symname) 98{ 99 struct super_block *sb = dir->i_sb; 100 int err = -ENAMETOOLONG; 101 unsigned l = strlen(symname)+1; 102 struct inode *inode; 103 struct exofs_i_info *oi; 104 105 if (l > sb->s_blocksize) 106 goto out; 107 108 inode = exofs_new_inode(dir, S_IFLNK | S_IRWXUGO); 109 err = PTR_ERR(inode); 110 if (IS_ERR(inode)) 111 goto out; 112 113 oi = exofs_i(inode); 114 if (l > sizeof(oi->i_data)) { 115 /* slow symlink */ 116 inode->i_op = &page_symlink_inode_operations; 117 inode->i_mapping->a_ops = &exofs_aops; 118 memset(oi->i_data, 0, sizeof(oi->i_data)); 119 120 err = page_symlink(inode, symname, l); 121 if (err) 122 goto out_fail; 123 } else { 124 /* fast symlink */ 125 inode->i_op = &simple_symlink_inode_operations; 126 inode->i_link = (char *)oi->i_data; 127 memcpy(oi->i_data, symname, l); 128 inode->i_size = l-1; 129 } 130 mark_inode_dirty(inode); 131 132 err = exofs_add_nondir(dentry, inode); 133out: 134 return err; 135 136out_fail: 137 inode_dec_link_count(inode); 138 iput(inode); 139 goto out; 140} 141 142static int exofs_link(struct dentry *old_dentry, struct inode *dir, 143 struct dentry *dentry) 144{ 145 struct inode *inode = d_inode(old_dentry); 146 147 inode->i_ctime = CURRENT_TIME; 148 inode_inc_link_count(inode); 149 ihold(inode); 150 151 return exofs_add_nondir(dentry, inode); 152} 153 154static int exofs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 155{ 156 struct inode *inode; 157 int err; 158 159 inode_inc_link_count(dir); 160 161 inode = exofs_new_inode(dir, S_IFDIR | mode); 162 err = PTR_ERR(inode); 163 if (IS_ERR(inode)) 164 goto out_dir; 165 166 inode->i_op = &exofs_dir_inode_operations; 167 inode->i_fop = &exofs_dir_operations; 168 inode->i_mapping->a_ops = &exofs_aops; 169 170 inode_inc_link_count(inode); 171 172 err = exofs_make_empty(inode, dir); 173 if (err) 174 goto out_fail; 175 176 err = exofs_add_link(dentry, inode); 177 if (err) 178 goto out_fail; 179 180 d_instantiate(dentry, inode); 181out: 182 return err; 183 184out_fail: 185 inode_dec_link_count(inode); 186 inode_dec_link_count(inode); 187 iput(inode); 188out_dir: 189 inode_dec_link_count(dir); 190 goto out; 191} 192 193static int exofs_unlink(struct inode *dir, struct dentry *dentry) 194{ 195 struct inode *inode = d_inode(dentry); 196 struct exofs_dir_entry *de; 197 struct page *page; 198 int err = -ENOENT; 199 200 de = exofs_find_entry(dir, dentry, &page); 201 if (!de) 202 goto out; 203 204 err = exofs_delete_entry(de, page); 205 if (err) 206 goto out; 207 208 inode->i_ctime = dir->i_ctime; 209 inode_dec_link_count(inode); 210 err = 0; 211out: 212 return err; 213} 214 215static int exofs_rmdir(struct inode *dir, struct dentry *dentry) 216{ 217 struct inode *inode = d_inode(dentry); 218 int err = -ENOTEMPTY; 219 220 if (exofs_empty_dir(inode)) { 221 err = exofs_unlink(dir, dentry); 222 if (!err) { 223 inode->i_size = 0; 224 inode_dec_link_count(inode); 225 inode_dec_link_count(dir); 226 } 227 } 228 return err; 229} 230 231static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry, 232 struct inode *new_dir, struct dentry *new_dentry) 233{ 234 struct inode *old_inode = d_inode(old_dentry); 235 struct inode *new_inode = d_inode(new_dentry); 236 struct page *dir_page = NULL; 237 struct exofs_dir_entry *dir_de = NULL; 238 struct page *old_page; 239 struct exofs_dir_entry *old_de; 240 int err = -ENOENT; 241 242 old_de = exofs_find_entry(old_dir, old_dentry, &old_page); 243 if (!old_de) 244 goto out; 245 246 if (S_ISDIR(old_inode->i_mode)) { 247 err = -EIO; 248 dir_de = exofs_dotdot(old_inode, &dir_page); 249 if (!dir_de) 250 goto out_old; 251 } 252 253 if (new_inode) { 254 struct page *new_page; 255 struct exofs_dir_entry *new_de; 256 257 err = -ENOTEMPTY; 258 if (dir_de && !exofs_empty_dir(new_inode)) 259 goto out_dir; 260 261 err = -ENOENT; 262 new_de = exofs_find_entry(new_dir, new_dentry, &new_page); 263 if (!new_de) 264 goto out_dir; 265 err = exofs_set_link(new_dir, new_de, new_page, old_inode); 266 new_inode->i_ctime = CURRENT_TIME; 267 if (dir_de) 268 drop_nlink(new_inode); 269 inode_dec_link_count(new_inode); 270 if (err) 271 goto out_dir; 272 } else { 273 err = exofs_add_link(new_dentry, old_inode); 274 if (err) 275 goto out_dir; 276 if (dir_de) 277 inode_inc_link_count(new_dir); 278 } 279 280 old_inode->i_ctime = CURRENT_TIME; 281 282 exofs_delete_entry(old_de, old_page); 283 mark_inode_dirty(old_inode); 284 285 if (dir_de) { 286 err = exofs_set_link(old_inode, dir_de, dir_page, new_dir); 287 inode_dec_link_count(old_dir); 288 if (err) 289 goto out_dir; 290 } 291 return 0; 292 293 294out_dir: 295 if (dir_de) { 296 kunmap(dir_page); 297 page_cache_release(dir_page); 298 } 299out_old: 300 kunmap(old_page); 301 page_cache_release(old_page); 302out: 303 return err; 304} 305 306const struct inode_operations exofs_dir_inode_operations = { 307 .create = exofs_create, 308 .lookup = exofs_lookup, 309 .link = exofs_link, 310 .unlink = exofs_unlink, 311 .symlink = exofs_symlink, 312 .mkdir = exofs_mkdir, 313 .rmdir = exofs_rmdir, 314 .mknod = exofs_mknod, 315 .rename = exofs_rename, 316 .setattr = exofs_setattr, 317}; 318 319const struct inode_operations exofs_special_inode_operations = { 320 .setattr = exofs_setattr, 321};