[GFS2] Add generation number
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / gfs2 / ops_file.c
index db4484a3efccc07add8751ce87911e8acf33525b..26f1d3249b0fce0803a77a67337d27f1128d8dd2 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
- * Copyright (C) 2004-2005 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
  *
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
@@ -22,7 +22,6 @@
 #include <linux/ext2_fs.h>
 #include <linux/crc32.h>
 #include <linux/iflags.h>
-#include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
 #include "gfs2.h"
@@ -106,7 +105,7 @@ static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
 int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
                       char *buf, loff_t *pos, unsigned size)
 {
-       struct inode *inode = ip->i_vnode;
+       struct inode *inode = &ip->i_inode;
        read_descriptor_t desc;
        desc.written = 0;
        desc.arg.buf = buf;
@@ -132,7 +131,7 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
 
 static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin)
 {
-       struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
+       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
        struct gfs2_holder i_gh;
        loff_t error;
 
@@ -179,7 +178,7 @@ static ssize_t __gfs2_file_aio_read(struct kiocb *iocb,
                                    unsigned long nr_segs, loff_t *ppos)
 {
        struct file *filp = iocb->ki_filp;
-       struct gfs2_inode *ip = filp->f_mapping->host->u.generic_ip;
+       struct gfs2_inode *ip = GFS2_I(filp->f_mapping->host);
        struct gfs2_holder gh;
        ssize_t retval;
        unsigned long seg;
@@ -334,7 +333,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
        int error;
 
        error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset,
-                                inum->no_formal_ino, type);
+                                inum->no_addr, type);
        if (error)
                return 1;
 
@@ -362,13 +361,13 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length,
 static int readdir_reg(struct file *file, void *dirent, filldir_t filldir)
 {
        struct inode *dir = file->f_mapping->host;
-       struct gfs2_inode *dip = dir->u.generic_ip;
+       struct gfs2_inode *dip = GFS2_I(dir);
        struct filldir_reg fdr;
        struct gfs2_holder d_gh;
        uint64_t offset = file->f_pos;
        int error;
 
-       fdr.fdr_sbd = dip->i_sbd;
+       fdr.fdr_sbd = GFS2_SB(dir);
        fdr.fdr_prefetch = 1;
        fdr.fdr_filldir = filldir;
        fdr.fdr_opaque = dirent;
@@ -452,8 +451,8 @@ static int filldir_bad_func(void *opaque, const char *name, unsigned int length,
 static int readdir_bad(struct file *file, void *dirent, filldir_t filldir)
 {
        struct inode *dir = file->f_mapping->host;
-       struct gfs2_inode *dip = dir->u.generic_ip;
-       struct gfs2_sbd *sdp = dip->i_sbd;
+       struct gfs2_inode *dip = GFS2_I(dir);
+       struct gfs2_sbd *sdp = GFS2_SB(dir);
        struct filldir_reg fdr;
        unsigned int entries, size;
        struct filldir_bad *fdb;
@@ -545,8 +544,6 @@ static const u32 iflags_to_gfs2[32] = {
        [iflag_Index] = GFS2_DIF_EXHASH,
        [iflag_JournalData] = GFS2_DIF_JDATA,
        [iflag_DirectIO] = GFS2_DIF_DIRECTIO,
-       [iflag_InheritDirectIO] = GFS2_DIF_INHERIT_DIRECTIO,
-       [iflag_InheritJdata] = GFS2_DIF_INHERIT_JDATA,
 };
 
 static const u32 gfs2_to_iflags[32] = {
@@ -557,13 +554,14 @@ static const u32 gfs2_to_iflags[32] = {
        [gfs2fl_ExHash] = IFLAG_INDEX,
        [gfs2fl_Jdata] = IFLAG_JOURNAL_DATA,
        [gfs2fl_Directio] = IFLAG_DIRECTIO,
-       [gfs2fl_InheritDirectio] = IFLAG_INHERITDIRECTIO,
-       [gfs2fl_InheritJdata] = IFLAG_INHERITJDATA,
+       [gfs2fl_InheritDirectio] = IFLAG_DIRECTIO,
+       [gfs2fl_InheritJdata] = IFLAG_JOURNAL_DATA,
 };
 
-static int gfs2_get_flags(struct inode *inode, u32 __user *ptr)
+static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
 {
-       struct gfs2_inode *ip = inode->u.generic_ip;
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
        u32 iflags;
@@ -572,7 +570,7 @@ static int gfs2_get_flags(struct inode *inode, u32 __user *ptr)
        error = gfs2_glock_nq_m_atime(1, &gh);
        if (error)
                return error;
-
+       
        iflags = iflags_cvt(gfs2_to_iflags, ip->i_di.di_flags);
        if (put_user(iflags, ptr))
                error = -EFAULT;
@@ -600,75 +598,86 @@ static int gfs2_get_flags(struct inode *inode, u32 __user *ptr)
  * @mask: Indicates which flags are valid
  *
  */
-static int do_gfs2_set_flags(struct inode *inode, u32 flags, u32 mask)
+static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
 {
-       struct gfs2_inode *ip = inode->u.generic_ip;
+       struct inode *inode = filp->f_dentry->d_inode;
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
        struct buffer_head *bh;
        struct gfs2_holder gh;
        int error;
-       u32 new_flags;
+       u32 new_flags, flags;
 
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
-       if (error)
+       if (error) {
+               gfs2_holder_uninit(&gh);
                return error;
+       }
 
-       new_flags = (ip->i_di.di_flags & ~mask) | (flags & mask);
+       flags = ip->i_di.di_flags;
+       new_flags = (flags & ~mask) | (reqflags & mask);
        if ((new_flags ^ flags) == 0)
                goto out;
 
+       if (S_ISDIR(inode->i_mode)) {
+               if ((new_flags ^ flags) & GFS2_DIF_JDATA)
+                       new_flags ^= (GFS2_DIF_JDATA|GFS2_DIF_INHERIT_JDATA);
+               if ((new_flags ^ flags) & GFS2_DIF_DIRECTIO)
+                       new_flags ^= (GFS2_DIF_DIRECTIO|GFS2_DIF_INHERIT_DIRECTIO);
+       }
+
        error = -EINVAL;
        if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET)
                goto out;
 
-       if (S_ISDIR(inode->i_mode)) {
-               if ((new_flags ^ flags) & (GFS2_DIF_JDATA | GFS2_DIF_DIRECTIO))
-                       goto out;
-       } else if (S_ISREG(inode->i_mode)) {
-               if ((new_flags ^ flags) & (GFS2_DIF_INHERIT_DIRECTIO|
-                                          GFS2_DIF_INHERIT_JDATA))
-                       goto out;
-       } else
-               goto out;
-
        error = -EPERM;
        if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE))
                goto out;
        if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
                goto out;
-       error = gfs2_repermission(inode, MAY_WRITE, NULL);
-       if (error)
+       if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) && 
+           !capable(CAP_LINUX_IMMUTABLE))
                goto out;
+       if (!IS_IMMUTABLE(inode)) {
+               error = permission(inode, MAY_WRITE, NULL);
+               if (error)
+                       goto out;
+       }
 
-       error = gfs2_meta_inode_buffer(ip, &bh);
+       error = gfs2_trans_begin(sdp, RES_DINODE, 0);
        if (error)
                goto out;
+       error = gfs2_meta_inode_buffer(ip, &bh);
+       if (error)
+               goto out_trans_end;
        gfs2_trans_add_bh(ip->i_gl, bh, 1);
        ip->i_di.di_flags = new_flags;
        gfs2_dinode_out(&ip->i_di, bh->b_data);
        brelse(bh);
+out_trans_end:
+       gfs2_trans_end(sdp);
 out:
        gfs2_glock_dq_uninit(&gh);
        return error;
 }
 
