1 /* 2 * linux/fs/minix/namei.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 #include "minix.h" 8 9 static inline void inc_count(struct inode *inode) 10 { 11 inode->i_nlink++; 12 mark_inode_dirty(inode); 13 } 14 15 static inline void dec_count(struct inode *inode) 16 { 17 inode->i_nlink--; 18 mark_inode_dirty(inode); 19 } 20 21 static int add_nondir(struct dentry *dentry, struct inode *inode) 22 { 23 int err = minix_add_link(dentry, inode); 24 if (!err) { 25 d_instantiate(dentry, inode); 26 return 0; 27 } 28 dec_count(inode); 29 iput(inode); 30 return err; 31 } 32 33 static int minix_hash(struct dentry *dentry, struct qstr *qstr) 34 { 35 unsigned long hash; 36 int i; 37 const unsigned char *name; 38 39 i = minix_sb(dentry->d_inode->i_sb)->s_namelen; 40 if (i >= qstr->len) 41 return 0; 42 /* Truncate the name in place, avoids having to define a compare 43 function. */ 44 qstr->len = i; 45 name = qstr->name; 46 hash = init_name_hash(); 47 while (i--) 48 hash = partial_name_hash(*name++, hash); 49 qstr->hash = end_name_hash(hash); 50 return 0; 51 } 52 53 struct dentry_operations minix_dentry_operations = { 54 .d_hash = minix_hash, 55 }; 56 57 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) 58 { 59 struct inode * inode = NULL; 60 ino_t ino; 61 62 dentry->d_op = dir->i_sb->s_root->d_op; 63 64 if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen) 65 return ERR_PTR(-ENAMETOOLONG); 66 67 ino = minix_inode_by_name(dentry); 68 if (ino) { 69 inode = iget(dir->i_sb, ino); 70 71 if (!inode) 72 return ERR_PTR(-EACCES); 73 } 74 d_add(dentry, inode); 75 return NULL; 76 } 77 78 static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) 79 { 80 int error; 81 struct inode *inode; 82 83 if (!old_valid_dev(rdev)) 84 return -EINVAL; 85 86 inode = minix_new_inode(dir, &error); 87 88 if (inode) { 89 inode->i_mode = mode; 90 minix_set_inode(inode, rdev); 91 mark_inode_dirty(inode); 92 error = add_nondir(dentry, inode); 93 } 94 return error; 95 } 96 97 static int minix_create(struct inode * dir, struct dentry *dentry, int mode, 98 struct nameidata *nd) 99 { 100 return minix_mknod(dir, dentry, mode, 0); 101 } 102 103 static int minix_symlink(struct inode * dir, struct dentry *dentry, 104 const char * symname) 105 { 106 int err = -ENAMETOOLONG; 107 int i = strlen(symname)+1; 108 struct inode * inode; 109 110 if (i > dir->i_sb->s_blocksize) 111 goto out; 112 113 inode = minix_new_inode(dir, &err); 114 if (!inode) 115 goto out; 116 117 inode->i_mode = S_IFLNK | 0777; 118 minix_set_inode(inode, 0); 119 err = page_symlink(inode, symname, i); 120 if (err) 121 goto out_fail; 122 123 err = add_nondir(dentry, inode); 124 out: 125 return err; 126 127 out_fail: 128 dec_count(inode); 129 iput(inode); 130 goto out; 131 } 132 133 static int minix_link(struct dentry * old_dentry, struct inode * dir, 134 struct dentry *dentry) 135 { 136 struct inode *inode = old_dentry->d_inode; 137 138 if (inode->i_nlink >= minix_sb(inode->i_sb)->s_link_max) 139 return -EMLINK; 140 141 inode->i_ctime = CURRENT_TIME_SEC; 142 inc_count(inode); 143 atomic_inc(&inode->i_count); 144 return add_nondir(dentry, inode); 145 } 146 147 static int minix_mkdir(struct inode * dir, struct dentry *dentry, int mode) 148 { 149 struct inode * inode; 150 int err = -EMLINK; 151 152 if (dir->i_nlink >= minix_sb(dir->i_sb)->s_link_max) 153 goto out; 154 155 inc_count(dir); 156 157 inode = minix_new_inode(dir, &err); 158 if (!inode) 159 goto out_dir; 160 161 inode->i_mode = S_IFDIR | mode; 162 if (dir->i_mode & S_ISGID) 163 inode->i_mode |= S_ISGID; 164 minix_set_inode(inode, 0); 165 166 inc_count(inode); 167 168 err = minix_make_empty(inode, dir); 169 if (err) 170 goto out_fail; 171 172 err = minix_add_link(dentry, inode); 173 if (err) 174 goto out_fail; 175 176 d_instantiate(dentry, inode); 177 out: 178 return err; 179 180 out_fail: 181 dec_count(inode); 182 dec_count(inode); 183 iput(inode); 184 out_dir: 185 dec_count(dir); 186 goto out; 187 } 188 189 static int minix_unlink(struct inode * dir, struct dentry *dentry) 190 { 191 int err = -ENOENT; 192 struct inode * inode = dentry->d_inode; 193 struct page * page; 194 struct minix_dir_entry * de; 195 196 de = minix_find_entry(dentry, &page); 197 if (!de) 198 goto end_unlink; 199 200 err = minix_delete_entry(de, page); 201 if (err) 202 goto end_unlink; 203 204 inode->i_ctime = dir->i_ctime; 205 dec_count(inode); 206 end_unlink: 207 return err; 208 } 209 210 static int minix_rmdir(struct inode * dir, struct dentry *dentry) 211 { 212 struct inode * inode = dentry->d_inode; 213 int err = -ENOTEMPTY; 214 215 if (minix_empty_dir(inode)) { 216 err = minix_unlink(dir, dentry); 217 if (!err) { 218 dec_count(dir); 219 dec_count(inode); 220 } 221 } 222 return err; 223 } 224 225 static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, 226 struct inode * new_dir, struct dentry *new_dentry) 227 { 228 struct minix_sb_info * info = minix_sb(old_dir->i_sb); 229 struct inode * old_inode = old_dentry->d_inode; 230 struct inode * new_inode = new_dentry->d_inode; 231 struct page * dir_page = NULL; 232 struct minix_dir_entry * dir_de = NULL; 233 struct page * old_page; 234 struct minix_dir_entry * old_de; 235 int err = -ENOENT; 236 237 old_de = minix_find_entry(old_dentry, &old_page); 238 if (!old_de) 239 goto out; 240 241 if (S_ISDIR(old_inode->i_mode)) { 242 err = -EIO; 243 dir_de = minix_dotdot(old_inode, &dir_page); 244 if (!dir_de) 245 goto out_old; 246 } 247 248 if (new_inode) { 249 struct page * new_page; 250 struct minix_dir_entry * new_de; 251 252 err = -ENOTEMPTY; 253 if (dir_de && !minix_empty_dir(new_inode)) 254 goto out_dir; 255 256 err = -ENOENT; 257 new_de = minix_find_entry(new_dentry, &new_page); 258 if (!new_de) 259 goto out_dir; 260 inc_count(old_inode); 261 minix_set_link(new_de, new_page, old_inode); 262 new_inode->i_ctime = CURRENT_TIME_SEC; 263 if (dir_de) 264 new_inode->i_nlink--; 265 dec_count(new_inode); 266 } else { 267 if (dir_de) { 268 err = -EMLINK; 269 if (new_dir->i_nlink >= info->s_link_max) 270 goto out_dir; 271 } 272 inc_count(old_inode); 273 err = minix_add_link(new_dentry, old_inode); 274 if (err) { 275 dec_count(old_inode); 276 goto out_dir; 277 } 278 if (dir_de) 279 inc_count(new_dir); 280 } 281 282 minix_delete_entry(old_de, old_page); 283 dec_count(old_inode); 284 285 if (dir_de) { 286 minix_set_link(dir_de, dir_page, new_dir); 287 dec_count(old_dir); 288 } 289 return 0; 290 291 out_dir: 292 if (dir_de) { 293 kunmap(dir_page); 294 page_cache_release(dir_page); 295 } 296 out_old: 297 kunmap(old_page); 298 page_cache_release(old_page); 299 out: 300 return err; 301 } 302 303 /* 304 * directories can handle most operations... 305 */ 306 struct inode_operations minix_dir_inode_operations = { 307 .create = minix_create, 308 .lookup = minix_lookup, 309 .link = minix_link, 310 .unlink = minix_unlink, 311 .symlink = minix_symlink, 312 .mkdir = minix_mkdir, 313 .rmdir = minix_rmdir, 314 .mknod = minix_mknod, 315 .rename = minix_rename, 316 .getattr = minix_getattr, 317 }; 318