X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=fs%2Fgfs2%2Fops_file.c;h=b52b9db1a2bdb0605bfee978ed933dd60531d163;hb=c594d8866460a2710c436839d79f334a0714a2a7;hp=145a29fa4ea48a4061799edc337a79a4652ef7e6;hpb=83b7a664a0c7c39ccfa4c72535dc1c001d4e7a18;p=linux-2.6-omap-h63xx.git diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 145a29fa4ea..b52b9db1a2b 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c @@ -4,7 +4,7 @@ * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. + * of the GNU General Public License version 2. */ #include @@ -21,11 +21,10 @@ #include #include #include -#include +#include #include #include "gfs2.h" -#include "lm_interface.h" #include "incore.h" #include "bmap.h" #include "dir.h" @@ -43,27 +42,6 @@ #include "util.h" #include "eaops.h" -/* "bad" is for NFS support */ -struct filldir_bad_entry { - char *fbe_name; - unsigned int fbe_length; - uint64_t fbe_offset; - struct gfs2_inum fbe_inum; - unsigned int fbe_type; -}; - -struct filldir_bad { - struct gfs2_sbd *fdb_sbd; - - struct filldir_bad_entry *fdb_entry; - unsigned int fdb_entry_num; - unsigned int fdb_entry_off; - - char *fdb_name; - unsigned int fdb_name_size; - unsigned int fdb_name_off; -}; - /* For regular, non-NFS */ struct filldir_reg { struct gfs2_sbd *fdr_sbd; @@ -79,7 +57,7 @@ struct filldir_reg { * any other part of this. Its use is purely as a flag so that we * know (in readpage()) whether or not do to locking. */ -struct file gfs2_internal_file_sentinal = { +struct file gfs2_internal_file_sentinel = { .f_flags = O_NOATIME|O_RDONLY, }; @@ -93,13 +71,13 @@ static int gfs2_read_actor(read_descriptor_t *desc, struct page *page, size = count; kaddr = kmap(page); - memcpy(desc->arg.buf, kaddr + offset, size); - kunmap(page); + memcpy(desc->arg.data, kaddr + offset, size); + kunmap(page); - desc->count = count - size; - desc->written += size; - desc->arg.buf += size; - return size; + desc->count = count - size; + desc->written += size; + desc->arg.buf += size; + return size; } int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, @@ -108,11 +86,11 @@ int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, struct inode *inode = &ip->i_inode; read_descriptor_t desc; desc.written = 0; - desc.arg.buf = buf; + desc.arg.data = buf; desc.count = size; desc.error = 0; do_generic_mapping_read(inode->i_mapping, ra_state, - &gfs2_internal_file_sentinal, pos, &desc, + &gfs2_internal_file_sentinel, pos, &desc, gfs2_read_actor); return desc.written ? desc.written : desc.error; } @@ -149,7 +127,7 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) } /** - * filldir_reg_func - Report a directory entry to the caller of gfs2_dir_read() + * filldir_func - Report a directory entry to the caller of gfs2_dir_read() * @opaque: opaque data used by the function * @name: the name of the directory entry * @length: the length of the name @@ -160,9 +138,9 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) * Returns: 0 on success, 1 if buffer full */ -static int filldir_reg_func(void *opaque, const char *name, unsigned int length, - uint64_t offset, struct gfs2_inum *inum, - unsigned int type) +static int filldir_func(void *opaque, const char *name, unsigned int length, + u64 offset, struct gfs2_inum_host *inum, + unsigned int type) { struct filldir_reg *fdr = (struct filldir_reg *)opaque; struct gfs2_sbd *sdp = fdr->fdr_sbd; @@ -174,11 +152,9 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, return 1; if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) { - gfs2_glock_prefetch_num(sdp, - inum->no_addr, &gfs2_inode_glops, + gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops, LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); - gfs2_glock_prefetch_num(sdp, - inum->no_addr, &gfs2_iopen_glops, + gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops, LM_ST_SHARED, LM_FLAG_TRY); } @@ -186,7 +162,7 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, } /** - * readdir_reg - Read directory entries from a directory + * gfs2_readdir - Read directory entries from a directory * @file: The directory to read from * @dirent: Buffer for dirents * @filldir: Function used to do the copying @@ -194,13 +170,13 @@ static int filldir_reg_func(void *opaque, const char *name, unsigned int length, * Returns: errno */ -static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) +static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) { struct inode *dir = file->f_mapping->host; struct gfs2_inode *dip = GFS2_I(dir); struct filldir_reg fdr; struct gfs2_holder d_gh; - uint64_t offset = file->f_pos; + u64 offset = file->f_pos; int error; fdr.fdr_sbd = GFS2_SB(dir); @@ -215,7 +191,7 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) return error; } - error = gfs2_dir_read(dir, &offset, &fdr, filldir_reg_func); + error = gfs2_dir_read(dir, &offset, &fdr, filldir_func); gfs2_glock_dq_uninit(&d_gh); @@ -225,173 +201,47 @@ static int readdir_reg(struct file *file, void *dirent, filldir_t filldir) } /** - * filldir_bad_func - Report a directory entry to the caller of gfs2_dir_read() - * @opaque: opaque data used by the function - * @name: the name of the directory entry - * @length: the length of the name - * @offset: the entry's offset in the directory - * @inum: the inode number the entry points to - * @type: the type of inode the entry points to + * fsflags_cvt + * @table: A table of 32 u32 flags + * @val: a 32 bit value to convert * - * For supporting NFS. + * This function can be used to convert between fsflags values and + * GFS2's own flags values. * - * Returns: 0 on success, 1 if buffer full + * Returns: the converted flags */ - -static int filldir_bad_func(void *opaque, const char *name, unsigned int length, - uint64_t offset, struct gfs2_inum *inum, - unsigned int type) +static u32 fsflags_cvt(const u32 *table, u32 val) { - struct filldir_bad *fdb = (struct filldir_bad *)opaque; - struct gfs2_sbd *sdp = fdb->fdb_sbd; - struct filldir_bad_entry *fbe; - - if (fdb->fdb_entry_off == fdb->fdb_entry_num || - fdb->fdb_name_off + length > fdb->fdb_name_size) - return 1; - - fbe = &fdb->fdb_entry[fdb->fdb_entry_off]; - fbe->fbe_name = fdb->fdb_name + fdb->fdb_name_off; - memcpy(fbe->fbe_name, name, length); - fbe->fbe_length = length; - fbe->fbe_offset = offset; - fbe->fbe_inum = *inum; - fbe->fbe_type = type; - - fdb->fdb_entry_off++; - fdb->fdb_name_off += length; - - if (!(length == 1 && *name == '.')) { - gfs2_glock_prefetch_num(sdp, - inum->no_addr, &gfs2_inode_glops, - LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY); - gfs2_glock_prefetch_num(sdp, - inum->no_addr, &gfs2_iopen_glops, - LM_ST_SHARED, LM_FLAG_TRY); + u32 res = 0; + while(val) { + if (val & 1) + res |= *table; + table++; + val >>= 1; } - - return 0; + return res; } -/** - * readdir_bad - Read directory entries from a directory - * @file: The directory to read from - * @dirent: Buffer for dirents - * @filldir: Function used to do the copying - * - * For supporting NFS. - * - * Returns: errno - */ - -static int readdir_bad(struct file *file, void *dirent, filldir_t filldir) -{ - struct inode *dir = file->f_mapping->host; - 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; - struct gfs2_holder d_gh; - uint64_t offset = file->f_pos; - unsigned int x; - struct filldir_bad_entry *fbe; - int error; - - entries = gfs2_tune_get(sdp, gt_entries_per_readdir); - size = sizeof(struct filldir_bad) + - entries * (sizeof(struct filldir_bad_entry) + GFS2_FAST_NAME_SIZE); - - fdb = kzalloc(size, GFP_KERNEL); - if (!fdb) - return -ENOMEM; - - fdb->fdb_sbd = sdp; - fdb->fdb_entry = (struct filldir_bad_entry *)(fdb + 1); - fdb->fdb_entry_num = entries; - fdb->fdb_name = ((char *)fdb) + sizeof(struct filldir_bad) + - entries * sizeof(struct filldir_bad_entry); - fdb->fdb_name_size = entries * GFS2_FAST_NAME_SIZE; - - gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh); - error = gfs2_glock_nq_atime(&d_gh); - if (error) { - gfs2_holder_uninit(&d_gh); - goto out; - } - - error = gfs2_dir_read(dir, &offset, fdb, filldir_bad_func); - - gfs2_glock_dq_uninit(&d_gh); - - fdr.fdr_sbd = sdp; - fdr.fdr_prefetch = 0; - fdr.fdr_filldir = filldir; - fdr.fdr_opaque = dirent; - - for (x = 0; x < fdb->fdb_entry_off; x++) { - fbe = &fdb->fdb_entry[x]; - - error = filldir_reg_func(&fdr, - fbe->fbe_name, fbe->fbe_length, - fbe->fbe_offset, - &fbe->fbe_inum, fbe->fbe_type); - if (error) { - file->f_pos = fbe->fbe_offset; - error = 0; - goto out; - } - } - - file->f_pos = offset; - - out: - kfree(fdb); - - return error; -} - -/** - * gfs2_readdir - Read directory entries from a directory - * @file: The directory to read from - * @dirent: Buffer for dirents - * @filldir: Function used to do the copying - * - * Returns: errno - */ - -static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) -{ - int error; - - if (strcmp(current->comm, "nfsd") != 0) - error = readdir_reg(file, dirent, filldir); - else - error = readdir_bad(file, dirent, filldir); - - return error; -} - -static const u32 iflags_to_gfs2[32] = { - [iflag_Sync] = GFS2_DIF_SYNC, - [iflag_Immutable] = GFS2_DIF_IMMUTABLE, - [iflag_Append] = GFS2_DIF_APPENDONLY, - [iflag_NoAtime] = GFS2_DIF_NOATIME, - [iflag_Index] = GFS2_DIF_EXHASH, - [iflag_JournalData] = GFS2_DIF_JDATA, - [iflag_DirectIO] = GFS2_DIF_DIRECTIO, +static const u32 fsflags_to_gfs2[32] = { + [3] = GFS2_DIF_SYNC, + [4] = GFS2_DIF_IMMUTABLE, + [5] = GFS2_DIF_APPENDONLY, + [7] = GFS2_DIF_NOATIME, + [12] = GFS2_DIF_EXHASH, + [14] = GFS2_DIF_JDATA, + [20] = GFS2_DIF_DIRECTIO, }; -static const u32 gfs2_to_iflags[32] = { - [gfs2fl_Sync] = IFLAG_SYNC, - [gfs2fl_Immutable] = IFLAG_IMMUTABLE, - [gfs2fl_AppendOnly] = IFLAG_APPEND, - [gfs2fl_NoAtime] = IFLAG_NOATIME, - [gfs2fl_ExHash] = IFLAG_INDEX, - [gfs2fl_Jdata] = IFLAG_JOURNAL_DATA, - [gfs2fl_Directio] = IFLAG_DIRECTIO, - [gfs2fl_InheritDirectio] = IFLAG_DIRECTIO, - [gfs2fl_InheritJdata] = IFLAG_JOURNAL_DATA, +static const u32 gfs2_to_fsflags[32] = { + [gfs2fl_Sync] = FS_SYNC_FL, + [gfs2fl_Immutable] = FS_IMMUTABLE_FL, + [gfs2fl_AppendOnly] = FS_APPEND_FL, + [gfs2fl_NoAtime] = FS_NOATIME_FL, + [gfs2fl_ExHash] = FS_INDEX_FL, + [gfs2fl_Jdata] = FS_JOURNAL_DATA_FL, + [gfs2fl_Directio] = FS_DIRECTIO_FL, + [gfs2fl_InheritDirectio] = FS_DIRECTIO_FL, + [gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL, }; static int gfs2_get_flags(struct file *filp, u32 __user *ptr) @@ -400,15 +250,15 @@ static int gfs2_get_flags(struct file *filp, u32 __user *ptr) struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int error; - u32 iflags; + u32 fsflags; gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh); 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)) + + fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_di.di_flags); + if (put_user(fsflags, ptr)) error = -EFAULT; gfs2_glock_dq_m(1, &gh); @@ -469,7 +319,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) goto out; if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY)) goto out; - if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) && + if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) && !capable(CAP_LINUX_IMMUTABLE)) goto out; if (!IS_IMMUTABLE(inode)) { @@ -486,7 +336,7 @@ static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) 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); + gfs2_dinode_out(ip, bh->b_data); brelse(bh); out_trans_end: gfs2_trans_end(sdp); @@ -497,19 +347,19 @@ out: static int gfs2_set_flags(struct file *filp, u32 __user *ptr) { - u32 iflags, gfsflags; - if (get_user(iflags, ptr)) + u32 fsflags, gfsflags; + if (get_user(fsflags, ptr)) return -EFAULT; - gfsflags = iflags_cvt(iflags_to_gfs2, iflags); + gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags); return do_gfs2_set_flags(filp, gfsflags, ~0); } static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch(cmd) { - case IFLAGS_GET_IOC: + case FS_IOC_GETFLAGS: return gfs2_get_flags(filp, (u32 __user *)arg); - case IFLAGS_SET_IOC: + case FS_IOC_SETFLAGS: return gfs2_set_flags(filp, (u32 __user *)arg); } return -ENOTTY; @@ -575,7 +425,7 @@ static int gfs2_open(struct inode *inode, struct file *file) gfs2_assert_warn(GFS2_SB(inode), !file->private_data); file->private_data = fp; - if (S_ISREG(ip->i_di.di_mode)) { + if (S_ISREG(ip->i_inode.i_mode)) { error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) @@ -665,7 +515,7 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; if (sdp->sd_args.ar_localflocks) { @@ -701,7 +551,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) int error = 0; state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; - flags = ((IS_SETLKW(cmd)) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; + flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; mutex_lock(&fp->f_fl_mutex); @@ -711,7 +561,7 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl) goto out; gfs2_glock_hold(gl); flock_lock_file_wait(file, - &(struct file_lock){.fl_type = F_UNLCK}); + &(struct file_lock){.fl_type = F_UNLCK}); gfs2_glock_dq_uninit(fl_gh); } else { error = gfs2_glock_get(GFS2_SB(&ip->i_inode), @@ -767,7 +617,7 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; - if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID) + if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; if (sdp->sd_args.ar_localflocks) @@ -776,37 +626,36 @@ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) if (fl->fl_type == F_UNLCK) { do_unflock(file, fl); return 0; - } else + } else { return do_flock(file, cmd, fl); + } } const struct file_operations gfs2_file_fops = { - .llseek = gfs2_llseek, - .read = generic_file_read, - .readv = generic_file_readv, - .aio_read = generic_file_aio_read, - .write = generic_file_write, - .writev = generic_file_writev, - .aio_write = generic_file_aio_write, - .unlocked_ioctl = gfs2_ioctl, - .mmap = gfs2_mmap, - .open = gfs2_open, - .release = gfs2_close, - .fsync = gfs2_fsync, - .lock = gfs2_lock, - .sendfile = generic_file_sendfile, - .flock = gfs2_flock, - .splice_read = generic_file_splice_read, - .splice_write = generic_file_splice_write, + .llseek = gfs2_llseek, + .read = do_sync_read, + .aio_read = generic_file_aio_read, + .write = do_sync_write, + .aio_write = generic_file_aio_write, + .unlocked_ioctl = gfs2_ioctl, + .mmap = gfs2_mmap, + .open = gfs2_open, + .release = gfs2_close, + .fsync = gfs2_fsync, + .lock = gfs2_lock, + .sendfile = generic_file_sendfile, + .flock = gfs2_flock, + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, }; const struct file_operations gfs2_dir_fops = { - .readdir = gfs2_readdir, - .unlocked_ioctl = gfs2_ioctl, - .open = gfs2_open, - .release = gfs2_close, - .fsync = gfs2_fsync, - .lock = gfs2_lock, - .flock = gfs2_flock, + .readdir = gfs2_readdir, + .unlocked_ioctl = gfs2_ioctl, + .open = gfs2_open, + .release = gfs2_close, + .fsync = gfs2_fsync, + .lock = gfs2_lock, + .flock = gfs2_flock, };