aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/ops_file.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-03-28 14:14:04 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2006-03-28 14:14:04 -0500
commit71b86f562b5eb6f94ea00bba060caa64d0137969 (patch)
tree63d982e09a9cb934fe656afe115031c0a9dc5e4a /fs/gfs2/ops_file.c
parent94aabbd99370f738da4f6cb4ea0b94cd9024002f (diff)
[GFS2] Further updates to dir and logging code
This reduces the size of the directory code by about 3k and gets readdir() to use the functions which were introduced in the previous directory code update. Two memory allocations are merged into one. Eliminates zeroing of some buffers which were never used before they were initialised by other data. There is still scope for further improvement in the directory code. On the logging side, a hand created mutex has been replaced by a standard Linux mutex in the log allocation code. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_file.c')
-rw-r--r--fs/gfs2/ops_file.c219
1 files changed, 215 insertions, 4 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 6333a14cf77a..ac8e1238cb6f 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -19,6 +19,8 @@
19#include <linux/smp_lock.h> 19#include <linux/smp_lock.h>
20#include <linux/fs.h> 20#include <linux/fs.h>
21#include <linux/gfs2_ondisk.h> 21#include <linux/gfs2_ondisk.h>
22#include <linux/ext2_fs.h>
23#include <linux/crc32.h>
22#include <asm/semaphore.h> 24#include <asm/semaphore.h>
23#include <asm/uaccess.h> 25#include <asm/uaccess.h>
24 26
@@ -39,6 +41,7 @@
39#include "rgrp.h" 41#include "rgrp.h"
40#include "trans.h" 42#include "trans.h"
41#include "util.h" 43#include "util.h"
44#include "eaops.h"
42 45
43/* "bad" is for NFS support */ 46/* "bad" is for NFS support */
44struct filldir_bad_entry { 47struct filldir_bad_entry {
@@ -357,7 +360,8 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
357 360
358static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) 361static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
359{ 362{
360 struct gfs2_inode *dip = file->f_mapping->host->u.generic_ip; 363 struct inode *dir = file->f_mapping->host;
364 struct gfs2_inode *dip = dir->u.generic_ip;
361 struct filldir_reg fdr; 365 struct filldir_reg fdr;
362 struct gfs2_holder d_gh; 366 struct gfs2_holder d_gh;
363 uint64_t offset = file->f_pos; 367 uint64_t offset = file->f_pos;
@@ -375,7 +379,7 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
375 return error; 379 return error;
376 } 380 }
377 381
378 error = gfs2_dir_read(dip, &offset, &fdr, filldir_reg_func); 382 error = gfs2_dir_read(dir, &offset, &fdr, filldir_reg_func);
379 383
380 gfs2_glock_dq_uninit(&d_gh); 384 gfs2_glock_dq_uninit(&d_gh);
381 385
@@ -446,7 +450,8 @@ static int filldir_bad_func(void *opaque, const char *name, unsigned int length,
446 450
447static int readdir_bad(struct file *file, void *dirent, filldir_t filldir) 451static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
448{ 452{
449 struct gfs2_inode *dip = file->f_mapping->host->u.generic_ip; 453 struct inode *dir = file->f_mapping->host;
454 struct gfs2_inode *dip = dir->u.generic_ip;
450 struct gfs2_sbd *sdp = dip->i_sbd; 455 struct gfs2_sbd *sdp = dip->i_sbd;
451 struct filldir_reg fdr; 456 struct filldir_reg fdr;
452 unsigned int entries, size; 457 unsigned int entries, size;
@@ -479,7 +484,7 @@ static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
479 goto out; 484 goto out;
480 } 485 }
481 486
482 error = gfs2_dir_read(dip, &offset, fdb, filldir_bad_func); 487 error = gfs2_dir_read(dir, &offset, fdb, filldir_bad_func);
483 488
484 gfs2_glock_dq_uninit(&d_gh); 489 gfs2_glock_dq_uninit(&d_gh);
485 490
@@ -531,6 +536,210 @@ static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
531 return error; 536 return error;
532} 537}
533 538
539const struct gfs2_flag_eattr {
540 u32 flag;
541 u32 ext2;
542} gfs2_flag_eattrs[] = {
543 {
544 .flag = GFS2_DIF_IMMUTABLE,
545 .ext2 = EXT2_IMMUTABLE_FL,
546 }, {
547 .flag = GFS2_DIF_APPENDONLY,
548 .ext2 = EXT2_APPEND_FL,
549 }, {
550 .flag = GFS2_DIF_JDATA,
551 .ext2 = EXT2_JOURNAL_DATA_FL,
552 }, {
553 .flag = GFS2_DIF_EXHASH,
554 .ext2 = EXT2_INDEX_FL,
555 }, {
556 .flag = GFS2_DIF_EA_INDIRECT,
557 }, {
558 .flag = GFS2_DIF_DIRECTIO,
559 }, {
560 .flag = GFS2_DIF_NOATIME,
561 .ext2 = EXT2_NOATIME_FL,
562 }, {
563 .flag = GFS2_DIF_SYNC,
564 .ext2 = EXT2_SYNC_FL,
565 }, {
566 .flag = GFS2_DIF_SYSTEM,
567 }, {
568 .flag = GFS2_DIF_TRUNC_IN_PROG,
569 }, {
570 .flag = GFS2_DIF_INHERIT_JDATA,
571 }, {
572 .flag = GFS2_DIF_INHERIT_DIRECTIO,
573 }, {
574 },
575};
576
577static const struct gfs2_flag_eattr *get_by_ext2(u32 ext2)
578{
579 const struct gfs2_flag_eattr *p = gfs2_flag_eattrs;
580 for(; p->flag; p++) {
581 if (ext2 == p->ext2)
582 return p;
583 }
584 return NULL;
585}
586
587static const struct gfs2_flag_eattr *get_by_gfs2(u32 gfs2)
588{
589 const struct gfs2_flag_eattr *p = gfs2_flag_eattrs;
590 for(; p->flag; p++) {
591 if (gfs2 == p->flag)
592 return p;
593 }
594 return NULL;
595}
596
597static u32 gfs2_flags_to_ext2(u32 gfs2)
598{
599 const struct gfs2_flag_eattr *ea;
600 u32 ext2 = 0;
601 u32 mask = 1;
602
603 for(; mask != 0; mask <<=1) {
604 if (mask & gfs2) {
605 ea = get_by_gfs2(mask);
606 if (ea)
607 ext2 |= ea->ext2;
608 }
609 }
610 return ext2;
611}
612
613static int gfs2_flags_from_ext2(u32 *gfs2, u32 ext2)
614{
615 const struct gfs2_flag_eattr *ea;
616 u32 mask = 1;
617
618 for(; mask != 0; mask <<= 1) {
619 if (mask & ext2) {
620 ea = get_by_ext2(mask);
621 if (ea == NULL)
622 return -EINVAL;
623 *gfs2 |= ea->flag;
624 }
625 }
626 return 0;
627}
628
629static int get_ext2_flags(struct inode *inode, u32 __user *ptr)
630{
631 struct gfs2_inode *ip = inode->u.generic_ip;
632 struct gfs2_holder gh;
633 int error;
634 u32 ext2;
635
636 gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
637 error = gfs2_glock_nq_m_atime(1, &gh);
638 if (error)
639 return error;
640
641 ext2 = gfs2_flags_to_ext2(ip->i_di.di_flags);
642 if (put_user(ext2, ptr))
643 error = -EFAULT;
644
645 gfs2_glock_dq_m(1, &gh);
646 gfs2_holder_uninit(&gh);
647 return error;
648}
649
650/* Flags that can be set by user space */
651#define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \
652 GFS2_DIF_DIRECTIO| \
653 GFS2_DIF_IMMUTABLE| \
654 GFS2_DIF_APPENDONLY| \
655 GFS2_DIF_NOATIME| \
656 GFS2_DIF_SYNC| \
657 GFS2_DIF_SYSTEM| \
658 GFS2_DIF_INHERIT_DIRECTIO| \
659 GFS2_DIF_INHERIT_JDATA)
660
661/**
662 * gfs2_set_flags - set flags on an inode
663 * @inode: The inode
664 * @flags: The flags to set
665 * @mask: Indicates which flags are valid
666 *
667 */
668static int gfs2_set_flags(struct inode *inode, u32 flags, u32 mask)
669{
670 struct gfs2_inode *ip = inode->u.generic_ip;
671 struct buffer_head *bh;
672 struct gfs2_holder gh;
673 int error;
674 u32 new_flags;
675
676 gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
677 error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
678 if (error)
679 return error;
680
681 new_flags = (ip->i_di.di_flags & ~mask) | (flags & mask);
682 if ((new_flags ^ flags) == 0)
683 goto out;
684
685 error = -EINVAL;
686 if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET)
687 goto out;
688
689 if (S_ISDIR(inode->i_mode)) {
690 if ((new_flags ^ flags) & (GFS2_DIF_JDATA | GFS2_DIF_DIRECTIO))
691 goto out;
692 } else if (S_ISREG(inode->i_mode)) {
693 if ((new_flags ^ flags) & (GFS2_DIF_INHERIT_DIRECTIO|
694 GFS2_DIF_INHERIT_JDATA))
695 goto out;
696 } else
697 goto out;
698
699 error = -EPERM;
700 if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE))
701 goto out;
702 if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
703 goto out;
704 error = gfs2_repermission(inode, MAY_WRITE, NULL);
705 if (error)
706 goto out;
707
708 error = gfs2_meta_inode_buffer(ip, &bh);
709 if (error)
710 goto out;
711 gfs2_trans_add_bh(ip->i_gl, bh, 1);
712 ip->i_di.di_flags = new_flags;
713 gfs2_dinode_out(&ip->i_di, bh->b_data);
714 brelse(bh);
715out:
716 gfs2_glock_dq_uninit(&gh);
717 return error;
718}
719
720static int set_ext2_flags(struct inode *inode, u32 __user *ptr)
721{
722 u32 ext2, gfs2;
723 if (get_user(ext2, ptr))
724 return -EFAULT;
725 if (gfs2_flags_from_ext2(&gfs2, ext2))
726 return -EINVAL;
727 return gfs2_set_flags(inode, gfs2, ~0);
728}
729
730int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
731 unsigned long arg)
732{
733 switch(cmd) {
734 case EXT2_IOC_GETFLAGS:
735 return get_ext2_flags(inode, (u32 __user *)arg);
736 case EXT2_IOC_SETFLAGS:
737 return set_ext2_flags(inode, (u32 __user *)arg);
738 }
739 return -ENOTTY;
740}
741
742
534/** 743/**
535 * gfs2_mmap - 744 * gfs2_mmap -
536 * @file: The file to map 745 * @file: The file to map
@@ -832,6 +1041,7 @@ struct file_operations gfs2_file_fops = {
832 .write = generic_file_write, 1041 .write = generic_file_write,
833 .writev = generic_file_writev, 1042 .writev = generic_file_writev,
834 .aio_write = generic_file_aio_write, 1043 .aio_write = generic_file_aio_write,
1044 .ioctl = gfs2_ioctl,
835 .mmap = gfs2_mmap, 1045 .mmap = gfs2_mmap,
836 .open = gfs2_open, 1046 .open = gfs2_open,
837 .release = gfs2_close, 1047 .release = gfs2_close,
@@ -843,6 +1053,7 @@ struct file_operations gfs2_file_fops = {
843 1053
844struct file_operations gfs2_dir_fops = { 1054struct file_operations gfs2_dir_fops = {
845 .readdir = gfs2_readdir, 1055 .readdir = gfs2_readdir,
1056 .ioctl = gfs2_ioctl,
846 .open = gfs2_open, 1057 .open = gfs2_open,
847 .release = gfs2_close, 1058 .release = gfs2_close,
848 .fsync = gfs2_fsync, 1059 .fsync = gfs2_fsync,