]> git.ipfire.org Git - people/ms/linux.git/blame - fs/minix/namei.c
Merge tag 'for-5.19-rc7-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[people/ms/linux.git] / fs / minix / namei.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * linux/fs/minix/namei.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
7
8#include "minix.h"
9
1da177e4
LT
10static int add_nondir(struct dentry *dentry, struct inode *inode)
11{
12 int err = minix_add_link(dentry, inode);
13 if (!err) {
14 d_instantiate(dentry, inode);
15 return 0;
16 }
78ec7b69 17 inode_dec_link_count(inode);
1da177e4
LT
18 iput(inode);
19 return err;
20}
21
00cd8dd3 22static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
1da177e4
LT
23{
24 struct inode * inode = NULL;
25 ino_t ino;
26
1da177e4
LT
27 if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen)
28 return ERR_PTR(-ENAMETOOLONG);
29
30 ino = minix_inode_by_name(dentry);
b0149516 31 if (ino)
a90a0880 32 inode = minix_iget(dir->i_sb, ino);
b0149516 33 return d_splice_alias(inode, dentry);
1da177e4
LT
34}
35
549c7297
CB
36static int minix_mknod(struct user_namespace *mnt_userns, struct inode *dir,
37 struct dentry *dentry, umode_t mode, dev_t rdev)
1da177e4
LT
38{
39 int error;
40 struct inode *inode;
41
42 if (!old_valid_dev(rdev))
43 return -EINVAL;
44
9eed1fb7 45 inode = minix_new_inode(dir, mode, &error);
1da177e4
LT
46
47 if (inode) {
1da177e4
LT
48 minix_set_inode(inode, rdev);
49 mark_inode_dirty(inode);
50 error = add_nondir(dentry, inode);
51 }
52 return error;
53}
54
549c7297
CB
55static int minix_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
56 struct dentry *dentry, umode_t mode)
60545d0d
AV
57{
58 int error;
59 struct inode *inode = minix_new_inode(dir, mode, &error);
60 if (inode) {
61 minix_set_inode(inode, 0);
62 mark_inode_dirty(inode);
63 d_tmpfile(dentry, inode);
64 }
65 return error;
66}
67
549c7297
CB
68static int minix_create(struct user_namespace *mnt_userns, struct inode *dir,
69 struct dentry *dentry, umode_t mode, bool excl)
1da177e4 70{
549c7297 71 return minix_mknod(mnt_userns, dir, dentry, mode, 0);
1da177e4
LT
72}
73
549c7297
CB
74static int minix_symlink(struct user_namespace *mnt_userns, struct inode *dir,
75 struct dentry *dentry, const char *symname)
1da177e4
LT
76{
77 int err = -ENAMETOOLONG;
78 int i = strlen(symname)+1;
79 struct inode * inode;
80
81 if (i > dir->i_sb->s_blocksize)
82 goto out;
83
9eed1fb7 84 inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
1da177e4
LT
85 if (!inode)
86 goto out;
87
1da177e4
LT
88 minix_set_inode(inode, 0);
89 err = page_symlink(inode, symname, i);
90 if (err)
91 goto out_fail;
92
93 err = add_nondir(dentry, inode);
94out:
95 return err;
96
97out_fail:
78ec7b69 98 inode_dec_link_count(inode);
1da177e4
LT
99 iput(inode);
100 goto out;
101}
102
103static int minix_link(struct dentry * old_dentry, struct inode * dir,
104 struct dentry *dentry)
105{
2b0143b5 106 struct inode *inode = d_inode(old_dentry);
1da177e4 107
02027d42 108 inode->i_ctime = current_time(inode);
78ec7b69 109 inode_inc_link_count(inode);
7de9c6ee 110 ihold(inode);
1da177e4
LT
111 return add_nondir(dentry, inode);
112}
113
549c7297
CB
114static int minix_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
115 struct dentry *dentry, umode_t mode)
1da177e4
LT
116{
117 struct inode * inode;
8de52778 118 int err;
1da177e4 119
78ec7b69 120 inode_inc_link_count(dir);
1da177e4 121
eee743fd 122 inode = minix_new_inode(dir, S_IFDIR | mode, &err);
1da177e4
LT
123 if (!inode)
124 goto out_dir;
125
1da177e4
LT
126 minix_set_inode(inode, 0);
127
78ec7b69 128 inode_inc_link_count(inode);
1da177e4
LT
129
130 err = minix_make_empty(inode, dir);
131 if (err)
132 goto out_fail;
133
134 err = minix_add_link(dentry, inode);
135 if (err)
136 goto out_fail;
137
138 d_instantiate(dentry, inode);
139out:
140 return err;
141
142out_fail:
78ec7b69
AD
143 inode_dec_link_count(inode);
144 inode_dec_link_count(inode);
1da177e4
LT
145 iput(inode);
146out_dir:
78ec7b69 147 inode_dec_link_count(dir);
1da177e4
LT
148 goto out;
149}
150
151static int minix_unlink(struct inode * dir, struct dentry *dentry)
152{
153 int err = -ENOENT;
2b0143b5 154 struct inode * inode = d_inode(dentry);
1da177e4
LT
155 struct page * page;
156 struct minix_dir_entry * de;
157
158 de = minix_find_entry(dentry, &page);
159 if (!de)
160 goto end_unlink;
161
162 err = minix_delete_entry(de, page);
163 if (err)
164 goto end_unlink;
165
166 inode->i_ctime = dir->i_ctime;
78ec7b69 167 inode_dec_link_count(inode);
1da177e4
LT
168end_unlink:
169 return err;
170}
171
172static int minix_rmdir(struct inode * dir, struct dentry *dentry)
173{
2b0143b5 174 struct inode * inode = d_inode(dentry);
1da177e4
LT
175 int err = -ENOTEMPTY;
176
177 if (minix_empty_dir(inode)) {
178 err = minix_unlink(dir, dentry);
179 if (!err) {
78ec7b69
AD
180 inode_dec_link_count(dir);
181 inode_dec_link_count(inode);
1da177e4
LT
182 }
183 }
184 return err;
185}
186
549c7297
CB
187static int minix_rename(struct user_namespace *mnt_userns,
188 struct inode *old_dir, struct dentry *old_dentry,
189 struct inode *new_dir, struct dentry *new_dentry,
f03b8ad8 190 unsigned int flags)
1da177e4 191{
2b0143b5
DH
192 struct inode * old_inode = d_inode(old_dentry);
193 struct inode * new_inode = d_inode(new_dentry);
1da177e4
LT
194 struct page * dir_page = NULL;
195 struct minix_dir_entry * dir_de = NULL;
196 struct page * old_page;
197 struct minix_dir_entry * old_de;
198 int err = -ENOENT;
199
f03b8ad8
MS
200 if (flags & ~RENAME_NOREPLACE)
201 return -EINVAL;
202
1da177e4
LT
203 old_de = minix_find_entry(old_dentry, &old_page);
204 if (!old_de)
205 goto out;
206
207 if (S_ISDIR(old_inode->i_mode)) {
208 err = -EIO;
209 dir_de = minix_dotdot(old_inode, &dir_page);
210 if (!dir_de)
211 goto out_old;
212 }
213
214 if (new_inode) {
215 struct page * new_page;
216 struct minix_dir_entry * new_de;
217
218 err = -ENOTEMPTY;
219 if (dir_de && !minix_empty_dir(new_inode))
220 goto out_dir;
221
222 err = -ENOENT;
223 new_de = minix_find_entry(new_dentry, &new_page);
224 if (!new_de)
225 goto out_dir;
1da177e4 226 minix_set_link(new_de, new_page, old_inode);
02027d42 227 new_inode->i_ctime = current_time(new_inode);
1da177e4 228 if (dir_de)
9a53c3a7 229 drop_nlink(new_inode);
78ec7b69 230 inode_dec_link_count(new_inode);
1da177e4 231 } else {
1da177e4 232 err = minix_add_link(new_dentry, old_inode);
6f88049c 233 if (err)
1da177e4 234 goto out_dir;
1da177e4 235 if (dir_de)
78ec7b69 236 inode_inc_link_count(new_dir);
1da177e4
LT
237 }
238
239 minix_delete_entry(old_de, old_page);
6f88049c 240 mark_inode_dirty(old_inode);
1da177e4
LT
241
242 if (dir_de) {
243 minix_set_link(dir_de, dir_page, new_dir);
78ec7b69 244 inode_dec_link_count(old_dir);
1da177e4
LT
245 }
246 return 0;
247
248out_dir:
249 if (dir_de) {
250 kunmap(dir_page);
09cbfeaf 251 put_page(dir_page);
1da177e4
LT
252 }
253out_old:
254 kunmap(old_page);
09cbfeaf 255 put_page(old_page);
1da177e4
LT
256out:
257 return err;
258}
259
260/*
261 * directories can handle most operations...
262 */
92e1d5be 263const struct inode_operations minix_dir_inode_operations = {
1da177e4
LT
264 .create = minix_create,
265 .lookup = minix_lookup,
266 .link = minix_link,
267 .unlink = minix_unlink,
268 .symlink = minix_symlink,
269 .mkdir = minix_mkdir,
270 .rmdir = minix_rmdir,
271 .mknod = minix_mknod,
272 .rename = minix_rename,
273 .getattr = minix_getattr,
60545d0d 274 .tmpfile = minix_tmpfile,
1da177e4 275};