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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [reiserfs/] [ioctl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
3
 */
4
 
5
#include <linux/fs.h>
6
#include <linux/reiserfs_fs.h>
7
#include <linux/sched.h>
8
#include <asm/uaccess.h>
9
#include <linux/smp_lock.h>
10
#include <linux/locks.h>
11
 
12
/*
13
** reiserfs_ioctl - handler for ioctl for inode
14
** supported commands:
15
**  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
16
**                           and prevent packing file (argument arg has to be non-zero)
17
**  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
18
**  3) That's all for a while ...
19
*/
20
int reiserfs_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
21
                unsigned long arg)
22
{
23
        unsigned int flags;
24
 
25
        switch (cmd) {
26
            case REISERFS_IOC_UNPACK:
27
                if( S_ISREG( inode -> i_mode ) ) {
28
                if (arg)
29
                    return reiserfs_unpack (inode, filp);
30
                        else
31
                                return 0;
32
                } else
33
                        return -ENOTTY;
34
        /*
35
         * Following {G,S}ETFLAGS, and {G,S}ETVERSION are providing ext2
36
         * binary compatible interface (used by lsattr(1), and chattr(1)) and
37
         * are * thus conceptually similar to appropriate pieces of
38
         * fs/ext2/ioctl.c
39
         */
40
        case REISERFS_IOC_GETFLAGS:
41
                flags = inode -> u.reiserfs_i.i_attrs;
42
                i_attrs_to_sd_attrs( inode, ( __u16 * ) &flags );
43
                return put_user(flags, (int *) arg);
44
        case REISERFS_IOC_SETFLAGS: {
45
                if (IS_RDONLY(inode))
46
                        return -EROFS;
47
 
48
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
49
                        return -EPERM;
50
 
51
                if (get_user(flags, (int *) arg))
52
                        return -EFAULT;
53
 
54
                if ( ( ( flags ^ inode->u.reiserfs_i.i_attrs) & ( REISERFS_IMMUTABLE_FL | REISERFS_APPEND_FL)) &&
55
                     !capable( CAP_LINUX_IMMUTABLE ) )
56
                        return -EPERM;
57
 
58
                if( ( flags & REISERFS_NOTAIL_FL ) &&
59
                    S_ISREG( inode -> i_mode ) ) {
60
                                int result;
61
 
62
                                result = reiserfs_unpack( inode, filp );
63
                                if( result )
64
                                        return result;
65
                }
66
                sd_attrs_to_i_attrs( flags, inode );
67
                inode -> u.reiserfs_i.i_attrs = flags;
68
                inode->i_ctime = CURRENT_TIME;
69
                mark_inode_dirty(inode);
70
                return 0;
71
        }
72
        case REISERFS_IOC_GETVERSION:
73
                return put_user(inode->i_generation, (int *) arg);
74
        case REISERFS_IOC_SETVERSION:
75
                if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
76
                        return -EPERM;
77
                if (IS_RDONLY(inode))
78
                        return -EROFS;
79
                if (get_user(inode->i_generation, (int *) arg))
80
                        return -EFAULT;
81
                inode->i_ctime = CURRENT_TIME;
82
                mark_inode_dirty(inode);
83
                return 0;
84
        default:
85
                return -ENOTTY;
86
        }
87
        return 0;
88
}
89
 
90
/*
91
** reiserfs_unpack
92
** Function try to convert tail from direct item into indirect.
93
** It set up nopack attribute in the inode.u.reiserfs_i.nopack
94
*/
95
int reiserfs_unpack (struct inode * inode, struct file * filp)
96
{
97
    int retval = 0;
98
    int index ;
99
    struct page *page ;
100
    unsigned long write_from ;
101
    unsigned long blocksize = inode->i_sb->s_blocksize ;
102
 
103
    if (inode->i_size == 0) {
104
        inode->u.reiserfs_i.i_flags |= i_nopack_mask;
105
        return 0 ;
106
    }
107
    /* ioctl already done */
108
    if (inode->u.reiserfs_i.i_flags & i_nopack_mask) {
109
        return 0 ;
110
    }
111
    lock_kernel();
112
 
113
    /* we need to make sure nobody is changing the file size beneath
114
    ** us
115
    */
116
    down(&inode->i_sem) ;
117
 
118
    write_from = inode->i_size & (blocksize - 1) ;
119
    /* if we are on a block boundary, we are already unpacked.  */
120
    if ( write_from == 0) {
121
        inode->u.reiserfs_i.i_flags |= i_nopack_mask;
122
        goto out ;
123
    }
124
 
125
    /* we unpack by finding the page with the tail, and calling
126
    ** reiserfs_prepare_write on that page.  This will force a
127
    ** reiserfs_get_block to unpack the tail for us.
128
    */
129
    index = inode->i_size >> PAGE_CACHE_SHIFT ;
130
    page = grab_cache_page(inode->i_mapping, index) ;
131
    retval = -ENOMEM;
132
    if (!page) {
133
        goto out ;
134
    }
135
    retval = reiserfs_prepare_write(NULL, page, write_from, blocksize) ;
136
    if (retval)
137
        goto out_unlock ;
138
 
139
    /* conversion can change page contents, must flush */
140
    flush_dcache_page(page) ;
141
    inode->u.reiserfs_i.i_flags |= i_nopack_mask;
142
    kunmap(page) ; /* mapped by prepare_write */
143
 
144
out_unlock:
145
    UnlockPage(page) ;
146
    page_cache_release(page) ;
147
 
148
out:
149
    up(&inode->i_sem) ;
150
    unlock_kernel();
151
    return retval;
152
}

powered by: WebSVN 2.1.0

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