Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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};