Whamcloud - gitweb
file llobdstat.pl was initially added on branch b_devel.
[fs/lustre-release.git] / lustre / lib / 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_support.h>
33 #include <linux/obd.h>
34 #include <linux/lustre_mds.h>
35 #include <linux/lustre_lib.h>
36 #include <linux/lustre_net.h>
37
38 #ifdef OBD_CTXT_DEBUG
39 /* Debugging check only needed during development */
40 #define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
41 #define ASSERT_NOT_KERNEL_CTXT(msg) LASSERT(!segment_eq(get_fs(), get_ds()))
42 #define ASSERT_KERNEL_CTXT(msg) LASSERT(segment_eq(get_fs(), get_ds()))
43 #else
44 #define ASSERT_CTXT_MAGIC(magic) do {} while(0)
45 #define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
46 #define ASSERT_KERNEL_CTXT(msg) do {} while(0)
47 #endif
48
49 /* push / pop to root of obd store */
50 void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
51                struct obd_ucred *uc)
52 {
53         //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
54         ASSERT_CTXT_MAGIC(new_ctx->magic);
55         OBD_SET_CTXT_MAGIC(save);
56
57         /*
58         CDEBUG(D_INFO,
59                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
60                save, current, current->fs, current->fs->pwd,
61                atomic_read(&current->fs->pwd->d_count),
62                atomic_read(&current->fs->pwd->d_inode->i_count),
63                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
64                current->fs->pwdmnt,
65                atomic_read(&current->fs->pwdmnt->mnt_count));
66         */
67
68         save->fs = get_fs();
69         LASSERT(atomic_read(&current->fs->pwd->d_count));
70         LASSERT(atomic_read(&new_ctx->pwd->d_count));
71         save->pwd = dget(current->fs->pwd);
72         save->pwdmnt = mntget(current->fs->pwdmnt);
73
74         LASSERT(save->pwd);
75         LASSERT(save->pwdmnt);
76         LASSERT(new_ctx->pwd);
77         LASSERT(new_ctx->pwdmnt);
78
79         if (uc) {
80                 save->fsuid = current->fsuid;
81                 save->fsgid = current->fsgid;
82                 save->cap = current->cap_effective;
83
84                 current->fsuid = uc->ouc_fsuid;
85                 current->fsgid = uc->ouc_fsgid;
86                 current->cap_effective = uc->ouc_cap;
87                 if (uc->ouc_suppgid1 != -1)
88                         current->groups[current->ngroups++] = uc->ouc_suppgid1;
89                 if (uc->ouc_suppgid2 != -1)
90                         current->groups[current->ngroups++] = uc->ouc_suppgid2;
91         }
92         set_fs(new_ctx->fs);
93         set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
94
95         /*
96         CDEBUG(D_INFO,
97                "= push %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
98                new_ctx, current, current->fs, current->fs->pwd,
99                atomic_read(&current->fs->pwd->d_count),
100                atomic_read(&current->fs->pwd->d_inode->i_count),
101                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
102                current->fs->pwdmnt,
103                atomic_read(&current->fs->pwdmnt->mnt_count));
104         */
105 }
106
107 void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
108               struct obd_ucred *uc)
109 {
110         //printk("pc0");
111         ASSERT_CTXT_MAGIC(saved->magic);
112         //printk("pc1");
113         ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
114
115         /*
116         CDEBUG(D_INFO,
117                " = pop  %p==%p = cur %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
118                new_ctx, current, current->fs, current->fs->pwd,
119                atomic_read(&current->fs->pwd->d_count),
120                atomic_read(&current->fs->pwd->d_inode->i_count),
121                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
122                current->fs->pwdmnt,
123                atomic_read(&current->fs->pwdmnt->mnt_count));
124         */
125
126         LASSERT(current->fs->pwd == new_ctx->pwd);
127         LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
128
129         set_fs(saved->fs);
130         set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
131
132         dput(saved->pwd);
133         mntput(saved->pwdmnt);
134         if (uc) {
135                 current->fsuid = saved->fsuid;
136                 current->fsgid = saved->fsgid;
137                 current->cap_effective = saved->cap;
138
139                 if (uc->ouc_suppgid1 != -1)
140                         current->ngroups--;
141                 if (uc->ouc_suppgid2 != -1)
142                         current->ngroups--;
143         }
144
145         /*
146         CDEBUG(D_INFO,
147                "= pop  %p->%p = cur fs %p pwd %p:d%d:i%d (%*s), pwdmnt %p:%d\n",
148                saved, current, current->fs, current->fs->pwd,
149                atomic_read(&current->fs->pwd->d_count),
150                atomic_read(&current->fs->pwd->d_inode->i_count),
151                current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
152                current->fs->pwdmnt,
153                atomic_read(&current->fs->pwdmnt->mnt_count));
154         */
155 }
156
157 /* utility to make a file */
158 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
159 {
160         struct dentry *dchild;
161         int err = 0;
162         ENTRY;
163
164         ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
165         CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
166
167         dchild = lookup_one_len(name, dir, strlen(name));
168         if (IS_ERR(dchild))
169                 GOTO(out_up, dchild);
170
171         if (dchild->d_inode) {
172                 if ((dchild->d_inode->i_mode & S_IFMT) != S_IFREG)
173                         GOTO(out_err, err = -EEXIST);
174
175                 GOTO(out_up, dchild);
176         }
177
178         err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
179         if (err)
180                 GOTO(out_err, err);
181
182         RETURN(dchild);
183
184 out_err:
185         dput(dchild);
186         dchild = ERR_PTR(err);
187 out_up:
188         return dchild;
189 }
190
191 /* utility to make a directory */
192 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
193 {
194         struct dentry *dchild;
195         int err = 0;
196         ENTRY;
197
198         ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
199         CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
200         dchild = lookup_one_len(name, dir, strlen(name));
201         if (IS_ERR(dchild))
202                 GOTO(out_up, dchild);
203
204         if (dchild->d_inode) {
205                 if (!S_ISDIR(dchild->d_inode->i_mode))
206                         GOTO(out_err, err = -ENOTDIR);
207
208                 GOTO(out_up, dchild);
209         }
210
211         err = vfs_mkdir(dir->d_inode, dchild, mode);
212         if (err)
213                 GOTO(out_err, err);
214
215         RETURN(dchild);
216
217 out_err:
218         dput(dchild);
219         dchild = ERR_PTR(err);
220 out_up:
221         return dchild;
222 }
223
224 /*
225  * Read a file from within kernel context.  Prior to calling this
226  * function we should already have done a push_ctxt().
227  */
228 int lustre_fread(struct file *file, char *str, int len, loff_t *off)
229 {
230         ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
231         if (!file || !file->f_op || !file->f_op->read || !off)
232                 RETURN(-ENOSYS);
233
234         return file->f_op->read(file, str, len, off);
235 }
236
237 /*
238  * Write a file from within kernel context.  Prior to calling this
239  * function we should already have done a push_ctxt().
240  */
241 int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off)
242 {
243         ENTRY;
244         ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
245         if (!file)
246                 RETURN(-ENOENT);
247         if (!file->f_op)
248                 RETURN(-ENOSYS);
249         if (!off)
250                 RETURN(-EINVAL);
251
252         if (!file->f_op->write)
253                 RETURN(-EROFS);
254
255         RETURN(file->f_op->write(file, str, len, off));
256 }
257
258 /*
259  * Sync a file from within kernel context.  Prior to calling this
260  * function we should already have done a push_ctxt().
261  */
262 int lustre_fsync(struct file *file)
263 {
264         ENTRY;
265         ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
266         if (!file || !file->f_op || !file->f_op->fsync)
267                 RETURN(-ENOSYS);
268
269         RETURN(file->f_op->fsync(file, file->f_dentry, 0));
270 }