fs_inode.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 #include <linux/smp_lock.h>
00035 
00036 
00037 #include "fsc_device.h"
00038 #include "rkfs.h"
00039 #include "parser.h"
00040 
00041 
00043 static struct inode *rkfs_root_inode;
00044 
00045 
00047 struct super_operations rkfs_sops = {
00048         read_inode: rkfs_super_read_inode,
00049         statfs: simple_statfs, /* handler from libfs */
00050         write_inode: rkfs_super_write_inode,
00051         delete_inode: rkfs_super_delete_inode
00052 };
00053 
00054 
00056 struct inode_operations rkfs_iops = {
00057         lookup: rkfs_inode_lookup,
00058         mkdir: rkfs_mkdir,
00059         rmdir: rkfs_rmdir,
00060         create : rkfs_inode_create,
00061         unlink: rkfs_inode_unlink,
00062         truncate: rkfs_inode_truncate,
00063         rename: rkfs_inode_rename
00064 };
00065 
00066 
00078 static int rkfs_fill_super(struct super_block *sb, void *data, int silent) {
00079         char query_string[MAX_QUERY_LENGTH + 1];
00080         char file_dircount[MAX_SIZE_LENGTH + 1];
00081         char file_filecount[MAX_SIZE_LENGTH + 1];
00082         char *data_pos;
00083         
00084         FSPDEBUG("rkfs_fill_super\n");
00085         // rkfs_deamon_test();
00086         
00087         /* test deamon connection */
00088         if (query("MYSQL1.1 TS", strlen("MYSQL1.1 TS")) != RKFS_DEF_QUERY_OK) {         
00089                 return -EFAULT;
00090         } 
00091         else {
00092                 if (ret_command.command_nr == CMD_ER_NR) {
00093                         FSPDEBUG("filesystem mount error, db connection failed\n");
00094                         return -EFAULT;
00095                 }
00096                 
00097         }
00098 
00099         sb->s_blocksize = RKFS_BLOCKSIZE;
00100         sb->s_blocksize_bits = RKFS_BLOCKSIZE_BITS;
00101         sb->s_magic = RKFS_MAGIC;
00102         
00103         /* super block operations */
00104         sb->s_op = &rkfs_sops;
00105         
00106         /* file_system_type */ 
00107         sb->s_type = &rkfs; 
00108         
00109         /* allocate an inode */
00110         rkfs_root_inode = iget(sb, RKFS_ROOT_INODE);
00111          
00112         /* set the inode ops */
00113         rkfs_root_inode->i_op = &rkfs_iops;
00114          
00115         rkfs_root_inode->i_mode = S_IFDIR|S_IRWXU;
00116         rkfs_root_inode->i_fop = &rkfs_dops;
00117 
00118         /* count of dirs in the root directory */
00119         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 RI %d", RKFS_ROOT_INODE);
00120         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00121                 return -EFAULT;
00122         } 
00123         else {
00124                 if (ret_command.command_nr == CMD_ER_NR) {
00125                         return -EFAULT;
00126                 }
00127         }
00128                 
00129         data_pos = ret_command.data;
00130         /* get number of dirs inside this dir */
00131         rkfs_next_data_item(&data_pos, file_dircount);
00132          
00133         /* get number of files inside this dir */
00134         rkfs_next_data_item(&data_pos, file_filecount);
00135         
00136         FSPDEBUG("dircount = '%s', filecount = '%s'\n", file_dircount, file_filecount);
00137         rkfs_root_inode->i_size = rkfs_atoi(file_dircount) + rkfs_atoi(file_filecount);
00138          
00139         /* we declare directorysize as sum of files and dirs inside */
00140         rkfs_root_inode->i_nlink = rkfs_atoi(file_dircount) + 2; 
00141 
00142         if (!(sb->s_root = d_alloc_root(rkfs_root_inode))) {
00143                 iput(rkfs_root_inode);
00144                 FSPDEBUG("filesystem mount error, not enough memory\n");
00145                 return -ENOMEM;
00146         }
00147         
00148         return 0;
00149 }
00150 
00151 
00165 int rkfs_get_sb (struct file_system_type *fs_type, int flags, const char *devname, void *data, 
00166                                  struct vfsmount *mnt) {
00167         int result;
00168         FSPDEBUG("rkfs_get_sb\n");
00169         /* rkfs_fill_super this will be called to fill the superblock */
00170         result = get_sb_single(
00171                                          fs_type,
00172                                          flags,
00173                                          data,
00174                                          &rkfs_fill_super, mnt);
00175         if (result == 0) {
00176                 FSPDEBUG("rkfs_get_sb succesfull\n");
00177         } 
00178         else {
00179                 FSPDEBUG("rkfs_get_sb: get_sb_single failed, return=%d\n", result);
00180         }
00181         
00182         return result;
00183 }
00184 
00185 
00194 void rkfs_kill_sb(struct super_block *super) {
00195         FSPDEBUG("rkfs_kill_sb\n\n\n\n");
00196         kill_anon_super(super);
00197 }
00198 
00199 
00208 void rkfs_super_read_inode(struct inode *inode) {
00209         char query_string[MAX_QUERY_LENGTH + 1];
00210         char file_size[MAX_SIZE_LENGTH + 1];
00211         char file_dircount[MAX_SIZE_LENGTH + 1];
00212         char file_filecount[MAX_SIZE_LENGTH + 1];
00213         char *data_pos = NULL;
00214 
00215         FSPDEBUG("rkfs_super_read_inode (%lu)\n", inode->i_ino);
00216         
00217         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 RI %lu", inode->i_ino);
00218         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00219                 make_bad_inode(inode); 
00220                 return;
00221         } 
00222         else {
00223                 if (ret_command.command_nr == CMD_ER_NR) {
00224                         make_bad_inode(inode);
00225                         /* return empty dentry, cannot return ENOENT! try cd or md*/
00226                         return; 
00227                 }
00228         }
00229         
00230         FSPRETCMD();
00231         data_pos = ret_command.data;
00232         
00233         /* we DON'T support file information like rights user etc. */
00234         if (strcmp(ret_command.param, "IS_FILE") == 0) { 
00235                 rkfs_next_data_item(&data_pos, file_size);
00236                 inode->i_size = rkfs_atoi(file_size);
00237                 
00238                 /* file */
00239                 inode->i_mode = S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; 
00240                 inode->i_fop = &rkfs_fops;
00241                 
00242                 /* set the inode ops */
00243                 inode->i_op = &rkfs_iops; 
00244                 FSPDEBUG("end of rkfs_super_read_inode from file branch\n");
00245         } 
00246         else {
00247                 
00248                 /* get number of dirs inside this dir */
00249                 rkfs_next_data_item(&data_pos, file_dircount);
00250                 
00251                 /* get number of files inside this dir */ 
00252                 rkfs_next_data_item(&data_pos, file_filecount);
00253                 FSPDEBUG("dircount = '%s', filecount = '%s'\n", file_dircount, file_filecount);
00254                 inode->i_size = rkfs_atoi(file_dircount) + rkfs_atoi(file_filecount); 
00255                 
00256                 /* we declare directory size as sum of files and dirs inside */
00257                 inode->i_nlink = rkfs_atoi(file_dircount) + 2;
00258                  
00259                 /* +1 for .. an . directory inside */
00260                 /* dir */
00261                 inode->i_mode = S_IFDIR|S_IXUSR|S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; 
00262                 inode->i_fop = &rkfs_dops;
00263                 
00264                 /* set the inode ops */
00265                 inode->i_op = &rkfs_iops; 
00266                 FSPDEBUG("end of rkfs_super_read_inode from dir branch\n");
00267         }
00268 }
00269 
00270 
00281 int rkfs_super_write_inode(struct inode *inode, int wait) {
00282         FSPDEBUG("rkfs_super_write_inode (i_ino = %d) = %d\n",
00283                 (int)inode->i_ino,(int)i_size_read(inode));
00284         return 0;
00285 }
00286 
00287 
00298 int rkfs_inode_unlink (struct inode *dir, struct dentry *dentry) {
00299         struct inode * inode = dentry->d_inode;
00300         char query_string[MAX_QUERY_LENGTH + 1];
00301         FSPDEBUG("rkfs_unlink_inode (i_ino = %lu)\n", (unsigned long int)inode->i_ino);
00302 
00303         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 RF %lu", (long unsigned int)inode->i_ino);
00304         
00305         /* test deamon connection */
00306         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {           
00307                 return -EFAULT;
00308         } 
00309         else {
00310                 if (ret_command.command_nr == CMD_ER_NR) {
00311                         return -EACCES; 
00312                 }
00313         }
00314 
00315         inode->i_size = 0;
00316         /* we have to update the number of files and dirs in parent directory - this value is used by readdir */
00317         dir->i_size--;  
00318         
00319         return 0;
00320 }
00321 
00322 
00332 void rkfs_super_delete_inode(struct inode *inode) {
00333         FSPDEBUG("rkfs_delete_inode (i_ino = %lu)\n", (long unsigned int)inode->i_ino);
00334         return generic_delete_inode(inode);
00335 }
00336 
00337 
00350 struct dentry *rkfs_inode_lookup(struct inode *parent_inode, struct dentry *dentry,
00351                                                                  struct nameidata *nameidata) {
00352         struct inode *file_inode;
00353         char query_string[MAX_QUERY_LENGTH + 1];
00354         char file_id[MAX_ID_LENGTH + 1];
00355         char* data_pos;
00356 
00357         FSPDEBUG("rkfs_inode_lookup\n");
00358         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 LU %lu %s", parent_inode->i_ino, dentry->d_name.name);
00359         
00360         /* test deamon connection */
00361         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00362                 return NULL;
00363         } 
00364         else {
00365                 if (ret_command.command_nr == CMD_ER_NR) {
00366                         /* return empty dentry, cannot return ENOENT! try cd or md*/
00367                         return NULL; 
00368                 }
00369         }
00370         
00371         data_pos = ret_command.data;
00372         
00373         /* get file_id */       
00374         rkfs_next_data_item(&data_pos, file_id);
00375         
00376         file_inode = iget(parent_inode->i_sb, rkfs_atoi(file_id));
00377         
00378         if (!file_inode) {
00379                 return ERR_PTR(-EACCES);
00380         }
00381         
00382         d_add(dentry, file_inode);
00383         return NULL;
00384 }
00385 
00386 
00387 
00400 int rkfs_inode_create(struct inode *dir, struct dentry *dirdentry, int mode, 
00401                                           struct nameidata *nd) {
00402         struct inode * inode;
00403         struct super_block *sb = dir->i_sb;
00404         char query_string[MAX_QUERY_LENGTH + 1];
00405         struct qstr qname;
00406         struct dentry *dentry;
00407 
00408         FSPDEBUG("rkfs_inode_create\n");
00409         
00410         /* allocate an inode */
00411         inode = new_inode(sb); 
00412         if (IS_ERR(inode)) {
00413                 return PTR_ERR(inode);
00414         }
00415 
00416         qname.name = dirdentry->d_name.name;
00417         qname.len = strlen (dirdentry->d_name.name);
00418         qname.hash = full_name_hash(qname.name, qname.len);
00419         
00420         /* Now we can create our dentry and the inode to go with it.*/
00421         dentry = d_alloc(dirdentry, &qname);
00422         if (! dentry) {
00423                 return 0;
00424         }
00425 
00426         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 CF %lu %s", dir->i_ino, dirdentry->d_name.name);
00427         
00428         /* test deamon connection */
00429         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {           
00430                 dput(dentry);
00431                 return 0;
00432         } 
00433         else {
00434                 if (ret_command.command_nr == CMD_ER_NR) {
00435                         dput(dentry);
00436                         return 0;
00437                 }
00438         }
00439 
00440         inode->i_ino = rkfs_atoi(ret_command.param);
00441         
00442         /* size of the new directory is 0 - no files inside */
00443         inode->i_size = 0; 
00444         
00445         /* create as dir, with wanted mode */
00446         inode->i_mode = S_IFREG | mode ;
00447         
00448         /* set the file ops */ 
00449         inode->i_fop = &rkfs_fops;
00450         
00451         /* set the inode ops */ 
00452         inode->i_op = &rkfs_iops; 
00453         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
00454         inode_inc_link_count(inode);
00455 
00456         d_add(dirdentry, inode);
00457         
00458         /* updating info of files present */
00459         dir->i_size++;
00460         
00461         /* ok */ 
00462         return 0; 
00463 }
00464 
00465 
00467 struct write_buffer {
00469         char data_buf[RKFS_BLOCKSIZE];
00471         char query_buf[RKFS_BLOCKSIZE + MAX_QUERY_LENGTH + 1];
00473         char query_len;
00474 } truncate_buffer;
00475 
00476 
00486 void rkfs_inode_truncate (struct inode * inode) {
00487         char query_string[MAX_QUERY_LENGTH + 1];
00488         long new_file_size = inode->i_size;
00489 
00490         FSPDEBUG("rkfs_inode_truncate\n");
00491 
00492         /* i_node->i_size contains the length after truncate */
00493         
00494         if (new_file_size == 0) {
00495                 snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 CR %lu", inode->i_ino);
00496                 if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00497                         return;
00498                 } 
00499                 else {
00500                                 if (ret_command.command_nr == CMD_ER_NR) {
00501                                 
00502                                 /* return empty dentry, cannot return ENOENT! try cd or md*/
00503                                 return; 
00504                         }
00505                 }
00506                 return;
00507         }
00508 
00509         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 TR %lu %lu", inode->i_ino, new_file_size);
00510         
00511         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00512                 return;
00513         } 
00514         else {
00515                         if (ret_command.command_nr == CMD_ER_NR) {
00516                         
00517                         /* return empty dentry, cannot return ENOENT! try cd or md*/
00518                         return; 
00519                 }
00520         }
00521                         
00522 }
00523 
00524 
00537 int rkfs_inode_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir, 
00538                                                                         struct dentry *new_dentry) {
00539         char query_string[MAX_QUERY_LENGTH + 1];
00540         char file_id[MAX_SIZE_LENGTH + 1];
00541         char* data_pos;
00542         long file_id_long;
00543         int is_file = 0;
00544 
00545         FSPDEBUG("rkfs_inode_rename\n");
00546         FSPDEBUG("rkfs_inode_rename (old_dir->i_ino='%lu', old_dentry->d_name='%s', new_dir->i_ino='%lu', new_dentry->d_name='%s')\n", (long)old_dir->i_ino, old_dentry->d_name.name, (long)new_dir->i_ino, new_dentry->d_name.name);
00547         
00548         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 LU %lu %s", old_dir->i_ino, old_dentry->d_name.name);
00549         
00550         /* test deamon connection */
00551         if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {           
00552                 return -ENOENT;
00553         } 
00554         else {
00555                 if (ret_command.command_nr == CMD_ER_NR) {
00556                         
00557                         /* return empty dentry, cannot return ENOENT! try cd or md*/
00558                         return -ENOENT; 
00559                 }
00560                 
00561         }
00562         
00563         data_pos = ret_command.data;
00564                 
00565         /* get file_id */
00566         rkfs_next_data_item(&data_pos, file_id);
00567         file_id_long = rkfs_atoi(file_id);
00568         
00569         if (strcmp(ret_command.param, "IS_FILE") == 0) {
00570                 is_file = 1;
00571         }
00572 
00573         if (old_dir->i_ino != new_dir->i_ino) {
00574                 snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 MV %s %lu", file_id, new_dir->i_ino);
00575                 if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00576                         return -ENOENT;
00577                 } 
00578                 else {
00579                         if (ret_command.command_nr == CMD_ER_NR) {
00580                                 
00581                                 /* return empty dentry, cannot return ENOENT! try cd or md*/
00582                                 return -ENOENT;
00583                         }
00584                 }
00585                 
00586                 old_dir->i_size--;
00587                 new_dir->i_size++;
00588         
00589                 if (!is_file) {
00590                         old_dir->i_nlink--;
00591                         new_dir->i_nlink--;     
00592                 }
00593                 
00594         }
00595         
00596         if (strcmp(old_dentry->d_name.name, new_dentry->d_name.name) != 0) {
00597                 if (is_file) {
00598                         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 DN %s %s", file_id, new_dentry->d_name.name);
00599                         
00600                 } else {        
00601                         snprintf(query_string, MAX_QUERY_LENGTH + 1, "MYSQL1.1 DD %s %s", file_id, new_dentry->d_name.name);
00602                 }
00603 
00604                 if (query(query_string, strlen(query_string)) != RKFS_DEF_QUERY_OK) {
00605                         return -ENOENT;
00606                 } 
00607                 else {
00608                         if (ret_command.command_nr == CMD_ER_NR) {
00609                                 
00610                                 /* return empty dentry, cannot return ENOENT! try cd or md*/
00611                                 return -ENOENT; 
00612                         }
00613                         
00614                 }
00615                 
00616         }
00617         
00618         return 0;
00619 }
00620 
00621 

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