00001
00014 #ifndef __KERNEL__
00015 # define __KERNEL__
00016 #endif
00017
00018
00019 #include <linux/init.h>
00020 #include <linux/kernel.h>
00021 #include <linux/module.h>
00022 #include <linux/version.h>
00023 #include <linux/fs.h>
00024 #include <linux/sched.h>
00025 #include <linux/statfs.h>
00026 #include <linux/mm.h>
00027 #include <asm/uaccess.h>
00028 #include <asm/errno.h>
00029 #include <linux/buffer_head.h>
00030 #include <linux/pagemap.h>
00031 #include <linux/proc_fs.h>
00032 #include <asm/atomic.h>
00033 #include <linux/string.h>
00034
00035
00036 #include "fsc_device.h"
00037 #include "rkfs.h"
00038 #include "parser.h"
00039
00040
00042 struct file_operations rkfs_fops = {
00043 open: rkfs_file_open,
00044 read: rkfs_file_read,
00045 readdir: rkfs_file_readdir,
00046 write: rkfs_file_write,
00047 release: rkfs_file_release,
00048 fsync: simple_sync_file,
00049 llseek: rkfs_file_llseek
00050 };
00051
00052
00065 ssize_t rkfs_file_read (struct file *filp, char __user *buf, size_t count, loff_t *ppos) {
00066 struct inode *file_inode = filp->f_dentry->d_inode;
00067 char query_string[MAX_QUERY_LENGTH + 1];
00068 char *data_pos;
00069 int block_number, block_end, curr_read_end;
00070
00071 FSPDEBUG("rkfs_file_read (*ppos = '%lu', count = '%lu')\n", (long)*ppos, (long)count);
00072
00073 if (*ppos > file_inode->i_size) {
00074 FSPDEBUG("file pos (%lu) > file size (%lu)\n", (long)*ppos, (long)file_inode->i_size);
00075 return 0;
00076 }
00077 FSPDEBUG("ppos = '%lu'\n", (long) *ppos);
00078
00079
00080 block_number = ((long) *ppos) / RKFS_BLOCKSIZE;
00081 FSPDEBUG("block_number='%d'\n", block_number);
00082
00083 block_end = (block_number + 1) * RKFS_BLOCKSIZE;
00084
00085 FSPDEBUG("block_end='%d'\n", block_end);
00086 FSPDEBUG("filesize = '%lu'\n", (long)file_inode->i_size);
00087
00088 curr_read_end = min((long)block_end, (long)(file_inode->i_size));
00089 FSPDEBUG("curr_read_end='%d'\n", curr_read_end);
00090
00091 if (*ppos + count > curr_read_end) {
00092 count = curr_read_end - *ppos;
00093 FSPDEBUG("count bigger, count = '%lu'\n", (long)count);
00094 }
00095
00096 if (count == 0) {
00097 return count;
00098 }
00099
00100 FSPDEBUG("count = '%lu' OK\n", (long)count);
00101
00102 snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 GB %lu %d", file_inode->i_ino, block_number);
00103 if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00104 return 0;
00105 }
00106 else {
00107 if (ret_command.command_nr == CMD_ER_NR) {
00108
00109 return 0;
00110 }
00111 }
00112
00113 data_pos = ret_command.data;
00114
00115 if (copy_to_user(buf, data_pos + *ppos - block_number * RKFS_BLOCKSIZE, count)) {
00116 return -EFAULT;
00117 }
00118
00119 *ppos += count;
00120 return count;
00121 }
00122
00123
00125 struct write_buffer {
00127 char data_buf[RKFS_BLOCKSIZE];
00129 char query_buf[RKFS_BLOCKSIZE + MAX_QUERY_LENGTH + 1];
00131 int query_len;
00132 } write_buffer;
00133
00134
00147 ssize_t rkfs_file_write (struct file *filp, const char __user *buf, size_t count, loff_t *ppos) {
00148 struct inode *file_inode = filp->f_dentry->d_inode;
00149 int block_number, block_end, curr_write_end, curr_block_length;
00150 char* data_pos;
00151 char* query_pos;
00152 int i;
00153 int append = 0;
00154
00155 FSPDEBUG("rkfs_file_write (*ppos = '%lu', count = '%lu')\n", (long)*ppos, (long)count);
00156
00157 FSPDEBUG("ppos = '%lu'\n", (long) *ppos);
00158
00159
00160 block_number = ((long) *ppos) / RKFS_BLOCKSIZE;
00161
00162 FSPDEBUG("block_number='%d'\n", block_number);
00163
00164 block_end = (block_number + 1) * RKFS_BLOCKSIZE;
00165
00166 FSPDEBUG("block_end='%d'\n", block_end);
00167 FSPDEBUG("filesize = '%lu'\n", (long)file_inode->i_size);
00168
00169 curr_block_length = min((long)((long)file_inode->i_size - block_number * RKFS_BLOCKSIZE),
00170 (long)RKFS_BLOCKSIZE);
00171
00172 FSPDEBUG("curr_block_length='%d'\n", curr_block_length);
00173
00174 curr_write_end = min((long)block_end, (long)(count + *ppos));
00175
00176 FSPDEBUG("curr_write_end='%d'\n", curr_write_end);
00177
00178 count = curr_write_end - *ppos;
00179
00180 FSPDEBUG("count bigger, count = '%lu'\n", (long)count);
00181
00182 if (*ppos > file_inode->i_size) {
00183 FSPDEBUG("*ppos > file_inode->i_size = '%lu'\n", (long)file_inode->i_size);
00184 file_inode->i_size = *ppos;
00185 rkfs_inode_truncate(file_inode);
00186 curr_block_length = min((long)((long)file_inode->i_size - block_number * RKFS_BLOCKSIZE),
00187 (long)RKFS_BLOCKSIZE);
00188 append = 1;
00189 }
00190
00191 if (*ppos == file_inode->i_size) {
00192 append = 1;
00193 }
00194
00195 if (count == 0) {
00196 FSPDEBUG("count == 0, return count\n");
00197 return count;
00198 }
00199
00200 if (copy_from_user(write_buffer.data_buf, buf, count)) {
00201 return -EFAULT;
00202 }
00203
00204 FSPDEBUG("reading block from database\n");
00205 snprintf(write_buffer.query_buf, MAX_QUERY_LENGTH + 1, "MYSQL1.1 GB %lu %d",
00206 (long)file_inode->i_ino, block_number);
00207 if (query(write_buffer.query_buf, strlen(write_buffer.query_buf)) != RKFS_DEF_QUERY_OK) {
00208 FSPDEBUG("return from database - error\n");
00209 return 0;
00210 }
00211 else {
00212 if (ret_command.command_nr == CMD_ER_NR) {
00213 if ((strcmp(ret_command.param, "BLOCK_NOT_EXISTS") == 0)) {
00214 snprintf(write_buffer.query_buf, MAX_QUERY_LENGTH + 1, "MYSQL1.1 AB %lu ",
00215 (long)file_inode->i_ino);
00216 write_buffer.query_len = strlen(write_buffer.query_buf);
00217 query_pos = write_buffer.query_buf + strlen(write_buffer.query_buf);
00218 memcpy(query_pos, write_buffer.data_buf, count);
00219 write_buffer.query_len += count;
00220
00221 if (query(write_buffer.query_buf, write_buffer.query_len) != RKFS_DEF_QUERY_OK) {
00222 FSPDEBUG("return from database - error\n");
00223 return 0;
00224 }
00225 else {
00226 if (ret_command.command_nr == CMD_ER_NR) {
00227 FSPDEBUG("return from database - command ret error\n");
00228
00229 return 0;
00230 }
00231 }
00232
00233 *ppos += count;
00234 file_inode->i_size = max ((long)curr_write_end, (long)file_inode->i_size);
00235 FSPDEBUG("returning count = '%lu', filesize='%lu',\n", (long unsigned int) count,
00236 (long unsigned int)file_inode->i_size);
00237
00238 return count;
00239 }
00240 else {
00241 FSPDEBUG("return from database - command ret error\n");
00242
00243 return 0;
00244 }
00245
00246 }
00247
00248 }
00249
00250 data_pos = ret_command.data + *ppos - block_number * RKFS_BLOCKSIZE;
00251 for (i=0; i<count; i++) {
00252 *(data_pos) = write_buffer.data_buf[i];
00253 data_pos++;
00254 }
00255
00256
00257 FSPDEBUG("block_number='%d'\n", block_number);
00258 snprintf(write_buffer.query_buf, MAX_QUERY_LENGTH + 1, "MYSQL1.1 RB %lu %d ",
00259 (long)file_inode->i_ino, block_number);
00260
00261 query_pos = write_buffer.query_buf + strlen(write_buffer.query_buf);
00262 write_buffer.query_len = strlen(write_buffer.query_buf);
00263
00264 if (append) {
00265 FSPDEBUG("curr_block_len='%d'\n", curr_block_length);
00266 FSPDEBUG("count = '%lu'\n", (long)count);
00267
00268 memcpy(query_pos, ret_command.data, curr_block_length + count);
00269 write_buffer.query_len += curr_block_length + count;
00270 } else {
00271 memcpy(query_pos, ret_command.data, curr_block_length);
00272 write_buffer.query_len += curr_block_length;
00273 }
00274
00275 if (query(write_buffer.query_buf, write_buffer.query_len) != RKFS_DEF_QUERY_OK) {
00276 FSPDEBUG("return from database - error\n");
00277 return 0;
00278 }
00279 else {
00280 if (ret_command.command_nr == CMD_ER_NR) {
00281 FSPDEBUG("return from database - command ret error\n");
00282
00283 return 0;
00284 }
00285
00286 }
00287
00288 *ppos += count;
00289
00290 file_inode->i_size = max ((long)curr_write_end, (long)file_inode->i_size);
00291
00292 FSPDEBUG("returning count = '%lu', filesize='%lu',\n", (long unsigned int) count,
00293 (long unsigned int)file_inode->i_size);
00294
00295 return count;
00296 }
00297
00298
00309 int rkfs_file_open(struct inode *inode, struct file *file) {
00310
00311 FSPDEBUG("rkfs_file_open (%lu)\n", file->f_dentry->d_inode->i_ino);
00312
00313 file->f_ra.ra_pages = 0;
00314
00315 return generic_file_open(inode, file);
00316 }
00317
00318
00329 int rkfs_file_release (struct inode *ino, struct file *file) {
00330
00331 FSPDEBUG("rkfs_file_release\n");
00332 return 0;
00333 }
00334
00335
00348 int rkfs_file_readdir(struct file *file, void *dirent, filldir_t filldir) {
00349 struct dentry *de = file->f_dentry;
00350
00351 int i;
00352 int filename_len;
00353 char filename[MAX_NAME_LENGTH + 1]="";
00354 char file_id[MAX_ID_LENGTH + 1]="";
00355 char *com_data_pos = NULL;
00356 char query_string[MAX_QUERY_LENGTH + 1];
00357 struct inode *dir = file->f_dentry->d_inode;
00358
00359 FSPDEBUG("rkfs_file_readdir\n");
00360
00361 if (file->f_pos > (dir->i_size - 1 + 2))
00362 return 1;
00363
00364 if (filldir(dirent, ".", 1 , file->f_pos++, de->d_inode->i_ino, DT_DIR))
00365 return 0;
00366
00367 if (filldir(dirent, "..", 2 , file->f_pos++, de->d_parent->d_inode->i_ino, DT_DIR))
00368 return 0;
00369
00370 snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 RE %lu", dir->i_ino);
00371 query(query_string, strlen(query_string));
00372
00373 if (ret_command.command_nr != CMD_OK_NR) {
00374 FSPDEBUG("rkfs_file_readdir error='%s'\n", ret_command.param);
00375 return 1;
00376 }
00377 else {
00378 com_data_pos = ret_command.data;
00379 for(i = 1; i <= rkfs_atoi(ret_command.param); i++) {
00380
00381 filename_len = rkfs_next_data_item(&com_data_pos, filename);
00382 rkfs_next_data_item(&com_data_pos, file_id);
00383
00384 if (*com_data_pos == 'f') {
00385 if (filldir(dirent, filename, filename_len, file->f_pos++, rkfs_atoi(file_id), DT_REG)) {
00386 return 0;
00387 }
00388
00389 }
00390
00391 else {
00392 if (filldir(dirent, filename, filename_len, file->f_pos++, rkfs_atoi(file_id), DT_DIR))
00393 return 0;
00394 }
00395
00396 com_data_pos += 2;
00397 }
00398
00399 return 1;
00400 }
00401
00402 }
00403
00404
00417 loff_t rkfs_file_llseek (struct file * file , loff_t offset, int origin) {
00418 FSPDEBUG("rkfs_file_llseek (offset='%lu', origin='%lu')\n", (long)offset, (long)origin);
00419 return generic_file_llseek(file, offset, origin);
00420 }
00421
00422