~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/configfs/inode.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c; c-basic-offset: 8; -*-
 
2
 * vim: noexpandtab sw=8 ts=8 sts=0:
 
3
 *
 
4
 * inode.c - basic inode and dentry operations.
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public
 
17
 * License along with this program; if not, write to the
 
18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
19
 * Boston, MA 021110-1307, USA.
 
20
 *
 
21
 * Based on sysfs:
 
22
 *      sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
 
23
 *
 
24
 * configfs Copyright (C) 2005 Oracle.  All rights reserved.
 
25
 *
 
26
 * Please see Documentation/filesystems/configfs/configfs.txt for more
 
27
 * information.
 
28
 */
 
29
 
 
30
#undef DEBUG
 
31
 
 
32
#include <linux/pagemap.h>
 
33
#include <linux/namei.h>
 
34
#include <linux/backing-dev.h>
 
35
#include <linux/capability.h>
 
36
#include <linux/sched.h>
 
37
#include <linux/lockdep.h>
 
38
#include <linux/slab.h>
 
39
 
 
40
#include <linux/configfs.h>
 
41
#include "configfs_internal.h"
 
42
 
 
43
#ifdef CONFIG_LOCKDEP
 
44
static struct lock_class_key default_group_class[MAX_LOCK_DEPTH];
 
45
#endif
 
46
 
 
47
extern struct super_block * configfs_sb;
 
48
 
 
49
static const struct address_space_operations configfs_aops = {
 
50
        .readpage       = simple_readpage,
 
51
        .write_begin    = simple_write_begin,
 
52
        .write_end      = simple_write_end,
 
53
};
 
54
 
 
55
static struct backing_dev_info configfs_backing_dev_info = {
 
56
        .name           = "configfs",
 
57
        .ra_pages       = 0,    /* No readahead */
 
58
        .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
 
59
};
 
60
 
 
61
static const struct inode_operations configfs_inode_operations ={
 
62
        .setattr        = configfs_setattr,
 
63
};
 
64
 
 
65
int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 
66
{
 
67
        struct inode * inode = dentry->d_inode;
 
68
        struct configfs_dirent * sd = dentry->d_fsdata;
 
69
        struct iattr * sd_iattr;
 
70
        unsigned int ia_valid = iattr->ia_valid;
 
71
        int error;
 
72
 
 
73
        if (!sd)
 
74
                return -EINVAL;
 
75
 
 
76
        sd_iattr = sd->s_iattr;
 
77
        if (!sd_iattr) {
 
78
                /* setting attributes for the first time, allocate now */
 
79
                sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
 
80
                if (!sd_iattr)
 
81
                        return -ENOMEM;
 
82
                /* assign default attributes */
 
83
                sd_iattr->ia_mode = sd->s_mode;
 
84
                sd_iattr->ia_uid = 0;
 
85
                sd_iattr->ia_gid = 0;
 
86
                sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
 
87
                sd->s_iattr = sd_iattr;
 
88
        }
 
89
        /* attributes were changed atleast once in past */
 
90
 
 
91
        error = simple_setattr(dentry, iattr);
 
92
        if (error)
 
93
                return error;
 
94
 
 
95
        if (ia_valid & ATTR_UID)
 
96
                sd_iattr->ia_uid = iattr->ia_uid;
 
97
        if (ia_valid & ATTR_GID)
 
98
                sd_iattr->ia_gid = iattr->ia_gid;
 
99
        if (ia_valid & ATTR_ATIME)
 
100
                sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
 
101
                                                inode->i_sb->s_time_gran);
 
102
        if (ia_valid & ATTR_MTIME)
 
103
                sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
 
104
                                                inode->i_sb->s_time_gran);
 
105
        if (ia_valid & ATTR_CTIME)
 
106
                sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
 
107
                                                inode->i_sb->s_time_gran);
 
108
        if (ia_valid & ATTR_MODE) {
 
109
                umode_t mode = iattr->ia_mode;
 
110
 
 
111
                if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
 
112
                        mode &= ~S_ISGID;
 
113
                sd_iattr->ia_mode = sd->s_mode = mode;
 
114
        }
 
115
 
 
116
        return error;
 
117
}
 
118
 
 
119
static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 
120
{
 
121
        inode->i_mode = mode;
 
122
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
123
}
 
124
 
 
125
static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
 
126
{
 
127
        inode->i_mode = iattr->ia_mode;
 
128
        inode->i_uid = iattr->ia_uid;
 
129
        inode->i_gid = iattr->ia_gid;
 
130
        inode->i_atime = iattr->ia_atime;
 
131
        inode->i_mtime = iattr->ia_mtime;
 
132
        inode->i_ctime = iattr->ia_ctime;
 
133
}
 
134
 
 
135
struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
 
136
{
 
137
        struct inode * inode = new_inode(configfs_sb);
 
138
        if (inode) {
 
139
                inode->i_ino = get_next_ino();
 
140
                inode->i_mapping->a_ops = &configfs_aops;
 
141
                inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
 
142
                inode->i_op = &configfs_inode_operations;
 
143
 
 
144
                if (sd->s_iattr) {
 
145
                        /* sysfs_dirent has non-default attributes
 
146
                         * get them for the new inode from persistent copy
 
147
                         * in sysfs_dirent
 
148
                         */
 
149
                        set_inode_attr(inode, sd->s_iattr);
 
150
                } else
 
151
                        set_default_inode_attr(inode, mode);
 
152
        }
 
153
        return inode;
 
154
}
 
155
 
 
156
#ifdef CONFIG_LOCKDEP
 
