OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [fs/] [autofs/] [root.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/* -*- linux-c -*- --------------------------------------------------------- *
2
 *
3
 * linux/fs/autofs/root.c
4
 *
5
 *  Copyright 1997 Transmeta Corporation -- All Rights Reserved
6
 *
7
 * This file is part of the Linux kernel and is made available under
8
 * the terms of the GNU General Public License, version 2, or at your
9
 * option, any later version, incorporated herein by reference.
10
 *
11
 * ------------------------------------------------------------------------- */
12
 
13
#include <linux/errno.h>
14
#include <linux/stat.h>
15
#include <linux/param.h>
16
#include "autofs_i.h"
17
 
18
static int autofs_root_readdir(struct inode *,struct file *,void *,filldir_t);
19
static int autofs_root_lookup(struct inode *,const char *,int,struct inode **);
20
static int autofs_root_symlink(struct inode *,const char *,int,const char *);
21
static int autofs_root_unlink(struct inode *,const char *,int);
22
static int autofs_root_rmdir(struct inode *,const char *,int);
23
static int autofs_root_mkdir(struct inode *,const char *,int,int);
24
static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
25
 
26
static struct file_operations autofs_root_operations = {
27
        NULL,                   /* lseek */
28
        NULL,                   /* read */
29
        NULL,                   /* write */
30
        autofs_root_readdir,    /* readdir */
31
        NULL,                   /* select */
32
        autofs_root_ioctl,      /* ioctl */
33
        NULL,                   /* mmap */
34
        NULL,                   /* open */
35
        NULL,                   /* release */
36
        NULL                    /* fsync */
37
};
38
 
39
struct inode_operations autofs_root_inode_operations = {
40
        &autofs_root_operations, /* file operations */
41
        NULL,                   /* create */
42
        autofs_root_lookup,     /* lookup */
43
        NULL,                   /* link */
44
        autofs_root_unlink,     /* unlink */
45
        autofs_root_symlink,    /* symlink */
46
        autofs_root_mkdir,      /* mkdir */
47
        autofs_root_rmdir,      /* rmdir */
48
        NULL,                   /* mknod */
49
        NULL,                   /* rename */
50
        NULL,                   /* readlink */
51
        NULL,                   /* follow_link */
52
        NULL,                   /* readpage */
53
        NULL,                   /* writepage */
54
        NULL,                   /* bmap */
55
        NULL,                   /* truncate */
56
        NULL                    /* permission */
57
};
58
 
59
static int autofs_root_readdir(struct inode *inode, struct file *filp,
60
                               void *dirent, filldir_t filldir)
61
{
62
        struct autofs_dir_ent *ent;
63
        struct autofs_dirhash *dirhash;
64
        off_t onr, nr;
65
 
66
        if (!inode || !S_ISDIR(inode->i_mode))
67
                return -ENOTDIR;
68
 
69
        dirhash = &((struct autofs_sb_info *)inode->i_sb->u.generic_sbp)->dirhash;
70
        nr = filp->f_pos;
71
 
72
        switch(nr)
73
        {
74
        case 0:
75
                if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
76
                        return 0;
77
                filp->f_pos = ++nr;
78
                /* fall through */
79
        case 1:
80
                if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
81
                        return 0;
82
                filp->f_pos = ++nr;
83
                /* fall through */
84
        default:
85
                while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr) ) {
86
                        if (filldir(dirent,ent->name,ent->len,onr,ent->ino) < 0)
87
                                return 0;
88
                        filp->f_pos = nr;
89
                }
90
                break;
91
        }
92
 
93
        return 0;
94
}
95
 
96
static int autofs_root_lookup(struct inode *dir, const char *name, int len,
97
                              struct inode **result)
