xref: /kernel/linux/linux-5.10/fs/ufs/namei.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * linux/fs/ufs/namei.c
4 *
5 * Migration to usage of "page cache" on May 2006 by
6 * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
7 *
8 * Copyright (C) 1998
9 * Daniel Pirkl <daniel.pirkl@email.cz>
10 * Charles University, Faculty of Mathematics and Physics
11 *
12 *  from
13 *
14 *  linux/fs/ext2/namei.c
15 *
16 * Copyright (C) 1992, 1993, 1994, 1995
17 * Remy Card (card@masi.ibp.fr)
18 * Laboratoire MASI - Institut Blaise Pascal
19 * Universite Pierre et Marie Curie (Paris VI)
20 *
21 *  from
22 *
23 *  linux/fs/minix/namei.c
24 *
25 *  Copyright (C) 1991, 1992  Linus Torvalds
26 *
27 *  Big-endian to little-endian byte-swapping/bitmaps by
28 *        David S. Miller (davem@caip.rutgers.edu), 1995
29 */
30
31#include <linux/time.h>
32#include <linux/fs.h>
33
34#include "ufs_fs.h"
35#include "ufs.h"
36#include "util.h"
37
38static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
39{
40	int err = ufs_add_link(dentry, inode);
41	if (!err) {
42		d_instantiate_new(dentry, inode);
43		return 0;
44	}
45	inode_dec_link_count(inode);
46	discard_new_inode(inode);
47	return err;
48}
49
50static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
51{
52	struct inode * inode = NULL;
53	ino_t ino;
54
55	if (dentry->d_name.len > UFS_MAXNAMLEN)
56		return ERR_PTR(-ENAMETOOLONG);
57
58	ino = ufs_inode_by_name(dir, &dentry->d_name);
59	if (ino)
60		inode = ufs_iget(dir->i_sb, ino);
61	return d_splice_alias(inode, dentry);
62}
63
64/*
65 * By the time this is called, we already have created
66 * the directory cache entry for the new file, but it
67 * is so far negative - it has no inode.
68 *
69 * If the create succeeds, we fill in the inode information
70 * with d_instantiate().
71 */
72static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode,
73		bool excl)
74{
75	struct inode *inode;
76
77	inode = ufs_new_inode(dir, mode);
78	if (IS_ERR(inode))
79		return PTR_ERR(inode);
80
81	inode->i_op = &ufs_file_inode_operations;
82	inode->i_fop = &ufs_file_operations;
83	inode->i_mapping->a_ops = &ufs_aops;
84	mark_inode_dirty(inode);
85	return ufs_add_nondir(dentry, inode);
86}
87
88static int ufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
89{
90	struct inode *inode;
91	int err;
92
93	if (!old_valid_dev(rdev))
94		return -EINVAL;
95
96	inode = ufs_new_inode(dir, mode);
97	err = PTR_ERR(inode);
98	if (!IS_ERR(inode)) {
99		init_special_inode(inode, mode, rdev);
100		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
101		mark_inode_dirty(inode);
102		err = ufs_add_nondir(dentry, inode);
103	}
104	return err;
105}
106
107static int ufs_symlink (struct inode * dir, struct dentry * dentry,
108	const char * symname)
109{
110	struct super_block * sb = dir->i_sb;
111	int err;
112	unsigned l = strlen(symname)+1;
113	struct inode * inode;
114
115	if (l > sb->s_blocksize)
116		return -ENAMETOOLONG;
117
118	inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
119	err = PTR_ERR(inode);
120	if (IS_ERR(inode))
121		return err;
122
123	if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
124		/* slow symlink */
125		inode->i_op = &page_symlink_inode_operations;
126		inode_nohighmem(inode);
127		inode->i_mapping->a_ops = &ufs_aops;
128		err = page_symlink(inode, symname, l);
129		if (err)
130			goto out_fail;
131	} else {
132		/* fast symlink */
133		inode->i_op = &simple_symlink_inode_operations;
134		inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
135		memcpy(inode->i_link, symname, l);
136		inode->i_size = l-1;
137	}
138	mark_inode_dirty(inode);
139
140	return ufs_add_nondir(dentry, inode);
141
142out_fail:
143	inode_dec_link_count(inode);
144	discard_new_inode(inode);
145	return err;
146}
147
148static int ufs_link (struct dentry * old_dentry, struct inode * dir,
149	struct dentry *dentry)
150{
151	struct inode *inode = d_inode(old_dentry);
152	int error;
153
154	inode->i_ctime = current_time(inode);
155	inode_inc_link_count(inode);
156	ihold(inode);
157
158	error = ufs_add_link(dentry, inode);
159	if (error) {
160		inode_dec_link_count(inode);
161		iput(inode);
162	} else
163		d_instantiate(dentry, inode);
164	return error;
165}
166
167static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
168{
169	struct inode * inode;
170	int err;
171
172	inode_inc_link_count(dir);
173
174	inode = ufs_new_inode(dir, S_IFDIR|mode);
175	err = PTR_ERR(inode);
176	if (IS_ERR(inode))
177		goto out_dir;
178
179	inode->i_op = &ufs_dir_inode_operations;
180	inode->i_fop = &ufs_dir_operations;
181	inode->i_mapping->a_ops = &ufs_aops;
182
183	inode_inc_link_count(inode);
184
185	err = ufs_make_empty(inode, dir);
186	if (err)
187		goto out_fail;
188
189	err = ufs_add_link(dentry, inode);
190	if (err)
191		goto out_fail;
192
193	d_instantiate_new(dentry, inode);
194	return 0;
195
196out_fail:
197	inode_dec_link_count(inode);
198	inode_dec_link_count(inode);
199	discard_new_inode(inode);
200out_dir:
201	inode_dec_link_count(dir);
202	return err;
203}
204
205static int ufs_unlink(struct inode *dir, struct dentry *dentry)
206{
207	struct inode * inode = d_inode(dentry);
208	struct ufs_dir_entry *de;
209	struct page *page;
210	int err = -ENOENT;
211
212	de = ufs_find_entry(dir, &dentry->d_name, &page);
213	if (!de)
214		goto out;
215
216	err = ufs_delete_entry(dir, de, page);
217	if (err)
218		goto out;
219
220	inode->i_ctime = dir->i_ctime;
221	inode_dec_link_count(inode);
222	err = 0;
223out:
224	return err;
225}
226
227static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
228{
229	struct inode * inode = d_inode(dentry);
230	int err= -ENOTEMPTY;
231
232	if (ufs_empty_dir (inode)) {
233		err = ufs_unlink(dir, dentry);
234		if (!err) {
235			inode->i_size = 0;
236			inode_dec_link_count(inode);
237			inode_dec_link_count(dir);
238		}
239	}
240	return err;
241}
242
243static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
244		      struct inode *new_dir, struct dentry *new_dentry,
245		      unsigned int flags)
246{
247	struct inode *old_inode = d_inode(old_dentry);
248	struct inode *new_inode = d_inode(new_dentry);
249	struct page *dir_page = NULL;
250	struct ufs_dir_entry * dir_de = NULL;
251	struct page *old_page;
252	struct ufs_dir_entry *old_de;
253	int err = -ENOENT;
254
255	if (flags & ~RENAME_NOREPLACE)
256		return -EINVAL;
257
258	old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
259	if (!old_de)
260		goto out;
261
262	if (S_ISDIR(old_inode->i_mode)) {
263		err = -EIO;
264		dir_de = ufs_dotdot(old_inode, &dir_page);
265		if (!dir_de)
266			goto out_old;
267	}
268
269	if (new_inode) {
270		struct page *new_page;
271		struct ufs_dir_entry *new_de;
272
273		err = -ENOTEMPTY;
274		if (dir_de && !ufs_empty_dir(new_inode))
275			goto out_dir;
276
277		err = -ENOENT;
278		new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
279		if (!new_de)
280			goto out_dir;
281		ufs_set_link(new_dir, new_de, new_page, old_inode, 1);
282		new_inode->i_ctime = current_time(new_inode);
283		if (dir_de)
284			drop_nlink(new_inode);
285		inode_dec_link_count(new_inode);
286	} else {
287		err = ufs_add_link(new_dentry, old_inode);
288		if (err)
289			goto out_dir;
290		if (dir_de)
291			inode_inc_link_count(new_dir);
292	}
293
294	/*
295	 * Like most other Unix systems, set the ctime for inodes on a
296 	 * rename.
297	 */
298	old_inode->i_ctime = current_time(old_inode);
299
300	ufs_delete_entry(old_dir, old_de, old_page);
301	mark_inode_dirty(old_inode);
302
303	if (dir_de) {
304		if (old_dir != new_dir)
305			ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0);
306		else {
307			kunmap(dir_page);
308			put_page(dir_page);
309		}
310		inode_dec_link_count(old_dir);
311	}
312	return 0;
313
314
315out_dir:
316	if (dir_de) {
317		kunmap(dir_page);
318		put_page(dir_page);
319	}
320out_old:
321	kunmap(old_page);
322	put_page(old_page);
323out:
324	return err;
325}
326
327const struct inode_operations ufs_dir_inode_operations = {
328	.create		= ufs_create,
329	.lookup		= ufs_lookup,
330	.link		= ufs_link,
331	.unlink		= ufs_unlink,
332	.symlink	= ufs_symlink,
333	.mkdir		= ufs_mkdir,
334	.rmdir		= ufs_rmdir,
335	.mknod		= ufs_mknod,
336	.rename		= ufs_rename,
337};
338