157
 
 
158
static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
 
159
                                          struct inode *inode)
 
160
{
 
161
        int depth = sd->s_depth;
 
162
 
 
163
        if (depth > 0) {
 
164
                if (depth <= ARRAY_SIZE(default_group_class)) {
 
165
                        lockdep_set_class(&inode->i_mutex,
 
166
                                          &default_group_class[depth - 1]);
 
167
                } else {
 
168
                        /*
 
169
                         * In practice the maximum level of locking depth is
 
170
                         * already reached. Just inform about possible reasons.
 
171
                         */
 
172
                        printk(KERN_INFO "configfs: Too many levels of inodes"
 
173
                               " for the locking correctness validator.\n");
 
174
                        printk(KERN_INFO "Spurious warnings may appear.\n");
 
175
                }
 
176
        }
 
177
}
 
178
 
 
179
#else /* CONFIG_LOCKDEP */
 
180
 
 
181
static void configfs_set_inode_lock_class(struct configfs_dirent *sd,
 
182
                                          struct inode *inode)
 
183
{
 
184
}
 
185
 
 
186
#endif /* CONFIG_LOCKDEP */
 
187
 
 
188
int configfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
 
189
{
 
190
        int error = 0;
 
191
        struct inode * inode = NULL;
 
192
        if (dentry) {
 
193
                if (!dentry->d_inode) {
 
194
                        struct configfs_dirent *sd = dentry->d_fsdata;
 
195
                        if ((inode = configfs_new_inode(mode, sd))) {
 
196
                                if (dentry->d_parent && dentry->d_parent->d_inode) {
 
197
                                        struct inode *p_inode = dentry->d_parent->d_inode;
 
198
                                        p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
 
199
                                }
 
200
                                configfs_set_inode_lock_class(sd, inode);
 
201
                                goto Proceed;
 
202
                        }
 
203
                        else
 
204
                                error = -ENOMEM;
 
205
                } else
 
206
                        error = -EEXIST;
 
207
        } else
 
208
                error = -ENOENT;
 
209
        goto Done;
 
210
 
 
211
 Proceed:
 
212
        if (init)
 
213
                error = init(inode);
 
214
        if (!error) {
 
215
                d_instantiate(dentry, inode);
 
216
                if (S_ISDIR(mode) || S_ISLNK(mode))
 
217
                        dget(dentry);  /* pin link and directory dentries in core */
 
218
        } else
 
219
                iput(inode);
 
220
 Done:
 
221
        return error;
 
222
}
 
223
 
 
224
/*
 
225
 * Get the name for corresponding element represented by the given configfs_dirent
 
226
 */
 
227
const unsigned char * configfs_get_name(struct configfs_dirent *sd)
 
228
{
 
229
        struct configfs_attribute *attr;
 
230
 
 
231
        BUG_ON(!sd || !sd->s_element);
 
232
 
 
233
        /* These always have a dentry, so use that */
 
234
        if (sd->s_type & (CONFIGFS_DIR | CONFIGFS_ITEM_LINK))
 
235
                return sd->s_dentry->d_name.name;
 
236
 
 
237
        if (sd->s_type & CONFIGFS_ITEM_ATTR) {
 
238
                attr = sd->s_element;
 
239
                return attr->ca_name;
 
240
        }
 
241
        return NULL;
 
242
}
 
243
 
 
244
 
 
245
/*
 
246
 * Unhashes the dentry corresponding to given configfs_dirent
 
247
 * Called with parent inode's i_mutex held.
 
248
 */
 
249
void configfs_drop_dentry(struct configfs_dirent * sd, struct dentry * parent)
 
250
{
 
251
        struct dentry * dentry = sd->s_dentry;
 
252
 
 
253
        if (dentry) {
 
254
                spin_lock(&dentry->d_lock);
 
255
                if (!(d_unhashed(dentry) && dentry->d_inode)) {
 
256
                        dget_dlock(dentry);
 
257
                        __d_drop(dentry);
 
258
                        spin_unlock(&dentry->d_lock);
 
259
                        simple_unlink(parent->d_inode, dentry);
 
260
                } else
 
261
                        spin_unlock(&dentry->d_lock);
 
262
        }
 
263
}
 
264
 
 
265
void configfs_hash_and_remove(struct dentry * dir, const char * name)
 
266
{
 
267
        struct configfs_dirent * sd;
 
268
        struct configfs_dirent * parent_sd = dir->d_fsdata;
 
269
 
 
270
        if (dir->d_inode == NULL)
 
271
                /* no inode means this hasn't been made visible yet */
 
272
                return;
 
273
 
 
274
        mutex_lock(&dir->d_inode->i_mutex);
 
275
        list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
 
276
                if (!sd->s_element)
 
277
                        continue;
 
278
                if (!strcmp(configfs_get_name(sd), name)) {
 
279
                        spin_lock(&configfs_dirent_lock);
 
280
                        list_del_init(&sd->s_sibling);
 
281
                        spin_unlock(&configfs_dirent_lock);
 
282
                        configfs_drop_dentry(sd, dir);
 
283
                        configfs_put(sd);
 
284
                        break;
 
285
                }
 
286
        }
 
287
        mutex_unlock(&dir->d_inode->i_mutex);
 
288
}
 
289
 
 
290
int __init configfs_inode_init(void)
 
291
{
 
292
        return bdi_init(&configfs_backing_dev_info);
 
293
}
 
294
 
 
295
void configfs_inode_exit(void)
 
296
{
 
297
        bdi_destroy(&configfs_backing_dev_info);
 
298
}