-static int gfs2_set_flags(struct inode *inode, u32 __user *ptr)
+static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
 {
        u32 iflags, gfsflags;
        if (get_user(iflags, ptr))
                return -EFAULT;
        gfsflags = iflags_cvt(iflags_to_gfs2, iflags);
-       return do_gfs2_set_flags(inode, gfsflags, ~0);
+       return do_gfs2_set_flags(filp, gfsflags, ~0);
 }
 
-int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
-              unsigned long arg)
+static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        switch(cmd) {
        case IFLAGS_GET_IOC:
-               return gfs2_get_flags(inode, (u32 __user *)arg);
+               return gfs2_get_flags(filp, (u32 __user *)arg);
        case IFLAGS_SET_IOC:
-               return gfs2_set_flags(inode, (u32 __user *)arg);
+               return gfs2_set_flags(filp, (u32 __user *)arg);
        }
        return -ENOTTY;
 }
@@ -684,7 +693,7 @@ int gfs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 
 static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
-       struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
+       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
        struct gfs2_holder i_gh;
        int error;
 
@@ -719,7 +728,7 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int gfs2_open(struct inode *inode, struct file *file)
 {
-       struct gfs2_inode *ip = inode->u.generic_ip;
+       struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder i_gh;
        struct gfs2_file *fp;
        int error;
@@ -730,10 +739,7 @@ static int gfs2_open(struct inode *inode, struct file *file)
 
        mutex_init(&fp->f_fl_mutex);
 
-       fp->f_inode = ip;
-       fp->f_vfile = file;
-
-       gfs2_assert_warn(ip->i_sbd, !file->private_data);
+       gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
        file->private_data = fp;
 
        if (S_ISREG(ip->i_di.di_mode)) {
@@ -802,9 +808,9 @@ static int gfs2_close(struct inode *inode, struct file *file)
 
 static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
-       struct gfs2_inode *ip = dentry->d_inode->u.generic_ip;
+       struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
 
-       gfs2_log_flush_glock(ip->i_gl);
+       gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
 
        return 0;
 }
@@ -820,8 +826,8 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
 
 static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 {
-       struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
-       struct gfs2_sbd *sdp = ip->i_sbd;
+       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+       struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
        struct lm_lockname name =
                { .ln_number = ip->i_num.no_addr,
                  .ln_type = LM_TYPE_PLOCK };
@@ -833,20 +839,15 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
 
        if (sdp->sd_args.ar_localflocks) {
                if (IS_GETLK(cmd)) {
-                       struct file_lock *tmp;
-                       lock_kernel();
-                       tmp = posix_test_lock(file, fl);
+                       struct file_lock tmp;
+                       int ret;
+                       ret = posix_test_lock(file, fl, &tmp);
                        fl->fl_type = F_UNLCK;
-                       if (tmp)
-                               memcpy(fl, tmp, sizeof(struct file_lock));
-                       unlock_kernel();
+                       if (ret)
+                               memcpy(fl, &tmp, sizeof(struct file_lock));
                        return 0;
                } else {
-                       int error;
-                       lock_kernel();
-                       error = posix_lock_file_wait(file, fl);
-                       unlock_kernel();
-                       return error;
+                       return posix_lock_file_wait(file, fl);
                }
        }
 
@@ -858,29 +859,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
                return gfs2_lm_plock(sdp, &name, file, cmd, fl);
 }
 
-/**
- * gfs2_sendfile - Send bytes to a file or socket
- * @in_file: The file to read from
- * @out_file: The file to write to
- * @count: The amount of data
- * @offset: The beginning file offset
- *
- * Outputs: offset - updated according to number of bytes read
- *
- * Returns: The number of bytes sent, errno on failure
- */
-
-static ssize_t gfs2_sendfile(struct file *in_file, loff_t *offset, size_t count,
-                            read_actor_t actor, void *target)
-{
-       return generic_file_sendfile(in_file, offset, count, actor, target);
-}
-
 static int do_flock(struct file *file, int cmd, struct file_lock *fl)
 {
        struct gfs2_file *fp = file->private_data;
        struct gfs2_holder *fl_gh = &fp->f_fl_gh;
-       struct gfs2_inode *ip = fp->f_inode;
+       struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
        struct gfs2_glock *gl;
        unsigned int state;
        int flags;
@@ -900,7 +883,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
                                     &(struct file_lock){.fl_type = F_UNLCK});          
                gfs2_glock_dq_uninit(fl_gh);
        } else {
-               error = gfs2_glock_get(ip->i_sbd,
+               error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
                                      ip->i_num.no_addr, &gfs2_flock_glops,
                                      CREATE, &gl);
                if (error)
@@ -917,7 +900,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
                        error = -EAGAIN;
        } else {
                error = flock_lock_file_wait(file, fl);
-               gfs2_assert_warn(ip->i_sbd, !error);
+               gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
        }
 
  out:
