From 667e9cd3c1193c9e858512ced5ebccd26e0e6ab2 Mon Sep 17 00:00:00 2001 From: braam Date: Sun, 11 Mar 2001 00:53:49 +0000 Subject: [PATCH] a working file system! --- lustre/include/linux/obd_class.h | 1 - lustre/include/linux/obdfs.h | 302 ++++-- lustre/obdclass/genops.c | 2 +- lustre/obdclass/obdcontrol | 640 ++++++------- lustre/obdfs/dir.c | 296 +++--- lustre/obdfs/file.c | 94 +- lustre/obdfs/namei.c | 1873 +++++++++++++++++++------------------- lustre/obdfs/rw.c | 726 +++++++-------- lustre/obdfs/super.c | 725 ++++++++------- lustre/obdfs/symlink.c | 78 +- 10 files changed, 2423 insertions(+), 2314 deletions(-) diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 6758bc6..93a5338 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -2,7 +2,6 @@ #define __LINUX_CLASS_OBD_H #include -#include #include #include diff --git a/lustre/include/linux/obdfs.h b/lustre/include/linux/obdfs.h index 3787608..6f60217 100644 --- a/lustre/include/linux/obdfs.h +++ b/lustre/include/linux/obdfs.h @@ -14,38 +14,59 @@ #include #include + +#define obd_unlock_page(page) do { if (PageLocked(page)) { \ + UnlockPage(page);\ + } else {\ + printk("file %s, line %d: expecting locked page\n",\ + __FILE__, __LINE__); \ + } \ +} while(0) + struct obdfs_pgrq { - struct list_head rq_plist; /* linked list of req's */ - unsigned long rq_jiffies; - struct page *rq_page; /* page to be written */ + struct list_head rq_plist; /* linked list of req's */ + unsigned long rq_jiffies; + struct page *rq_page; /* page to be written */ }; -struct list_head obdfs_super_list; /* list of all OBDFS superblocks */ +struct list_head obdfs_super_list; /* list of all OBDFS superblocks */ struct obdfs_sb_info { - struct list_head osi_list; /* list of supers */ - struct obd_conn osi_conn; - struct super_block *osi_super; - struct obd_device *osi_obd; - struct obd_ops *osi_ops; - ino_t osi_rootino; /* number of root inode */ - int osi_minor; /* minor of /dev/obdX */ - struct list_head osi_inodes; /* list of dirty inodes */ - unsigned long osi_cache_count; - struct semaphore osi_list_mutex; + struct list_head osi_list; /* list of supers */ + struct obd_conn osi_conn; + struct super_block *osi_super; + struct obd_device *osi_obd; + struct obd_ops *osi_ops; + ino_t osi_rootino; /* number of root inode */ + int osi_minor; /* minor of /dev/obdX */ + struct list_head osi_inodes; /* list of dirty inodes */ + unsigned long osi_cache_count; + struct semaphore osi_list_mutex; }; struct obdfs_inode_info { - int oi_flags; - struct list_head oi_inodes; - struct list_head oi_pages; - char oi_inline[OBD_INLINESZ]; + int oi_flags; + struct list_head oi_inodes; + struct list_head oi_pages; + char oi_inline[OBD_INLINESZ]; }; /* dir.c */ +#define EXT2_DIR_PAD 4 +#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) +#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ + ~EXT2_DIR_ROUND) +#define EXT2_NAME_LEN 255 +struct ext2_dir_entry_2 { + __u32 inode; /* Inode number */ + __u16 rec_len; /* Directory entry length */ + __u8 name_len; /* Name length */ + __u8 file_type; + char name[EXT2_NAME_LEN]; /* File name */ +}; int obdfs_check_dir_entry (const char * function, struct inode * dir, - struct ext2_dir_entry_2 * de, struct page * page, - unsigned long offset); + struct ext2_dir_entry_2 * de, struct page * page, + unsigned long offset); extern struct file_operations obdfs_dir_operations; extern struct inode_operations obdfs_dir_inode_operations; @@ -61,6 +82,97 @@ int obdfs_flush_reqs(struct list_head *inode_list, unsigned long check_time); int obdfs_flush_dirty_pages(unsigned long check_time); /* namei.c */ +/* + * Structure of the super block + */ +struct ext2_super_block { + __u32 s_inodes_count; /* Inodes count */ + __u32 s_blocks_count; /* Blocks count */ + __u32 s_r_blocks_count; /* Reserved blocks count */ + __u32 s_free_blocks_count; /* Free blocks count */ + __u32 s_free_inodes_count; /* Free inodes count */ + __u32 s_first_data_block; /* First Data Block */ + __u32 s_log_block_size; /* Block size */ + __s32 s_log_frag_size; /* Fragment size */ + __u32 s_blocks_per_group; /* # Blocks per group */ + __u32 s_frags_per_group; /* # Fragments per group */ + __u32 s_inodes_per_group; /* # Inodes per group */ + __u32 s_mtime; /* Mount time */ + __u32 s_wtime; /* Write time */ + __u16 s_mnt_count; /* Mount count */ + __s16 s_max_mnt_count; /* Maximal mount count */ + __u16 s_magic; /* Magic signature */ + __u16 s_state; /* File system state */ + __u16 s_errors; /* Behaviour when detecting errors */ + __u16 s_minor_rev_level; /* minor revision level */ + __u32 s_lastcheck; /* time of last check */ + __u32 s_checkinterval; /* max. time between checks */ + __u32 s_creator_os; /* OS */ + __u32 s_rev_level; /* Revision level */ + __u16 s_def_resuid; /* Default uid for reserved blocks */ + __u16 s_def_resgid; /* Default gid for reserved blocks */ + /* + * These fields are for EXT2_DYNAMIC_REV superblocks only. + * + * Note: the difference between the compatible feature set and + * the incompatible feature set is that if there is a bit set + * in the incompatible feature set that the kernel doesn't + * know about, it should refuse to mount the filesystem. + * + * e2fsck's requirements are more strict; if it doesn't know + * about a feature in either the compatible or incompatible + * feature set, it must abort and not try to meddle with + * things it doesn't understand... + */ + __u32 s_first_ino; /* First non-reserved inode */ + __u16 s_inode_size; /* size of inode structure */ + __u16 s_block_group_nr; /* block group # of this superblock */ + __u32 s_feature_compat; /* compatible feature set */ + __u32 s_feature_incompat; /* incompatible feature set */ + __u32 s_feature_ro_compat; /* readonly-compatible feature set */ + __u8 s_uuid[16]; /* 128-bit uuid for volume */ + char s_volume_name[16]; /* volume name */ + char s_last_mounted[64]; /* directory where last mounted */ + __u32 s_algorithm_usage_bitmap; /* For compression */ + /* + * Performance hints. Directory preallocation should only + * happen if the EXT2_COMPAT_PREALLOC flag is on. + */ + __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ + __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ + __u16 s_padding1; + __u32 s_reserved[204]; /* Padding to the end of the block */ +}; + +#define EXT2_SB(sb) (&((sb)->u.ext2_sb)) +/* + * Maximal count of links to a file + */ +#define EXT2_LINK_MAX 32000 +/* + * Ext2 directory file types. Only the low 3 bits are used. The + * other bits are reserved for now. + */ +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_REG_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHRDEV 3 +#define EXT2_FT_BLKDEV 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 + +#define EXT2_FT_MAX 8 + +#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ +#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ +#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 +#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_es->s_feature_compat & cpu_to_le32(mask) ) +#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ + ( EXT2_SB(sb)->s_es->s_feature_incompat & cpu_to_le32(mask) ) + + struct dentry *obdfs_lookup(struct inode * dir, struct dentry *dentry); int obdfs_create (struct inode * dir, struct dentry * dentry, int mode); int obdfs_mkdir(struct inode *dir, struct dentry *dentry, int mode); @@ -68,28 +180,28 @@ int obdfs_rmdir(struct inode *dir, struct dentry *dentry); int obdfs_unlink(struct inode *dir, struct dentry *dentry); int obdfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev); int obdfs_symlink(struct inode *dir, struct dentry *dentry, - const char *symname); + const char *symname); int obdfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry); + struct dentry *dentry); int obdfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); + struct inode *new_dir, struct dentry *new_dentry); /* rw.c */ -int obdfs_do_writepage(struct inode *, struct page *, int sync); +int obdfs_do_writepage(struct page *, int sync); int obdfs_init_pgrqcache(void); void obdfs_cleanup_pgrqcache(void); inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq); -int obdfs_readpage(struct dentry *dentry, struct page *page); -int obdfs_writepage(struct dentry *dentry, struct page *page); +int obdfs_readpage(struct file *file, struct page *page); +int obdfs_writepage(struct page *page); struct page *obdfs_getpage(struct inode *inode, unsigned long offset, - int create, int locked); + int create, int locked); int obdfs_write_one_page(struct file *file, struct page *page, - unsigned long offset, unsigned long bytes, - const char * buf); + unsigned long offset, unsigned long bytes, + const char * buf); int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, obd_count num_oa, - struct obdo **obdos, obd_count *oa_bufs, - struct page **pages, char **bufs, obd_size *counts, - obd_off *offsets, obd_flag *flags); + struct obdo **obdos, obd_count *oa_bufs, + struct page **pages, char **bufs, obd_size *counts, + obd_off *offsets, obd_flag *flags); void obdfs_truncate(struct inode *inode); /* super.c */ @@ -107,50 +219,50 @@ void obdfs_sysctl_clean(void); static inline struct obdfs_inode_info *obdfs_i2info(struct inode *inode) { - return (struct obdfs_inode_info *)&(inode->u.generic_ip); + return (struct obdfs_inode_info *)&(inode->u.generic_ip); } static inline struct obdfs_sb_info *obdfs_i2sbi(struct inode *inode) { - return (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp); + return (struct obdfs_sb_info *) &(inode->i_sb->u.generic_sbp); } static inline struct list_head *obdfs_iplist(struct inode *inode) { - struct obdfs_inode_info *info = obdfs_i2info(inode); + struct obdfs_inode_info *info = obdfs_i2info(inode); - return &info->oi_pages; + return &info->oi_pages; } static inline struct list_head *obdfs_islist(struct inode *inode) { - struct obdfs_inode_info *info = obdfs_i2info(inode); + struct obdfs_inode_info *info = obdfs_i2info(inode); - return &info->oi_inodes; + return &info->oi_inodes; } static inline struct list_head *obdfs_slist(struct inode *inode) { - struct obdfs_sb_info *sbi = obdfs_i2sbi(inode); + struct obdfs_sb_info *sbi = obdfs_i2sbi(inode); - return &sbi->osi_inodes; + return &sbi->osi_inodes; } -#define obd_down(mutex) { \ - /* CDEBUG(D_INFO, "get lock\n"); */ \ - obdfs_mutex_start = jiffies; \ - down(mutex); \ - if (jiffies - obdfs_mutex_start) \ - CDEBUG(D_CACHE, "waited on mutex %ld jiffies\n", \ - jiffies - obdfs_mutex_start); \ +#define obd_down(mutex) { \ + /* CDEBUG(D_INFO, "get lock\n"); */ \ + obdfs_mutex_start = jiffies; \ + down(mutex); \ + if (jiffies - obdfs_mutex_start) \ + CDEBUG(D_CACHE, "waited on mutex %ld jiffies\n", \ + jiffies - obdfs_mutex_start); \ } -#define obd_up(mutex) { \ - up(mutex); \ - if (jiffies - obdfs_mutex_start > 1) \ - CDEBUG(D_CACHE, "held mutex for %ld jiffies\n", \ - jiffies - obdfs_mutex_start); \ - /* CDEBUG(D_INFO, "free lock\n"); */ \ +#define obd_up(mutex) { \ + up(mutex); \ + if (jiffies - obdfs_mutex_start > 1) \ + CDEBUG(D_CACHE, "held mutex for %ld jiffies\n", \ + jiffies - obdfs_mutex_start); \ + /* CDEBUG(D_INFO, "free lock\n"); */ \ } /* We track if a page has been added to the OBD page cache by stting a @@ -158,66 +270,66 @@ static inline struct list_head *obdfs_slist(struct inode *inode) * used for a while. */ #define PG_obdcache 29 -#define OBDAddCachePage(page) test_and_set_bit(PG_obdcache, &(page)->flags) -#define OBDClearCachePage(page) clear_bit(PG_obdcache, &(page)->flags) +#define OBDAddCachePage(page) test_and_set_bit(PG_obdcache, &(page)->flags) +#define OBDClearCachePage(page) clear_bit(PG_obdcache, &(page)->flags) static inline void obdfs_print_plist(struct inode *inode) { - struct list_head *page_list = obdfs_iplist(inode); - struct list_head *tmp; - - CDEBUG(D_INFO, "inode %ld: page", inode->i_ino); - /* obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); */ - if (list_empty(page_list)) { - CDEBUG(D_INFO, " list empty\n"); - obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); - return; - } - - tmp = page_list; - while ( (tmp = tmp->next) != page_list) { - struct obdfs_pgrq *pgrq; - pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); - CDEBUG(D_INFO, " %p", pgrq->rq_page); - } - CDEBUG(D_INFO, "\n"); - /* obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); */ + struct list_head *page_list = obdfs_iplist(inode); + struct list_head *tmp; + + CDEBUG(D_INFO, "inode %ld: page", inode->i_ino); + /* obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); */ + if (list_empty(page_list)) { + CDEBUG(D_INFO, " list empty\n"); + obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); + return; + } + + tmp = page_list; + while ( (tmp = tmp->next) != page_list) { + struct obdfs_pgrq *pgrq; + pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); + CDEBUG(D_INFO, " %p", pgrq->rq_page); + } + CDEBUG(D_INFO, "\n"); + /* obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); */ } static inline int obdfs_has_inline(struct inode *inode) { - return (obdfs_i2info(inode)->oi_flags & OBD_FL_INLINEDATA); + return (obdfs_i2info(inode)->oi_flags & OBD_FL_INLINEDATA); } static void inline obdfs_from_inode(struct obdo *oa, struct inode *inode) { - struct obdfs_inode_info *oinfo = obdfs_i2info(inode); - - CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n", - inode->i_ino, (long)oa->o_id, oa->o_valid); - obdo_from_inode(oa, inode); - if (obdfs_has_inline(inode)) { - CDEBUG(D_INODE, "copying inline data from inode to obdo\n"); - memcpy(oa->o_inline, oinfo->oi_inline, OBD_INLINESZ); - oa->o_obdflags |= OBD_FL_INLINEDATA; - oa->o_valid |= OBD_MD_FLINLINE; - } + struct obdfs_inode_info *oinfo = obdfs_i2info(inode); + + CDEBUG(D_INFO, "src inode %ld, dst obdo %ld valid 0x%08x\n", + inode->i_ino, (long)oa->o_id, oa->o_valid); + obdo_from_inode(oa, inode); + if (obdfs_has_inline(inode)) { + CDEBUG(D_INODE, "copying inline data from inode to obdo\n"); + memcpy(oa->o_inline, oinfo->oi_inline, OBD_INLINESZ); + oa->o_obdflags |= OBD_FL_INLINEDATA; + oa->o_valid |= OBD_MD_FLINLINE; + } } /* obdfs_from_inode */ static void inline obdfs_to_inode(struct inode *inode, struct obdo *oa) { - struct obdfs_inode_info *oinfo = obdfs_i2info(inode); + struct obdfs_inode_info *oinfo = obdfs_i2info(inode); - CDEBUG(D_INFO, "src obdo %ld valid 0x%08x, dst inode %ld\n", - (long)oa->o_id, oa->o_valid, inode->i_ino); + CDEBUG(D_INFO, "src obdo %ld valid 0x%08x, dst inode %ld\n", + (long)oa->o_id, oa->o_valid, inode->i_ino); - obdo_to_inode(inode, oa); + obdo_to_inode(inode, oa); - if (obdo_has_inline(oa)) { - CDEBUG(D_INODE, "copying inline data from obdo to inode\n"); - memcpy(oinfo->oi_inline, oa->o_inline, OBD_INLINESZ); - oinfo->oi_flags |= OBD_FL_INLINEDATA; - } + if (obdo_has_inline(oa)) { + CDEBUG(D_INODE, "copying inline data from obdo to inode\n"); + memcpy(oinfo->oi_inline, oa->o_inline, OBD_INLINESZ); + oinfo->oi_flags |= OBD_FL_INLINEDATA; + } } /* obdfs_to_inode */ #define NOLOCK 0 diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index f73dc27..445b410 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -301,7 +301,7 @@ int gen_copy_data(struct obd_conn *dst_conn, struct obdo *dst, dst->o_size = src->o_size; dst->o_blocks = src->o_blocks; dst->o_valid |= (OBD_MD_FLSIZE | OBD_MD_FLBLOCKS); - UnlockPage(page); + obd_unlock_page(page); __free_page(page); EXIT; diff --git a/lustre/obdclass/obdcontrol b/lustre/obdclass/obdcontrol index 59dda5a..94aea02 100755 --- a/lustre/obdclass/obdcontrol +++ b/lustre/obdclass/obdcontrol @@ -97,30 +97,30 @@ use IO::Handle; # this may be different on other architectures # we use 32-bit integers for all 64-bit quantities in this program -# #define OBD_INLINESZ 60 -# #define OBD_OBDMDSZ 60 +# #define OBD_INLINESZ 60 +# #define OBD_OBDMDSZ 60 # /* Note: 64-bit types are 64-bit aligned in structure */ # struct obdo { -# obd_id o_id; -# obd_gr o_gr; -# obd_time o_atime; -# obd_time o_mtime; -# obd_time o_ctime; -# obd_size o_size; -# obd_blocks o_blocks; -# obd_blksize o_blksize; -# obd_mode o_mode; -# obd_uid o_uid; -# obd_gid o_gid; -# obd_flag o_flags; -# obd_flag o_obdflags; -# obd_count o_nlink; -# obd_count o_generation; -# obd_flag o_valid; /* hot fields in this obdo */ -# char o_inline[60]; -# char o_obdmd[60]; -# struct list_head o_list; -# struct obd_ops *o_op; +# obd_id o_id; +# obd_gr o_gr; +# obd_time o_atime; +# obd_time o_mtime; +# obd_time o_ctime; +# obd_size o_size; +# obd_blocks o_blocks; +# obd_blksize o_blksize; +# obd_mode o_mode; +# obd_uid o_uid; +# obd_gid o_gid; +# obd_flag o_flags; +# obd_flag o_obdflags; +# obd_count o_nlink; +# obd_count o_generation; +# obd_flag o_valid; /* hot fields in this obdo */ +# char o_inline[60]; +# char o_obdmd[60]; +# struct list_head o_list; +# struct obd_ops *o_op; # }; sub obdo_pack { @@ -139,9 +139,9 @@ sub obdo_pack { $obdo->{gid}, $obdo->{flags}, $obdo->{obdflags}, - $obdo->{nlink}, - $obdo->{generation}, - $obdo->{valid}, + $obdo->{nlink}, + $obdo->{generation}, + $obdo->{valid}, $obdo->{inline}, $obdo->{obdmd}, 0, 0, # struct list_head @@ -245,7 +245,7 @@ my %commands = ); # -# setup completion function +# setup completion function # my @jcm_cmd_list = keys %commands; @@ -258,9 +258,9 @@ Device($::device); sub readl { if ( $file ) { - my $str = ; - chop($str); - return $str; + my $str = ; + chop($str); + return $str; } else { return $term->readline(@_); } @@ -278,7 +278,7 @@ if ( $file ) { $term = new Term::ReadLine 'obdcontrol '; $attribs = $term->Attribs; $attribs->{attempted_completion_function} = \&completeme; - $term->ornaments('md,me,,'); # bold face prompt + $term->ornaments('md,me,,'); # bold face prompt # make sure stdout is not buffered STDOUT->autoflush(1); @@ -292,9 +292,9 @@ if ( $file ) { sub completeme { my ($text, $line, $start, $end) = @_; if (substr($line, 0, $start) =~ /^\s*$/) { - $attribs->{completion_word} = \@jcm_cmd_list; - return $term->completion_matches($text, - $attribs->{'list_completion_function'}); + $attribs->{completion_word} = \@jcm_cmd_list; + return $term->completion_matches($text, + $attribs->{'list_completion_function'}); } } @@ -303,7 +303,7 @@ sub find_command { my $name; my @completions = completeme($given, $given, 0, length($given)); if ($#completions == 0) { - $name = shift @completions; + $name = shift @completions; } return $name; @@ -325,17 +325,17 @@ sub execute_line { my $cmd; if ( $file ) { - $cmd = $word; + $cmd = $word; } else { - $cmd = find_command($word); + $cmd = find_command($word); } unless ($cmd) { - printf STDERR "$word: No such command, or not unique.\n"; - return (-1); + printf STDERR "$word: No such command, or not unique.\n"; + return (-1); } if ($cmd eq "help" || $cmd eq "exit" || $cmd eq "quit") { - return (&{$commands{$cmd}->{func}}(@cmdline)); + return (&{$commands{$cmd}->{func}}(@cmdline)); } # Call the function. @@ -348,11 +348,11 @@ sub Device { my $device = shift; if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); + print "Disconnecting active session ($::client_id)..."; + Disconnect($::client_id); } if (! $device ) { - $device = "/dev/obd0"; + $device = "/dev/obd0"; } $::device = $device; # Open the device, as we need an FD for the ioctl @@ -368,33 +368,33 @@ sub Attach { my $datalen = 0; if ( ! $type ) { - print "error: missing type\n"; + print "error: missing type\n"; usage: - print "usage: attach {obdext2 | obdsnap | obdscsi}\n"; - return; + print "usage: attach {obdext2 | obdsnap | obdscsi}\n"; + return; } if ($type eq "obdscsi" ) { - my $adapter = shift; - my $bus = shift; - my $tid = shift; - my $lun = shift; + my $adapter = shift; + my $bus = shift; + my $tid = shift; + my $lun = shift; - $data = pack("iiii", $adapter, $bus, $tid, $lun); - $datalen = 4 * 4; + $data = pack("iiii", $adapter, $bus, $tid, $lun); + $datalen = 4 * 4; } elsif ($type eq "obdsnap" ) { - my $snapdev = shift; - my $snapidx = shift; - my $tableno = shift; + my $snapdev = shift; + my $snapidx = shift; + my $tableno = shift; - $data = pack("iii", $snapdev, $snapidx, $tableno); - $datalen = 3 * 4; + $data = pack("iii", $snapdev, $snapidx, $tableno); + $datalen = 3 * 4; } elsif ($type eq "obdext2") { - $data = pack("i", 4711); # bogus data - $datalen = 0; + $data = pack("i", 4711); # bogus data + $datalen = 0; } else { - print "error: unknown attach type $type\n"; - goto usage; + print "error: unknown attach type $type\n"; + goto usage; } my $len = length($type); @@ -406,11 +406,11 @@ usage: my $rc = ioctl(DEV_OBD, &OBD_IOC_ATTACH, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -421,19 +421,19 @@ sub Detach { my $rc = ioctl(DEV_OBD, &OBD_IOC_DETACH, $data); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub TestExt2Iterator { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $err = 0; @@ -450,19 +450,19 @@ sub TestExt2Iterator { my $rc = ioctl(DEV_OBD, &OBD_EXT2_RUNIT, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub SnapDelete { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $err = 0; @@ -481,11 +481,11 @@ sub SnapDelete { my $rc = ioctl(DEV_OBD, &OBD_SNAP_DELETE, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -499,32 +499,32 @@ sub SnapRestore { # don't do anything until connected if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } if ( ! $snaptable || ! defined $restoreto ) { - print "Usage: snaprestore \"restore to slot\" \"snaptable\" \"tableno\"\n"; - return; + print "Usage: snaprestore \"restore to slot\" \"snaptable\" \"tableno\"\n"; + return; } if ( ! -f $snaptable ) { - print "Table $snaptable doesn't exist\n"; - return; + print "Table $snaptable doesn't exist\n"; + return; } my $table = ReadSnapShotTable($snaptable); $restoretime = FindSnapInTable($table, $restoreto); if ( ! defined $table->{0} || ! defined $restoretime ) { - PrintSnapShotTable($table); - print "No current or $restoreto slot in this table\n"; - return; + PrintSnapShotTable($table); + print "No current or $restoreto slot in this table\n"; + return; } my $currentindex = $table->{0}; if ( $table->{$restoretime} == $currentindex ) { - print "You should not restore to the current snapshot\n"; - return; + print "You should not restore to the current snapshot\n"; + return; } # swap the entries for 0 and $restoreto @@ -552,19 +552,19 @@ sub SnapRestore { my $rc = ioctl(DEV_OBD, &OBD_SNAP_RESTORE, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Snaprestore finished (success)\n"; - delete $table->{$restoretime} if defined $restoretime; - # write it back - WriteSnapShotTable($snaptable, $table); - - # set it in the kernel - SnapSetTable($tableno, $snaptable); - # PrintSnapShotTable($table); + print "Snaprestore finished (success)\n"; + delete $table->{$restoretime} if defined $restoretime; + # write it back + WriteSnapShotTable($snaptable, $table); + + # set it in the kernel + SnapSetTable($tableno, $snaptable); + # PrintSnapShotTable($table); } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -573,14 +573,14 @@ sub FindSnapInTable { my $snapno =shift; foreach my $restoretime ( keys %{$table} ) { - if ( $table->{$restoretime} == $snapno) { - print "Found key $restoretime for snapno $snapno\n"; - return $restoretime; - } + if ( $table->{$restoretime} == $snapno) { + print "Found key $restoretime for snapno $snapno\n"; + return $restoretime; + } } undef; } - + sub SnapPrint { my $err = 0; @@ -598,11 +598,11 @@ sub SnapPrint { my $rc = ioctl(DEV_OBD, &OBD_SNAP_PRINTTABLE, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -617,7 +617,7 @@ sub SnapSetTable { my $datalen = 0; if ( ! -f $file ) { - print "No such file $file\n"; + print "No such file $file\n"; } $table = ReadSnapShotTable($file); @@ -626,15 +626,15 @@ sub SnapSetTable { print "Snapcount $snapcount\n"; if ( ! defined $table->{0} ) { - print "No current snapshot in table! First make one\n"; - return ; + print "No current snapshot in table! First make one\n"; + return ; } $data = pack("ii", $snaptableno, $snapcount); $datalen = 2 * 4; foreach my $time (sort keys %{$table}) { - # XXX we should change to pack LL instead of I for times - $data .= pack("Ii", $time, $table->{$time}); - $datalen += 8; + # XXX we should change to pack LL instead of I for times + $data .= pack("Ii", $time, $table->{$time}); + $datalen += 8; } my $len = length($type); @@ -645,11 +645,11 @@ sub SnapSetTable { my $rc = ioctl(DEV_OBD, &OBD_SNAP_SETTABLE, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -658,7 +658,7 @@ sub SnapShotTable { my $file = &readl("enter file name: "); if ( ! -f $file ) { - `touch $file`; + `touch $file`; } my $table = ReadSnapShotTable($file); @@ -675,14 +675,14 @@ sub SnapShotTable { my $time = &readl("enter time or 'now' or 'current': "); my $oldtime = SnapFindTimeFromIdx($idx, $table); if (defined $oldtime) { - print "This already exists, first clean up\n"; - goto again; + print "This already exists, first clean up\n"; + goto again; } if ( $time eq 'now' ) { - $time = time; + $time = time; } elsif ( $time eq 'current' ) { - $time = 0; + $time = 0; } $table->{$time} = $idx; goto again; @@ -696,7 +696,7 @@ sub SnapShotTable { done: my $ok = &readl("OK with new table? [Yn]: "); unless ( $ok eq "n" ) { - WriteSnapShotTable($file, $table); + WriteSnapShotTable($file, $table); } } @@ -705,9 +705,9 @@ sub SnapFindTimeFromIdx { my $table = shift; foreach my $time ( keys %{$table} ) { - if ( $table->{$time} == $idx ) { - return $time; - } + if ( $table->{$time} == $idx ) { + return $time; + } } undef; } @@ -717,11 +717,11 @@ sub PrintSnapShotTable { my $time; foreach $time ( sort keys %{$table} ) { - my $stime = localtime($time); - if ( ! $time ) { - $stime = "current"; - } - printf "Time: %s -- Index %d\n", $stime, $table->{$time}; + my $stime = localtime($time); + if ( ! $time ) { + $stime = "current"; + } + printf "Time: %s -- Index %d\n", $stime, $table->{$time}; } } @@ -732,8 +732,8 @@ sub ReadSnapShotTable { open FH, "<$file"; while ( ) { - my ($time, $index) = split ; - $table->{$time} = $index; + my ($time, $index) = split ; + $table->{$time} = $index; } close FH; @@ -748,7 +748,7 @@ sub WriteSnapShotTable { open FH, ">$file"; foreach my $time ( sort keys %{$table} ) { - print FH "$time $table->{$time}\n"; + print FH "$time $table->{$time}\n"; } close FH; } @@ -770,11 +770,11 @@ sub Copy { my $rc = ioctl(DEV_OBD, &OBD_IOC_COPY, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -793,11 +793,11 @@ sub Migrate { my $rc = ioctl(DEV_OBD, &OBD_IOC_MIGR, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -812,11 +812,11 @@ sub Format { my $rc = ioctl(DEV_OBD, &OBD_IOC_FORMATOBD, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -831,11 +831,11 @@ sub Partition { my $rc = ioctl(DEV_OBD, &OBD_IOC_PARTITION, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -849,25 +849,25 @@ sub Setup { # by type here if ($arg && !defined($::st = stat($arg))) { - print "$dev is not a valid device\n"; - return; + print "$dev is not a valid device\n"; + return; } if ( $arg ) { - $dev = $::st->rdev() unless $dev; - $data = pack("i", $dev); - $datalen = 4; + $dev = $::st->rdev() unless $dev; + $data = pack("i", $dev); + $datalen = 4; } my $packed = pack("ip", $datalen, $data); my $rc = ioctl(DEV_OBD, &OBD_IOC_SETUP, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -876,12 +876,12 @@ sub Cleanup { my $rc = ioctl(DEV_OBD, &OBD_IOC_CLEANUP, $err); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; - $::client_id = 0; + print "Finished (success)\n"; + $::client_id = 0; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -894,13 +894,13 @@ sub Connect { $id = unpack("I", $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - $::client_id = $id; - print "Client ID : $id\n"; - print "Finished (success)\n"; + $::client_id = $id; + print "Client ID : $id\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -908,33 +908,33 @@ sub Disconnect { my $id = shift; if (!defined($id)) { - $id = $::client_id; + $id = $::client_id; } if (!defined($id)) { - print "syntax: disconnect [client ID]\n"; - print "When client ID is not given, the last valid client ID to be returned by a\n"; - print "connect command this session is used; there is no such ID.\n"; - return; + print "syntax: disconnect [client ID]\n"; + print "When client ID is not given, the last valid client ID to be returned by a\n"; + print "connect command this session is used; there is no such ID.\n"; + return; } my $packed = pack("L", $id); my $rc = ioctl(DEV_OBD, &OBD_IOC_DISCONNECT, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - $::client_id = undef; - print "Finished (success)\n"; + $::client_id = undef; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Create { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $num = shift; @@ -948,45 +948,45 @@ sub Create { } if (!defined($mode)) { - $mode = 0100644; # create a file (rw-r--r--) if not specified + $mode = 0100644; # create a file (rw-r--r--) if not specified } if (scalar($num) < 1 || defined($quiet) && $quiet ne "quiet") { - print "usage: create [ [ [quiet]]]\n"; - return; + print "usage: create [ [ [quiet]]]\n"; + return; } my $i; - my $id = 0; # can't currently request IDs + my $id = 0; # can't currently request IDs print "Creating " . scalar($num) . " object"; if (scalar($num) > 1) { - print "s"; + print "s"; } print "\n"; for ($i = 0; $i < scalar($num); $i++) { - my $obdo; - $obdo->{id} = $id; - $obdo->{mode} = scalar($mode); - $obdo->{valid} = &OBD_MD_FLMODE; + my $obdo; + $obdo->{id} = $id; + $obdo->{mode} = scalar($mode); + $obdo->{valid} = &OBD_MD_FLMODE; - my $packed = pack("I", $::client_id) . obdo_pack($obdo); - $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed); - if ($rc ne "0 but true") { - last; - } elsif (!defined($quiet)) { - $obdo = obdo_unpack($packed, 4); - print "Created object #$obdo->{id}.\n"; - } + my $packed = pack("I", $::client_id) . obdo_pack($obdo); + $rc = ioctl(DEV_OBD, &OBD_IOC_CREATE, $packed); + if ($rc ne "0 but true") { + last; + } elsif (!defined($quiet)) { + $obdo = obdo_unpack($packed, 4); + print "Created object #$obdo->{id}.\n"; + } } if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -995,25 +995,25 @@ sub Sync { my $rc = ioctl(DEV_OBD, &OBD_IOC_SYNC, $err); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Destroy { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; if (!defined($id) || scalar($id) < 1) { - print "usage: destroy \n"; - return; + print "usage: destroy \n"; + return; } print "Destroying object $id...\n"; @@ -1021,25 +1021,25 @@ sub Destroy { my $rc = ioctl(DEV_OBD, &OBD_IOC_DESTROY, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Getattr { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; if (!defined($id) || scalar($id) < 1) { - print "invalid arguments; type \"help getattr\" for a synopsis\n"; - return; + print "invalid arguments; type \"help getattr\" for a synopsis\n"; + return; } # see Setattr @@ -1050,26 +1050,26 @@ sub Getattr { my $rc = ioctl(DEV_OBD, &OBD_IOC_GETATTR, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - $obdo = obdo_unpack($packed, 4); - obdo_print($obdo); + $obdo = obdo_unpack($packed, 4); + obdo_print($obdo); } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Setattr { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; if (!defined($id) || scalar($id) < 1) { - print "invalid arguments; type \"help setattr\" for a synopsis\n"; - return; + print "invalid arguments; type \"help setattr\" for a synopsis\n"; + return; } # XXX we do not currently set all of the fields in the obdo @@ -1085,25 +1085,25 @@ sub Setattr { $obdo->{valid} = 0; if (defined($obdo->{atime})) { - $obdo->{valid} |= &OBD_MD_FLATIME; + $obdo->{valid} |= &OBD_MD_FLATIME; } if (defined($obdo->{mtime})) { - $obdo->{valid} |= &OBD_MD_FLMTIME; + $obdo->{valid} |= &OBD_MD_FLMTIME; } if (defined($obdo->{ctime})) { - $obdo->{valid} |= &OBD_MD_FLCTIME; + $obdo->{valid} |= &OBD_MD_FLCTIME; } if (defined($obdo->{size})) { - $obdo->{valid} |= &OBD_MD_FLSIZE; + $obdo->{valid} |= &OBD_MD_FLSIZE; } if (defined($obdo->{mode})) { - $obdo->{valid} |= &OBD_MD_FLMODE; + $obdo->{valid} |= &OBD_MD_FLMODE; } if (defined($obdo->{uid})) { - $obdo->{valid} |= &OBD_MD_FLUID; + $obdo->{valid} |= &OBD_MD_FLUID; } if (defined($obdo->{gid})) { - $obdo->{valid} |= &OBD_MD_FLGID; + $obdo->{valid} |= &OBD_MD_FLGID; } printf "valid is %x, mode is %o\n", $obdo->{valid}, $obdo->{mode}; @@ -1111,18 +1111,18 @@ sub Setattr { my $rc = ioctl(DEV_OBD, &OBD_IOC_SETATTR, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Read { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; @@ -1130,17 +1130,17 @@ sub Read { my $offset = shift; if (!defined($id) || scalar($id) < 1 || !defined($count) || - $count < 1 || (defined($offset) && $offset < 0)) { - print "invalid arguments; type \"help read\" for a synopsis\n"; - return; + $count < 1 || (defined($offset) && $offset < 0)) { + print "invalid arguments; type \"help read\" for a synopsis\n"; + return; } if (!defined($offset)) { - $offset = 0; + $offset = 0; } print("Reading $count bytes starting at byte $offset from object " . - "$id...\n"); + "$id...\n"); # "allocate" a large enough buffer my $buf = sprintf("%${count}s", " "); @@ -1151,31 +1151,31 @@ sub Read { # the perl we're using doesn't support pack type Q, and offset is 64 bits my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $count, $offset); + pack("p LL LL", $buf, $count, $offset); my $rc = ioctl(DEV_OBD, &OBD_IOC_READ, $packed); $retval = unpack("l", $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print substr($buf, 0, $retval); - print "\nRead $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - } else { - print "Finished (error $retval)\n"; - } + if ($retval >= 0) { + print substr($buf, 0, $retval); + print "\nRead $retval of an attempted $count bytes.\n"; + print "Finished (success)\n"; + } else { + print "Finished (error $retval)\n"; + } } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Read2 { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; @@ -1183,17 +1183,17 @@ sub Read2 { my $offset = shift; if (!defined($id) || scalar($id) < 1 || !defined($count) || - $count < 1 || (defined($offset) && $offset < 0)) { - print "invalid arguments; type \"help read\" for a synopsis\n"; - return; + $count < 1 || (defined($offset) && $offset < 0)) { + print "invalid arguments; type \"help read\" for a synopsis\n"; + return; } if (!defined($offset)) { - $offset = 0; + $offset = 0; } print("Reading $count bytes starting at byte $offset from object " . - "$id...\n"); + "$id...\n"); # "allocate" a large enough buffer my $buf = sprintf("%${count}s", " "); @@ -1204,31 +1204,31 @@ sub Read2 { # the perl we're using doesn't support pack type Q, and offset is 64 bits my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $count, $offset); + pack("p LL LL", $buf, $count, $offset); my $rc = ioctl(DEV_OBD, &OBD_IOC_READ2, $packed); $retval = unpack("l", $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print substr($buf, 0, $retval); - print "\nRead $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - } else { - print "Finished (error $retval)\n"; - } + if ($retval >= 0) { + print substr($buf, 0, $retval); + print "\nRead $retval of an attempted $count bytes.\n"; + print "Finished (success)\n"; + } else { + print "Finished (error $retval)\n"; + } } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Write { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; @@ -1237,14 +1237,14 @@ sub Write { my $count = length($text); if (!defined($id) || scalar($id) < 1 || !defined($offset) || - scalar($offset) < 0) { - print "invalid arguments; type \"help write\" for a synopsis\n"; - return; + scalar($offset) < 0) { + print "invalid arguments; type \"help write\" for a synopsis\n"; + return; } if (!defined($text)) { - $text = ""; - $count = 0; + $text = ""; + $count = 0; } print("Writing $count bytes starting at byte $offset to object $id...\n"); @@ -1254,30 +1254,30 @@ sub Write { # the perl we're using doesn't support pack type Q my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $count, $offset); + pack("p LL LL", $text, $count, $offset); my $rc = ioctl(DEV_OBD, &OBD_IOC_WRITE, $packed); $retval = unpack("l", $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print "\nWrote $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - } else { - print "Finished (error $retval)\n"; - } + if ($retval >= 0) { + print "\nWrote $retval of an attempted $count bytes.\n"; + print "Finished (success)\n"; + } else { + print "Finished (error $retval)\n"; + } } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Punch { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } my $id = shift; @@ -1285,9 +1285,9 @@ sub Punch { my $count = shift; if (!defined($id) || scalar($id) < 1 || !defined($start) || - scalar($start) < 0 || !defined($count) || scalar($count) < 0) { - print "invalid arguments; type \"help punch\" for a synopsis\n"; - return; + scalar($start) < 0 || !defined($count) || scalar($count) < 0) { + print "invalid arguments; type \"help punch\" for a synopsis\n"; + return; } print("Punching $count bytes starting at byte $start from object $id...\n"); @@ -1297,23 +1297,23 @@ sub Punch { # the perl we're using doesn't support pack type Q my $packed = pack("L", $::client_id) . obdo_pack($obdo) . - pack("p LL LL", $buf, $start, $count); + pack("p LL LL", $buf, $start, $count); my $rc = ioctl(DEV_OBD, &OBD_IOC_PUNCH, $packed); $retval = unpack("l", $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - if ($retval >= 0) { - print "\nPunched $retval of an attempted $count bytes.\n"; - print "Finished (success)\n"; - } else { - print "Finished (error $retval)\n"; - } + if ($retval >= 0) { + print "\nPunched $retval of an attempted $count bytes.\n"; + print "Finished (success)\n"; + } else { + print "Finished (error $retval)\n"; + } } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -1321,12 +1321,12 @@ sub Preallocate { my $num = shift; if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } if (!defined($num) || scalar($num) < 1 || scalar($num) > 32) { - $num = 32; + $num = 32; } print "Preallocating $num objects...\n"; @@ -1336,19 +1336,19 @@ sub Preallocate { my $rc = ioctl(DEV_OBD, &OBD_IOC_PREALLOCATE, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - my $alloc = unpack("x4L", $packed); - my @ids = unpack("x8L32", $packed); - my $i; - - print "Got $alloc objects: "; - foreach $i (@ids) { - print $i . " "; - } - print "\nFinished (success)\n"; + my $alloc = unpack("x4L", $packed); + my @ids = unpack("x8L32", $packed); + my $i; + + print "Got $alloc objects: "; + foreach $i (@ids) { + print $i . " "; + } + print "\nFinished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -1356,18 +1356,18 @@ sub Decusecount { my $rc = ioctl(DEV_OBD, &OBD_IOC_DEC_USE_COUNT, 0); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - print "Finished (success)\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } sub Statfs { if (!defined($::client_id)) { - print "You must first ``connect''.\n"; - return; + print "You must first ``connect''.\n"; + return; } # struct statfs { @@ -1384,22 +1384,22 @@ sub Statfs { # }; my $packed = pack("LLLLLLLIILL6", $::client_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0); + 0, 0, 0, 0, 0, 0); my $rc = ioctl(DEV_OBD, &OBD_IOC_STATFS, $packed); if (!defined $rc) { - print STDERR "ioctl failed: $!\n"; + print STDERR "ioctl failed: $!\n"; } elsif ($rc eq "0 but true") { - # skip both the conn_id and the fs_type in the buffer - my ($bsize, $blocks, $bfree, $bavail, $files, $ffree) = - unpack("x4x4LLLLLL", $packed); - print("$bsize byte blocks: $blocks, " . ($blocks - $bfree) . " used, " . - "$bfree free ($bavail available).\n"); - print "$files files, " . ($files - $ffree) . " used, $ffree free.\n"; - print "Finished (success)\n"; + # skip both the conn_id and the fs_type in the buffer + my ($bsize, $blocks, $bfree, $bavail, $files, $ffree) = + unpack("x4x4LLLLLL", $packed); + print("$bsize byte blocks: $blocks, " . ($blocks - $bfree) . " used, " . + "$bfree free ($bavail available).\n"); + print "$files files, " . ($files - $ffree) . " used, $ffree free.\n"; + print "Finished (success)\n"; } else { - print "ioctl returned error code $rc.\n"; + print "ioctl returned error code $rc.\n"; } } @@ -1407,16 +1407,16 @@ sub Help { my $cmd = shift; if ( !$cmd || !$commands{$cmd} ) { - print "Comands: ", join( ' ', @jcm_cmd_list), "\n"; + print "Comands: ", join( ' ', @jcm_cmd_list), "\n"; } else { - print "Usage: " . $commands{$cmd}->{doc} . "\n"; + print "Usage: " . $commands{$cmd}->{doc} . "\n"; } } sub Quit { if ($::client_id) { - print "Disconnecting active session ($::client_id)..."; - Disconnect($::client_id); + print "Disconnecting active session ($::client_id)..."; + Disconnect($::client_id); } exit; } diff --git a/lustre/obdfs/dir.c b/lustre/obdfs/dir.c index 56db69a..59e6fb0 100644 --- a/lustre/obdfs/dir.c +++ b/lustre/obdfs/dir.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -40,190 +39,173 @@ #include static ssize_t obdfs_dir_read (struct file * filp, char * buf, - size_t count, loff_t *ppos) + size_t count, loff_t *ppos) { - return -EISDIR; + return -EISDIR; } static int obdfs_readdir(struct file *, void *, filldir_t); struct file_operations obdfs_dir_operations = { - NULL, /* lseek - default */ - obdfs_dir_read, /* read */ - NULL, /* write - bad */ - obdfs_readdir, /* readdir */ - NULL, /* poll - default */ - NULL, /* ioctl */ - NULL, /* mmap */ - NULL, /* no special open code */ - NULL, /* flush */ - NULL, /* no special release code */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL /* lock */ + read: obdfs_dir_read, + readdir: obdfs_readdir }; struct inode_operations obdfs_dir_inode_operations = { - &obdfs_dir_operations, /* default directory file-ops */ - obdfs_create, /* create */ - obdfs_lookup, /* lookup */ - obdfs_link, /* link */ - obdfs_unlink, /* unlink */ - obdfs_symlink, /* symlink */ - obdfs_mkdir, /* mkdir */ - obdfs_rmdir, /* rmdir */ - obdfs_mknod, /* mknod */ - obdfs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - obdfs_readpage, /* readpage */ - obdfs_writepage, /* writepage */ - obdfs_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ + create: obdfs_create, + lookup: obdfs_lookup, + link: obdfs_link, + unlink: obdfs_unlink, + symlink: obdfs_symlink, + mkdir: obdfs_mkdir, + rmdir: obdfs_rmdir, + mknod: obdfs_mknod, + rename: obdfs_rename, + truncate: obdfs_truncate }; int obdfs_check_dir_entry (const char * function, struct inode * dir, - struct ext2_dir_entry_2 * de, - struct page * page, - unsigned long offset) + struct ext2_dir_entry_2 * de, + struct page * page, + unsigned long offset) { - const char * error_msg = NULL; - return 1; - - ENTRY; - if ( !de ) { - error_msg = "null de passed"; - return 1; - } - - if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) - error_msg = "rec_len is smaller than minimal"; - else if (le16_to_cpu(de->rec_len) % 4 != 0) - error_msg = "rec_len % 4 != 0"; - else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len)) - error_msg = "rec_len is too small for name_len"; - else if (dir && ((char *) de - (char *)page_address(page)) + le16_to_cpu(de->rec_len) > - dir->i_sb->s_blocksize) - error_msg = "directory entry across blocks"; + const char * error_msg = NULL; + return 1; + + ENTRY; + if ( !de ) { + error_msg = "null de passed"; + return 1; + } + + if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) + error_msg = "rec_len is smaller than minimal"; + else if (le16_to_cpu(de->rec_len) % 4 != 0) + error_msg = "rec_len % 4 != 0"; + else if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(de->name_len)) + error_msg = "rec_len is too small for name_len"; + else if (dir && ((char *) de - (char *)page_address(page)) + le16_to_cpu(de->rec_len) > + dir->i_sb->s_blocksize) + error_msg = "directory entry across blocks"; #if 0 /* this one doesn't yet work for OBDFS */ - else + else if (dir && le32_to_cpu(de->inode) > le32_to_cpu(dir->i_sb->u.ext2_sb.s_es->s_inodes_count)) - error_msg = "inode out of bounds"; + error_msg = "inode out of bounds"; #endif - if (error_msg != NULL) - ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - " - "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", - dir->i_ino, error_msg, offset, - (unsigned long) le32_to_cpu(de->inode), - le16_to_cpu(de->rec_len), de->name_len); - EXIT; - return error_msg == NULL ? 1 : 0; + if (error_msg != NULL) + ext2_error (dir->i_sb, function, "bad entry in directory #%lu: %s - " + "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", + dir->i_ino, error_msg, offset, + (unsigned long) le32_to_cpu(de->inode), + le16_to_cpu(de->rec_len), de->name_len); + EXIT; + return error_msg == NULL ? 1 : 0; } static int obdfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { - int error = 0; - unsigned long offset; - int stored; - struct ext2_dir_entry_2 * de; - struct super_block * sb; - struct page *page; - struct inode *inode = filp->f_dentry->d_inode; - - ENTRY; - - sb = inode->i_sb; - - stored = 0; - offset = filp->f_pos & (PAGE_SIZE - 1); - - OIDEBUG(inode); - while (!error && !stored && filp->f_pos < inode->i_size) { - page = obdfs_getpage(inode, filp->f_pos, 0, LOCKED); - /* PDEBUG(page, "readdir"); */ - if (!page) { - ext2_error (sb, "ext2_readdir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, (unsigned long)filp->f_pos); - filp->f_pos += PAGE_SIZE - offset; - continue; - } + int error = 0; + unsigned long offset; + int stored; + struct ext2_dir_entry_2 * de; + struct super_block * sb; + struct page *page; + struct inode *inode = filp->f_dentry->d_inode; + + ENTRY; + + sb = inode->i_sb; + + stored = 0; + offset = filp->f_pos & (PAGE_SIZE - 1); + + OIDEBUG(inode); + while (!error && !stored && filp->f_pos < inode->i_size) { + page = obdfs_getpage(inode, filp->f_pos, 0, LOCKED); + /* PDEBUG(page, "readdir"); */ + if (!page) { + ext2_error (sb, "ext2_readdir", + "directory #%lu contains a hole at offset %lu", + inode->i_ino, (unsigned long)filp->f_pos); + filp->f_pos += PAGE_SIZE - offset; + continue; + } #if 0 - /* XXX need to do read ahead and support stuff below */ + /* XXX need to do read ahead and support stuff below */ revalidate: - /* If the dir block has changed since the last call to - * readdir(2), then we might be pointing to an invalid - * dirent right now. Scan from the start of the block - * to make sure. */ - if (filp->f_version != inode->i_version) { - for (i = 0; i < sb->s_blocksize && i < offset; ) { - de = (struct ext2_dir_entry_2 *) - (bh->b_data + i); - /* It's too expensive to do a full - * dirent test each time round this - * loop, but we do have to test at - * least that it is non-zero. A - * failure will be detected in the - * dirent test below. */ - if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) - break; - i += le16_to_cpu(de->rec_len); - } - offset = i; - filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) - | offset; - filp->f_version = inode->i_version; - } -#endif - while (!error && filp->f_pos < inode->i_size - && offset < PAGE_SIZE) { - de = (struct ext2_dir_entry_2 *) ((char *)page_address(page) + offset); + /* If the dir block has changed since the last call to + * readdir(2), then we might be pointing to an invalid + * dirent right now. Scan from the start of the block + * to make sure. */ + if (filp->f_version != inode->i_version) { + for (i = 0; i < sb->s_blocksize && i < offset; ) { + de = (struct ext2_dir_entry_2 *) + (bh->b_data + i); + /* It's too expensive to do a full + * dirent test each time round this + * loop, but we do have to test at + * least that it is non-zero. A + * failure will be detected in the + * dirent test below. */ + if (le16_to_cpu(de->rec_len) < EXT2_DIR_REC_LEN(1)) + break; + i += le16_to_cpu(de->rec_len); + } + offset = i; + filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) + | offset; + filp->f_version = inode->i_version; + } +#endif + while (!error && filp->f_pos < inode->i_size + && offset < PAGE_SIZE) { + de = (struct ext2_dir_entry_2 *) ((char *)page_address(page) + offset); #if 0 - if (!obdfs_check_dir_entry ("ext2_readdir", inode, de, - bh, offset)) { - /* On error, skip the f_pos to the + if (!obdfs_check_dir_entry ("ext2_readdir", inode, de, + bh, offset)) { + /* On error, skip the f_pos to the next block. */ - filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) - + sb->s_blocksize; - brelse (bh); - return stored; - } + filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + + sb->s_blocksize; + brelse (bh); + return stored; + } #endif - offset += le16_to_cpu(de->rec_len); - if (le32_to_cpu(de->inode)) { - /* We might block in the next section - * if the data destination is - * currently swapped out. So, use a - * version stamp to detect whether or - * not the directory has been modified - * during the copy operation. - */ - /* XXX - unsigned long version = inode->i_version; - */ - error = filldir(dirent, de->name, - de->name_len, - filp->f_pos, le32_to_cpu(de->inode)); - if (error) - break; + offset += le16_to_cpu(de->rec_len); + if (le32_to_cpu(de->inode)) { + unsigned char d_type = DT_UNKNOWN; + /* We might block in the next section + * if the data destination is + * currently swapped out. So, use a + * version stamp to detect whether or + * not the directory has been modified + * during the copy operation. + */ + /* XXX + unsigned long version = inode->i_version; + */ + error = filldir + (dirent, de->name, de->name_len, + filp->f_pos, le32_to_cpu(de->inode), + d_type); + if (error) + break; #if 0 - if (version != inode->i_version) - goto revalidate; + if (version != inode->i_version) + goto revalidate; #endif - stored ++; - } - filp->f_pos += le16_to_cpu(de->rec_len); - } - offset = 0; - UnlockPage(page); - page_cache_release(page); - } - UPDATE_ATIME(inode); - EXIT; - return 0; + stored ++; + } + filp->f_pos += le16_to_cpu(de->rec_len); + } + offset = 0; + obd_unlock_page(page); + page_cache_release(page); + } + UPDATE_ATIME(inode); + EXIT; + return 0; } diff --git a/lustre/obdfs/file.c b/lustre/obdfs/file.c index 4416161..7623a9a 100644 --- a/lustre/obdfs/file.c +++ b/lustre/obdfs/file.c @@ -15,7 +15,7 @@ * ext2 fs regular file handling primitives * * 64-bit file support on 64-bit platforms by Jakub Jelinek - * (jj@sunsite.ms.mff.cuni.cz) + * (jj@sunsite.ms.mff.cuni.cz) */ #include @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -37,17 +36,17 @@ static inline void remove_suid(struct inode *inode) { - unsigned int mode; + unsigned int mode; - /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ - mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; + /* set S_IGID if S_IXGRP is set, and always set S_ISUID */ + mode = (inode->i_mode & S_IXGRP)*(S_ISGID/S_IXGRP) | S_ISUID; - /* was any of the uid bits set? */ - mode &= inode->i_mode; - if (mode && !capable(CAP_FSETID)) { - inode->i_mode &= ~mode; - mark_inode_dirty(inode); - } + /* was any of the uid bits set? */ + mode &= inode->i_mode; + if (mode && !capable(CAP_FSETID)) { + inode->i_mode &= ~mode; + mark_inode_dirty(inode); + } } /* @@ -56,57 +55,40 @@ static inline void remove_suid(struct inode *inode) static ssize_t obdfs_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - ssize_t retval; - CDEBUG(D_INFO, "Writing inode %ld, %d bytes, offset %ld\n", - file->f_dentry->d_inode->i_ino, count, (long)*ppos); + ssize_t retval; + CDEBUG(D_INFO, "Writing inode %ld, %d bytes, offset %ld\n", + file->f_dentry->d_inode->i_ino, count, (long)*ppos); - retval = generic_file_write(file, buf, count, - ppos, obdfs_write_one_page); - CDEBUG(D_INFO, "Wrote %d\n", retval); - if (retval > 0) { - struct inode *inode = file->f_dentry->d_inode; - remove_suid(inode); - inode->i_ctime = inode->i_mtime = CURRENT_TIME; - mark_inode_dirty(inode); - } - EXIT; - return retval; + retval = generic_file_write(file, buf, count, ppos); + CDEBUG(D_INFO, "Wrote %d\n", retval); + if (retval > 0) { + struct inode *inode = file->f_dentry->d_inode; + remove_suid(inode); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; + mark_inode_dirty(inode); + } + EXIT; + return retval; } struct file_operations obdfs_file_operations = { - NULL, /* lseek - default */ - generic_file_read, /* read */ - obdfs_file_write, /* write */ - NULL, /* readdir - bad */ - NULL, /* poll */ - NULL, /* ioctl */ - generic_file_mmap, /* mmap */ - NULL, /* open */ - NULL, /* flush */ - NULL, /* release */ - NULL /* XXX add XXX */, /* fsync */ - NULL, /* fasync */ - NULL /* lock */ + read: generic_file_read, /* read */ + write: obdfs_file_write, /* write */ + mmap: generic_file_mmap, /* mmap */ }; +extern int obdfs_notify_change(struct dentry *de, struct iattr *attr); struct inode_operations obdfs_file_inode_operations = { - &obdfs_file_operations, /* default directory file-ops */ - obdfs_create, /* create */ - obdfs_lookup, /* lookup */ - obdfs_link, /* link */ - obdfs_unlink, /* unlink */ - obdfs_symlink, /* symlink */ - obdfs_mkdir, /* mkdir */ - obdfs_rmdir, /* rmdir */ - obdfs_mknod, /* mknod */ - obdfs_rename, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* get_block */ - obdfs_readpage, /* readpage */ - obdfs_writepage, /* writepage */ - obdfs_truncate, /* truncate */ - NULL, /* permission */ - NULL /* revalidate */ + create: obdfs_create, + lookup: obdfs_lookup, + link: obdfs_link, + unlink: obdfs_unlink, + symlink: obdfs_symlink, + mkdir: obdfs_mkdir, + rmdir: obdfs_rmdir, + mknod: obdfs_mknod, + rename: obdfs_rename, + truncate: obdfs_truncate, + setattr: obdfs_notify_change }; diff --git a/lustre/obdfs/namei.c b/lustre/obdfs/namei.c index c474514..66bba9e 100644 --- a/lustre/obdfs/namei.c +++ b/lustre/obdfs/namei.c @@ -15,7 +15,7 @@ * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 + * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 * * Changes for use in OBDFS * Copyright (c) 1999, Seagate Technology Inc. @@ -37,6 +37,8 @@ #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS) #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b)) + + /* * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. * @@ -44,17 +46,17 @@ * `de != NULL' is guaranteed by caller. */ static inline int ext2_match (int len, const char * const name, - struct ext2_dir_entry_2 * de) + struct ext2_dir_entry_2 * de) { - if (len != de->name_len) - return 0; - if (!de->inode) - return 0; - return !memcmp(name, de->name, len); + if (len != de->name_len) + return 0; + if (!de->inode) + return 0; + return !memcmp(name, de->name, len); } /* - * obdfs_find_entry() + * obdfs_find_entry() * * finds an entry in the specified directory with the wanted name. It * returns the cache buffer in which the entry was found, and the entry @@ -62,126 +64,124 @@ static inline int ext2_match (int len, const char * const name, * entry - you'll have to do that yourself if you want to. */ static struct page * obdfs_find_entry (struct inode * dir, - const char * const name, int namelen, - struct ext2_dir_entry_2 ** res_dir, - int lock) + const char * const name, int namelen, + struct ext2_dir_entry_2 ** res_dir, + int lock) { - struct super_block * sb; - unsigned long offset; - struct page * page; - - ENTRY; - CDEBUG(D_INFO, "find entry for %*s\n", namelen, name); - - *res_dir = NULL; - sb = dir->i_sb; - - if (namelen > EXT2_NAME_LEN) - return NULL; - - CDEBUG(D_INFO, "dirsize is %Ld\n", dir->i_size); - - page = 0; - offset = 0; - while ( offset < dir->i_size ) { - struct ext2_dir_entry_2 * de; - char * dlimit; - - page = obdfs_getpage(dir, offset, 0, lock); - - if ( !page ) { - CDEBUG(D_INFO, "No page, offset %lx\n", offset); - return NULL; - } - - de = (struct ext2_dir_entry_2 *) page_address(page); - dlimit = (char *)page_address(page) + PAGE_SIZE; - while ((char *) de < dlimit) { - /* this code is executed quadratically often */ - /* do minimal checking `by hand' */ - int de_len; - /* CDEBUG(D_INFO, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n", - de, le16_to_cpu(de->rec_len), page_address(page), - page_address(page) + PAGE_SIZE, offset); */ - - if ((char *) de + namelen <= dlimit && - ext2_match (namelen, name, de)) { - /* found a match - - just to be sure, do a full check */ - if (!obdfs_check_dir_entry("ext2_find_entry", - dir, de, page, offset)) - goto failure; - *res_dir = de; - EXIT; - return page; - } - /* prevent looping on a bad block */ - de_len = le16_to_cpu(de->rec_len); - if (de_len <= 0) { - printk("Bad entry at %p len %d\n", de, de_len); - goto failure; - } - offset += de_len; - de = (struct ext2_dir_entry_2 *) - ((char *) de + de_len); - /* CDEBUG(D_INFO, "Next while %lx\n", offset); */ - } - if ( lock ) - UnlockPage(page); - page_cache_release(page); - page = NULL; - CDEBUG(D_INFO, "Next for %lx\n", offset); - } + struct super_block * sb; + unsigned long offset; + struct page * page; + + ENTRY; + CDEBUG(D_INFO, "find entry for %*s\n", namelen, name); + + *res_dir = NULL; + sb = dir->i_sb; + + if (namelen > EXT2_NAME_LEN) + return NULL; + + CDEBUG(D_INFO, "dirsize is %Ld\n", dir->i_size); + + page = 0; + offset = 0; + while ( offset < dir->i_size ) { + struct ext2_dir_entry_2 * de; + char * dlimit; + + page = obdfs_getpage(dir, offset, 0, lock); + + if ( !page ) { + CDEBUG(D_INFO, "No page, offset %lx\n", offset); + return NULL; + } + + de = (struct ext2_dir_entry_2 *) page_address(page); + dlimit = (char *)page_address(page) + PAGE_SIZE; + while ((char *) de < dlimit) { + /* this code is executed quadratically often */ + /* do minimal checking `by hand' */ + int de_len; + /* CDEBUG(D_INFO, "Entry %p len %d, page at %#lx - %#lx , offset %lx\n", + de, le16_to_cpu(de->rec_len), page_address(page), + page_address(page) + PAGE_SIZE, offset); */ + + if ((char *) de + namelen <= dlimit && + ext2_match (namelen, name, de)) { + /* found a match - + just to be sure, do a full check */ + if (!obdfs_check_dir_entry("ext2_find_entry", + dir, de, page, offset)) + goto failure; + *res_dir = de; + EXIT; + return page; + } + /* prevent looping on a bad block */ + de_len = le16_to_cpu(de->rec_len); + if (de_len <= 0) { + printk("Bad entry at %p len %d\n", de, de_len); + goto failure; + } + offset += de_len; + de = (struct ext2_dir_entry_2 *) + ((char *) de + de_len); + /* CDEBUG(D_INFO, "Next while %lx\n", offset); */ + } + obd_unlock_page(page); + page_cache_release(page); + page = NULL; + CDEBUG(D_INFO, "Next for %lx\n", offset); + } failure: - CDEBUG(D_INFO, "Negative case, page %p, offset %ld\n", page, offset); - if (page) { - if (lock) - UnlockPage(page); - page_cache_release(page); - } - EXIT; - return NULL; + CDEBUG(D_INFO, "Negative case, page %p, offset %ld\n", page, offset); + if (page) { + obd_unlock_page(page); + page_cache_release(page); + } + EXIT; + return NULL; } /* obdfs_find_entry */ struct dentry *obdfs_lookup(struct inode *dir, struct dentry *dentry) { - struct inode * inode; - struct ext2_dir_entry_2 * de; - struct page *page; - ENTRY; - - if (dentry->d_name.len > EXT2_NAME_LEN) - return ERR_PTR(-ENAMETOOLONG); - - page = obdfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, - &de, LOCKED); - inode = NULL; - if ( !page ) - CDEBUG(D_INFO, "No page - negative entry.\n"); - if ( page && !de ) { - CDEBUG(D_INODE, "Danger: PAGE but de.\n"); - return ERR_PTR(-ENOENT); - } - if (page) { - unsigned long ino = le32_to_cpu(de->inode); - UnlockPage(page); - page_cache_release(page); - inode = iget(dir->i_sb, ino); - - if (!inode) { - CDEBUG(D_INODE, "No inode.\n"); - EXIT; - return ERR_PTR(-EACCES); - } - } - d_add(dentry, inode); - EXIT; - return NULL; + struct inode * inode; + struct ext2_dir_entry_2 * de; + struct page *page; + ENTRY; + + if (dentry->d_name.len > EXT2_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + page = obdfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, + &de, LOCKED); + inode = NULL; + if ( !page ) + CDEBUG(D_INFO, "No page - negative entry.\n"); + if ( page && !de ) { + CDEBUG(D_INODE, "Danger: PAGE but de.\n"); + return ERR_PTR(-ENOENT); + } + if (page) { + unsigned long ino = le32_to_cpu(de->inode); + page_cache_release(page); + obd_unlock_page(page); + inode = iget(dir->i_sb, ino); + + if (!inode) { + CDEBUG(D_INODE, "No inode.\n"); + EXIT; + return ERR_PTR(-EACCES); + } + } + d_add(dentry, inode); + EXIT; + return NULL; } /* obdfs_lookup */ /* - * obdfs_add_entry() + * obdfs_add_entry() * * adds a file entry to the specified directory, using the same * semantics as ext2_find_entry(). It returns NULL if it failed. @@ -198,161 +198,161 @@ struct dentry *obdfs_lookup(struct inode *dir, struct dentry *dentry) * on the inode protects this page as well. */ static struct page *obdfs_add_entry (struct inode * dir, - const char * name, int namelen, - struct ext2_dir_entry_2 ** res_dir, - int *err) + const char * name, int namelen, + struct ext2_dir_entry_2 ** res_dir, + int *err) { - unsigned long offset; - unsigned short rec_len; - struct page *page; - struct ext2_dir_entry_2 * de, * de1; - struct super_block * sb; - - ENTRY; - *err = -EINVAL; - *res_dir = NULL; - if (!dir || !dir->i_nlink) { - CDEBUG(D_INODE, "bad directory\n"); - EXIT; - return NULL; - } - sb = dir->i_sb; - - if (!namelen) { - CDEBUG(D_INODE, "bad directory\n"); - EXIT; - return NULL; - } - /* - * Is this a busy deleted directory? Can't create new files if so - */ - if (dir->i_size == 0) - { - OIDEBUG(dir); - *err = -ENOENT; - EXIT; - return NULL; - } - page = obdfs_getpage(dir, 0, 0, LOCKED); - if (!page) { - EXIT; - return NULL; - } - rec_len = EXT2_DIR_REC_LEN(namelen); - /* CDEBUG(D_INFO, "reclen: %d\n", rec_len); */ - /* PDEBUG(page, "starting search"); */ - offset = 0; - de = (struct ext2_dir_entry_2 *) page_address(page); - *err = -ENOSPC; - while (1) { - /* CDEBUG(D_INFO, - "Entry at %p, (page at %#lx - %#lx), offset %ld\n", - de, page_address(page), page_address(page) + PAGE_SIZE, - offset); */ - if ((char *)de >= PAGE_SIZE + (char *)page_address(page)) { - UnlockPage(page); - page_cache_release(page); - page = obdfs_getpage(dir, offset, 1, LOCKED); - if (!page) { - EXIT; - return NULL; - } - /* PDEBUG(page, "new directory page"); */ - if (dir->i_size <= offset) { - if (dir->i_size == 0) { - *err = -ENOENT; - EXIT; - return NULL; - } - - CDEBUG(D_INFO, "creating next block\n"); - - de = (struct ext2_dir_entry_2 *) page_address(page); - de->inode = 0; - de->rec_len = cpu_to_le16(PAGE_SIZE); - dir->i_size = offset + PAGE_SIZE; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - } else { - - CDEBUG(D_INFO, "skipping to next block\n"); - - de = (struct ext2_dir_entry_2 *) page_address(page); - } - } - if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page, - offset)) { - *err = -ENOENT; - UnlockPage(page); - page_cache_release(page); - EXIT; - return NULL; - } - CDEBUG(D_INFO, "\n"); - if (ext2_match (namelen, name, de)) { - *err = -EEXIST; - UnlockPage(page); - page_cache_release(page); - EXIT; - return NULL; - } - /* CDEBUG(D_INFO, "Testing for enough space at de %p\n", de);*/ - if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) || - (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) { - offset += le16_to_cpu(de->rec_len); - /* CDEBUG(D_INFO, - "Found enough space de %p, offset %#lx\n", - de, offset); */ - if (le32_to_cpu(de->inode)) { - /*CDEBUG(D_INFO, "Insert new in %p\n", de);*/ - de1 = (struct ext2_dir_entry_2 *) ((char *) de + - EXT2_DIR_REC_LEN(de->name_len)); - /*CDEBUG(D_INFO, "-- de1 at %p\n", de1);*/ - de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) - - EXT2_DIR_REC_LEN(de->name_len)); - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); - de = de1; - } - /* CDEBUG(D_INFO, - "Reclen adjusted; copy %d bytes to %p, " - "page at %#lx EOP at %#lx\n", - namelen, de->name, page_address(page), - page_address(page) + PAGE_SIZE); */ - de->inode = 0; - de->name_len = namelen; - de->file_type = 0; - memcpy (de->name, name, namelen); - /* - * XXX shouldn't update any times until successful - * completion of syscall, but too many callers depend - * on this. - * - * XXX similarly, too many callers depend on - * ext2_new_inode() setting the times, but error - * recovery deletes the inode, so the worst that can - * happen is that the times are slightly out of date - * and/or different from the directory change time. - */ - dir->i_mtime = dir->i_ctime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - dir->i_version = ++event; - *res_dir = de; - *err = 0; - /* PDEBUG(page, "add_entry"); */ - /* XXX unlock page here */ - EXIT; - return page; - } - offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - - UnlockPage(page); - page_cache_release(page); - /* PDEBUG(page, "add_entry"); */ - EXIT; - return NULL; + unsigned long offset; + unsigned short rec_len; + struct page *page; + struct ext2_dir_entry_2 * de, * de1; + struct super_block * sb; + + ENTRY; + *err = -EINVAL; + *res_dir = NULL; + if (!dir || !dir->i_nlink) { + CDEBUG(D_INODE, "bad directory\n"); + EXIT; + return NULL; + } + sb = dir->i_sb; + + if (!namelen) { + CDEBUG(D_INODE, "bad directory\n"); + EXIT; + return NULL; + } + /* + * Is this a busy deleted directory? Can't create new files if so + */ + if (dir->i_size == 0) + { + OIDEBUG(dir); + *err = -ENOENT; + EXIT; + return NULL; + } + page = obdfs_getpage(dir, 0, 0, LOCKED); + if (!page) { + EXIT; + return NULL; + } + rec_len = EXT2_DIR_REC_LEN(namelen); + /* CDEBUG(D_INFO, "reclen: %d\n", rec_len); */ + /* PDEBUG(page, "starting search"); */ + offset = 0; + de = (struct ext2_dir_entry_2 *) page_address(page); + *err = -ENOSPC; + while (1) { + /* CDEBUG(D_INFO, + "Entry at %p, (page at %#lx - %#lx), offset %ld\n", + de, page_address(page), page_address(page) + PAGE_SIZE, + offset); */ + if ((char *)de >= PAGE_SIZE + (char *)page_address(page)) { + obd_unlock_page(page); + page_cache_release(page); + page = obdfs_getpage(dir, offset, 1, LOCKED); + if (!page) { + EXIT; + return NULL; + } + /* PDEBUG(page, "new directory page"); */ + if (dir->i_size <= offset) { + if (dir->i_size == 0) { + *err = -ENOENT; + EXIT; + return NULL; + } + + CDEBUG(D_INFO, "creating next block\n"); + + de = (struct ext2_dir_entry_2 *) page_address(page); + de->inode = 0; + de->rec_len = cpu_to_le16(PAGE_SIZE); + dir->i_size = offset + PAGE_SIZE; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(dir); + } else { + + CDEBUG(D_INFO, "skipping to next block\n"); + + de = (struct ext2_dir_entry_2 *) page_address(page); + } + } + if (!obdfs_check_dir_entry ("ext2_add_entry", dir, de, page, + offset)) { + *err = -ENOENT; + obd_unlock_page(page); + page_cache_release(page); + EXIT; + return NULL; + } + CDEBUG(D_INFO, "\n"); + if (ext2_match (namelen, name, de)) { + *err = -EEXIST; + obd_unlock_page(page); + page_cache_release(page); + EXIT; + return NULL; + } + /* CDEBUG(D_INFO, "Testing for enough space at de %p\n", de);*/ + if ((le32_to_cpu(de->inode) == 0 && le16_to_cpu(de->rec_len) >= rec_len) || + (le16_to_cpu(de->rec_len) >= EXT2_DIR_REC_LEN(de->name_len) + rec_len)) { + offset += le16_to_cpu(de->rec_len); + /* CDEBUG(D_INFO, + "Found enough space de %p, offset %#lx\n", + de, offset); */ + if (le32_to_cpu(de->inode)) { + /*CDEBUG(D_INFO, "Insert new in %p\n", de);*/ + de1 = (struct ext2_dir_entry_2 *) ((char *) de + + EXT2_DIR_REC_LEN(de->name_len)); + /*CDEBUG(D_INFO, "-- de1 at %p\n", de1);*/ + de1->rec_len = cpu_to_le16(le16_to_cpu(de->rec_len) - + EXT2_DIR_REC_LEN(de->name_len)); + de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); + de = de1; + } + /* CDEBUG(D_INFO, + "Reclen adjusted; copy %d bytes to %p, " + "page at %#lx EOP at %#lx\n", + namelen, de->name, page_address(page), + page_address(page) + PAGE_SIZE); */ + de->inode = 0; + de->name_len = namelen; + de->file_type = 0; + memcpy (de->name, name, namelen); + /* + * XXX shouldn't update any times until successful + * completion of syscall, but too many callers depend + * on this. + * + * XXX similarly, too many callers depend on + * ext2_new_inode() setting the times, but error + * recovery deletes the inode, so the worst that can + * happen is that the times are slightly out of date + * and/or different from the directory change time. + */ + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(dir); + dir->i_version = ++event; + *res_dir = de; + *err = 0; + PDEBUG(page, "add_entry"); + /* XXX unlock page here */ + EXIT; + return page; + } + offset += le16_to_cpu(de->rec_len); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + } + + obd_unlock_page(page); + page_cache_release(page); + /* PDEBUG(page, "add_entry"); */ + EXIT; + return NULL; } /* obdfs_add_entry */ /* @@ -360,55 +360,56 @@ static struct page *obdfs_add_entry (struct inode * dir, * previous entry */ static int obdfs_delete_entry (struct ext2_dir_entry_2 * dir, - struct page * page) + struct page * page) { - struct ext2_dir_entry_2 * de, * pde; - int i; - - i = 0; - pde = NULL; - de = (struct ext2_dir_entry_2 *) page_address(page); - while (i < PAGE_SIZE) { - if (!obdfs_check_dir_entry ("ext2_delete_entry", NULL, - de, page, i)) - return -EIO; - if (de == dir) { - if (pde) - pde->rec_len = - cpu_to_le16(le16_to_cpu(pde->rec_len) + - le16_to_cpu(dir->rec_len)); - else - dir->inode = 0; - return 0; - } - i += le16_to_cpu(de->rec_len); - pde = de; - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - return -ENOENT; + struct ext2_dir_entry_2 * de, * pde; + int i; + + i = 0; + pde = NULL; + de = (struct ext2_dir_entry_2 *) page_address(page); + while (i < PAGE_SIZE) { + if (!obdfs_check_dir_entry ("ext2_delete_entry", NULL, + de, page, i)) + return -EIO; + if (de == dir) { + if (pde) + pde->rec_len = + cpu_to_le16(le16_to_cpu(pde->rec_len) + + le16_to_cpu(dir->rec_len)); + else + dir->inode = 0; + return 0; + } + i += le16_to_cpu(de->rec_len); + pde = de; + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + } + return -ENOENT; } /* obdfs_delete_entry */ static inline void ext2_set_de_type(struct super_block *sb, - struct ext2_dir_entry_2 *de, - umode_t mode) { - /* XXX fix this to check for obdfs feature, not ext2 feature */ - if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) - return; - if (S_ISREG(mode)) - de->file_type = EXT2_FT_REG_FILE; - else if (S_ISDIR(mode)) - de->file_type = EXT2_FT_DIR; - else if (S_ISLNK(mode)) - de->file_type = EXT2_FT_SYMLINK; - else if (S_ISSOCK(mode)) - de->file_type = EXT2_FT_SOCK; - else if (S_ISFIFO(mode)) - de->file_type = EXT2_FT_FIFO; - else if (S_ISCHR(mode)) - de->file_type = EXT2_FT_CHRDEV; - else if (S_ISBLK(mode)) - de->file_type = EXT2_FT_BLKDEV; + struct ext2_dir_entry_2 *de, + umode_t mode) { + return; + /* XXX fix this to check for obdfs feature, not ext2 feature */ + if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE)) + return; + if (S_ISREG(mode)) + de->file_type = EXT2_FT_REG_FILE; + else if (S_ISDIR(mode)) + de->file_type = EXT2_FT_DIR; + else if (S_ISLNK(mode)) + de->file_type = EXT2_FT_SYMLINK; + else if (S_ISSOCK(mode)) + de->file_type = EXT2_FT_SOCK; + else if (S_ISFIFO(mode)) + de->file_type = EXT2_FT_FIFO; + else if (S_ISCHR(mode)) + de->file_type = EXT2_FT_CHRDEV; + else if (S_ISBLK(mode)) + de->file_type = EXT2_FT_BLKDEV; } @@ -418,90 +419,90 @@ static inline void ext2_set_de_type(struct super_block *sb, #if 0 static void show_dentry(struct list_head * dlist, int subdirs) { - struct list_head *tmp = dlist; - - while ((tmp = tmp->next) != dlist) { - struct dentry * dentry; - const char * unhashed = ""; - - if ( subdirs ) - dentry = list_entry(tmp, struct dentry, d_child); - else - dentry = list_entry(tmp, struct dentry, d_alias); - - if (list_empty(&dentry->d_hash)) - unhashed = "(unhashed)"; - - if ( dentry->d_inode ) - printk("show_dentry: %s/%s, d_count=%d%s (ino %ld, dev %d, ct %d)\n", - dentry->d_parent->d_name.name, - dentry->d_name.name, dentry->d_count, - unhashed, dentry->d_inode->i_ino, - dentry->d_inode->i_dev, - dentry->d_inode->i_count); - else - printk("show_dentry: %s/%s, d_count=%d%s \n", - dentry->d_parent->d_name.name, - dentry->d_name.name, dentry->d_count, - unhashed); - } + struct list_head *tmp = dlist; + + while ((tmp = tmp->next) != dlist) { + struct dentry * dentry; + const char * unhashed = ""; + + if ( subdirs ) + dentry = list_entry(tmp, struct dentry, d_child); + else + dentry = list_entry(tmp, struct dentry, d_alias); + + if (list_empty(&dentry->d_hash)) + unhashed = "(unhashed)"; + + if ( dentry->d_inode ) + printk("show_dentry: %s/%s, d_count=%d%s (ino %ld, dev %d, ct %d)\n", + dentry->d_parent->d_name.name, + dentry->d_name.name, dentry->d_count, + unhashed, dentry->d_inode->i_ino, + dentry->d_inode->i_dev, + dentry->d_inode->i_count); + else + printk("show_dentry: %s/%s, d_count=%d%s \n", + dentry->d_parent->d_name.name, + dentry->d_name.name, dentry->d_count, + unhashed); + } } /* show_dentry */ #endif static struct inode *obdfs_new_inode(struct inode *dir, int mode) { - struct obdo *oa; - struct inode *inode; - int err; - - ENTRY; - if (IOPS(dir, create) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no create method!\n"); - EXIT; - return ERR_PTR(-EIO); - } - oa = obdo_alloc(); - if (!oa) { - EXIT; - return ERR_PTR(-ENOMEM); - } - - /* Send a hint to the create method on the type of file to create */ - oa->o_mode = mode; - oa->o_valid |= OBD_MD_FLMODE; - - err = IOPS(dir, create)(IID(dir), oa); - - if ( err ) { - CDEBUG(D_INODE, "fatal: creating new inode (err %d)\n", err); - obdo_free(oa); - EXIT; - return ERR_PTR(err); - } - - inode = iget(dir->i_sb, (ino_t)oa->o_id); - - if (!inode) { - CDEBUG(D_INODE, "fatal: get new inode %ld\n", (long)oa->o_id); - IOPS(dir, destroy)(IID(dir), oa); - obdo_free(oa); - EXIT; - return ERR_PTR(-EIO); - } - - if (!list_empty(&inode->i_dentry)) { - CDEBUG(D_INODE, "New inode (%ld) has aliases!\n", inode->i_ino); - IOPS(dir, destroy)(IID(dir), oa); - obdo_free(oa); - iput(inode); - EXIT; - return ERR_PTR(-EIO); - } - obdo_free(oa); - - EXIT; - return inode; + struct obdo *oa; + struct inode *inode; + int err; + + ENTRY; + if (IOPS(dir, create) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no create method!\n"); + EXIT; + return ERR_PTR(-EIO); + } + oa = obdo_alloc(); + if (!oa) { + EXIT; + return ERR_PTR(-ENOMEM); + } + + /* Send a hint to the create method on the type of file to create */ + oa->o_mode = mode; + oa->o_valid |= OBD_MD_FLMODE; + + err = IOPS(dir, create)(IID(dir), oa); + + if ( err ) { + CDEBUG(D_INODE, "fatal: creating new inode (err %d)\n", err); + obdo_free(oa); + EXIT; + return ERR_PTR(err); + } + + inode = iget(dir->i_sb, (ino_t)oa->o_id); + + if (!inode) { + CDEBUG(D_INODE, "fatal: get new inode %ld\n", (long)oa->o_id); + IOPS(dir, destroy)(IID(dir), oa); + obdo_free(oa); + EXIT; + return ERR_PTR(-EIO); + } + + if (!list_empty(&inode->i_dentry)) { + CDEBUG(D_INODE, "New inode (%ld) has aliases!\n", inode->i_ino); + IOPS(dir, destroy)(IID(dir), oa); + obdo_free(oa); + iput(inode); + EXIT; + return ERR_PTR(-EIO); + } + obdo_free(oa); + + EXIT; + return inode; } /* obdfs_new_inode */ @@ -515,174 +516,173 @@ static struct inode *obdfs_new_inode(struct inode *dir, int mode) */ int obdfs_create (struct inode * dir, struct dentry * dentry, int mode) { - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; - int err = -EIO; + struct inode * inode; + struct page *page; + struct ext2_dir_entry_2 * de; + int err = -EIO; ENTRY; - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } - - inode->i_op = &obdfs_file_inode_operations; - mark_inode_dirty(inode); - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) { - inode->i_nlink--; - mark_inode_dirty(inode); - iput (inode); - EXIT; - return err; - } - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, S_IFREG); - dir->i_version = ++event; - - err = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - UnlockPage(page); - - page_cache_release(page); - d_instantiate(dentry, inode); - EXIT; - return err; + inode = obdfs_new_inode(dir, mode); + if ( IS_ERR(inode) ) { + EXIT; + return PTR_ERR(inode); + } + + inode->i_op = &obdfs_file_inode_operations; + mark_inode_dirty(inode); + page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!page) { + inode->i_nlink--; + mark_inode_dirty(inode); + iput (inode); + EXIT; + return err; + } + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type(dir->i_sb, de, S_IFREG); + dir->i_version = ++event; + + err = obdfs_do_writepage(page, IS_SYNC(dir)); + obd_unlock_page(page); + page_cache_release(page); + d_instantiate(dentry, inode); + EXIT; + return err; } /* obdfs_create */ int obdfs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev) { - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; - struct obdfs_inode_info *oinfo; - int err; + struct inode * inode; + struct page *page; + struct ext2_dir_entry_2 * de; + struct obdfs_inode_info *oinfo; + int err; ENTRY; - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } - - inode->i_uid = current->fsuid; - init_special_inode(inode, mode, rdev); - oinfo = obdfs_i2info(inode); - ((obd_count *)oinfo->oi_inline)[0] = rdev; - oinfo->oi_flags |= OBD_FL_INLINEDATA; - - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) - goto out_no_entry; - de->inode = cpu_to_le32(inode->i_ino); - dir->i_version = ++event; - ext2_set_de_type(dir->i_sb, de, inode->i_mode); - mark_inode_dirty(inode); - - err = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - UnlockPage(page); - - d_instantiate(dentry, inode); - page_cache_release(page); - err = 0; + inode = obdfs_new_inode(dir, mode); + if ( IS_ERR(inode) ) { + EXIT; + return PTR_ERR(inode); + } + + inode->i_uid = current->fsuid; + init_special_inode(inode, mode, rdev); + oinfo = obdfs_i2info(inode); + ((obd_count *)oinfo->oi_inline)[0] = rdev; + oinfo->oi_flags |= OBD_FL_INLINEDATA; + + page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!page) + goto out_no_entry; + de->inode = cpu_to_le32(inode->i_ino); + dir->i_version = ++event; + ext2_set_de_type(dir->i_sb, de, inode->i_mode); + mark_inode_dirty(inode); + + err = obdfs_do_writepage(page, IS_SYNC(dir)); + obd_unlock_page(page); + + d_instantiate(dentry, inode); + page_cache_release(page); + err = 0; out: - return err; + return err; out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput(inode); - goto out; + inode->i_nlink--; + mark_inode_dirty(inode); + iput(inode); + goto out; } /* obdfs_mknod */ int obdfs_mkdir(struct inode * dir, struct dentry * dentry, int mode) { - struct inode * inode; - struct page *page, *inode_page; - struct ext2_dir_entry_2 * de; - int err; - - ENTRY; - - err = -EMLINK; - if (dir->i_nlink >= EXT2_LINK_MAX) - goto out; - - mode |= S_IFDIR; - if (dir->i_mode & S_ISGID) - mode |= S_ISGID; - - inode = obdfs_new_inode(dir, mode); - if ( IS_ERR(inode) ) { - EXIT; - return PTR_ERR(inode); - } - - inode->i_op = &obdfs_dir_inode_operations; - inode->i_blocks = 0; - inode_page = obdfs_getpage(inode, 0, 1, LOCKED); - if (!inode_page) { - inode->i_nlink--; /* is this nlink == 0? */ - mark_inode_dirty(inode); - iput (inode); - return -EIO; - } - de = (struct ext2_dir_entry_2 *) page_address(inode_page); - - /* create . and .. */ - de->inode = cpu_to_le32(inode->i_ino); - de->name_len = 1; - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); - strcpy (de->name, "."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - de->inode = cpu_to_le32(dir->i_ino); - de->rec_len = cpu_to_le16(PAGE_SIZE - EXT2_DIR_REC_LEN(1)); - de->name_len = 2; - strcpy (de->name, ".."); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - inode->i_nlink = 2; - - err = obdfs_do_writepage(inode, inode_page, IS_SYNC(inode)); - inode->i_blocks = PAGE_SIZE/inode->i_sb->s_blocksize; - inode->i_size = PAGE_SIZE; - UnlockPage(inode_page); - page_cache_release(inode_page); - mark_inode_dirty(inode); - if (err) { - EXIT; - goto out_no_entry; - } - - /* now deal with the parent */ - page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) { - EXIT; - goto out_no_entry; - } - - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, S_IFDIR); - dir->i_version = ++event; - - dir->i_nlink++; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - err = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - - UnlockPage(page); - - page_cache_release(page); - d_instantiate(dentry, inode); - EXIT; + struct inode * inode; + struct page *page, *inode_page; + struct ext2_dir_entry_2 * de; + int err; + + ENTRY; + + err = -EMLINK; + if (dir->i_nlink >= EXT2_LINK_MAX) + goto out; + + mode |= S_IFDIR; + if (dir->i_mode & S_ISGID) + mode |= S_ISGID; + + inode = obdfs_new_inode(dir, mode); + if ( IS_ERR(inode) ) { + EXIT; + return PTR_ERR(inode); + } + + inode->i_op = &obdfs_dir_inode_operations; + inode->i_blocks = 0; + inode_page = obdfs_getpage(inode, 0, 1, LOCKED); + if (!inode_page) { + inode->i_nlink--; /* is this nlink == 0? */ + mark_inode_dirty(inode); + iput (inode); + return -EIO; + } + de = (struct ext2_dir_entry_2 *) page_address(inode_page); + + /* create . and .. */ + de->inode = cpu_to_le32(inode->i_ino); + de->name_len = 1; + de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len)); + strcpy (de->name, "."); + ext2_set_de_type(dir->i_sb, de, S_IFDIR); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + de->inode = cpu_to_le32(dir->i_ino); + de->rec_len = cpu_to_le16(PAGE_SIZE - EXT2_DIR_REC_LEN(1)); + de->name_len = 2; + strcpy (de->name, ".."); + ext2_set_de_type(dir->i_sb, de, S_IFDIR); + inode->i_nlink = 2; + + err = obdfs_do_writepage(inode_page, IS_SYNC(inode)); + inode->i_blocks = PAGE_SIZE/inode->i_sb->s_blocksize; + inode->i_size = PAGE_SIZE; + obd_unlock_page(inode_page); + page_cache_release(inode_page); + mark_inode_dirty(inode); + if (err) { + EXIT; + goto out_no_entry; + } + + /* now deal with the parent */ + page = obdfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!page) { + EXIT; + goto out_no_entry; + } + + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type(dir->i_sb, de, S_IFDIR); + dir->i_version = ++event; + + dir->i_nlink++; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(dir); + err = obdfs_do_writepage(page, IS_SYNC(dir)); + + obd_unlock_page(page); + + page_cache_release(page); + d_instantiate(dentry, inode); + EXIT; out: - return err; + return err; out_no_entry: - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput (inode); - goto out; + inode->i_nlink = 0; + mark_inode_dirty(inode); + iput (inode); + goto out; } /* obdfs_mkdir */ @@ -691,450 +691,449 @@ out_no_entry: */ static int empty_dir (struct inode * inode) { - unsigned long offset; - struct page *page; - struct ext2_dir_entry_2 * de, * de1; - struct super_block * sb; - - sb = inode->i_sb; - if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) || - !(page = obdfs_getpage (inode, 0, 0, LOCKED))) { - ext2_warning (inode->i_sb, "empty_dir", - "bad directory (dir #%lu) - no data block", - inode->i_ino); - return 1; - } - de = (struct ext2_dir_entry_2 *) page_address(page); - de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || - strcmp (".", de->name) || strcmp ("..", de1->name)) { - ext2_warning (inode->i_sb, "empty_dir", - "bad directory (dir #%lu) - no `.' or `..'", - inode->i_ino); - page_cache_release(page); - return 1; - } - offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len)); - while (offset < inode->i_size ) { - if (!page || (void *) de >= (void *) (page_address(page) + PAGE_SIZE)) { - if (page) { - UnlockPage(page); - page_cache_release(page); - } - page = obdfs_getpage(inode, offset, 0, LOCKED); - if (!page) { + unsigned long offset; + struct page *page; + struct ext2_dir_entry_2 * de, * de1; + struct super_block * sb; + + sb = inode->i_sb; + if (inode->i_size < EXT2_DIR_REC_LEN(1) + EXT2_DIR_REC_LEN(2) || + !(page = obdfs_getpage (inode, 0, 0, LOCKED))) { + ext2_warning (inode->i_sb, "empty_dir", + "bad directory (dir #%lu) - no data block", + inode->i_ino); + return 1; + } + de = (struct ext2_dir_entry_2 *) page_address(page); + de1 = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + if (le32_to_cpu(de->inode) != inode->i_ino || !le32_to_cpu(de1->inode) || + strcmp (".", de->name) || strcmp ("..", de1->name)) { + ext2_warning (inode->i_sb, "empty_dir", + "bad directory (dir #%lu) - no `.' or `..'", + inode->i_ino); + page_cache_release(page); + return 1; + } + offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); + de = (struct ext2_dir_entry_2 *) ((char *) de1 + le16_to_cpu(de1->rec_len)); + while (offset < inode->i_size ) { + if (!page || (void *) de >= (void *) (page_address(page) + PAGE_SIZE)) { + if (page) { + obd_unlock_page(page); + page_cache_release(page); + } + page = obdfs_getpage(inode, offset, 0, LOCKED); + if (!page) { #if 0 - ext2_error (sb, "empty_dir", - "directory #%lu contains a hole at offset %lu", - inode->i_ino, offset); + ext2_error (sb, "empty_dir", + "directory #%lu contains a hole at offset %lu", + inode->i_ino, offset); #endif - offset += sb->s_blocksize; - continue; - } - de = (struct ext2_dir_entry_2 *) page_address(page); - } - if (!obdfs_check_dir_entry ("empty_dir", inode, de, page, - offset)) { - UnlockPage(page); - page_cache_release(page); - return 1; - } - if (le32_to_cpu(de->inode)) { - UnlockPage(page); - page_cache_release(page); - return 0; - } - offset += le16_to_cpu(de->rec_len); - de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); - } - UnlockPage(page); - page_cache_release(page); - return 1; + offset += sb->s_blocksize; + continue; + } + de = (struct ext2_dir_entry_2 *) page_address(page); + } + if (!obdfs_check_dir_entry ("empty_dir", inode, de, page, + offset)) { + obd_unlock_page(page); + page_cache_release(page); + return 1; + } + if (le32_to_cpu(de->inode)) { + obd_unlock_page(page); + page_cache_release(page); + return 0; + } + offset += le16_to_cpu(de->rec_len); + de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); + } + obd_unlock_page(page); + page_cache_release(page); + return 1; } /* empty_dir */ int obdfs_rmdir (struct inode * dir, struct dentry *dentry) { - int retval; - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; - - ENTRY; - - retval = -ENOENT; - page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); - if (!page) - goto end_rmdir; - - inode = dentry->d_inode; - DQUOT_INIT(inode); - - retval = -EIO; - if (le32_to_cpu(de->inode) != inode->i_ino) - goto end_rmdir; - - retval = -ENOTEMPTY; - if (!empty_dir (inode)) - goto end_rmdir; - - retval = obdfs_delete_entry (de, page); - dir->i_version = ++event; - if (retval) - goto end_rmdir; - retval = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - /* XXX handle err? */ - UnlockPage(page); - - if (inode->i_nlink != 2) - ext2_warning (inode->i_sb, "ext2_rmdir", - "empty directory has nlink!=2 (%d)", - inode->i_nlink); - inode->i_version = ++event; - inode->i_nlink = 0; - inode->i_size = 0; - mark_inode_dirty(inode); - dir->i_nlink--; - inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - d_delete(dentry); + int retval; + struct inode * inode; + struct page *page; + struct ext2_dir_entry_2 * de; + + ENTRY; + + retval = -ENOENT; + page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); + if (!page) + goto end_rmdir; + + inode = dentry->d_inode; + DQUOT_INIT(inode); + + retval = -EIO; + if (le32_to_cpu(de->inode) != inode->i_ino) + goto end_rmdir; + + retval = -ENOTEMPTY; + if (!empty_dir (inode)) + goto end_rmdir; + + retval = obdfs_delete_entry (de, page); + dir->i_version = ++event; + if (retval) + goto end_rmdir; + retval = obdfs_do_writepage(page, IS_SYNC(dir)); + /* XXX handle err? */ + obd_unlock_page(page); + + if (inode->i_nlink != 2) + ext2_warning (inode->i_sb, "ext2_rmdir", + "empty directory has nlink!=2 (%d)", + inode->i_nlink); + inode->i_version = ++event; + inode->i_nlink = 0; + inode->i_size = 0; + mark_inode_dirty(inode); + dir->i_nlink--; + inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(dir); + d_delete(dentry); end_rmdir: - if ( page ) - page_cache_release(page); - EXIT; - return retval; + if ( page ) + page_cache_release(page); + EXIT; + return retval; } /* obdfs_rmdir */ int obdfs_unlink(struct inode * dir, struct dentry *dentry) { - int retval; - struct inode * inode; - struct page *page; - struct ext2_dir_entry_2 * de; + int retval; + struct inode * inode; + struct page *page; + struct ext2_dir_entry_2 * de; ENTRY; - retval = -ENOENT; - page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); - if (!page) - goto end_unlink; - - inode = dentry->d_inode; - DQUOT_INIT(inode); - - retval = -EIO; - if (le32_to_cpu(de->inode) != inode->i_ino) - goto end_unlink; - - if (!inode->i_nlink) { - ext2_warning (inode->i_sb, "ext2_unlink", - "Deleting nonexistent file (%lu), %d", - inode->i_ino, inode->i_nlink); - inode->i_nlink = 1; - } - retval = obdfs_delete_entry (de, page); - if (retval) - goto end_unlink; - dir->i_version = ++event; - retval = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - /* XXX handle err? */ - UnlockPage(page); - - dir->i_ctime = dir->i_mtime = CURRENT_TIME; - dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(dir); - inode->i_nlink--; - mark_inode_dirty(inode); - inode->i_ctime = dir->i_ctime; - d_delete(dentry); /* This also frees the inode */ + retval = -ENOENT; + page = obdfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, LOCKED); + if (!page) + goto end_unlink; + + inode = dentry->d_inode; + DQUOT_INIT(inode); + + retval = -EIO; + if (le32_to_cpu(de->inode) != inode->i_ino) + goto end_unlink; + + if (!inode->i_nlink) { + ext2_warning (inode->i_sb, "ext2_unlink", + "Deleting nonexistent file (%lu), %d", + inode->i_ino, inode->i_nlink); + inode->i_nlink = 1; + } + retval = obdfs_delete_entry (de, page); + if (retval) + goto end_unlink; + dir->i_version = ++event; + retval = obdfs_do_writepage(page, IS_SYNC(dir)); + /* XXX handle err? */ + obd_unlock_page(page); + + dir->i_ctime = dir->i_mtime = CURRENT_TIME; + dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(dir); + inode->i_nlink--; + mark_inode_dirty(inode); + inode->i_ctime = dir->i_ctime; + d_delete(dentry); /* This also frees the inode */ end_unlink: - if (page) - page_cache_release(page); - EXIT; - return retval; + if (page) + page_cache_release(page); + EXIT; + return retval; } /* obdfs_unlink */ int obdfs_symlink (struct inode * dir, struct dentry *dentry, - const char * symname) + const char * symname) { - struct inode * inode; - struct ext2_dir_entry_2 * de; - struct obdfs_inode_info *oinfo; - struct page* page = NULL, * name_page = NULL; - char * link; - int l, err; + struct inode * inode; + struct ext2_dir_entry_2 * de; + struct obdfs_inode_info *oinfo; + struct page* page = NULL, * name_page = NULL; + char * link; + int l, err; ENTRY; - err = -ENAMETOOLONG; - l = strlen(symname)+1; - if (l > PAGE_SIZE) { - EXIT; - goto out; - } - - inode = obdfs_new_inode(dir, S_IFLNK); - if ( IS_ERR(inode) ) { - EXIT; - goto out; - } - - inode->i_mode = S_IFLNK | S_IRWXUGO; - oinfo = obdfs_i2info(inode); - - if (l >= sizeof(oinfo->oi_inline)) { - CDEBUG(D_INFO, "l=%d, normal symlink\n", l); - inode->i_op = &obdfs_symlink_inode_operations; - - name_page = obdfs_getpage(inode, 0, 1, LOCKED); - if (!name_page) { - EXIT; - err = -ENOMEM; - goto out_no_entry; - } - link = (char *)page_address(name_page); - } else { - CDEBUG(D_INFO, "l=%d, fast symlink\n", l); - inode->i_op = &obdfs_fast_symlink_inode_operations; - link = oinfo->oi_inline; - oinfo->oi_flags |= OBD_FL_INLINEDATA; - } - memcpy(link, symname, l); - if (name_page) { - err = obdfs_do_writepage(inode, name_page, IS_SYNC(inode)); - /* PDEBUG(name_page, "symlink"); */ - UnlockPage(name_page); - page_cache_release(name_page); - if (err) { - EXIT; - goto out_no_entry; - } - } - inode->i_size = l-1; - mark_inode_dirty(inode); - - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, - &de, &err); - if (!page) - goto out_no_entry; - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, S_IFLNK); - dir->i_version = ++event; - err = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - UnlockPage(page); - - d_instantiate(dentry, inode); + err = -ENAMETOOLONG; + l = strlen(symname)+1; + if (l > PAGE_SIZE) { + EXIT; + goto out; + } + + inode = obdfs_new_inode(dir, S_IFLNK); + if ( IS_ERR(inode) ) { + EXIT; + goto out; + } + + inode->i_mode = S_IFLNK | S_IRWXUGO; + oinfo = obdfs_i2info(inode); + + if (l >= sizeof(oinfo->oi_inline)) { + CDEBUG(D_INFO, "l=%d, normal symlink\n", l); + inode->i_op = &obdfs_symlink_inode_operations; + + name_page = obdfs_getpage(inode, 0, 1, LOCKED); + if (!name_page) { + EXIT; + err = -ENOMEM; + goto out_no_entry; + } + link = (char *)page_address(name_page); + } else { + CDEBUG(D_INFO, "l=%d, fast symlink\n", l); + inode->i_op = &obdfs_fast_symlink_inode_operations; + link = oinfo->oi_inline; + oinfo->oi_flags |= OBD_FL_INLINEDATA; + } + memcpy(link, symname, l); + if (name_page) { + err = obdfs_do_writepage(name_page, IS_SYNC(inode)); + /* PDEBUG(name_page, "symlink"); */ + obd_unlock_page(name_page); + page_cache_release(name_page); + if (err) { + EXIT; + goto out_no_entry; + } + } + inode->i_size = l-1; + mark_inode_dirty(inode); + + page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, + &de, &err); + if (!page) + goto out_no_entry; + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type(dir->i_sb, de, S_IFLNK); + dir->i_version = ++event; + err = obdfs_do_writepage(page, IS_SYNC(dir)); + obd_unlock_page(page); + + d_instantiate(dentry, inode); out: - EXIT; - return err; + EXIT; + return err; out_no_entry: - inode->i_nlink--; - mark_inode_dirty(inode); - iput (inode); - goto out; + inode->i_nlink--; + mark_inode_dirty(inode); + iput (inode); + goto out; } /* obdfs_symlink */ int obdfs_link (struct dentry * old_dentry, - struct inode * dir, struct dentry *dentry) + struct inode * dir, struct dentry *dentry) { - struct inode *inode = old_dentry->d_inode; - struct ext2_dir_entry_2 * de; - struct page *page; - int err; + struct inode *inode = old_dentry->d_inode; + struct ext2_dir_entry_2 * de; + struct page *page; + int err; ENTRY; - if (S_ISDIR(inode->i_mode)) - return -EPERM; + if (S_ISDIR(inode->i_mode)) + return -EPERM; - if (inode->i_nlink >= EXT2_LINK_MAX) - return -EMLINK; + if (inode->i_nlink >= EXT2_LINK_MAX) + return -EMLINK; - page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); - if (!page) - return err; + page = obdfs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err); + if (!page) + return err; - de->inode = cpu_to_le32(inode->i_ino); - ext2_set_de_type(dir->i_sb, de, inode->i_mode); - dir->i_version = ++event; + de->inode = cpu_to_le32(inode->i_ino); + ext2_set_de_type(dir->i_sb, de, inode->i_mode); + dir->i_version = ++event; - err = obdfs_do_writepage(dir, page, IS_SYNC(dir)); - UnlockPage(page); + err = obdfs_do_writepage(page, IS_SYNC(dir)); + obd_unlock_page(page); - page_cache_release(page); - inode->i_nlink++; - inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - inode->i_count++; - d_instantiate(dentry, inode); - return err; + page_cache_release(page); + inode->i_nlink++; + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + atomic_inc(&inode->i_count); + d_instantiate(dentry, inode); + return err; } /* obdfs_link */ #define PARENT_INO(buffer) \ - ((struct ext2_dir_entry_2 *) ((char *) buffer + \ - le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode + ((struct ext2_dir_entry_2 *) ((char *) buffer + \ + le16_to_cpu(((struct ext2_dir_entry_2 *) buffer)->rec_len)))->inode /* * Anybody can rename anything with this: the permission checks are left to the * higher-level routines. */ int obdfs_rename (struct inode * old_dir, struct dentry *old_dentry, - struct inode * new_dir, struct dentry *new_dentry) + struct inode * new_dir, struct dentry *new_dentry) { - struct inode * old_inode, * new_inode; - struct page * old_page, * new_page, * dir_page; - struct ext2_dir_entry_2 * old_de, * new_de; - int retval; + struct inode * old_inode, * new_inode; + struct page * old_page, * new_page, * dir_page; + struct ext2_dir_entry_2 * old_de, * new_de; + int retval; ENTRY; - new_page = dir_page = NULL; - - /* does the old entry exist? - if not get out */ - old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de, NOLOCK); - /* PDEBUG(old_page, "rename - old page"); */ - /* - * Check for inode number is _not_ due to possible IO errors. - * We might rmdir the source, keep it as pwd of some process - * and merrily kill the link to whatever was created under the - * same name. Goodbye sticky bit ;-< - */ - old_inode = old_dentry->d_inode; - retval = -ENOENT; - if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino) { - EXIT; - goto end_rename; - } - - /* find new inode */ - new_inode = new_dentry->d_inode; - new_page = obdfs_find_entry (new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_de, NOLOCK); - /* PDEBUG(new_page, "rename - new page "); */ - if (new_page) { - if (!new_inode) { - page_cache_release(new_page); - new_page = NULL; - } else { - DQUOT_INIT(new_inode); - } - } - /* in this case we to check more ... */ - if (S_ISDIR(old_inode->i_mode)) { - /* can only rename into empty new directory */ - if (new_inode) { - retval = -ENOTEMPTY; - if (!empty_dir (new_inode)) { - EXIT; - goto end_rename; - } - } - retval = -EIO; - dir_page = obdfs_getpage (old_inode, 0, 0, LOCKED); - /* PDEBUG(dir_page, "rename dir page"); */ - - if (!dir_page) { - EXIT; - goto end_rename; - } - if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != - old_dir->i_ino) { - EXIT; - goto end_rename; - } - retval = -EMLINK; - if (!new_inode && new_dir!=old_dir && - new_dir->i_nlink >= EXT2_LINK_MAX) { - EXIT; - goto end_rename; - } - } - /* create the target dir entry */ - if (!new_page) { - new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name, - new_dentry->d_name.len, &new_de, - &retval); - /* PDEBUG(new_page, "rename new page"); */ - if (!new_page) { - EXIT; - goto end_rename; - } - } - new_dir->i_version = ++event; - - /* - * remove the old entry - */ - new_de->inode = le32_to_cpu(old_inode->i_ino); - if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb, - EXT2_FEATURE_INCOMPAT_FILETYPE)) - new_de->file_type = old_de->file_type; - - obdfs_delete_entry (old_de, old_page); - - old_dir->i_version = ++event; - if (new_inode) { - new_inode->i_nlink--; - new_inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(new_inode); - } - old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; - old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(old_dir); - if (dir_page) { - PARENT_INO(page_address(dir_page)) =le32_to_cpu(new_dir->i_ino); - retval = obdfs_do_writepage(old_inode, dir_page, - IS_SYNC(old_inode)); - /* XXX handle err - not sure if this is correct */ - if (retval) { - EXIT; - goto end_rename; - } - old_dir->i_nlink--; - mark_inode_dirty(old_dir); - if (new_inode) { - new_inode->i_nlink--; - mark_inode_dirty(new_inode); - } else { - new_dir->i_nlink++; - new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; - mark_inode_dirty(new_dir); - } - } - if ( old_page != new_page ) { - unsigned long index = old_page->index; - /* lock the old_page and release unlocked copy */ - CDEBUG(D_INFO, "old_page at %p\n", old_page); - page_cache_release(old_page); - old_page = obdfs_getpage(old_dir, index << PAGE_SHIFT, 0, - LOCKED); - CDEBUG(D_INFO, "old_page at %p\n", old_page); - retval = obdfs_do_writepage(old_dir, old_page,IS_SYNC(old_dir)); - /* XXX handle err - not sure if this is correct */ - if (retval) { - EXIT; - goto end_rename; - } - } - - retval = obdfs_do_writepage(new_dir, new_page, IS_SYNC(new_dir)); + new_page = dir_page = NULL; + + /* does the old entry exist? - if not get out */ + old_page = obdfs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de, NOLOCK); + /* PDEBUG(old_page, "rename - old page"); */ + /* + * Check for inode number is _not_ due to possible IO errors. + * We might rmdir the source, keep it as pwd of some process + * and merrily kill the link to whatever was created under the + * same name. Goodbye sticky bit ;-< + */ + old_inode = old_dentry->d_inode; + retval = -ENOENT; + if (!old_page || le32_to_cpu(old_de->inode) != old_inode->i_ino) { + EXIT; + goto end_rename; + } + + /* find new inode */ + new_inode = new_dentry->d_inode; + new_page = obdfs_find_entry (new_dir, new_dentry->d_name.name, + new_dentry->d_name.len, &new_de, NOLOCK); + /* PDEBUG(new_page, "rename - new page "); */ + if (new_page) { + if (!new_inode) { + page_cache_release(new_page); + new_page = NULL; + } else { + DQUOT_INIT(new_inode); + } + } + /* in this case we to check more ... */ + if (S_ISDIR(old_inode->i_mode)) { + /* can only rename into empty new directory */ + if (new_inode) { + retval = -ENOTEMPTY; + if (!empty_dir (new_inode)) { + EXIT; + goto end_rename; + } + } + retval = -EIO; + dir_page = obdfs_getpage (old_inode, 0, 0, LOCKED); + /* PDEBUG(dir_page, "rename dir page"); */ + + if (!dir_page) { + EXIT; + goto end_rename; + } + if (le32_to_cpu(PARENT_INO(page_address(dir_page))) != + old_dir->i_ino) { + EXIT; + goto end_rename; + } + retval = -EMLINK; + if (!new_inode && new_dir!=old_dir && + new_dir->i_nlink >= EXT2_LINK_MAX) { + EXIT; + goto end_rename; + } + } + /* create the target dir entry */ + if (!new_page) { + new_page = obdfs_add_entry (new_dir, new_dentry->d_name.name, + new_dentry->d_name.len, &new_de, + &retval); + /* PDEBUG(new_page, "rename new page"); */ + if (!new_page) { + EXIT; + goto end_rename; + } + } + new_dir->i_version = ++event; + + /* + * remove the old entry + */ + new_de->inode = le32_to_cpu(old_inode->i_ino); + if (EXT2_HAS_INCOMPAT_FEATURE(new_dir->i_sb, + EXT2_FEATURE_INCOMPAT_FILETYPE)) + new_de->file_type = old_de->file_type; + + obdfs_delete_entry (old_de, old_page); + + old_dir->i_version = ++event; + if (new_inode) { + new_inode->i_nlink--; + new_inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(new_inode); + } + old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; + old_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(old_dir); + if (dir_page) { + PARENT_INO(page_address(dir_page)) =le32_to_cpu(new_dir->i_ino); + retval = obdfs_do_writepage(dir_page, IS_SYNC(old_inode)); + /* XXX handle err - not sure if this is correct */ + if (retval) { + EXIT; + goto end_rename; + } + old_dir->i_nlink--; + mark_inode_dirty(old_dir); + if (new_inode) { + new_inode->i_nlink--; + mark_inode_dirty(new_inode); + } else { + new_dir->i_nlink++; + new_dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL; + mark_inode_dirty(new_dir); + } + } + if ( old_page != new_page ) { + unsigned long index = old_page->index; + /* lock the old_page and release unlocked copy */ + CDEBUG(D_INFO, "old_page at %p\n", old_page); + page_cache_release(old_page); + old_page = obdfs_getpage(old_dir, index << PAGE_SHIFT, 0, + LOCKED); + CDEBUG(D_INFO, "old_page at %p\n", old_page); + retval = obdfs_do_writepage(old_page,IS_SYNC(old_dir)); + /* XXX handle err - not sure if this is correct */ + if (retval) { + EXIT; + goto end_rename; + } + } + + retval = obdfs_do_writepage(new_page, IS_SYNC(new_dir)); end_rename: - if (old_page && PageLocked(old_page) ) - UnlockPage(old_page); - if (old_page) - page_cache_release(old_page); - if (new_page && PageLocked(new_page) ) - UnlockPage(new_page); - if (new_page) - page_cache_release(new_page); - if (dir_page && PageLocked(dir_page) ) - UnlockPage(dir_page); - if (dir_page) - page_cache_release(dir_page); - - return retval; + if (old_page && PageLocked(old_page) ) + obd_unlock_page(old_page); + if (old_page) + page_cache_release(old_page); + if (new_page && PageLocked(new_page) ) + obd_unlock_page(new_page); + if (new_page) + page_cache_release(new_page); + if (dir_page && PageLocked(dir_page) ) + obd_unlock_page(dir_page); + if (dir_page) + page_cache_release(dir_page); + + return retval; } /* obdfs_rename */ diff --git a/lustre/obdfs/rw.c b/lustre/obdfs/rw.c index ce58fd6..7b8a368 100644 --- a/lustre/obdfs/rw.c +++ b/lustre/obdfs/rw.c @@ -37,204 +37,205 @@ /* SYNCHRONOUS I/O for an inode */ static int obdfs_brw(int rw, struct inode *inode, struct page *page, int create) { - obd_count num_obdo = 1; - obd_count bufs_per_obdo = 1; - struct obdo *oa; - char *buf = (char *)page_address(page); - obd_size count = PAGE_SIZE; - obd_off offset = ((obd_off)page->index) << PAGE_SHIFT; - obd_flag flags = create ? OBD_BRW_CREATE : 0; - int err; - - ENTRY; - if (IOPS(inode, brw) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); - EXIT; - return -EIO; - } - - oa = obdo_fromid(IID(inode), inode->i_ino, OBD_MD_FLNOTOBD); - if ( IS_ERR(oa) ) { - EXIT; - return PTR_ERR(oa); - } - obdfs_from_inode(oa, inode); - - err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo, - &buf, &count, &offset, &flags); - - if ( !err ) - obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */ - - obdo_free(oa); - - EXIT; - return err; + obd_count num_obdo = 1; + obd_count bufs_per_obdo = 1; + struct obdo *oa; + char *buf = (char *)page_address(page); + obd_size count = PAGE_SIZE; + obd_off offset = ((obd_off)page->index) << PAGE_SHIFT; + obd_flag flags = create ? OBD_BRW_CREATE : 0; + int err; + + ENTRY; + if (IOPS(inode, brw) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); + EXIT; + return -EIO; + } + + oa = obdo_fromid(IID(inode), inode->i_ino, OBD_MD_FLNOTOBD); + if ( IS_ERR(oa) ) { + EXIT; + return PTR_ERR(oa); + } + obdfs_from_inode(oa, inode); + + err = IOPS(inode, brw)(rw, IID(inode), num_obdo, &oa, &bufs_per_obdo, + &buf, &count, &offset, &flags); + + if ( !err ) + obdfs_to_inode(inode, oa); /* copy o_blocks to i_blocks */ + + obdo_free(oa); + + EXIT; + return err; } /* obdfs_brw */ /* returns the page unlocked, but with a reference */ -int obdfs_readpage(struct dentry *dentry, struct page *page) +int obdfs_readpage(struct file *file, struct page *page) { - struct inode *inode = dentry->d_inode; - int rc; - - ENTRY; - /* PDEBUG(page, "READ"); */ - rc = obdfs_brw(READ, inode, page, 0); - if ( !rc ) { - SetPageUptodate(page); - UnlockPage(page); - } - /* PDEBUG(page, "READ"); */ - EXIT; - return rc; + struct dentry *dentry = file->f_dentry; + struct inode *inode = dentry->d_inode; + int rc; + + ENTRY; + /* PDEBUG(page, "READ"); */ + rc = obdfs_brw(READ, inode, page, 0); + if ( !rc ) { + SetPageUptodate(page); + obd_unlock_page(page); + } + /* PDEBUG(page, "READ"); */ + EXIT; + return rc; } /* obdfs_readpage */ static kmem_cache_t *obdfs_pgrq_cachep = NULL; int obdfs_init_pgrqcache(void) { - ENTRY; - if (obdfs_pgrq_cachep == NULL) { - CDEBUG(D_CACHE, "allocating obdfs_pgrq_cache\n"); - obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq", - sizeof(struct obdfs_pgrq), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (obdfs_pgrq_cachep == NULL) { - EXIT; - return -ENOMEM; - } else { - CDEBUG(D_CACHE, "allocated cache at %p\n", - obdfs_pgrq_cachep); - } - } else { - CDEBUG(D_CACHE, "using existing cache at %p\n", - obdfs_pgrq_cachep); - } - EXIT; - return 0; + ENTRY; + if (obdfs_pgrq_cachep == NULL) { + CDEBUG(D_CACHE, "allocating obdfs_pgrq_cache\n"); + obdfs_pgrq_cachep = kmem_cache_create("obdfs_pgrq", + sizeof(struct obdfs_pgrq), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (obdfs_pgrq_cachep == NULL) { + EXIT; + return -ENOMEM; + } else { + CDEBUG(D_CACHE, "allocated cache at %p\n", + obdfs_pgrq_cachep); + } + } else { + CDEBUG(D_CACHE, "using existing cache at %p\n", + obdfs_pgrq_cachep); + } + EXIT; + return 0; } /* obdfs_init_wreqcache */ inline void obdfs_pgrq_del(struct obdfs_pgrq *pgrq) { - --obdfs_cache_count; - CDEBUG(D_INFO, "deleting page %p from list [count %ld]\n", - pgrq->rq_page, obdfs_cache_count); - list_del(&pgrq->rq_plist); - OBDClearCachePage(pgrq->rq_page); - kmem_cache_free(obdfs_pgrq_cachep, pgrq); + --obdfs_cache_count; + CDEBUG(D_INFO, "deleting page %p from list [count %ld]\n", + pgrq->rq_page, obdfs_cache_count); + list_del(&pgrq->rq_plist); + OBDClearCachePage(pgrq->rq_page); + kmem_cache_free(obdfs_pgrq_cachep, pgrq); } void obdfs_cleanup_pgrqcache(void) { - ENTRY; - if (obdfs_pgrq_cachep != NULL) { - CDEBUG(D_CACHE, "destroying obdfs_pgrqcache at %p, count %ld\n", - obdfs_pgrq_cachep, obdfs_cache_count); - if (kmem_cache_destroy(obdfs_pgrq_cachep)) - printk(KERN_INFO __FUNCTION__ - ": unable to free all of cache\n"); - obdfs_pgrq_cachep = NULL; - } else - printk(KERN_INFO __FUNCTION__ ": called with NULL pointer\n"); - - EXIT; + ENTRY; + if (obdfs_pgrq_cachep != NULL) { + CDEBUG(D_CACHE, "destroying obdfs_pgrqcache at %p, count %ld\n", + obdfs_pgrq_cachep, obdfs_cache_count); + if (kmem_cache_destroy(obdfs_pgrq_cachep)) + printk(KERN_INFO __FUNCTION__ + ": unable to free all of cache\n"); + obdfs_pgrq_cachep = NULL; + } else + printk(KERN_INFO __FUNCTION__ ": called with NULL pointer\n"); + + EXIT; } /* obdfs_cleanup_wreqcache */ /* called with the list lock held */ static struct page *obdfs_find_page_index(struct inode *inode, - unsigned long index) + unsigned long index) { - struct list_head *page_list = obdfs_iplist(inode); - struct list_head *tmp; - struct page *page; - - ENTRY; - - CDEBUG(D_INFO, "looking for inode %ld pageindex %ld\n", - inode->i_ino, index); - OIDEBUG(inode); - - if (list_empty(page_list)) { - EXIT; - return NULL; - } - tmp = page_list; - while ( (tmp = tmp->next) != page_list ) { - struct obdfs_pgrq *pgrq; - - pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); - page = pgrq->rq_page; - if (index == page->index) { - CDEBUG(D_INFO, - "INDEX SEARCH found page %p, index %ld\n", - page, index); - EXIT; - return page; - } - } - - EXIT; - return NULL; + struct list_head *page_list = obdfs_iplist(inode); + struct list_head *tmp; + struct page *page; + + ENTRY; + + CDEBUG(D_INFO, "looking for inode %ld pageindex %ld\n", + inode->i_ino, index); + OIDEBUG(inode); + + if (list_empty(page_list)) { + EXIT; + return NULL; + } + tmp = page_list; + while ( (tmp = tmp->next) != page_list ) { + struct obdfs_pgrq *pgrq; + + pgrq = list_entry(tmp, struct obdfs_pgrq, rq_plist); + page = pgrq->rq_page; + if (index == page->index) { + CDEBUG(D_INFO, + "INDEX SEARCH found page %p, index %ld\n", + page, index); + EXIT; + return page; + } + } + + EXIT; + return NULL; } /* obdfs_find_page_index */ /* call and free pages from Linux page cache: called with io lock on inodes */ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, - obd_count num_obdos, struct obdo **obdos, - obd_count *oa_bufs, struct page **pages, char **bufs, - obd_size *counts, obd_off *offsets, obd_flag *flags) + obd_count num_obdos, struct obdo **obdos, + obd_count *oa_bufs, struct page **pages, char **bufs, + obd_size *counts, obd_off *offsets, obd_flag *flags) { - int err; - - ENTRY; - if (IOPS(inodes[0], brw) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); - EXIT; - return -EIO; - } - - CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n", - num_io, num_obdos); - if (obd_debug_level & D_INFO) { /* DEBUGGING */ - int i; - printk("OBDOS: "); - for (i = 0; i < num_obdos; i++) - printk("%ld:0x%p ", (long)obdos[i]->o_id, obdos[i]); - - printk("\nPAGES: "); - for (i = 0; i < num_io; i++) - printk("0x%p ", pages[i]); - printk("\n"); - } - - err = IOPS(inodes[0], brw)(WRITE, IID(inodes[0]), num_obdos, obdos, - oa_bufs, bufs, counts, offsets, flags); - - CDEBUG(D_INFO, "BRW done\n"); - /* release the pages from the page cache */ - while ( num_io > 0 ) { - --num_io; - CDEBUG(D_INFO, "calling put_page for %p, index %ld\n", - pages[num_io], pages[num_io]->index); - /* PDEBUG(pages[num_io], "do_vec_wr"); */ - put_page(pages[num_io]); - /* PDEBUG(pages[num_io], "do_vec_wr"); */ - } - CDEBUG(D_INFO, "put_page done\n"); - - while ( num_obdos > 0) { - --num_obdos; - CDEBUG(D_INFO, "free obdo %ld\n",(long)obdos[num_obdos]->o_id); - /* copy o_blocks to i_blocks */ - obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]); - obdo_free(obdos[num_obdos]); - } - CDEBUG(D_INFO, "obdo_free done\n"); - EXIT; - return err; + int err; + + ENTRY; + if (IOPS(inodes[0], brw) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no brw method!\n"); + EXIT; + return -EIO; + } + + CDEBUG(D_INFO, "writing %d page(s), %d obdo(s) in vector\n", + num_io, num_obdos); + if (obd_debug_level & D_INFO) { /* DEBUGGING */ + int i; + printk("OBDOS: "); + for (i = 0; i < num_obdos; i++) + printk("%ld:0x%p ", (long)obdos[i]->o_id, obdos[i]); + + printk("\nPAGES: "); + for (i = 0; i < num_io; i++) + printk("0x%p ", pages[i]); + printk("\n"); + } + + err = IOPS(inodes[0], brw)(WRITE, IID(inodes[0]), num_obdos, obdos, + oa_bufs, bufs, counts, offsets, flags); + + CDEBUG(D_INFO, "BRW done\n"); + /* release the pages from the page cache */ + while ( num_io > 0 ) { + --num_io; + CDEBUG(D_INFO, "calling put_page for %p, index %ld\n", + pages[num_io], pages[num_io]->index); + /* PDEBUG(pages[num_io], "do_vec_wr"); */ + put_page(pages[num_io]); + /* PDEBUG(pages[num_io], "do_vec_wr"); */ + } + CDEBUG(D_INFO, "put_page done\n"); + + while ( num_obdos > 0) { + --num_obdos; + CDEBUG(D_INFO, "free obdo %ld\n",(long)obdos[num_obdos]->o_id); + /* copy o_blocks to i_blocks */ + obdfs_to_inode(inodes[num_obdos], obdos[num_obdos]); + obdo_free(obdos[num_obdos]); + } + CDEBUG(D_INFO, "obdo_free done\n"); + EXIT; + return err; } @@ -244,95 +245,97 @@ int obdfs_do_vec_wr(struct inode **inodes, obd_count num_io, */ static int obdfs_add_page_to_cache(struct inode *inode, struct page *page) { - int err = 0; - ENTRY; - - /* The PG_obdcache bit is cleared by obdfs_pgrq_del() BEFORE the page - * is written, so at worst we will write the page out twice. - * - * If the page has the PG_obdcache bit set, then the inode MUST be - * on the superblock dirty list so we don't need to check this. - * Dirty inodes are removed from the superblock list ONLY when they - * don't have any more cached pages. It is possible to have an inode - * with no dirty pages on the superblock list, but not possible to - * have an inode with dirty pages NOT on the superblock dirty list. - */ - if (!OBDAddCachePage(page)) { - struct obdfs_pgrq *pgrq; - pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL); - if (!pgrq) { - OBDClearCachePage(page); - EXIT; - return -ENOMEM; - } - /* not really necessary since we set all pgrq fields here - memset(pgrq, 0, sizeof(*pgrq)); - */ - - pgrq->rq_page = page; - pgrq->rq_jiffies = jiffies; - get_page(pgrq->rq_page); - - obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); - list_add(&pgrq->rq_plist, obdfs_iplist(inode)); - obdfs_cache_count++; - - /* If inode isn't already on superblock inodes list, add it. - * - * We increment the reference count on the inode to keep it - * from being freed from memory. This _should_ be an iget() - * with an iput() in both flush_reqs() and put_inode(), but - * since put_inode() is called from iput() we can't call iput() - * again there. Instead we just increment/decrement i_count, - * which is mostly what iget/iput do for an inode in memory. - */ - if ( list_empty(obdfs_islist(inode)) ) { - inode->i_count++; - CDEBUG(D_INFO, - "adding inode %ld to superblock list %p\n", - inode->i_ino, obdfs_slist(inode)); - list_add(obdfs_islist(inode), obdfs_slist(inode)); - } - obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); - } - - /* XXX For testing purposes, we can write out the page here. - err = obdfs_flush_reqs(obdfs_slist(inode), ~0UL); - */ - - EXIT; - return err; + int err = 0; + ENTRY; + + /* The PG_obdcache bit is cleared by obdfs_pgrq_del() BEFORE the page + * is written, so at worst we will write the page out twice. + * + * If the page has the PG_obdcache bit set, then the inode MUST be + * on the superblock dirty list so we don't need to check this. + * Dirty inodes are removed from the superblock list ONLY when they + * don't have any more cached pages. It is possible to have an inode + * with no dirty pages on the superblock list, but not possible to + * have an inode with dirty pages NOT on the superblock dirty list. + */ + if (!OBDAddCachePage(page)) { + struct obdfs_pgrq *pgrq; + pgrq = kmem_cache_alloc(obdfs_pgrq_cachep, SLAB_KERNEL); + if (!pgrq) { + OBDClearCachePage(page); + EXIT; + return -ENOMEM; + } + /* not really necessary since we set all pgrq fields here + memset(pgrq, 0, sizeof(*pgrq)); + */ + + pgrq->rq_page = page; + pgrq->rq_jiffies = jiffies; + get_page(pgrq->rq_page); + + obd_down(&obdfs_i2sbi(inode)->osi_list_mutex); + list_add(&pgrq->rq_plist, obdfs_iplist(inode)); + obdfs_cache_count++; + + /* If inode isn't already on superblock inodes list, add it. + * + * We increment the reference count on the inode to keep it + * from being freed from memory. This _should_ be an iget() + * with an iput() in both flush_reqs() and put_inode(), but + * since put_inode() is called from iput() we can't call iput() + * again there. Instead we just increment/decrement i_count, + * which is mostly what iget/iput do for an inode in memory. + */ + if ( list_empty(obdfs_islist(inode)) ) { + atomic_inc(&inode->i_count); + CDEBUG(D_INFO, + "adding inode %ld to superblock list %p\n", + inode->i_ino, obdfs_slist(inode)); + list_add(obdfs_islist(inode), obdfs_slist(inode)); + } + obd_up(&obdfs_i2sbi(inode)->osi_list_mutex); + } + + /* XXX For testing purposes, we can write out the page here. + err = obdfs_flush_reqs(obdfs_slist(inode), ~0UL); + */ + + EXIT; + return err; } /* obdfs_add_page_to_cache */ /* select between SYNC and ASYNC I/O methods */ -int obdfs_do_writepage(struct inode *inode, struct page *page, int sync) +int obdfs_do_writepage(struct page *page, int sync) { - int err; - - ENTRY; - /* PDEBUG(page, "WRITEPAGE"); */ - if ( sync ) - err = obdfs_brw(WRITE, inode, page, 1); - else { - err = obdfs_add_page_to_cache(inode, page); - CDEBUG(D_INFO, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n", - inode->i_ino, page, err, Page_Uptodate(page)); - } - - if ( !err ) - SetPageUptodate(page); - /* PDEBUG(page,"WRITEPAGE"); */ - EXIT; - return err; + struct inode *inode = page->mapping->host; + int err; + + ENTRY; + /* PDEBUG(page, "WRITEPAGE"); */ + if ( sync ) + err = obdfs_brw(WRITE, inode, page, 1); + else { + err = obdfs_add_page_to_cache(inode, page); + CDEBUG(D_INFO, "DO_WR ino: %ld, page %p, err %d, uptodate %d\n", + inode->i_ino, page, err, Page_Uptodate(page)); + } + + if ( !err ) + SetPageUptodate(page); + /* PDEBUG(page,"WRITEPAGE"); */ + EXIT; + return err; } /* obdfs_do_writepage */ /* returns the page unlocked, but with a reference */ -int obdfs_writepage(struct dentry *dentry, struct page *page) +int obdfs_writepage(struct page *page) { - return obdfs_do_writepage(dentry->d_inode, page, 0); + return obdfs_do_writepage(page, 0); } + /* * This does the "real" work of the write. The generic routine has * allocated the page, locked it, done all the page alignment stuff @@ -345,31 +348,31 @@ int obdfs_writepage(struct dentry *dentry, struct page *page) * Return value is the number of bytes written. */ int obdfs_write_one_page(struct file *file, struct page *page, - unsigned long offset, unsigned long bytes, - const char * buf) + unsigned long offset, unsigned long bytes, + const char * buf) { - struct inode *inode = file->f_dentry->d_inode; - int err; - - ENTRY; - /* We check for complete page writes here, as we then don't have to - * get the page before writing over everything anyways. - */ - if ( !Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE) ) { - err = obdfs_brw(READ, inode, page, 0); - if ( err ) - return err; - SetPageUptodate(page); - } - - if (copy_from_user((u8*)page_address(page) + offset, buf, bytes)) - return -EFAULT; - - lock_kernel(); - err = obdfs_writepage(file->f_dentry, page); - unlock_kernel(); - - return (err < 0 ? err : bytes); + struct inode *inode = file->f_dentry->d_inode; + int err; + + ENTRY; + /* We check for complete page writes here, as we then don't have to + * get the page before writing over everything anyways. + */ + if ( !Page_Uptodate(page) && (offset != 0 || bytes != PAGE_SIZE) ) { + err = obdfs_brw(READ, inode, page, 0); + if ( err ) + return err; + SetPageUptodate(page); + } + + if (copy_from_user((u8*)page_address(page) + offset, buf, bytes)) + return -EFAULT; + + lock_kernel(); + err = obdfs_writepage(page); + unlock_kernel(); + + return (err < 0 ? err : bytes); } /* obdfs_write_one_page */ /* @@ -381,104 +384,109 @@ int obdfs_write_one_page(struct file *file, struct page *page, * modeled on NFS code. */ struct page *obdfs_getpage(struct inode *inode, unsigned long offset, - int create, int locked) + int create, int locked) { - struct page * page; - int index; - int err; - - ENTRY; - - offset = offset & PAGE_CACHE_MASK; - CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n", - inode->i_ino, offset, create, locked); - index = offset >> PAGE_CACHE_SHIFT; - - page = grab_cache_page(&inode->i_data, index); - - /* Yuck, no page */ - if (! page) { - printk(KERN_WARNING " grab_cache_page says no dice ...\n"); - EXIT; - return NULL; - } - - /* PDEBUG(page, "GETPAGE: got page - before reading\n"); */ - /* now check if the data in the page is up to date */ - if ( Page_Uptodate(page)) { - if (!locked) - UnlockPage(page); - EXIT; - return page; - } + struct page * page; + int index; + int err; + + ENTRY; + + offset = offset & PAGE_CACHE_MASK; + CDEBUG(D_INFO, "ino: %ld, offset %ld, create %d, locked %d\n", + inode->i_ino, offset, create, locked); + index = offset >> PAGE_CACHE_SHIFT; + + page = grab_cache_page(&inode->i_data, index); + + /* Yuck, no page */ + if (! page) { + printk(KERN_WARNING " grab_cache_page says no dice ...\n"); + EXIT; + return NULL; + } + + /* PDEBUG(page, "GETPAGE: got page - before reading\n"); */ + /* now check if the data in the page is up to date */ + if ( Page_Uptodate(page)) { + if (!locked) { + if (PageLocked(page)) + obd_unlock_page(page); + } else { + printk("file %s, line %d: expecting locked page\n", + __FILE__, __LINE__); + } + EXIT; + return page; + } #ifdef EXT2_OBD_DEBUG - if ((obd_debug_level & D_INFO) && obdfs_find_page_index(inode, index)) { - CDEBUG(D_INFO, "OVERWRITE: found dirty page %p, index %ld\n", - page, page->index); - } + if ((obd_debug_level & D_INFO) && obdfs_find_page_index(inode, index)) { + CDEBUG(D_INFO, "OVERWRITE: found dirty page %p, index %ld\n", + page, page->index); + } #endif - err = obdfs_brw(READ, inode, page, create); - - if ( err ) { - SetPageError(page); - UnlockPage(page); - EXIT; - return page; - } - - if ( !locked ) - UnlockPage(page); - SetPageUptodate(page); - /* PDEBUG(page,"GETPAGE - after reading"); */ - EXIT; - return page; + err = obdfs_brw(READ, inode, page, create); + + if ( err ) { + SetPageError(page); + obd_unlock_page(page); + EXIT; + return page; + } + + if ( !locked ) + obd_unlock_page(page); + SetPageUptodate(page); + /* PDEBUG(page,"GETPAGE - after reading"); */ + EXIT; + return page; } /* obdfs_getpage */ void obdfs_truncate(struct inode *inode) { - struct obdo *oa; - int err; - ENTRY; - - obdfs_dequeue_pages(inode); - - if (IOPS(inode, punch) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no punch method!\n"); - EXIT; - return; - } - oa = obdo_alloc(); - if ( !oa ) { - /* XXX This would give an inconsistent FS, so deal with it as - * best we can for now - an obdo on the stack is not pretty. - */ - struct obdo obdo; - - printk(__FUNCTION__ ": obdo_alloc failed - using stack!\n"); - - obdo.o_valid = OBD_MD_FLNOTOBD; - obdfs_from_inode(&obdo, inode); - - err = IOPS(inode, punch)(IID(inode), &obdo, obdo.o_size, 0); - } else { - oa->o_valid = OBD_MD_FLNOTOBD; - obdfs_from_inode(oa, inode); - - CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n", - (long)oa->o_id, oa->o_size); - err = IOPS(inode, punch)(IID(inode), oa, oa->o_size, 0); - - obdo_free(oa); - } - - if (err) { - printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err); - EXIT; - return; - } - EXIT; + struct obdo *oa; + int err; + ENTRY; + + obdfs_dequeue_pages(inode); + + if (IOPS(inode, punch) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no punch method!\n"); + EXIT; + return; + } + oa = obdo_alloc(); + if ( !oa ) { + /* XXX This would give an inconsistent FS, so deal with it as + * best we can for now - an obdo on the stack is not pretty. + */ + struct obdo obdo; + + printk(__FUNCTION__ ": obdo_alloc failed - using stack!\n"); + + obdo.o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(&obdo, inode); + + err = IOPS(inode, punch)(IID(inode), &obdo, obdo.o_size, 0); + } else { + oa->o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(oa, inode); + + CDEBUG(D_INFO, "calling punch for %ld (%Lu bytes at 0)\n", + (long)oa->o_id, oa->o_size); + err = IOPS(inode, punch)(IID(inode), oa, oa->o_size, 0); + + obdo_free(oa); + } + + if (err) { + printk(__FUNCTION__ ": obd_truncate fails (%d)\n", err); + EXIT; + return; + } + EXIT; } /* obdfs_truncate */ diff --git a/lustre/obdfs/super.c b/lustre/obdfs/super.c index 191cb87..04853f9 100644 --- a/lustre/obdfs/super.c +++ b/lustre/obdfs/super.c @@ -4,6 +4,7 @@ * Copryright (C) 1996 Peter J. Braam * Copryright (C) 1999 Stelias Computing Inc. * Copryright (C) 1999 Seagate Technology Inc. + * Copryright (C) 2001 Mountain View Data, Inc. * */ @@ -33,6 +34,7 @@ #include struct list_head obdfs_super_list; +struct address_space_operations obdfs_aops; struct super_operations obdfs_super_operations; long obdfs_cache_count = 0; long obdfs_mutex_start = 0; @@ -40,212 +42,227 @@ long obd_memory = 0; static char *obdfs_read_opt(const char *opt, char *data) { - char *value; - char *retval; - - CDEBUG(D_INFO, "option: %s, data %s\n", opt, data); - if ( strncmp(opt, data, strlen(opt)) ) - return NULL; - - if ( (value = strchr(data, '=')) == NULL ) - return NULL; - - value++; - OBD_ALLOC(retval, char *, strlen(value) + 1); - if ( !retval ) { - printk(KERN_ALERT __FUNCTION__ ": out of memory!\n"); - return NULL; - } - - memcpy(retval, value, strlen(value)+1); - CDEBUG(D_PSDEV, "Assigned option: %s, value %s\n", opt, retval); - return retval; + char *value; + char *retval; + + CDEBUG(D_INFO, "option: %s, data %s\n", opt, data); + if ( strncmp(opt, data, strlen(opt)) ) + return NULL; + + if ( (value = strchr(data, '=')) == NULL ) + return NULL; + + value++; + OBD_ALLOC(retval, char *, strlen(value) + 1); + if ( !retval ) { + printk(KERN_ALERT __FUNCTION__ ": out of memory!\n"); + return NULL; + } + + memcpy(retval, value, strlen(value)+1); + CDEBUG(D_PSDEV, "Assigned option: %s, value %s\n", opt, retval); + return retval; } static void obdfs_options(char *options, char **dev, char **vers) { - char *this_char; - - if (!options) - return; - - for (this_char = strtok (options, ","); - this_char != NULL; - this_char = strtok (NULL, ",")) { - CDEBUG(D_INFO, "this_char %s\n", this_char); - if ( (!*dev && (*dev = obdfs_read_opt("device", this_char)))|| - (!*vers && (*vers = obdfs_read_opt("version", this_char))) ) - continue; - - } + char *this_char; + + if (!options) + return; + + for (this_char = strtok (options, ","); + this_char != NULL; + this_char = strtok (NULL, ",")) { + CDEBUG(D_INFO, "this_char %s\n", this_char); + if ( (!*dev && (*dev = obdfs_read_opt("device", this_char)))|| + (!*vers && (*vers = obdfs_read_opt("version", this_char))) ) + continue; + + } } static int obdfs_getdev(char *devpath, int *dev) { - struct dentry *dentry; - kdev_t devno; - - dentry = lookup_dentry(devpath, NULL, 0); - if (IS_ERR(dentry)) - return PTR_ERR(dentry); - - if (!S_ISCHR(dentry->d_inode->i_mode)) - return -ENODEV; - - devno = dentry->d_inode->i_rdev; - if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) - return -ENODEV; - - if ( MINOR(devno) >= MAX_OBD_DEVICES ) - return -ENODEV; - - *dev = devno; - return 0; + struct dentry *dentry; + kdev_t devno; + struct nameidata nd; + int error = 0; + + ENTRY; + if (path_init(devpath, LOOKUP_POSITIVE, &nd)) + error = path_walk(devpath, &nd); + if (error) + return error; + + dentry = nd.dentry; + if (!S_ISCHR(dentry->d_inode->i_mode)) + return -ENODEV; + + devno = dentry->d_inode->i_rdev; + if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) + return -ENODEV; + + if ( MINOR(devno) >= MAX_OBD_DEVICES ) + return -ENODEV; + + *dev = devno; + return 0; } static struct super_block * obdfs_read_super(struct super_block *sb, - void *data, int silent) + void *data, int silent) { struct inode *root = 0; - struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)(&sb->u.generic_sbp); - struct obd_device *obddev; - char *device = NULL; - char *version = NULL; - int devno; - int err; - unsigned long blocksize; - unsigned long blocksize_bits; - unsigned long root_ino; - int scratch; - - - ENTRY; + struct obdfs_sb_info *sbi = (struct obdfs_sb_info *)(&sb->u.generic_sbp); + struct obd_device *obddev; + char *device = NULL; + char *version = NULL; + int devno; + int err; + unsigned long blocksize; + unsigned long blocksize_bits; + unsigned long root_ino; + int scratch; + + + ENTRY; MOD_INC_USE_COUNT; - - memset(sbi, 0, sizeof(*sbi)); - - obdfs_options(data, &device, &version); - if ( !device ) { - printk(__FUNCTION__ ": no device\n"); - EXIT; - goto ERR; - } - - if ( (err = obdfs_getdev(device, &devno)) ) { - printk("Cannot get devno of %s, error %d\n", device, err); - EXIT; - goto ERR;; - } - - if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) { - printk(__FUNCTION__ ": wrong major number %d!\n", MAJOR(devno)); - EXIT; - goto ERR; - } - - if ( MINOR(devno) >= MAX_OBD_DEVICES ) { - printk(__FUNCTION__ ": minor of %s too high (%d)\n", - device, MINOR(devno)); - EXIT; - goto ERR; - } - - obddev = &obd_dev[MINOR(devno)]; - - if ( ! (obddev->obd_flags & OBD_ATTACHED) || - ! (obddev->obd_flags & OBD_SET_UP) ){ - printk("device %s not attached or not set up (%d)\n", - device, MINOR(devno)); - EXIT; - goto ERR;; - } - - sbi->osi_obd = obddev; - sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops; - - sbi->osi_conn.oc_dev = obddev; + + memset(sbi, 0, sizeof(*sbi)); + + CDEBUG(D_INFO, "\n"); + obdfs_options(data, &device, &version); + if ( !device ) { + printk(__FUNCTION__ ": no device\n"); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + if ( (err = obdfs_getdev(device, &devno)) ) { + printk("Cannot get devno of %s, error %d\n", device, err); + EXIT; + goto ERR;; + } + + CDEBUG(D_INFO, "\n"); + if ( MAJOR(devno) != OBD_PSDEV_MAJOR ) { + printk(__FUNCTION__ ": wrong major number %d!\n", MAJOR(devno)); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + if ( MINOR(devno) >= MAX_OBD_DEVICES ) { + printk(__FUNCTION__ ": minor of %s too high (%d)\n", + device, MINOR(devno)); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + obddev = &obd_dev[MINOR(devno)]; + + CDEBUG(D_INFO, "\n"); + if ( ! (obddev->obd_flags & OBD_ATTACHED) || + ! (obddev->obd_flags & OBD_SET_UP) ){ + printk("device %s not attached or not set up (%d)\n", + device, MINOR(devno)); + EXIT; + goto ERR;; + } + + CDEBUG(D_INFO, "\n"); + sbi->osi_obd = obddev; + sbi->osi_ops = sbi->osi_obd->obd_type->typ_ops; + + sbi->osi_conn.oc_dev = obddev; err = sbi->osi_ops->o_connect(&sbi->osi_conn); - if ( err ) { - printk("OBDFS: cannot connect to %s\n", device); - EXIT; - goto ERR; - } - - /* list of dirty inodes, and a mutex to hold while modifying it */ - INIT_LIST_HEAD(&sbi->osi_inodes); - sema_init(&sbi->osi_list_mutex, 1); - - sbi->osi_super = sb; - - err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize"), - "blocksize", &scratch, - (void *)&blocksize); - if ( err ) { - printk("getinfo call to drive failed (blocksize)\n"); - EXIT; - goto ERR; - } - - err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize_bits"), - "blocksize_bits", &scratch, - (void *)&blocksize_bits); - if ( err ) { - printk("getinfo call to drive failed (blocksize_bits)\n"); - EXIT; - goto ERR; - } - - err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("root_ino"), - "root_ino", &scratch, (void *)&root_ino); - if ( err ) { - printk("getinfo call to drive failed (root_ino)\n"); - EXIT; - goto ERR; - } - - lock_super(sb); - + if ( err ) { + printk("OBDFS: cannot connect to %s\n", device); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + /* list of dirty inodes, and a mutex to hold while modifying it */ + INIT_LIST_HEAD(&sbi->osi_inodes); + sema_init(&sbi->osi_list_mutex, 1); + + CDEBUG(D_INFO, "\n"); + sbi->osi_super = sb; + + CDEBUG(D_INFO, "\n"); + err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize"), + "blocksize", &scratch, + (void *)&blocksize); + if ( err ) { + printk("getinfo call to drive failed (blocksize)\n"); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("blocksize_bits"), + "blocksize_bits", &scratch, + (void *)&blocksize_bits); + if ( err ) { + printk("getinfo call to drive failed (blocksize_bits)\n"); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); + err = sbi->osi_ops->o_get_info(&sbi->osi_conn, strlen("root_ino"), + "root_ino", &scratch, (void *)&root_ino); + if ( err ) { + printk("getinfo call to drive failed (root_ino)\n"); + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "\n"); sb->s_blocksize = blocksize; sb->s_blocksize_bits = (unsigned char)blocksize_bits; sb->s_magic = OBDFS_SUPER_MAGIC; sb->s_op = &obdfs_super_operations; - /* XXX how to get "sb->s_flags |= MS_RDONLY" here for snapshots? */ + /* XXX how to get "sb->s_flags |= MS_RDONLY" here for snapshots? */ - /* make root inode */ - root = iget(sb, root_ino); + /* make root inode */ + CDEBUG(D_INFO, "\n"); + root = iget(sb, root_ino); if (!root || is_bad_inode(root)) { - printk("OBDFS: bad iget for root\n"); - sb->s_dev = 0; - err = -ENOENT; - unlock_super(sb); - EXIT; - goto ERR; - } - - CDEBUG(D_INFO, "obdfs_read_super: sbdev %d, rootino: %ld, dev %s, " - "minor: %d, blocksize: %ld, blocksize bits %ld\n", - sb->s_dev, root->i_ino, device, MINOR(devno), - blocksize, blocksize_bits); - sb->s_root = d_alloc_root(root); - list_add(&sbi->osi_list, &obdfs_super_list); - unlock_super(sb); - OBD_FREE(device, strlen(device) + 1); - if (version) - OBD_FREE(version, strlen(version) + 1); - EXIT; + printk("OBDFS: bad iget for root\n"); + sb->s_dev = 0; + err = -ENOENT; + EXIT; + goto ERR; + } + + CDEBUG(D_INFO, "obdfs_read_super: sbdev %d, rootino: %ld, dev %s, " + "minor: %d, blocksize: %ld, blocksize bits %ld\n", + sb->s_dev, root->i_ino, device, MINOR(devno), + blocksize, blocksize_bits); + sb->s_root = d_alloc_root(root); + list_add(&sbi->osi_list, &obdfs_super_list); + OBD_FREE(device, strlen(device) + 1); + if (version) + OBD_FREE(version, strlen(version) + 1); + EXIT; return sb; ERR: - MOD_DEC_USE_COUNT; - if (device) - OBD_FREE(device, strlen(device) + 1); - if (version) - OBD_FREE(version, strlen(version) + 1); - if (sbi) { - sbi->osi_super = NULL; - } + MOD_DEC_USE_COUNT; + if (device) + OBD_FREE(device, strlen(device) + 1); + if (version) + OBD_FREE(version, strlen(version) + 1); + if (sbi) { + sbi->osi_super = NULL; + } if (root) { iput(root); } @@ -260,89 +277,95 @@ static void obdfs_put_super(struct super_block *sb) ENTRY; sb->s_dev = 0; - - sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp; - obdfs_flush_reqs(&sbi->osi_inodes, ~0UL); + + sbi = (struct obdfs_sb_info *) &sb->u.generic_sbp; + obdfs_flush_reqs(&sbi->osi_inodes, ~0UL); - OPS(sb,disconnect)(ID(sb)); - list_del(&sbi->osi_list); - memset(sbi, 0, sizeof(*sbi)); - - printk(KERN_INFO "OBDFS: Bye bye.\n"); + OPS(sb,disconnect)(ID(sb)); + list_del(&sbi->osi_list); + memset(sbi, 0, sizeof(*sbi)); + + printk(KERN_INFO "OBDFS: Bye bye.\n"); MOD_DEC_USE_COUNT; - EXIT; + EXIT; } /* obdfs_put_super */ /* all filling in of inodes postponed until lookup */ static void obdfs_read_inode(struct inode *inode) { - struct obdo *oa; - - ENTRY; - oa = obdo_fromid(IID(inode), inode->i_ino, - OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS); - if ( IS_ERR(oa) ) { - printk(__FUNCTION__ ": obdo_fromid failed\n"); - EXIT; - return /* PTR_ERR(oa) */; - } - - ODEBUG(oa); - obdfs_to_inode(inode, oa); - INIT_LIST_HEAD(obdfs_iplist(inode)); /* list of dirty pages on inode */ - INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */ - - obdo_free(oa); - /* OIDEBUG(inode); */ - - if (S_ISREG(inode->i_mode)) { - inode->i_op = &obdfs_file_inode_operations; - EXIT; - } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = &obdfs_dir_inode_operations; - EXIT; - } else if (S_ISLNK(inode->i_mode)) { - inode->i_op = inode->i_blocks - ?&obdfs_symlink_inode_operations - :&obdfs_fast_symlink_inode_operations; - EXIT; - } else { - init_special_inode(inode, inode->i_mode, - ((int *)obdfs_i2info(inode)->oi_inline)[0]); - } - - return; + struct obdo *oa; + + ENTRY; + oa = obdo_fromid(IID(inode), inode->i_ino, + OBD_MD_FLNOTOBD | OBD_MD_FLBLOCKS); + if ( IS_ERR(oa) ) { + printk(__FUNCTION__ ": obdo_fromid failed\n"); + EXIT; + return /* PTR_ERR(oa) */; + } + + ODEBUG(oa); + obdfs_to_inode(inode, oa); + INIT_LIST_HEAD(obdfs_iplist(inode)); /* list of dirty pages on inode */ + INIT_LIST_HEAD(obdfs_islist(inode)); /* list of inodes in superblock */ + + obdo_free(oa); + /* OIDEBUG(inode); */ + + if (S_ISREG(inode->i_mode)) { + inode->i_op = &obdfs_file_inode_operations; + inode->i_fop = &obdfs_file_operations; + inode->i_mapping->a_ops = &obdfs_aops; + EXIT; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &obdfs_dir_inode_operations; + inode->i_fop = &obdfs_dir_operations; + EXIT; + } else if (S_ISLNK(inode->i_mode)) { + if (inode->i_blocks) { + inode->i_op = &obdfs_symlink_inode_operations; + inode->i_mapping->a_ops = &obdfs_aops; + }else { + inode->i_op = &obdfs_fast_symlink_inode_operations; + } + EXIT; + } else { + init_special_inode(inode, inode->i_mode, + ((int *)obdfs_i2info(inode)->oi_inline)[0]); + } + + return; } /* obdfs_read_inode */ -static void obdfs_write_inode(struct inode *inode) +static void obdfs_write_inode(struct inode *inode, int wait) { - struct obdo *oa; - int err; - - ENTRY; - if (IOPS(inode, setattr) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); - EXIT; - return; - } - oa = obdo_alloc(); - if ( !oa ) { - printk(__FUNCTION__ ": obdo_alloc failed\n"); - EXIT; - return; - } - - oa->o_valid = OBD_MD_FLNOTOBD; - obdfs_from_inode(oa, inode); - err = IOPS(inode, setattr)(IID(inode), oa); - - if ( err ) - printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err); - - EXIT; - obdo_free(oa); + struct obdo *oa; + int err; + + ENTRY; + if (IOPS(inode, setattr) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); + EXIT; + return; + } + oa = obdo_alloc(); + if ( !oa ) { + printk(__FUNCTION__ ": obdo_alloc failed\n"); + EXIT; + return; + } + + oa->o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(oa, inode); + err = IOPS(inode, setattr)(IID(inode), oa); + + if ( err ) + printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err); + + EXIT; + obdo_free(oa); } /* obdfs_write_inode */ @@ -353,115 +376,112 @@ static void obdfs_write_inode(struct inode *inode) */ static void obdfs_put_inode(struct inode *inode) { - ENTRY; - if (inode->i_nlink) { - EXIT; - return; - } - - obdfs_dequeue_pages(inode); - EXIT; + ENTRY; + if (inode->i_nlink) { + EXIT; + return; + } + + obdfs_dequeue_pages(inode); + EXIT; } /* obdfs_put_inode */ static void obdfs_delete_inode(struct inode *inode) { - struct obdo *oa; - int err; + struct obdo *oa; + int err; ENTRY; - if (IOPS(inode, destroy) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no destroy method!\n"); - EXIT; - return; - } - - oa = obdo_alloc(); - if ( !oa ) { - printk(__FUNCTION__ ": obdo_alloc failed\n"); - EXIT; - return; - } - oa->o_valid = OBD_MD_FLNOTOBD; - obdfs_from_inode(oa, inode); - - ODEBUG(oa); - err = IOPS(inode, destroy)(IID(inode), oa); - obdo_free(oa); - - if (err) { - printk(__FUNCTION__ ": obd_destroy fails (%d)\n", err); - EXIT; - return; - } - - EXIT; + if (IOPS(inode, destroy) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no destroy method!\n"); + EXIT; + return; + } + + oa = obdo_alloc(); + if ( !oa ) { + printk(__FUNCTION__ ": obdo_alloc failed\n"); + EXIT; + return; + } + oa->o_valid = OBD_MD_FLNOTOBD; + obdfs_from_inode(oa, inode); + + ODEBUG(oa); + err = IOPS(inode, destroy)(IID(inode), oa); + obdo_free(oa); + + if (err) { + printk(__FUNCTION__ ": obd_destroy fails (%d)\n", err); + EXIT; + return; + } + + EXIT; } /* obdfs_delete_inode */ -static int obdfs_notify_change(struct dentry *de, struct iattr *attr) +int obdfs_notify_change(struct dentry *de, struct iattr *attr) { - struct inode *inode = de->d_inode; - struct obdo *oa; - int err; - - ENTRY; - if (IOPS(inode, setattr) == NULL) { - printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); - EXIT; - return -EIO; - } - oa = obdo_alloc(); - if ( !oa ) { - printk(__FUNCTION__ ": obdo_alloc failed\n"); - return -ENOMEM; - } - - oa->o_id = inode->i_ino; - obdo_from_iattr(oa, attr); + struct inode *inode = de->d_inode; + struct obdo *oa; + int err; + + ENTRY; + if (IOPS(inode, setattr) == NULL) { + printk(KERN_ERR __FUNCTION__ ": no setattr method!\n"); + EXIT; + return -EIO; + } + oa = obdo_alloc(); + if ( !oa ) { + printk(__FUNCTION__ ": obdo_alloc failed\n"); + return -ENOMEM; + } + + oa->o_id = inode->i_ino; + obdo_from_iattr(oa, attr); err = IOPS(inode, setattr)(IID(inode), oa); - if ( err ) - printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err); + if ( err ) + printk(__FUNCTION__ ": obd_setattr fails (%d)\n", err); - EXIT; - obdo_free(oa); + EXIT; + obdo_free(oa); return err; } /* obdfs_notify_change */ -static int obdfs_statfs(struct super_block *sb, struct statfs *buf, - int bufsize) +static int obdfs_statfs(struct super_block *sb, struct statfs *buf) { - struct statfs tmp; - int err; + struct statfs tmp; + int bufsize = sizeof(*buf); + int err; - ENTRY; + ENTRY; - err = OPS(sb,statfs)(ID(sb), &tmp); - if ( err ) { - printk(__FUNCTION__ ": obd_statfs fails (%d)\n", err); - return err; - } - copy_to_user(buf, &tmp, (bufsize -#include #include #include #include @@ -28,60 +27,59 @@ static int obdfs_fast_readlink(struct dentry *dentry, char *buffer, int buflen) { - char *s = obdfs_i2info(dentry->d_inode)->oi_inline; - return vfs_readlink(dentry, buffer, buflen, s); + char *s = obdfs_i2info(dentry->d_inode)->oi_inline; + return vfs_readlink(dentry, buffer, buflen, s); } -static struct dentry *obdfs_fast_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags) +static int obdfs_fast_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s = obdfs_i2info(dentry->d_inode)->oi_inline; - return vfs_follow_link(dentry, base, flags, s); + char *s = obdfs_i2info(dentry->d_inode)->oi_inline; + return vfs_follow_link(nd, s); } struct inode_operations obdfs_fast_symlink_inode_operations = { - readlink: obdfs_fast_readlink, - follow_link: obdfs_fast_follow_link, + readlink: obdfs_fast_readlink, + follow_link: obdfs_fast_follow_link, }; static int obdfs_readlink(struct dentry *dentry, char *buffer, int buflen) { - struct page *page = NULL; - int res; + struct page *page = NULL; + int res; - ENTRY; - OIDEBUG(dentry->d_inode); - page = obdfs_getpage(dentry->d_inode, 0, 0, 0); - /* PDEBUG(page, "readlink"); */ - if (!page) { - EXIT; - return 0; - } - res = vfs_readlink(dentry, buffer, buflen, (char *)page_address(page)); - page_cache_release(page); - EXIT; - return res; + ENTRY; + OIDEBUG(dentry->d_inode); + page = obdfs_getpage(dentry->d_inode, 0, 0, 0); + /* PDEBUG(page, "readlink"); */ + if (!page) { + EXIT; + return 0; + } + res = vfs_readlink(dentry, buffer, buflen, (char *)page_address(page)); + page_cache_release(page); + EXIT; + return res; } /* obdfs_readlink */ -static struct dentry * obdfs_follow_link(struct dentry * dentry, - struct dentry *base, - unsigned int follow) +static int obdfs_follow_link(struct dentry * dentry, + struct nameidata *nd) { - struct page *page = NULL; - struct dentry *res; + struct page *page = NULL; + int res; - ENTRY; - OIDEBUG(dentry->d_inode); - page = obdfs_getpage(dentry->d_inode, 0, 0, 0); - /* PDEBUG(page, "follow_link"); */ - if (!page) { - dput(base); - EXIT; - return ERR_PTR(-EIO); - } - res = vfs_follow_link(dentry, base, follow, (char *)page_address(page)); - page_cache_release(page); - EXIT; - return res; + ENTRY; + OIDEBUG(dentry->d_inode); + page = obdfs_getpage(dentry->d_inode, 0, 0, 0); + /* PDEBUG(page, "follow_link"); */ + if (!page) { + dput(nd->dentry); + EXIT; + return -EIO; + } + res = vfs_follow_link(nd, (char *)page_address(page)); + page_cache_release(page); + EXIT; + return res; } struct inode_operations obdfs_symlink_inode_operations = { -- 1.8.3.1