1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * Copyright (C) 2002 Cluster File Systems, Inc.
8 * This code is issued under the GNU General Public License.
9 * See the file COPYING in this distribution
11 * by Peter Braam <braam@clusterfs.com>
12 * and Andreas Dilger <adilger@clusterfs.com>
17 #include <linux/version.h>
19 #include <asm/unistd.h>
21 #define DEBUG_SUBSYSTEM S_FILTER
23 #include <linux/obd_support.h>
24 #include <linux/obd.h>
25 #include <linux/lustre_mds.h>
26 #include <linux/lustre_lib.h>
27 #include <linux/lustre_net.h>
30 /* Debugging check only needed during development */
31 #define ASSERT_CTXT_MAGIC(magic) LASSERT((magic) == OBD_RUN_CTXT_MAGIC)
32 #define ASSERT_NOT_KERNEL_CTXT(msg) LASSERT(!segment_eq(get_fs(), get_ds()))
33 #define ASSERT_KERNEL_CTXT(msg) LASSERT(segment_eq(get_fs(), get_ds()))
35 #define ASSERT_CTXT_MAGIC(magic) do {} while(0)
36 #define ASSERT_NOT_KERNEL_CTXT(msg) do {} while(0)
37 #define ASSERT_KERNEL_CTXT(msg) do {} while(0)
40 /* push / pop to root of obd store */
41 void push_ctxt(struct obd_run_ctxt *save, struct obd_run_ctxt *new_ctx,
44 //ASSERT_NOT_KERNEL_CTXT("already in kernel context!\n");
45 ASSERT_CTXT_MAGIC(new_ctx->magic);
46 OBD_SET_CTXT_MAGIC(save);
49 CDEBUG(D_INFO, "== push %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
50 save, current, current->fs, current->fs->pwd,
51 current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
56 LASSERT(atomic_read(¤t->fs->pwd->d_count));
57 LASSERT(atomic_read(&new_ctx->pwd->d_count));
58 save->pwd = dget(current->fs->pwd);
59 save->pwdmnt = mntget(current->fs->pwdmnt);
62 LASSERT(save->pwdmnt);
63 LASSERT(new_ctx->pwd);
64 LASSERT(new_ctx->pwdmnt);
67 save->fsuid = current->fsuid;
68 save->fsgid = current->fsgid;
69 save->cap = current->cap_effective;
71 current->fsuid = uc->ouc_fsuid;
72 current->fsgid = uc->ouc_fsgid;
73 current->cap_effective = uc->ouc_cap;
76 set_fs_pwd(current->fs, new_ctx->pwdmnt, new_ctx->pwd);
79 CDEBUG(D_INFO, "== push %p==%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
80 new_ctx, current, current->fs, current->fs->pwd,
81 current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
86 void pop_ctxt(struct obd_run_ctxt *saved, struct obd_run_ctxt *new_ctx,
90 ASSERT_CTXT_MAGIC(saved->magic);
92 ASSERT_KERNEL_CTXT("popping non-kernel context!\n");
95 CDEBUG(D_INFO, " == pop %p==%p == cur %p pwd %p (%*s), pwdmnt %p\n",
96 new_ctx, current, current->fs, current->fs->pwd,
97 current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
101 LASSERT(current->fs->pwd == new_ctx->pwd);
102 LASSERT(current->fs->pwdmnt == new_ctx->pwdmnt);
107 set_fs_pwd(current->fs, saved->pwdmnt, saved->pwd);
112 mntput(saved->pwdmnt);
115 current->fsuid = saved->fsuid;
116 current->fsgid = saved->fsgid;
117 current->cap_effective = saved->cap;
121 CDEBUG(D_INFO, "== pop %p->%p == cur fs %p pwd %p (%*s), pwdmnt %p\n",
122 saved, current, current->fs, current->fs->pwd,
123 current->fs->pwd->d_name.len, current->fs->pwd->d_name.name,
124 current->fs->pwdmnt);
128 /* utility to make a file */
129 struct dentry *simple_mknod(struct dentry *dir, char *name, int mode)
131 struct dentry *dchild;
135 ASSERT_KERNEL_CTXT("kernel doing mknod outside kernel context\n");
136 CDEBUG(D_INODE, "creating file %*s\n", (int)strlen(name), name);
138 down(&dir->d_inode->i_sem);
139 dchild = lookup_one_len(name, dir, strlen(name));
141 GOTO(out_up, dchild);
143 if (dchild->d_inode) {
144 if ((dchild->d_inode->i_mode & S_IFMT) != S_IFREG)
145 GOTO(out_err, err = -EEXIST);
147 GOTO(out_up, dchild);
150 err = vfs_create(dir->d_inode, dchild, (mode & ~S_IFMT) | S_IFREG);
154 up(&dir->d_inode->i_sem);
159 dchild = ERR_PTR(err);
161 up(&dir->d_inode->i_sem);
165 /* utility to make a directory */
166 struct dentry *simple_mkdir(struct dentry *dir, char *name, int mode)
168 struct dentry *dchild;
172 ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
173 CDEBUG(D_INODE, "creating directory %*s\n", (int)strlen(name), name);
174 down(&dir->d_inode->i_sem);
175 dchild = lookup_one_len(name, dir, strlen(name));
177 GOTO(out_up, dchild);
179 if (dchild->d_inode) {
180 if (!S_ISDIR(dchild->d_inode->i_mode))
181 GOTO(out_err, err = -ENOTDIR);
183 GOTO(out_up, dchild);
186 err = vfs_mkdir(dir->d_inode, dchild, mode);
190 up(&dir->d_inode->i_sem);
195 dchild = ERR_PTR(err);
197 up(&dir->d_inode->i_sem);
202 * Read a file from within kernel context. Prior to calling this
203 * function we should already have done a push_ctxt().
205 int lustre_fread(struct file *file, char *str, int len, loff_t *off)
207 ASSERT_KERNEL_CTXT("kernel doing read outside kernel context\n");
208 if (!file || !file->f_op || !file->f_op->read || !off)
211 return file->f_op->read(file, str, len, off);
215 * Write a file from within kernel context. Prior to calling this
216 * function we should already have done a push_ctxt().
218 int lustre_fwrite(struct file *file, const char *str, int len, loff_t *off)
221 ASSERT_KERNEL_CTXT("kernel doing write outside kernel context\n");
229 if (!file->f_op->write)
232 RETURN(file->f_op->write(file, str, len, off));
236 * Sync a file from within kernel context. Prior to calling this
237 * function we should already have done a push_ctxt().
239 int lustre_fsync(struct file *file)
242 ASSERT_KERNEL_CTXT("kernel doing sync outside kernel context\n");
243 if (!file || !file->f_op || !file->f_op->fsync)
246 RETURN(file->f_op->fsync(file, file->f_dentry, 0));