@@ -949,8 +932,8 @@ static void do_unflock(struct file *file, struct file_lock *fl)
 
 static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
 {
-       struct gfs2_inode *ip = file->f_mapping->host->u.generic_ip;
-       struct gfs2_sbd *sdp = ip->i_sbd;
+       struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
+       struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
 
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
@@ -967,7 +950,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl)
                return do_flock(file, cmd, fl);
 }
 
-struct file_operations gfs2_file_fops = {
+const struct file_operations gfs2_file_fops = {
        .llseek = gfs2_llseek,
        .read = gfs2_read,
        .readv = gfs2_file_readv,
@@ -975,19 +958,21 @@ struct file_operations gfs2_file_fops = {
        .write = generic_file_write,
        .writev = generic_file_writev,
        .aio_write = generic_file_aio_write,
-       .ioctl = gfs2_ioctl,
+       .unlocked_ioctl = gfs2_ioctl,
        .mmap = gfs2_mmap,
        .open = gfs2_open,
        .release = gfs2_close,
        .fsync = gfs2_fsync,
        .lock = gfs2_lock,
-       .sendfile = gfs2_sendfile,
+       .sendfile = generic_file_sendfile,
        .flock = gfs2_flock,
+       .splice_read = generic_file_splice_read,
+       .splice_write = generic_file_splice_write,
 };
 
-struct file_operations gfs2_dir_fops = {
+const struct file_operations gfs2_dir_fops = {
        .readdir = gfs2_readdir,
-       .ioctl = gfs2_ioctl,
+       .unlocked_ioctl = gfs2_ioctl,
        .open = gfs2_open,
        .release = gfs2_close,
        .fsync = gfs2_fsync,