2 * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved.
4 * Portions based on Adam Richter's smalldevfs and thus
5 * Copyright 2002-2003 Yggdrasil Computing, Inc.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it would be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write the Free Software Foundation, Inc., 59
24 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
26 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
27 * Mountain View, CA 94043, or:
31 * For further information regarding this notice, see:
33 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
36 #include <linux/module.h>
37 #include <linux/kernel.h>
39 #include <linux/mount.h>
40 #include <linux/namei.h>
41 #include <linux/string.h>
42 #include <linux/slab.h>
43 #include <linux/dcache.h>
44 #include <asm/sn/hwgfs.h>
47 extern struct vfsmount *hwgfs_vfsmount;
56 char buf[strlen(*path)+1];
59 while ((slash = strchr(*path, '/')) != NULL) {
60 int len = slash - *path;
61 memcpy(buf, *path, len);
64 error = link_path_walk(buf, nd);
68 nd->dentry = lookup_create(nd, is_dir);
69 nd->flags |= LOOKUP_PARENT;
70 if (unlikely(IS_ERR(nd->dentry)))
71 return PTR_ERR(nd->dentry);
73 if (!nd->dentry->d_inode)
74 error = vfs_mkdir(nd->dentry->d_parent->d_inode,
77 up(&nd->dentry->d_parent->d_inode->i_sem);
87 /* On success, returns with parent_inode->i_sem taken. */
93 struct inode **parent_inode,
94 struct dentry **dentry)
100 dir = hwgfs_vfsmount->mnt_sb->s_root;
102 memset(&nd, 0, sizeof(nd));
103 nd.flags = LOOKUP_PARENT;
104 nd.mnt = mntget(hwgfs_vfsmount);
105 nd.dentry = dget(dir);
107 error = walk_parents_mkdir(&name, &nd, is_dir);
111 error = link_path_walk(name, &nd);
115 *dentry = lookup_create(&nd, is_dir);
117 if (unlikely(IS_ERR(*dentry)))
118 return PTR_ERR(*dentry);
119 *parent_inode = (*dentry)->d_parent->d_inode;
131 len += de->d_name.len + 1; /* count the '/' */
134 return len; /* -1 because we omit the leading '/',
135 +1 because we include trailing '\0' */
144 struct dentry *hwgfs_root;
146 char *path_orig = path;
148 if (unlikely(de == NULL))
151 hwgfs_root = hwgfs_vfsmount->mnt_sb->s_root;
152 if (unlikely(de == hwgfs_root))
155 spin_lock(&dcache_lock);
156 len = path_len(de, hwgfs_root);
158 spin_unlock(&dcache_lock);
159 return -ENAMETOOLONG;
166 path -= de->d_name.len;
167 memcpy(path, de->d_name.name, de->d_name.len);
169 if (de == hwgfs_root)
174 spin_unlock(&dcache_lock);
175 BUG_ON(path != path_orig);
190 dev_t devnum = MKDEV(major, minor);
191 struct inode *parent_inode;
192 struct dentry *dentry;
195 error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
196 if (likely(!error)) {
197 error = vfs_mknod(parent_inode, dentry, mode, devnum);
198 if (likely(!error)) {
200 * Do this inside parents i_sem to avoid racing
204 dentry->d_inode->i_fop = ops;
205 dentry->d_fsdata = info;
206 up(&parent_inode->i_sem);
208 up(&parent_inode->i_sem);
223 hwgfs_handle_t *handle,
226 struct inode *parent_inode;
227 struct dentry *dentry;
230 error = hwgfs_decode(dir, name, 0, &parent_inode, &dentry);
231 if (likely(!error)) {
232 error = vfs_symlink(parent_inode, dentry, link);
233 dentry->d_fsdata = info;
236 up(&parent_inode->i_sem);
248 struct inode *parent_inode;
249 struct dentry *dentry;
252 error = hwgfs_decode(dir, name, 1, &parent_inode, &dentry);
253 if (likely(!error)) {
254 error = vfs_mkdir(parent_inode, dentry, 0755);
255 up(&parent_inode->i_sem);
257 if (unlikely(error)) {
261 dentry->d_fsdata = info;
271 struct inode *parent_inode = de->d_parent->d_inode;
273 if (S_ISDIR(de->d_inode->i_mode))
274 vfs_rmdir(parent_inode, de);
276 vfs_unlink(parent_inode, de);
279 /* XXX: this function is utterly bogus. Every use of it is racy and the
280 prototype is stupid. You have been warned. --hch. */
285 unsigned int major, /* IGNORED */
286 unsigned int minor, /* IGNORED */
287 char type, /* IGNORED */
288 int traverse_symlinks)
290 struct dentry *dentry = NULL;
296 memset(&nd, 0, sizeof(nd));
298 nd.mnt = mntget(hwgfs_vfsmount);
299 nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
300 if (traverse_symlinks)
301 nd.flags = LOOKUP_FOLLOW;
303 error = link_path_walk(name, &nd);
304 if (likely(!error)) {
306 path_release(&nd); /* stale data from here! */
316 struct dentry *parent;
318 spin_lock(&de->d_lock);
319 parent = de->d_parent;
320 spin_unlock(&de->d_lock);
330 if (unlikely(de == NULL))
343 EXPORT_SYMBOL(hwgfs_generate_path);
344 EXPORT_SYMBOL(hwgfs_register);
345 EXPORT_SYMBOL(hwgfs_unregister);
346 EXPORT_SYMBOL(hwgfs_mk_symlink);
347 EXPORT_SYMBOL(hwgfs_mk_dir);
348 EXPORT_SYMBOL(hwgfs_find_handle);
349 EXPORT_SYMBOL(hwgfs_get_parent);
350 EXPORT_SYMBOL(hwgfs_set_info);
351 EXPORT_SYMBOL(hwgfs_get_info);