Whamcloud - gitweb
merge b_devel into HEAD, which will become 0.7.3
[fs/lustre-release.git] / lustre / obdclass / simple.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002, 2003 Cluster File Systems, Inc.
5  *  Author: Peter Braam <braam@clusterfs.com>
6  *  Aurhot: Andreas Dilger <adilger@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define EXPORT_SYMTAB
25
26 #include <linux/version.h>
27 #include <linux/fs.h>
28 #include <asm/unistd.h>
29
30 #define DEBUG_SUBSYSTEM S_FILTER
31
32 #include <linux/obd.h>
33 #include <linux/lustre_lib.h>
34
35 /* Debugging check only needed during development */
36 #ifdef OBD_CTXT_DEBUG
37 # define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
38 # define ASSERT_NOT_KERNEL_CTXT(msg) LASSERT(!segment_eq(get_fs(), get_ds()))
39 # define ASSERT_KERNEL_CTXT(msg) LASSERT(segment_eq(get_fs(), get_ds()))
40 #else
41 # define ASSERT_CTXT_MAGIC(magic) do {} while(0)
42 # define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
43 # define ASSERT_KERNEL_CTXT(msg) do {} while(0)
44 #endif
45
46 /* push / pop to root of obd store */
47 void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
48                struct obd_ucred *uc)
49 {
50         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
51         ASSERT_CTXT_MAGIC(new_ctx->magic);
52         OBD_SET_CTXT_MAGIC(save);
53
54         /*
55         CDEBUG(D_INFO,
56                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
57                save, current, current->fs, current->fs->pwd,
58                atomic_read(&current->fs->pwd->d_count),
59                atomic_read(&current->fs->pwd->d_inode->i_count),
60                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
61                current->fs->pwdmnt,
62                atomic_read(&current->fs->pwdmnt->mnt_count));
63         */
64
65         save->fs = get_fs();
66         LASSERT(atomic_read(&current->fs->pwd->d_count));
67         LASSERT(atomic_read(&new_ctx->pwd->d_count));
68         save->pwd = dget(current->fs->pwd);
69         save->pwdmnt = mntget(current->fs->pwdmnt);
70         save->ngroups = current->ngroups;
71
72         LASSERT(save->pwd);
73         LASSERT(save->pwdmnt);
74         LASSERT(new_ctx->pwd);
75         LASSERT(new_ctx->pwdmnt);
76
77         if (uc) {
78                 save->ouc.ouc_fsuid = current->fsuid;
79                 save->ouc.ouc_fsgid = current->fsgid;
80                 save->ouc.ouc_cap = current->cap_effective;
81                 save->ouc.ouc_suppgid1 = current->groups[0];
82                 save->ouc.ouc_suppgid2 = current->groups[1];
83
84                 current->fsuid = uc->ouc_fsuid;
85                 current->fsgid = uc->ouc_fsgid;
86                 current->cap_effective = uc->ouc_cap;
87                 current->ngroups = 0;
88
89                 if (uc->ouc_suppgid1 != -1)
90                         current->groups[current->ngroups++] = uc->ouc_suppgid1;
91                 if (uc->ouc_suppgid2 != -1)
92                         current->groups[current->ngroups++] = uc->ouc_suppgid2;
93         }
94         set_fs(new_ctx->fs);
95         set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
96
97         /*
98         CDEBUG(D_INFO,
99                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
100                new_ctx, current, current->fs, current->fs->pwd,
101                atomic_read(&current->fs->pwd->d_count),
102                atomic_read(&current->fs->pwd->d_inode->i_count),
103                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
104                current->fs->pwdmnt,
105                atomic_read(&current->fs->pwdmnt->mnt_count));
106         */
107 }
108 EXPORT_SYMBOL(push_ctxt);
109
110 void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
111               struct obd_ucred *uc)
112 {
113         //printk("pc0");
114         ASSERT_CTXT_MAGIC(saved->magic);
115         //printk("pc1");
116         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
117
118         /*
119         CDEBUG(D_INFO,
120                " = pop  %p==%p = cur %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
121                new_ctx, current, current->fs, current->fs->pwd,
122                atomic_read(&current->fs->pwd->d_count),
123                atomic_read(&current->fs->pwd->d_inode->i_count),
124                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
125                current->fs->pwdmnt,
126                atomic_read(&current->fs->pwdmnt->mnt_count));
127         */
128
129         LASSERT(current->fs->pwd == new_ctx->pwd);
130         LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
131
132         set_fs(saved->fs);
133         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
134
135         dput(saved->pwd);
136         mntput(saved->pwdmnt);
137         if (uc) {
138                 current->fsuid = saved->ouc.ouc_fsuid;
139                 current->fsgid = saved->ouc.ouc_fsgid;
140                 current->cap_effective = saved->ouc.ouc_cap;
141                 current->ngroups = saved->ngroups;
142                 current->groups[0] = saved->ouc.ouc_suppgid1;
143                 current->groups[1] = saved->ouc.ouc_suppgid2;
144         }
145
146         /*
147         CDEBUG(D_INFO,
148                "= pop  %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
149                saved, current, current->fs, current->fs->pwd,
150                atomic_read(&current->fs->pwd->d_count),
151                atomic_read(&current->fs->pwd->d_inode->i_count),
152                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
153                current->fs->pwdmnt,
154                atomic_read(&current->fs->pwdmnt->mnt_count));
155         */
156 }
157 EXPORT_SYMBOL(pop_ctxt);
158
159 /* utility to make a file */
160 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
161 {
162         struct dentry *dchild;
163         int err = 0;
164         ENTRY;
165
166         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
167         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
168
169         dchild = ll_lookup_one_len(name, dir, strlen(name));
170         if (IS_ERR(dchild))
171                 GOTO(out_up, dchild);
172
173         if (dchild->d_inode) {
174                 if (!S_ISREG(dchild->d_inode->i_mode))
175                         GOTO(out_err, err = -EEXIST);
176
177                 GOTO(out_up, dchild);
178         }
179
180         err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
181         if (err)
182                 GOTO(out_err, err);
183
184         RETURN(dchild);
185
186 out_err:
187         dput(dchild);
188         dchild = ERR_PTR(err);
189 out_up:
190         return dchild;
191 }
192 EXPORT_SYMBOL(simple_mknod);
193
194 /* utility to make a directory */
195 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
196 {
197         struct dentry *dchild;
198         int err = 0;
199         ENTRY;
200
201         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
202         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
203         dchild = ll_lookup_one_len(name, dir, strlen(name));
204         if (IS_ERR(dchild))
205                 GOTO(out_up, dchild);
206
207         if (dchild->d_inode) {
208                 if (!S_ISDIR(dchild->d_inode->i_mode))
209                         GOTO(out_err, err = -ENOTDIR);
210
211                 GOTO(out_up, dchild);
212         }
213
214         err = vfs_mkdir(dir->d_inode, dchild, mode);
215         if (err)
216                 GOTO(out_err, err);
217
218         RETURN(dchild);
219
220 out_err:
221         dput(dchild);
222         dchild = ERR_PTR(err);
223 out_up:
224         return dchild;
225 }
226 EXPORT_SYMBOL(simple_mkdir);
227
228 /*
229  * Read a file from within kernel context.  Prior to calling this
230  * function we should already have done a push_ctxt().
231  */
232 int lustre_fread(struct file *file, void *buf, int len, loff_t *off)
233 {
234         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
235         if (!file || !file->f_op || !file->f_op->read || !off)
236                 RETURN(-ENOSYS);
237
238         return file->f_op->read(file, buf, len, off);
239 }
240 EXPORT_SYMBOL(lustre_fread);
241
242 /*
243  * Write a file from within kernel context.  Prior to calling this
244  * function we should already have done a push_ctxt().
245  */
246 int lustre_fwrite(struct file *file, const void *buf, int len, loff_t *off)
247 {
248         ENTRY;
249         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
250         if (!file)
251                 RETURN(-ENOENT);
252         if (!file->f_op)
253                 RETURN(-ENOSYS);
254         if (!off)
255                 RETURN(-EINVAL);
256
257         if (!file->f_op->write)
258                 RETURN(-EROFS);
259
260         RETURN(file->f_op->write(file, buf, len, off));
261 }
262 EXPORT_SYMBOL(lustre_fwrite);
263
264 /*
265  * Sync a file from within kernel context.  Prior to calling this
266  * function we should already have done a push_ctxt().
267  */
268 int lustre_fsync(struct file *file)
269 {
270         ENTRY;
271         ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
272         if (!file || !file->f_op || !file->f_op->fsync)
273                 RETURN(-ENOSYS);
274
275         RETURN(file->f_op->fsync(file, file->f_dentry, 0));
276 }
277 EXPORT_SYMBOL(lustre_fsync);