andaboard.
aboutsummaryrefslogblamecommitdiffstats
path: root/fs/libfs.c
blob: c88eab55aec95f4ab26427da882fd88c8b3ef512 (plain) (tree)
1
2
3
4
5
6
7
8
9
10






                                        
                       

                        
                           
                        
                           

                              
 

                        




                                                        








                                                                           
                                                             
 
                                            








                                                                      
                                                            









                                                                                            
                                                                          




                                                 
                                                      



                            



                                                                 
                                                                        











                                                                     

                                                    






                                              
                                                                








                                                                   

                                                            
                                                       

                                                              
                                                    
                                                                                 
                                                                                      
                                                          
                                            
                                                           

                                            
                                                               
                                                     

                 
                                                
















                                                                        
                                                    
                                                   
                                                       


















                                                                         
                                                   


                                                                 

                                                                             
                                                                                 


                                                                                      
                                                 
                                 
 
                                                           
                                                             



                                                                           
                                                 

                                                                                      
                                                         
                                                
                                                           


                                              
                                                     








                                                                                       
                                                      




                                           
                                     

  
                                                             


                                        



                                                                



                                                                          
                                                                         

                                                                  

                                                                          




                                                                 
                                   

                               
                                         

                                         
                           
                                                       



                            





                                                                              
                                                   









                                                                     
                         
                                
                               

       
                                   
                                






                                                                                    
                         
                     




                                     




                                       
                                   



                                                                       
                                 


                                            

                
                                     







                                                                    
                          








                                                          
                                    
                                   
                        














                                                                   
                                            
                                   
                                    
                                   







                                                                 
   
                                                 




                                           





                                                                        





                                                              

                                            



                                              

                                                        
                                   

                                


                              

                                                         
                             

                                



                          





                                                                        

                                        
 
                                                                  




                               





                                                                               

 




















                                                                                



                                                                      

                                                  


                                                                    


                                                             

         







                                                              
 
                             





                                 




                                                                         

                                                                 
 







                                               
                                           




                               




                                                                           
                                       


                                                                        
                           







                                                                   






                                                                            






                                                         














                                                                                
                                                                                     




                                          
                                                                























                                                           













                                                                            



                                                                            

                   

                               
                                       


                                        

                                                  
                               
                     



                            
   

































                                                                               












                                                                              
















                                                                     





                                                                           














                                                                          













































                                                                                              


                            

                                  



                                                                      
                                                                      




                                                                        
                                                                        









                                                  
                                      
                        
                                 





                                             
                                                               

















                                                               



                                                     
                                                    
                                             





                                                  
                                                                      

                                                                     

                                                                           
    
                                   












                                                                    


                               



                                                     




                                                     

                                                    


                                                                         
    
                                   


                   



























                                                                              
                                     































                                                                              
                                     


                                        









                                                                           
 
                                                    








                                                             
                                            



                          

                                  











                                                                      

                                                                     






                                                                        

                                                                          





                                         






                                                             
 




                                
                            

                                  


                                           




                                 




                                 
                          

                                       
                                      
                                       
                                      


                                          
                                    
                                       

                                     
/*
 *	fs/libfs.c
 *	Library for filesystems writers.
 */

#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/slab.h>
#include <linux/mount.h>
#include <linux/vfs.h>
#include <linux/quotaops.h>
#include <linux/mutex.h>
#include <linux/exportfs.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h>

#include <asm/uaccess.h>

static inline int simple_positive(struct dentry *dentry)
{
	return dentry->d_inode && !d_unhashed(dentry);
}

int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
		   struct kstat *stat)
{
	struct inode *inode = dentry->d_inode;
	generic_fillattr(inode, stat);
	stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
	return 0;
}

int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
{
	buf->f_type = dentry->d_sb->s_magic;
	buf->f_bsize = PAGE_CACHE_SIZE;
	buf->f_namelen = NAME_MAX;
	return 0;
}

/*
 * Retaining negative dentries for an in-memory filesystem just wastes
 * memory and lookup time: arrange for them to be deleted immediately.
 */