98
{
99
        struct autofs_sb_info *sbi;
100
        struct autofs_dir_ent *ent;
101
        struct inode *res;
102
        autofs_hash_t hash;
103
        int status, oz_mode;
104
 
105
        DPRINTK(("autofs_root_lookup: name = "));
106
        autofs_say(name,len);
107
 
108
        *result = NULL;
109
        if (!dir)
110
                return -ENOENT;
111
 
112
        if (len > NAME_MAX)
113
                return -ENOENT;
114
 
115
        if (!S_ISDIR(dir->i_mode)) {
116
                iput(dir);
117
                return -ENOTDIR;
118
        }
119
 
120
        /* Handle special cases: . and ..; since this is a root directory,
121
           they both point to the inode itself */
122
        *result = dir;
123
        if (!len)
124
                return 0;
125
        if (name[0] == '.') {
126
                if (len == 1)
127
                        return 0;
128
                if (name[1] == '.' && len == 2)
129
                        return 0;
130
        }
131
 
132
        *result = res = NULL;
133
        sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
134
 
135
        hash = autofs_hash(name,len);
136
 
137
        oz_mode = autofs_oz_mode(sbi);
138
        DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", current->pid, current->pgrp, sbi->catatonic, oz_mode));
139
 
140
        do {
141
                while ( !(ent = autofs_hash_lookup(&sbi->dirhash,hash,name,len)) ) {
142
                        DPRINTK(("lookup failed, pid = %u, pgrp = %u\n", current->pid, current->pgrp));
143
 
144
                        if ( oz_mode ) {
145
                                iput(dir);
146
                                return -ENOENT;
147
                        } else {
148
                                status = autofs_wait(sbi,hash,name,len);
149
                                DPRINTK(("autofs_wait returned %d\n", status));
150
                                if ( status ) {
151
                                        iput(dir);
152
                                        return status;
153
                                }
154
                        }
155
                }
156
 
157
                DPRINTK(("lookup successful, inode = %08x\n", (unsigned int)ent->ino));
158
 
159
                if (!(res = iget(dir->i_sb,ent->ino))) {
160
                        printk("autofs: iget returned null!\n");
161
                        iput(dir);
162
                        return -EACCES;
163
                }
164
 
165
                if ( !oz_mode && S_ISDIR(res->i_mode) && res->i_sb == dir->i_sb ) {
166
                        /* Not a mount point yet, call 1-800-DAEMON */
167
                        DPRINTK(("autofs: waiting on non-mountpoint dir, inode = %lu, pid = %u, pgrp = %u\n", res->i_ino, current->pid, current->pgrp));
168
                        iput(res);
169
                        res = NULL;
170
                        status = autofs_wait(sbi,hash,name,len);
171
                        if ( status ) {
172
                                iput(dir);
173
                                return status;
174
                        }
175
                }
176
        } while(!res);
177
        autofs_update_usage(&sbi->dirhash,ent);
178
 
179
        *result = res;
180
        iput(dir);
181
        return 0;
182
}
183
 
184
static int autofs_root_symlink(struct inode *dir, const char *name, int len, const char *symname)
185
{
186
        struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
187
        struct autofs_dirhash *dh = &sbi->dirhash;
188
        autofs_hash_t hash = autofs_hash(name,len);
189
        struct autofs_dir_ent *ent;
190
        unsigned int n;
191
        int slsize;
192
        struct autofs_symlink *sl;
193
 
194
        DPRINTK(("autofs_root_symlink: %s <- ", symname));
195
        autofs_say(name,len);
196
 
197
        if ( !autofs_oz_mode(sbi) ) {
198
                iput(dir);
199
                return -EPERM;
200
        }
201
        if ( len > NAME_MAX)
202
                return -ENAMETOOLONG;
203
 
204
        if ( autofs_hash_lookup(dh,hash,name,len) ) {
205
                iput(dir);
206
                return -EEXIST;
207
        }
208
        n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
209
        if ( n >= AUTOFS_MAX_SYMLINKS ) {
210
                iput(dir);
211
                return -ENOSPC;
212
        }
213
        set_bit(n,sbi->symlink_bitmap);
214
        sl = &sbi->symlink[n];
215
        sl->len = strlen(symname);
216
        sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
217
        if ( !sl->data ) {
218
                clear_bit(n,sbi->symlink_bitmap);
219
                iput(dir);
220
                return -ENOSPC;
221
        }
222
        ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
223
        if ( !ent ) {
224
                kfree(sl->data);
225
                clear_bit(n,sbi->symlink_bitmap);
226
                iput(dir);
227
                return -ENOSPC;
228
        }
229
        ent->name = kmalloc(len, GFP_KERNEL);
230
        if ( !ent->name ) {
231
                kfree(sl->data);
232
                kfree(ent);
233
                clear_bit(n,sbi->symlink_bitmap);
234
                iput(dir);
235
                return -ENOSPC;
236
        }
237
        memcpy(sl->data,symname,slsize);
238
        sl->mtime = CURRENT_TIME;
239
 
240
        ent->ino = AUTOFS_FIRST_SYMLINK + n;
241
        ent->hash = hash;
242
        memcpy(ent->name,name,ent->len = len);
243
 
244
        autofs_hash_insert(dh,ent);
245
        iput(dir);
246
 
247
        return 0;
248
}
249
 
