diff options
Diffstat (limited to 'fs/orangefs/orangefs-cache.c')
-rw-r--r-- | fs/orangefs/orangefs-cache.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c new file mode 100644 index 000000000000..900a2e38e11b --- /dev/null +++ b/fs/orangefs/orangefs-cache.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * (C) 2001 Clemson University and The University of Chicago | ||
3 | * | ||
4 | * See COPYING in top-level directory. | ||
5 | */ | ||
6 | |||
7 | #include "protocol.h" | ||
8 | #include "orangefs-kernel.h" | ||
9 | |||
10 | /* tags assigned to kernel upcall operations */ | ||
11 | static __u64 next_tag_value; | ||
12 | static DEFINE_SPINLOCK(next_tag_value_lock); | ||
13 | |||
14 | /* the orangefs memory caches */ | ||
15 | |||
16 | /* a cache for orangefs upcall/downcall operations */ | ||
17 | static struct kmem_cache *op_cache; | ||
18 | |||
19 | int op_cache_initialize(void) | ||
20 | { | ||
21 | op_cache = kmem_cache_create("orangefs_op_cache", | ||
22 | sizeof(struct orangefs_kernel_op_s), | ||
23 | 0, | ||
24 | ORANGEFS_CACHE_CREATE_FLAGS, | ||
25 | NULL); | ||
26 | |||
27 | if (!op_cache) { | ||
28 | gossip_err("Cannot create orangefs_op_cache\n"); | ||
29 | return -ENOMEM; | ||
30 | } | ||
31 | |||
32 | /* initialize our atomic tag counter */ | ||
33 | spin_lock(&next_tag_value_lock); | ||
34 | next_tag_value = 100; | ||
35 | spin_unlock(&next_tag_value_lock); | ||
36 | return 0; | ||
37 | } | ||
38 | |||
39 | int op_cache_finalize(void) | ||
40 | { | ||
41 | kmem_cache_destroy(op_cache); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | char *get_opname_string(struct orangefs_kernel_op_s *new_op) | ||
46 | { | ||
47 | if (new_op) { | ||
48 | __s32 type = new_op->upcall.type; | ||
49 | |||
50 | if (type == ORANGEFS_VFS_OP_FILE_IO) | ||
51 | return "OP_FILE_IO"; | ||
52 | else if (type == ORANGEFS_VFS_OP_LOOKUP) | ||
53 | return "OP_LOOKUP"; | ||
54 | else if (type == ORANGEFS_VFS_OP_CREATE) | ||
55 | return "OP_CREATE"; | ||
56 | else if (type == ORANGEFS_VFS_OP_GETATTR) | ||
57 | return "OP_GETATTR"; | ||
58 | else if (type == ORANGEFS_VFS_OP_REMOVE) | ||
59 | return "OP_REMOVE"; | ||
60 | else if (type == ORANGEFS_VFS_OP_MKDIR) | ||
61 | return "OP_MKDIR"; | ||
62 | else if (type == ORANGEFS_VFS_OP_READDIR) | ||
63 | return "OP_READDIR"; | ||
64 | else if (type == ORANGEFS_VFS_OP_READDIRPLUS) | ||
65 | return "OP_READDIRPLUS"; | ||
66 | else if (type == ORANGEFS_VFS_OP_SETATTR) | ||
67 | return "OP_SETATTR"; | ||
68 | else if (type == ORANGEFS_VFS_OP_SYMLINK) | ||
69 | return "OP_SYMLINK"; | ||
70 | else if (type == ORANGEFS_VFS_OP_RENAME) | ||
71 | return "OP_RENAME"; | ||
72 | else if (type == ORANGEFS_VFS_OP_STATFS) | ||
73 | return "OP_STATFS"; | ||
74 | else if (type == ORANGEFS_VFS_OP_TRUNCATE) | ||
75 | return "OP_TRUNCATE"; | ||
76 | else if (type == ORANGEFS_VFS_OP_MMAP_RA_FLUSH) | ||
77 | return "OP_MMAP_RA_FLUSH"; | ||
78 | else if (type == ORANGEFS_VFS_OP_FS_MOUNT) | ||
79 | return "OP_FS_MOUNT"; | ||
80 | else if (type == ORANGEFS_VFS_OP_FS_UMOUNT) | ||
81 | return "OP_FS_UMOUNT"; | ||
82 | else if (type == ORANGEFS_VFS_OP_GETXATTR) | ||
83 | return "OP_GETXATTR"; | ||
84 | else if (type == ORANGEFS_VFS_OP_SETXATTR) | ||
85 | return "OP_SETXATTR"; | ||
86 | else if (type == ORANGEFS_VFS_OP_LISTXATTR) | ||
87 | return "OP_LISTXATTR"; | ||
88 | else if (type == ORANGEFS_VFS_OP_REMOVEXATTR) | ||
89 | return "OP_REMOVEXATTR"; | ||
90 | else if (type == ORANGEFS_VFS_OP_PARAM) | ||
91 | return "OP_PARAM"; | ||
92 | else if (type == ORANGEFS_VFS_OP_PERF_COUNT) | ||
93 | return "OP_PERF_COUNT"; | ||
94 | else if (type == ORANGEFS_VFS_OP_CANCEL) | ||
95 | return "OP_CANCEL"; | ||
96 | else if (type == ORANGEFS_VFS_OP_FSYNC) | ||
97 | return "OP_FSYNC"; | ||
98 | else if (type == ORANGEFS_VFS_OP_FSKEY) | ||
99 | return "OP_FSKEY"; | ||
100 | } | ||
101 | return "OP_UNKNOWN?"; | ||
102 | } | ||
103 | |||
104 | void orangefs_new_tag(struct orangefs_kernel_op_s *op) | ||
105 | { | ||
106 | spin_lock(&next_tag_value_lock); | ||
107 | op->tag = next_tag_value++; | ||
108 | if (next_tag_value == 0) | ||
109 | next_tag_value = 100; | ||
110 | spin_unlock(&next_tag_value_lock); | ||
111 | } | ||
112 | |||
113 | struct orangefs_kernel_op_s *op_alloc(__s32 type) | ||
114 | { | ||
115 | struct orangefs_kernel_op_s *new_op = NULL; | ||
116 | |||
117 | new_op = kmem_cache_zalloc(op_cache, GFP_KERNEL); | ||
118 | if (new_op) { | ||
119 | INIT_LIST_HEAD(&new_op->list); | ||
120 | spin_lock_init(&new_op->lock); | ||
121 | init_completion(&new_op->waitq); | ||
122 | |||
123 | new_op->upcall.type = ORANGEFS_VFS_OP_INVALID; | ||
124 | new_op->downcall.type = ORANGEFS_VFS_OP_INVALID; | ||
125 | new_op->downcall.status = -1; | ||
126 | |||
127 | new_op->op_state = OP_VFS_STATE_UNKNOWN; | ||
128 | |||
129 | /* initialize the op specific tag and upcall credentials */ | ||
130 | orangefs_new_tag(new_op); | ||
131 | new_op->upcall.type = type; | ||
132 | new_op->attempts = 0; | ||
133 | gossip_debug(GOSSIP_CACHE_DEBUG, | ||
134 | "Alloced OP (%p: %llu %s)\n", | ||
135 | new_op, | ||
136 | llu(new_op->tag), | ||
137 | get_opname_string(new_op)); | ||
138 | |||
139 | new_op->upcall.uid = from_kuid(current_user_ns(), | ||
140 | current_fsuid()); | ||
141 | |||
142 | new_op->upcall.gid = from_kgid(current_user_ns(), | ||
143 | current_fsgid()); | ||
144 | } else { | ||
145 | gossip_err("op_alloc: kmem_cache_zalloc failed!\n"); | ||
146 | } | ||
147 | return new_op; | ||
148 | } | ||
149 | |||
150 | void op_release(struct orangefs_kernel_op_s *orangefs_op) | ||
151 | { | ||
152 | if (orangefs_op) { | ||
153 | gossip_debug(GOSSIP_CACHE_DEBUG, | ||
154 | "Releasing OP (%p: %llu)\n", | ||
155 | orangefs_op, | ||
156 | llu(orangefs_op->tag)); | ||
157 | kmem_cache_free(op_cache, orangefs_op); | ||
158 | } else { | ||
159 | gossip_err("NULL pointer in op_release\n"); | ||
160 | } | ||
161 | } | ||