static int simple_delete_dentry(const struct dentry *dentry)
{
	return 1;
}

/*
 * Lookup the data. This is trivial - if the dentry didn't already
 * exist, we know it is negative.  Set d_op to delete negative dentries.
 */
struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	static const struct dentry_operations simple_dentry_operations = {
		.d_delete = simple_delete_dentry,
	};

	if (dentry->d_name.len > NAME_MAX)
		return ERR_PTR(-ENAMETOOLONG);
	d_set_d_op(dentry, &simple_dentry_operations);
	d_add(dentry, NULL);
	return NULL;
}

int dcache_dir_open(struct inode *inode, struct file *file)
{
	static struct qstr cursor_name = {.len = 1, .name = "."};

	file->private_data = d_alloc(file->f_path.dentry, &cursor_name);

	return file->private_data ? 0 : -ENOMEM;
}

int dcache_dir_close(struct inode *inode, struct file *file)
{
	dput(file->private_data);
	return 0;
}

loff_t dcache_dir_lseek(struct file *file, loff_t offset, int origin)
{
	struct dentry *dentry = file->f_path.dentry;
	mutex_lock(&dentry->d_inode->i_mutex);
	switch (origin) {
		case 1:
			offset += file->f_pos;
		case 0:
			if (offset >= 0)
				break;
		default:
			mutex_unlock(&dentry->d_inode->i_mutex);
			return -EINVAL;
	}
	if (offset != file->f_pos) {
		file->f_pos = offset;
		if (file->f_pos >= 2) {
			struct list_head *p;
			struct dentry *cursor = file->private_data;
			loff_t n = file->f_pos - 2;

			spin_lock(&dentry->d_lock);
			/* d_lock not required for cursor */
			list_del(&cursor->d_u.d_child);
			p = dentry->d_subdirs.next;
			while (n && p != &dentry->d_subdirs) {
				struct dentry *next;
				next = list_entry(p, struct dentry, d_u.d_child);
				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
				if (simple_positive(next))
					n--;
				spin_unlock(&next->d_lock);
				p = p->next;
			}
			list_add_tail(&cursor->d_u.d_child, p);
			spin_unlock(&dentry->d_lock);
		}
	}
	mutex_unlock(&dentry->d_inode->i_mutex);
	return offset;
}

/* Relationship between i_mode and the DT_xxx types */
static inline unsigned char dt_type(struct inode *inode)
{
	return (inode->i_mode >> 12) & 15;
}

/*
 * Directory is locked and all positive dentries in it are safe, since
 * for ramfs-type trees they can't go away without unlink() or rmdir(),
 * both impossible due to the lock on directory.
 */

int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
	struct dentry *dentry = filp->f_path.dentry;
	struct dentry *cursor = filp->private_data;
	struct list_head *p, *q = &cursor->d_u.d_child;
	ino_t ino;
	int i = filp->f_pos;

	switch (i) {
		case 0:
			ino = dentry->d_inode->i_ino;
			if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		case 1:
			ino = parent_ino(dentry);
			if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
				break;
			filp->f_pos++;
			i++;
			/* fallthrough */
		default:
			spin_lock(&dentry->d_lock);
			if (filp->f_pos == 2)
				list_move(q, &dentry->d_subdirs);

			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
				struct dentry *next;
				next = list_entry(p, struct dentry, d_u.d_child);
				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
				if (!simple_positive(next)) {
					spin_unlock(&next->d_lock);
					continue;
				}

				spin_unlock(&next->d_lock);
				spin_unlock(&dentry->d_lock);
				if (filldir(dirent, next->d_name.name, 
					    next->d_name.len, filp->f_pos, 
					    next->d_inode->i_ino, 
					    dt_type(next->d_inode)) < 0)
					return 0;
				spin_lock(&dentry->d_lock);
				spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
				/* next is still alive */
				list_move(q, p);
				spin_unlock(&next->d_lock);
				p = q;
				filp->f_pos++;
			}