250
static int autofs_root_unlink(struct inode *dir, const char *name, int len)
251
{
252
        struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
253
        struct autofs_dirhash *dh = &sbi->dirhash;
254
        autofs_hash_t hash = autofs_hash(name,len);
255
        struct autofs_dir_ent *ent;
256
        unsigned int n;
257
 
258
        iput(dir);              /* Nothing below can sleep */
259
 
260
        if ( !autofs_oz_mode(sbi) )
261
                return -EPERM;
262
 
263
        if(len > NAME_MAX)
264
                return -ENAMETOOLONG;
265
 
266
        ent = autofs_hash_lookup(dh,hash,name,len);
267
        if ( !ent )
268
                return -ENOENT;
269
 
270
        n = ent->ino - AUTOFS_FIRST_SYMLINK;
271
        if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap) )
272
                return -EINVAL; /* Not a symlink inode, can't unlink */
273
 
274
        autofs_hash_delete(ent);
275
        clear_bit(n,sbi->symlink_bitmap);
276
        kfree(sbi->symlink[n].data);
277
 
278
        return 0;
279
}
280
 
281
static int autofs_root_rmdir(struct inode *dir, const char *name, int len)
282
{
283
        struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
284
        struct autofs_dirhash *dh = &sbi->dirhash;
285
        autofs_hash_t hash = autofs_hash(name,len);
286
        struct autofs_dir_ent *ent;
287
 
288
        if ( !autofs_oz_mode(sbi) ) {
289
                iput(dir);
290
                return -EPERM;
291
        }
292
        ent = autofs_hash_lookup(dh,hash,name,len);
293
        if ( !ent ) {
294
                iput(dir);
295
                return -ENOENT;
296
        }
297
        if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) {
298
                iput(dir);
299
                return -ENOTDIR; /* Not a directory */
300
        }
301
        autofs_hash_delete(ent);
302
        dir->i_nlink--;
303
        iput(dir);
304
 
305
        return 0;
306
}
307
 
308
static int autofs_root_mkdir(struct inode *dir, const char *name, int len, int mode)
309
{
310
        struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
311
        struct autofs_dirhash *dh = &sbi->dirhash;
312
        autofs_hash_t hash = autofs_hash(name,len);
313
        struct autofs_dir_ent *ent;
314
 
315
        if ( !autofs_oz_mode(sbi) ) {
316
                iput(dir);
317
                return -EPERM;
318
        }
319
        ent = autofs_hash_lookup(dh,hash,name,len);
320
        if ( ent ) {
321
                iput(dir);
322
                return -EEXIST;
323
        }
324
        if ( sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO ) {
325
                printk("autofs: Out of inode numbers -- what the heck did you do??\n");
326
                iput(dir);
327
                return -ENOSPC;
328
        }
329
        ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
330
        if ( !ent ) {
331
                iput(dir);
332
                return -ENOSPC;
333
        }
334
        ent->name = kmalloc(len, GFP_KERNEL);
335
        if ( !ent->name ) {
336
                kfree(ent);
337
                iput(dir);
338
                return -ENOSPC;
339
        }
340
        ent->hash = hash;
341
        memcpy(ent->name, name, ent->len = len);
342
        ent->ino = sbi->next_dir_ino++;
343
        autofs_hash_insert(dh,ent);
344
        dir->i_nlink++;
345
        iput(dir);
346
 
347
        return 0;
348
}
349
 
