fs_file.c

Go to the documentation of this file.
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> /* unlock_page */
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         /* blocks are always full except the last one*/
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                         /* return empty dentry, cannot return ENOENT! try cd or md*/
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         /* blocks are always full except the last one*/
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                                                 /* return empty dentry, cannot return ENOENT! try cd or md*/
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                                         /* return empty dentry, cannot return ENOENT! try cd or md*/
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                         /* return empty dentry, cannot return ENOENT! try cd or md*/
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; //generic_file_write(filp, buf, count, ppos);
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         /* No read-ahead */
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         /* nothing else to do */
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         /* inode->size is number of files and directories in the dir */
00361         if (file->f_pos > (dir->i_size - 1 + 2)) 
00362                 return 1;
00363                 
00364         if (filldir(dirent, ".", 1 /* len */, file->f_pos++, de->d_inode->i_ino, DT_DIR))
00365                 return 0;
00366                 
00367         if (filldir(dirent, "..", 2 /* len */, 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                         /* com_data_pos == 'd' */ 
00391                         else {
00392                                 if (filldir(dirent, filename, filename_len, file->f_pos++, rkfs_atoi(file_id), DT_DIR))
00393                                         return 0;
00394                         }
00395                         /* eat f or d and slash */
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 

Generated on Mon May 28 13:33:08 2007 for MYSQLFS by  doxygen 1.5.0