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 <bharrosh@panasas.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				   struct nameidata *nd)
 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, int mode,
 63			 struct nameidata *nd)
 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, int 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 = &exofs_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 = &exofs_fast_symlink_inode_operations;
126		memcpy(oi->i_data, symname, l);
127		inode->i_size = l-1;
128	}
129	mark_inode_dirty(inode);
130
131	err = exofs_add_nondir(dentry, inode);
132out:
133	return err;
134
135out_fail:
136	inode_dec_link_count(inode);
137	iput(inode);
138	goto out;
139}
140
141static int exofs_link(struct dentry *old_dentry, struct inode *dir,
142		struct dentry *dentry)
143{
144	struct inode *inode = old_dentry->d_inode;
145
146	if (inode->i_nlink >= EXOFS_LINK_MAX)
147		return -EMLINK;
148
149	inode->i_ctime = CURRENT_TIME;
150	inode_inc_link_count(inode);
151	ihold(inode);
152
153	return exofs_add_nondir(dentry, inode);
154}
155
156static int exofs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
157{
158	struct inode *inode;
159	int err = -EMLINK;
160
161	if (dir->i_nlink >= EXOFS_LINK_MAX)
162		goto out;
163
164	inode_inc_link_count(dir);
165
166	inode = exofs_new_inode(dir, S_IFDIR | mode);
167	err = PTR_ERR(inode);
168	if (IS_ERR(inode))
169		goto out_dir;
170
171	inode->i_op = &exofs_dir_inode_operations;
172	inode->i_fop = &exofs_dir_operations;
173	inode->i_mapping->a_ops = &exofs_aops;
174
175	inode_inc_link_count(inode);
176
177	err = exofs_make_empty(inode, dir);
178	if (err)
179		goto out_fail;
180
181	err = exofs_add_link(dentry, inode);
182	if (err)
183		goto out_fail;
184
185	d_instantiate(dentry, inode);
186out:
187	return err;
188
189out_fail:
190	inode_dec_link_count(inode);
191	inode_dec_link_count(inode);
192	iput(inode);
193out_dir:
194	inode_dec_link_count(dir);
195	goto out;
196}
197
198static int exofs_unlink(struct inode *dir, struct dentry *dentry)
199{
200	struct inode *inode = dentry->d_inode;
201	struct exofs_dir_entry *de;
202	struct page *page;
203	int err = -ENOENT;
204
205	de = exofs_find_entry(dir, dentry, &page);
206	if (!de)
207		goto out;
208
209	err = exofs_delete_entry(de, page);
210	if (err)
211		goto out;
212
213	inode->i_ctime = dir->i_ctime;
214	inode_dec_link_count(inode);
215	err = 0;
216out:
217	return err;
218}
219
220static int exofs_rmdir(struct inode *dir, struct dentry *dentry)
221{
222	struct inode *inode = dentry->d_inode;
223	int err = -ENOTEMPTY;
224
225	if (exofs_empty_dir(inode)) {
226		err = exofs_unlink(dir, dentry);
227		if (!err) {
228			inode->i_size = 0;
229			inode_dec_link_count(inode);
230			inode_dec_link_count(dir);
231		}
232	}
233	return err;
234}
235
236static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry,
237		struct inode *new_dir, struct dentry *new_dentry)
238{
239	struct inode *old_inode = old_dentry->d_inode;
240	struct inode *new_inode = new_dentry->d_inode;
241	struct page *dir_page = NULL;
242	struct exofs_dir_entry *dir_de = NULL;
243	struct page *old_page;
244	struct exofs_dir_entry *old_de;
245	int err = -ENOENT;
246
247	old_de = exofs_find_entry(old_dir, old_dentry, &old_page);
248	if (!old_de)
249		goto out;
250
251	if (S_ISDIR(old_inode->i_mode)) {
252		err = -EIO;
253		dir_de = exofs_dotdot(old_inode, &dir_page);
254		if (!dir_de)
255			goto out_old;
256	}
257
258	if (new_inode) {
259		struct page *new_page;
260		struct exofs_dir_entry *new_de;
261
262		err = -ENOTEMPTY;
263		if (dir_de && !exofs_empty_dir(new_inode))
264			goto out_dir;
265
266		err = -ENOENT;
267		new_de = exofs_find_entry(new_dir, new_dentry, &new_page);
268		if (!new_de)
269			goto out_dir;
270		err = exofs_set_link(new_dir, new_de, new_page, old_inode);
271		new_inode->i_ctime = CURRENT_TIME;
272		if (dir_de)
273			drop_nlink(new_inode);
274		inode_dec_link_count(new_inode);
275		if (err)
276			goto out_dir;
277	} else {
278		if (dir_de) {
279			err = -EMLINK;
280			if (new_dir->i_nlink >= EXOFS_LINK_MAX)
281				goto out_dir;
282		}
283		err = exofs_add_link(new_dentry, old_inode);
284		if (err)
285			goto out_dir;
286		if (dir_de)
287			inode_inc_link_count(new_dir);
288	}
289
290	old_inode->i_ctime = CURRENT_TIME;
291
292	exofs_delete_entry(old_de, old_page);
293	mark_inode_dirty(old_inode);
294
295	if (dir_de) {
296		err = exofs_set_link(old_inode, dir_de, dir_page, new_dir);
297		inode_dec_link_count(old_dir);
298		if (err)
299			goto out_dir;
300	}
301	return 0;
302
303
304out_dir:
305	if (dir_de) {
306		kunmap(dir_page);
307		page_cache_release(dir_page);
308	}
309out_old:
310	kunmap(old_page);
311	page_cache_release(old_page);
312out:
313	return err;
314}
315
316const struct inode_operations exofs_dir_inode_operations = {
317	.create 	= exofs_create,
318	.lookup 	= exofs_lookup,
319	.link   	= exofs_link,
320	.unlink 	= exofs_unlink,
321	.symlink	= exofs_symlink,
322	.mkdir  	= exofs_mkdir,
323	.rmdir  	= exofs_rmdir,
324	.mknod  	= exofs_mknod,
325	.rename 	= exofs_rename,
326	.setattr	= exofs_setattr,
327};
328
329const struct inode_operations exofs_special_inode_operations = {
330	.setattr	= exofs_setattr,
331};