350
/* Get/set timeout ioctl() operation */
351
static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
352
                                         unsigned long *p)
353
{
354
        int rv;
355
        unsigned long ntimeout;
356
 
357
#if LINUX_VERSION_CODE < kver(2,1,0)
358
        if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(unsigned long))) )
359
                return rv;
360
        ntimeout = get_user(p);
361
        put_user(sbi->exp_timeout/HZ, p);
362
#else
363
        if ( (rv = get_user(ntimeout, p)) ||
364
             (rv = put_user(sbi->exp_timeout/HZ, p)) )
365
                return rv;
366
#endif
367
 
368
        if ( ntimeout > ULONG_MAX/HZ )
369
                sbi->exp_timeout = 0;
370
        else
371
                sbi->exp_timeout = ntimeout * HZ;
372
 
373
        return 0;
374
}
375
 
376
/* Return protocol version */
377
static inline int autofs_get_protover(int *p)
378
{
379
#if LINUX_VERSION_CODE < kver(2,1,0)
380
        int rv;
381
        if ( (rv = verify_area(VERIFY_WRITE, p, sizeof(int))) )
382
                return rv;
383
        put_user(AUTOFS_PROTO_VERSION, p);
384
        return 0;
385
#else
386
        return put_user(AUTOFS_PROTO_VERSION, p);
387
#endif
388
}
389
 
390
/* Perform an expiry operation */
391
static inline int autofs_expire_run(struct autofs_sb_info *sbi,
392
                                    struct autofs_packet_expire *pkt_p)
393
{
394
        struct autofs_dir_ent *ent;
395
        struct autofs_packet_expire pkt;
396
        struct autofs_dirhash *dh = &(sbi->dirhash);
397
 
398
        memset(&pkt,0,sizeof pkt);
399
 
400
        pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
401
        pkt.hdr.type = autofs_ptype_expire;
402
 
403
        if ( !sbi->exp_timeout ||
404
             !(ent = autofs_expire(dh,sbi->exp_timeout)) )
405
                return -EAGAIN;
406
 
407
        pkt.len = ent->len;
408
        memcpy(pkt.name, ent->name, pkt.len);
409
        pkt.name[pkt.len] = '\0';
410
 
411
        if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
412
                return -EFAULT;
413
 
414
        autofs_update_usage(dh,ent);
415
 
416
        return 0;
417
}
418
 
419
/*
420
 * ioctl()'s on the root directory is the chief method for the daemon to
421
 * generate kernel reactions
422
 */
423
static int autofs_root_ioctl(struct inode *inode, struct file *filp,
424
                             unsigned int cmd, unsigned long arg)
425
{
426
        struct autofs_sb_info *sbi =
427
                (struct autofs_sb_info *)inode->i_sb->u.generic_sbp;
428
 
429
        DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp));
430
 
431
        if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
432
             _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
433
                return -ENOTTY;
434
 
435
        if ( !autofs_oz_mode(sbi) && !fsuser() )
436
                return -EPERM;
437
 
438
        switch(cmd) {
439
        case AUTOFS_IOC_READY:  /* Wait queue: go ahead and retry */
440
                return autofs_wait_release(sbi,arg,0);
441
        case AUTOFS_IOC_FAIL:   /* Wait queue: fail with ENOENT */
442
                return autofs_wait_release(sbi,arg,-ENOENT);
443
        case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
444
                autofs_catatonic_mode(sbi);
445
                return 0;
446
        case AUTOFS_IOC_PROTOVER: /* Get protocol version */
447
                return autofs_get_protover((int *)arg);
448
        case AUTOFS_IOC_SETTIMEOUT:
449
                return autofs_get_set_timeout(sbi,(unsigned long *)arg);
450
        case AUTOFS_IOC_EXPIRE:
451
                return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg);
452
        default:
453
                return -ENOSYS;
454
        }
455
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.