From 676952b9bd85d03929922c101352a5677979f9e6 Mon Sep 17 00:00:00 2001 From: Dave McCracken Date: Tue, 5 Feb 2002 18:39:27 -0800 Subject: [PATCH] Third version of signal changes for thread groups During the course of developing our pthread library (the NGPT pthread library) it became clear we needed some kernel support for handling signals. This patch helps the library by redirecting all signals sent to tasks in a thread group to the thread group leader. It also defines the tkill() system call so the library can signal a specific task if necessary. Given that as far as I know NGPT is the only user of thread groups, and that this change would benefit any other user of thread groups, I'm submitting this for inclusion in the 2.5 kernel. Note that this patch also adds support for sys_gettid() for the architectures that don't have it. While this could have been split into a spearate patch, it would create conflicts since this patch also adds sys_tkill(), so I felt it was cleaner to leave them together. Dave McCracken ====================================================================== Dave McCracken IBM Linux Base Kernel Team 1-512-838-3059 dmccr@us.ibm.com T/L 678-3059 --- include/linux/sched.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index 6805d6ae39df..5d3f7b02ce08 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -564,6 +564,7 @@ extern int in_egroup_p(gid_t); extern void proc_caches_init(void); extern void flush_signals(struct task_struct *); extern void flush_signal_handlers(struct task_struct *); +extern void sig_exit(int, int, struct siginfo *); extern int dequeue_signal(sigset_t *, siginfo_t *); extern void block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask); @@ -839,9 +840,14 @@ do { \ #define for_each_task(p) \ for (p = &init_task ; (p = p->next_task) != &init_task ; ) +#define for_each_thread(task) \ + for (task = next_thread(current) ; task != current ; task = next_thread(task)) + #define next_thread(p) \ list_entry((p)->thread_group.next, struct task_struct, thread_group) +#define thread_group_leader(p) (p->pid == p->tgid) + static inline void unhash_process(struct task_struct *p) { write_lock_irq(&tasklist_lock); -- cgit v1.2.3 From 628561a60392ef1e0887fa1b2157004490497126 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Tue, 5 Feb 2002 18:46:24 -0800 Subject: [PATCH] (1/2) inode trimming more inode->u trimming - socket_i is killed. --- arch/sparc/kernel/sys_sunos.c | 2 +- arch/sparc64/kernel/sys_sunos32.c | 2 +- arch/sparc64/solaris/ioctl.c | 10 ++--- arch/sparc64/solaris/socket.c | 10 +---- arch/sparc64/solaris/socksys.c | 12 +++++- arch/sparc64/solaris/timod.c | 6 +-- drivers/block/nbd.c | 11 +++-- fs/ncpfs/inode.c | 2 +- fs/ncpfs/sock.c | 8 ++-- fs/smbfs/sock.c | 4 +- include/linux/fs.h | 16 +++++++- include/linux/net.h | 4 +- include/net/sock.h | 4 +- net/ax25/af_ax25.c | 2 +- net/ipv6/icmp.c | 14 +------ net/ipv6/mcast.c | 14 +------ net/ipv6/ndisc.c | 14 +------ net/netrom/af_netrom.c | 2 +- net/packet/af_packet.c | 4 +- net/rose/af_rose.c | 2 +- net/socket.c | 84 +++++++++++++++++++++++++++------------ net/unix/af_unix.c | 2 +- net/unix/garbage.c | 2 +- net/x25/af_x25.c | 2 +- 24 files changed, 128 insertions(+), 105 deletions(-) (limited to 'include/linux') diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 8dd283c38e85..5ea80c32d368 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -646,7 +646,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) inode = file->f_dentry->d_inode; - socket = &inode->u.socket_i; + socket = SOCKET_I(inode); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index 47e5a445a2a0..526a11af116f 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -612,7 +612,7 @@ sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) inode = file->f_dentry->d_inode; - socket = &inode->u.socket_i; + socket = SOCKET_I(inode); local.sin_family = AF_INET; local.sin_addr.s_addr = INADDR_ANY; diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c index 72c8f3405b40..a920499e23f4 100644 --- a/arch/sparc64/solaris/ioctl.c +++ b/arch/sparc64/solaris/ioctl.c @@ -308,7 +308,7 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) case 110: /* SI_GETUDATA */ { int etsdusize, servtype; - switch (ino->u.socket_i.type) { + switch (SOCKET_I(ino)->type) { case SOCK_STREAM: etsdusize = 1; servtype = 2; @@ -326,16 +326,16 @@ static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) __put_user(0, &((struct solaris_si_udata *)A(arg))->so_state) || __put_user(0, &((struct solaris_si_udata *)A(arg))->so_options) || __put_user(16384, &((struct solaris_si_udata *)A(arg))->tsdusize) || - __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) || - __put_user(ino->u.socket_i.type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) || - __put_user(ino->u.socket_i.ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol)) + __put_user(SOCKET_I(ino)->ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_family) || + __put_user(SOCKET_I(ino)->type, &((struct solaris_si_udata *)A(arg))->sockparams.sp_type) || + __put_user(SOCKET_I(ino)->ops->family, &((struct solaris_si_udata *)A(arg))->sockparams.sp_protocol)) return (EFAULT << 8) | TSYSERR; return 0; } case 101: /* O_SI_GETUDATA */ { int etsdusize, servtype; - switch (ino->u.socket_i.type) { + switch (SOCKET_I(ino)->type) { case SOCK_STREAM: etsdusize = 1; servtype = 2; diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c index e40b380922c8..6233516951ac 100644 --- a/arch/sparc64/solaris/socket.c +++ b/arch/sparc64/solaris/socket.c @@ -248,12 +248,6 @@ asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen) 24 for IPv6, about 80 for AX.25 */ -/* XXX These as well... */ -extern __inline__ struct socket *socki_lookup(struct inode *inode) -{ - return &inode->u.socket_i; -} - extern __inline__ struct socket *sockfd_lookup(int fd, int *err) { struct file *file; @@ -265,13 +259,13 @@ extern __inline__ struct socket *sockfd_lookup(int fd, int *err) } inode = file->f_dentry->d_inode; - if (!inode->i_sock || !socki_lookup(inode)) { + if (!inode->i_sock) { *err = -ENOTSOCK; fput(file); return NULL; } - return socki_lookup(inode); + return SOCKET_I(inode); } extern __inline__ void sockfd_put(struct socket *sock) diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c index dd06c16183f8..f6d5fab7c315 100644 --- a/arch/sparc64/solaris/socksys.c +++ b/arch/sparc64/solaris/socksys.c @@ -6,6 +6,13 @@ * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) */ +/* + * Dave, _please_ give me specifications on this fscking mess so that I + * could at least get it into the state when it wouldn't screw the rest of + * the kernel over. socksys.c and timod.c _stink_ and we are not talking + * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV + */ + #include #include #include @@ -86,6 +93,9 @@ static int socksys_open(struct inode * inode, struct file * filp) return fd; /* * N.B. The following operations are not legal! + * + * No shit. WTF is it supposed to do, anyway? + * * Try instead: * d_delete(filp->f_dentry), then d_instantiate with sock inode */ @@ -93,7 +103,7 @@ static int socksys_open(struct inode * inode, struct file * filp) filp->f_dentry = dget(fcheck(fd)->f_dentry); filp->f_dentry->d_inode->i_rdev = inode->i_rdev; filp->f_dentry->d_inode->i_flock = inode->i_flock; - filp->f_dentry->d_inode->u.socket_i.file = filp; + SOCKET_I(filp->f_dentry->d_inode)->file = filp; filp->f_op = &socksys_file_ops; sock = (struct sol_socket_struct*) mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c index d2799895117b..06e9590187ab 100644 --- a/arch/sparc64/solaris/timod.c +++ b/arch/sparc64/solaris/timod.c @@ -149,7 +149,7 @@ static void timod_wake_socket(unsigned int fd) struct socket *sock; SOLD("wakeing socket"); - sock = ¤t->files->fd[fd]->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(current->files->fd[fd]->f_dentry->d_inode); wake_up_interruptible(&sock->wait); read_lock(&sock->sk->callback_lock); if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) @@ -640,7 +640,7 @@ int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len, ino = filp->f_dentry->d_inode; sock = (struct sol_socket_struct *)filp->private_data; SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); - if ( ctl_maxlen > 0 && !sock->pfirst && ino->u.socket_i.type == SOCK_STREAM + if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) { SOLD("calling LISTEN"); args[0] = fd; @@ -730,7 +730,7 @@ int timod_getmsg(unsigned int fd, char *ctl_buf, int ctl_maxlen, s32 *ctl_len, *flags_p = 0; if (ctl_maxlen >= 0) { SOLD("ACCEPT perhaps?"); - if (ino->u.socket_i.type == SOCK_STREAM && sock->state == TS_IDLE) { + if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) { struct T_conn_ind ind; char *buf = getpage(); int len = BUF_SIZE; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index c58f725576a5..80ce7fd4d72c 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -418,10 +418,13 @@ static int nbd_ioctl(struct inode *inode, struct file *file, file = fget(arg); if (file) { inode = file->f_dentry->d_inode; - /* N.B. Should verify that it's a socket */ - lo->file = file; - lo->sock = &inode->u.socket_i; - error = 0; + if (inode->i_sock) { + lo->file = file; + lo->sock = SOCKET_I(inode); + error = 0; + } else { + fput(file); + } } return error; case NBD_SET_BLKSIZE: diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 32e089bd5ec0..e4ed0426d766 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -365,7 +365,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent) sock_inode = ncp_filp->f_dentry->d_inode; if (!S_ISSOCK(sock_inode->i_mode)) goto out_bad_file2; - sock = &sock_inode->u.socket_i; + sock = SOCKET_I(sock_inode); if (!sock) goto out_bad_file2; diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c index 470ea5e96ae3..095498a2b5b8 100644 --- a/fs/ncpfs/sock.c +++ b/fs/ncpfs/sock.c @@ -101,7 +101,7 @@ static int do_ncp_rpc_call(struct ncp_server *server, int size, struct ncp_reply_header reply; file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); init_timeout = server->m.time_out; max_timeout = NCP_MAX_RPC_TIMEOUT; @@ -269,7 +269,7 @@ static int do_tcp_rcv(struct ncp_server *server, void *buffer, size_t len) { int result = 0; file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); dataread = 0; @@ -348,7 +348,7 @@ static int do_ncp_tcp_rpc_call(struct ncp_server *server, int size, *((struct ncp_request_header *) (server->packet)); file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); ncptcp_xmit_hdr[0] = htonl(NCP_TCP_XMIT_MAGIC); ncptcp_xmit_hdr[1] = htonl(size + 16); @@ -444,7 +444,7 @@ static int ncp_do_request(struct ncp_server *server, int size, } #endif /* CONFIG_NCPFS_PACKET_SIGNING */ file = server->ncp_filp; - sock = &file->f_dentry->d_inode->u.socket_i; + sock = SOCKET_I(file->f_dentry->d_inode); /* N.B. this isn't needed ... check socket type? */ if (!sock) { printk(KERN_ERR "ncp_rpc_call: socki_lookup failed\n"); diff --git a/fs/smbfs/sock.c b/fs/smbfs/sock.c index 46313b623c7b..8c66f4c5e655 100644 --- a/fs/smbfs/sock.c +++ b/fs/smbfs/sock.c @@ -176,7 +176,7 @@ int smb_valid_socket(struct inode * inode) { return (inode && S_ISSOCK(inode->i_mode) && - inode->u.socket_i.type == SOCK_STREAM); + SOCKET_I(inode)->type == SOCK_STREAM); } static struct socket * @@ -190,7 +190,7 @@ server_sock(struct smb_sb_info *server) if (!smb_valid_socket(file->f_dentry->d_inode)) PARANOIA("bad socket!\n"); #endif - return &file->f_dentry->d_inode->u.socket_i; + return SOCKET_I(file->f_dentry->d_inode); } return NULL; } diff --git a/include/linux/fs.h b/include/linux/fs.h index cdfaac0cdc0e..b150576116ce 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -456,11 +456,25 @@ struct inode { /* struct umsdos_inode_info umsdos_i; */ struct romfs_inode_info romfs_i; struct proc_inode_info proc_i; - struct socket socket_i; void *generic_ip; } u; }; +struct socket_alloc { + struct socket socket; + struct inode vfs_inode; +}; + +static inline struct socket *SOCKET_I(struct inode *inode) +{ + return &list_entry(inode, struct socket_alloc, vfs_inode)->socket; +} + +static inline struct inode *SOCK_INODE(struct socket *socket) +{ + return &list_entry(socket, struct socket_alloc, socket)->vfs_inode; +} + #include /* will die */ #include diff --git a/include/linux/net.h b/include/linux/net.h index 39493fc2e265..8cd440ce36d6 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -23,6 +23,7 @@ #include struct poll_table_struct; +struct inode; #define NPROTO 32 /* should be enough for now.. */ @@ -68,7 +69,6 @@ struct socket unsigned long flags; struct proto_ops *ops; - struct inode *inode; struct fasync_struct *fasync_list; /* Asynchronous wake up list */ struct file *file; /* File back pointer for gc */ struct sock *sk; @@ -78,8 +78,6 @@ struct socket unsigned char passcred; }; -#define SOCK_INODE(S) ((S)->inode) - struct scm_cookie; struct vm_area_struct; struct page; diff --git a/include/net/sock.h b/include/net/sock.h index e4b723ca4545..c5e1646d8f75 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1022,7 +1022,7 @@ static inline int sock_i_uid(struct sock *sk) int uid; read_lock(&sk->callback_lock); - uid = sk->socket ? sk->socket->inode->i_uid : 0; + uid = sk->socket ? SOCK_INODE(sk->socket)->i_uid : 0; read_unlock(&sk->callback_lock); return uid; } @@ -1032,7 +1032,7 @@ static inline unsigned long sock_i_ino(struct sock *sk) unsigned long ino; read_lock(&sk->callback_lock); - ino = sk->socket ? sk->socket->inode->i_ino : 0; + ino = sk->socket ? SOCK_INODE(sk->socket)->i_ino : 0; read_unlock(&sk->callback_lock); return ino; } diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 59e1cf120b58..7b7374c9d81f 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1756,7 +1756,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length) len += sprintf(buffer + len, " %d %d %ld\n", atomic_read(&ax25->sk->wmem_alloc), atomic_read(&ax25->sk->rmem_alloc), - ax25->sk->socket != NULL ? ax25->sk->socket->inode->i_ino : 0L); + ax25->sk->socket != NULL ? SOCK_INODE(ax25->sk->socket)->i_ino : 0L); } else { len += sprintf(buffer + len, " * * *\n"); } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index d0ddcde24ce9..97bfcda70b3f 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -637,21 +637,11 @@ int __init icmpv6_init(struct net_proto_family *ops) struct sock *sk; int err; - icmpv6_socket = sock_alloc(); - if (icmpv6_socket == NULL) { - printk(KERN_ERR - "Failed to create the ICMP6 control socket.\n"); - return -1; - } - icmpv6_socket->inode->i_uid = 0; - icmpv6_socket->inode->i_gid = 0; - icmpv6_socket->type = SOCK_RAW; - - if ((err = ops->create(icmpv6_socket, IPPROTO_ICMPV6)) < 0) { + err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &icmpv6_socket); + if (err < 0) { printk(KERN_ERR "Failed to initialize the ICMP6 control socket (err %d).\n", err); - sock_release(icmpv6_socket); icmpv6_socket = NULL; /* for safety */ return err; } diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3d243fabd47a..6dcfb30fadda 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -751,21 +751,11 @@ int __init igmp6_init(struct net_proto_family *ops) struct sock *sk; int err; - igmp6_socket = sock_alloc(); - if (igmp6_socket == NULL) { + err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); + if (err < 0) { printk(KERN_ERR - "Failed to create the IGMP6 control socket.\n"); - return -1; - } - igmp6_socket->inode->i_uid = 0; - igmp6_socket->inode->i_gid = 0; - igmp6_socket->type = SOCK_RAW; - - if((err = ops->create(igmp6_socket, IPPROTO_ICMPV6)) < 0) { - printk(KERN_DEBUG "Failed to initialize the IGMP6 control socket (err %d).\n", err); - sock_release(igmp6_socket); igmp6_socket = NULL; /* For safety. */ return err; } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 838f7eebc396..658f559e6ac7 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1214,21 +1214,11 @@ int __init ndisc_init(struct net_proto_family *ops) struct sock *sk; int err; - ndisc_socket = sock_alloc(); - if (ndisc_socket == NULL) { + err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &ndisc_socket); + if (err < 0) { printk(KERN_ERR - "Failed to create the NDISC control socket.\n"); - return -1; - } - ndisc_socket->inode->i_uid = 0; - ndisc_socket->inode->i_gid = 0; - ndisc_socket->type = SOCK_RAW; - - if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) { - printk(KERN_DEBUG "Failed to initialize the NDISC control socket (err %d).\n", err); - sock_release(ndisc_socket); ndisc_socket = NULL; /* For safety. */ return err; } diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index f37bb2433e26..3c6f247a5305 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1204,7 +1204,7 @@ static int nr_get_info(char *buffer, char **start, off_t offset, int length) s->protinfo.nr->window, atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), - s->socket != NULL ? s->socket->inode->i_ino : 0L); + s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L); pos = begin + len; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index a0ae47666a30..272d42608490 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1575,7 +1575,7 @@ static void packet_mm_open(struct vm_area_struct *vma) { struct file *file = vma->vm_file; struct inode *inode = file->f_dentry->d_inode; - struct socket * sock = &inode->u.socket_i; + struct socket * sock = SOCKET_I(inode); struct sock *sk = sock->sk; if (sk) @@ -1586,7 +1586,7 @@ static void packet_mm_close(struct vm_area_struct *vma) { struct file *file = vma->vm_file; struct inode *inode = file->f_dentry->d_inode; - struct socket * sock = &inode->u.socket_i; + struct socket * sock = SOCKET_I(inode); struct sock *sk = sock->sk; if (sk) diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index d721721e8d8e..957315f805c4 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1370,7 +1370,7 @@ static int rose_get_info(char *buffer, char **start, off_t offset, int length) s->protinfo.rose->idle / (60 * HZ), atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), - s->socket != NULL ? s->socket->inode->i_ino : 0L); + s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L); pos = begin + len; diff --git a/net/socket.c b/net/socket.c index 0be746b10e8a..7d8d0e6b2a2d 100644 --- a/net/socket.c +++ b/net/socket.c @@ -272,7 +272,47 @@ static int sockfs_statfs(struct super_block *sb, struct statfs *buf) return 0; } +static kmem_cache_t * sock_inode_cachep; + +static struct inode *sock_alloc_inode(struct super_block *sb) +{ + struct socket_alloc *ei; + ei = (struct socket_alloc *)kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL); + if (!ei) + return NULL; + init_waitqueue_head(&ei->socket.wait); + return &ei->vfs_inode; +} + +static void sock_destroy_inode(struct inode *inode) +{ + kmem_cache_free(sock_inode_cachep, + list_entry(inode, struct socket_alloc, vfs_inode)); +} + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct socket_alloc *ei = (struct socket_alloc *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + +static int init_inodecache(void) +{ + sock_inode_cachep = kmem_cache_create("sock_inode_cache", + sizeof(struct socket_alloc), + 0, SLAB_HWCACHE_ALIGN, + init_once, NULL); + if (sock_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + static struct super_operations sockfs_ops = { + alloc_inode: sock_alloc_inode, + destroy_inode: sock_destroy_inode, statfs: sockfs_statfs, }; @@ -282,7 +322,7 @@ static struct super_block * sockfs_read_super(struct super_block *sb, void *data sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = SOCKFS_MAGIC; - sb->s_op = &sockfs_ops; + sb->s_op = &sockfs_ops; root = new_inode(sb); if (!root) return NULL; @@ -347,10 +387,10 @@ static int sock_map_fd(struct socket *sock) goto out; } - sprintf(name, "[%lu]", sock->inode->i_ino); + sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); this.name = name; this.len = strlen(name); - this.hash = sock->inode->i_ino; + this.hash = SOCK_INODE(sock)->i_ino; file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); if (!file->f_dentry) { @@ -360,11 +400,11 @@ static int sock_map_fd(struct socket *sock) goto out; } file->f_dentry->d_op = &sockfs_dentry_operations; - d_add(file->f_dentry, sock->inode); + d_add(file->f_dentry, SOCK_INODE(sock)); file->f_vfsmnt = mntget(sock_mnt); sock->file = file; - file->f_op = sock->inode->i_fop = &socket_file_ops; + file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; file->f_mode = 3; file->f_flags = O_RDWR; file->f_pos = 0; @@ -375,11 +415,6 @@ out: return fd; } -extern __inline__ struct socket *socki_lookup(struct inode *inode) -{ - return &inode->u.socket_i; -} - /** * sockfd_lookup - Go from a file number to its socket slot * @fd: file handle @@ -406,7 +441,7 @@ struct socket *sockfd_lookup(int fd, int *err) } inode = file->f_dentry->d_inode; - if (!inode->i_sock || !(sock = socki_lookup(inode))) + if (!inode->i_sock || !(sock = SOCKET_I(inode))) { *err = -ENOTSOCK; fput(file); @@ -443,15 +478,13 @@ struct socket *sock_alloc(void) return NULL; inode->i_dev = NODEV; - sock = socki_lookup(inode); + sock = SOCKET_I(inode); inode->i_mode = S_IFSOCK|S_IRWXUGO; inode->i_sock = 1; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; - sock->inode = inode; - init_waitqueue_head(&sock->wait); sock->fasync_list = NULL; sock->state = SS_UNCONNECTED; sock->flags = 0; @@ -493,7 +526,7 @@ void sock_release(struct socket *sock) sockets_in_use[smp_processor_id()].counter--; if (!sock->file) { - iput(sock->inode); + iput(SOCK_INODE(sock)); return; } sock->file=NULL; @@ -553,7 +586,7 @@ static ssize_t sock_read(struct file *file, char *ubuf, if (size==0) /* Match SYS5 behaviour */ return 0; - sock = socki_lookup(file->f_dentry->d_inode); + sock = SOCKET_I(file->f_dentry->d_inode); msg.msg_name=NULL; msg.msg_namelen=0; @@ -586,7 +619,7 @@ static ssize_t sock_write(struct file *file, const char *ubuf, if(size==0) /* Match SYS5 behaviour */ return 0; - sock = socki_lookup(file->f_dentry->d_inode); + sock = SOCKET_I(file->f_dentry->d_inode); msg.msg_name=NULL; msg.msg_namelen=0; @@ -612,7 +645,7 @@ ssize_t sock_sendpage(struct file *file, struct page *page, if (ppos != &file->f_pos) return -ESPIPE; - sock = socki_lookup(file->f_dentry->d_inode); + sock = SOCKET_I(file->f_dentry->d_inode); flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT; if (more) @@ -627,7 +660,7 @@ int sock_readv_writev(int type, struct inode * inode, struct file * file, struct msghdr msg; struct socket *sock; - sock = socki_lookup(inode); + sock = SOCKET_I(inode); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -681,7 +714,7 @@ int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, int err; unlock_kernel(); - sock = socki_lookup(inode); + sock = SOCKET_I(inode); err = sock->ops->ioctl(sock, cmd, arg); lock_kernel(); @@ -697,13 +730,13 @@ static unsigned int sock_poll(struct file *file, poll_table * wait) /* * We can't return errors to poll, so it's either yes or no. */ - sock = socki_lookup(file->f_dentry->d_inode); + sock = SOCKET_I(file->f_dentry->d_inode); return sock->ops->poll(file, sock, wait); } static int sock_mmap(struct file * file, struct vm_area_struct * vma) { - struct socket *sock = socki_lookup(file->f_dentry->d_inode); + struct socket *sock = SOCKET_I(file->f_dentry->d_inode); return sock->ops->mmap(file, sock, vma); } @@ -721,7 +754,7 @@ int sock_close(struct inode *inode, struct file *filp) return 0; } sock_fasync(-1, filp, 0); - sock_release(socki_lookup(inode)); + sock_release(SOCKET_I(inode)); return 0; } @@ -754,7 +787,7 @@ static int sock_fasync(int fd, struct file *filp, int on) } - sock = socki_lookup(filp->f_dentry->d_inode); + sock = SOCKET_I(filp->f_dentry->d_inode); if ((sk=sock->sk) == NULL) return -EINVAL; @@ -1521,7 +1554,7 @@ int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg) { struct socket *sock; - sock = socki_lookup (filp->f_dentry->d_inode); + sock = SOCKET_I (filp->f_dentry->d_inode); if (sock && sock->ops) return sock_no_fcntl(sock, cmd, arg); return(-EINVAL); @@ -1711,6 +1744,7 @@ void __init sock_init(void) * Initialize the protocols module. */ + init_inodecache(); register_filesystem(&sock_fs_type); sock_mnt = kern_mount(&sock_fs_type); /* The real protocol initialization is performed when diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 77a034a364ac..2cba30f76eca 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -711,7 +711,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* * All right, let's create it. */ - mode = S_IFSOCK | (sock->inode->i_mode & ~current->fs->umask); + mode = S_IFSOCK | (SOCK_INODE(sock)->i_mode & ~current->fs->umask); err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0); if (err) goto out_mknod_dput; diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 457515db9b18..8581b06c94ae 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -101,7 +101,7 @@ extern inline unix_socket *unix_get_socket(struct file *filp) * Socket ? */ if (inode->i_sock) { - struct socket * sock = &inode->u.socket_i; + struct socket * sock = SOCKET_I(inode); struct sock * s = sock->sk; /* diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index cbd52721c9b3..b8ea06165822 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1239,7 +1239,7 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length) s->protinfo.x25->t23 / HZ, atomic_read(&s->wmem_alloc), atomic_read(&s->rmem_alloc), - s->socket != NULL ? s->socket->inode->i_ino : 0L); + s->socket != NULL ? SOCK_INODE(s->socket)->i_ino : 0L); pos = begin + len; -- cgit v1.2.3 From 4b64f8f057859370e0035428993ee3fa3f40fc78 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Tue, 5 Feb 2002 18:46:27 -0800 Subject: [PATCH] (2/2) inode trimming procfs switched to alloc_inode/destroy_inode. --- drivers/net/wan/comx.c | 4 +- drivers/net/wireless/airo.c | 39 +++++------------ drivers/pci/proc.c | 8 ++-- drivers/pnp/isapnp_proc.c | 2 +- drivers/usb/ov511.c | 2 +- drivers/usb/uhci-debug.h | 2 +- drivers/zorro/proc.c | 2 +- fs/proc/base.c | 103 ++++++++++++++++++++++++++------------------ fs/proc/generic.c | 14 +++--- fs/proc/inode.c | 43 ++++++++++++++++-- fs/proc/root.c | 6 ++- include/linux/fs.h | 2 - include/linux/proc_fs.h | 22 ++++++++++ kernel/sysctl.c | 2 +- net/8021q/vlanproc.c | 2 +- net/atm/proc.c | 6 +-- net/wanrouter/wanmain.c | 2 +- net/wanrouter/wanproc.c | 8 ++-- 18 files changed, 165 insertions(+), 104 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c index 2d673bfda099..96d6f326ceb5 100644 --- a/drivers/net/wan/comx.c +++ b/drivers/net/wan/comx.c @@ -876,7 +876,7 @@ cleanup_dev: static int comx_rmdir(struct inode *dir, struct dentry *dentry) { - struct proc_dir_entry *entry = dentry->d_inode->u.generic_ip; + struct proc_dir_entry *entry = PDE(dentry->d_inode); struct net_device *dev = entry->data; struct comx_channel *ch = dev->priv; int ret; @@ -928,7 +928,7 @@ static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry) struct proc_dir_entry *de; struct inode *inode = NULL; - if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) { + if ((de = PDE(dir)) != NULL) { for (de = de->subdir ; de ; de = de->next) { if ((de && de->low_ino) && (de->namelen == dentry->d_name.len) && diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 96448599116c..72f4225836d1 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2280,7 +2280,7 @@ static ssize_t proc_write( struct file *file, static int proc_status_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *apriv = (struct airo_info *)dev->priv; CapabilityRid cap_rid; @@ -2289,8 +2289,6 @@ static int proc_status_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2364,7 +2362,7 @@ static int proc_stats_rid_open( struct inode *inode, struct file *file, u16 rid ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *apriv = (struct airo_info *)dev->priv; StatsRid stats; @@ -2372,9 +2370,6 @@ static int proc_stats_rid_open( struct inode *inode, int *vals = stats.vals; MOD_INC_USE_COUNT; - - dp = inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2433,7 +2428,7 @@ static void checkThrottle(ConfigRid *config) { static void proc_config_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = file->private_data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; ConfigRid config; @@ -2442,7 +2437,6 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { int need_reset = 0; if ( !data->writelen ) return; - dp = (struct proc_dir_entry *) inode->u.generic_ip; disable_MAC(ai); readConfigRid(ai, &config); @@ -2629,7 +2623,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) { static int proc_config_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; ConfigRid config; @@ -2637,8 +2631,6 @@ static int proc_config_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2723,7 +2715,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) { static void proc_SSID_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; SsidRid SSID_rid; @@ -2759,7 +2751,7 @@ inline static u8 hexVal(char c) { static void proc_APList_on_close( struct inode *inode, struct file *file ) { struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; APListRid APList_rid; @@ -2852,7 +2844,7 @@ static int set_wep_key(struct airo_info *ai, u16 index, static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; int i; @@ -2862,7 +2854,6 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { memset(key, 0, sizeof(key)); - dp = (struct proc_dir_entry *) inode->u.generic_ip; data = (struct proc_data *)file->private_data; if ( !data->writelen ) return; @@ -2894,7 +2885,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { static int proc_wepkey_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; char *ptr; @@ -2905,8 +2896,6 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2948,7 +2937,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) { static int proc_SSID_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; int i; @@ -2957,8 +2946,6 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -2996,7 +2983,7 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) { static int proc_APList_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; int i; @@ -3005,8 +2992,6 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3048,7 +3033,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) { static int proc_BSSList_open( struct inode *inode, struct file *file ) { struct proc_data *data; - struct proc_dir_entry *dp = inode->u.generic_ip; + struct proc_dir_entry *dp = PDE(inode); struct net_device *dev = dp->data; struct airo_info *ai = (struct airo_info*)dev->priv; char *ptr; @@ -3059,8 +3044,6 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) { MOD_INC_USE_COUNT; - dp = (struct proc_dir_entry *) inode->u.generic_ip; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index 81ad8145422d..8ac8673c803d 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -45,7 +45,7 @@ static ssize_t proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { const struct inode *ino = file->f_dentry->d_inode; - const struct proc_dir_entry *dp = ino->u.generic_ip; + const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; unsigned int pos = *ppos; unsigned int cnt, size; @@ -127,7 +127,7 @@ static ssize_t proc_bus_pci_write(struct file *file, const char *buf, size_t nbytes, loff_t *ppos) { const struct inode *ino = file->f_dentry->d_inode; - const struct proc_dir_entry *dp = ino->u.generic_ip; + const struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; int pos = *ppos; int cnt; @@ -199,7 +199,7 @@ struct pci_filp_private { static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - const struct proc_dir_entry *dp = inode->u.generic_ip; + const struct proc_dir_entry *dp = PDE(inode); struct pci_dev *dev = dp->data; #ifdef HAVE_PCI_MMAP struct pci_filp_private *fpriv = file->private_data; @@ -241,7 +241,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma) { struct inode *inode = file->f_dentry->d_inode; - const struct proc_dir_entry *dp = inode->u.generic_ip; + const struct proc_dir_entry *dp = PDE(inode); struct pci_dev *dev = dp->data; struct pci_filp_private *fpriv = file->private_data; int ret; diff --git a/drivers/pnp/isapnp_proc.c b/drivers/pnp/isapnp_proc.c index 08085e106b13..11e1b2c4b4a1 100644 --- a/drivers/pnp/isapnp_proc.c +++ b/drivers/pnp/isapnp_proc.c @@ -234,7 +234,7 @@ static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence) static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { struct inode *ino = file->f_dentry->d_inode; - struct proc_dir_entry *dp = ino->u.generic_ip; + struct proc_dir_entry *dp = PDE(ino); struct pci_dev *dev = dp->data; int pos = *ppos; int cnt, size = 256; diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c index c84a6691aec8..dc6b2b282421 100644 --- a/drivers/usb/ov511.c +++ b/drivers/usb/ov511.c @@ -5618,7 +5618,7 @@ ov511_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg = (void *) ularg; int rc; - pde = (struct proc_dir_entry *) inode->u.generic_ip; + pde = PDE(inode); if (!pde) return -ENOENT; diff --git a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h index 5ff42d2393d6..ed8b768a0064 100644 --- a/drivers/usb/uhci-debug.h +++ b/drivers/usb/uhci-debug.h @@ -476,7 +476,7 @@ struct uhci_proc { static int uhci_proc_open(struct inode *inode, struct file *file) { - const struct proc_dir_entry *dp = inode->u.generic_ip; + const struct proc_dir_entry *dp = PDE(inode); struct uhci *uhci = dp->data; struct uhci_proc *up; unsigned long flags; diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 28b7c4272dd8..c5cc2534c4f1 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -45,7 +45,7 @@ static ssize_t proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) { struct inode *ino = file->f_dentry->d_inode; - struct proc_dir_entry *dp = ino->u.generic_ip; + struct proc_dir_entry *dp = PDE(ino); struct zorro_dev *dev = dp->data; struct ConfigDev cd; int pos = *ppos; diff --git a/fs/proc/base.c b/fs/proc/base.c index ed0da13a0e91..e472c395cccd 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -37,6 +37,11 @@ #define fake_ino(pid,ino) (((pid)<<16)|(ino)) +static inline struct task_struct *proc_task(struct inode *inode) +{ + return PROC_I(inode)->task; +} + ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*); int proc_pid_stat(struct task_struct*,char*); int proc_pid_status(struct task_struct*,char*); @@ -45,9 +50,10 @@ int proc_pid_cpu(struct task_struct*,char*); static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { - if (inode->u.proc_i.file) { - *mnt = mntget(inode->u.proc_i.file->f_vfsmnt); - *dentry = dget(inode->u.proc_i.file->f_dentry); + struct file *file = PROC_I(inode)->file; + if (file) { + *mnt = mntget(file->f_vfsmnt); + *dentry = dget(file->f_dentry); return 0; } return -ENOENT; @@ -58,7 +64,7 @@ static int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfs struct mm_struct * mm; struct vm_area_struct * vma; int result = -ENOENT; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); task_lock(task); mm = task->mm; @@ -89,11 +95,11 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs { struct fs_struct *fs; int result = -ENOENT; - task_lock(inode->u.proc_i.task); - fs = inode->u.proc_i.task->fs; + task_lock(proc_task(inode)); + fs = proc_task(inode)->fs; if(fs) atomic_inc(&fs->count); - task_unlock(inode->u.proc_i.task); + task_unlock(proc_task(inode)); if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->pwdmnt); @@ -109,11 +115,11 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf { struct fs_struct *fs; int result = -ENOENT; - task_lock(inode->u.proc_i.task); - fs = inode->u.proc_i.task->fs; + task_lock(proc_task(inode)); + fs = proc_task(inode)->fs; if(fs) atomic_inc(&fs->count); - task_unlock(inode->u.proc_i.task); + task_unlock(proc_task(inode)); if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->rootmnt); @@ -238,7 +244,7 @@ static ssize_t pid_maps_read(struct file * file, char * buf, size_t count, loff_t *ppos) { struct inode * inode = file->f_dentry->d_inode; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); ssize_t res; res = proc_pid_read_maps(task, file, buf, count, ppos); @@ -252,7 +258,7 @@ static struct file_operations proc_maps_operations = { extern struct seq_operations mounts_op; static int mounts_open(struct inode *inode, struct file *file) { - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); int ret = seq_open(file, &mounts_op); if (!ret) { @@ -298,14 +304,14 @@ static ssize_t proc_info_read(struct file * file, char * buf, unsigned long page; ssize_t length; ssize_t end; - struct task_struct *task = inode->u.proc_i.task; + struct task_struct *task = proc_task(inode); if (count > PROC_BLOCK_SIZE) count = PROC_BLOCK_SIZE; if (!(page = __get_free_page(GFP_KERNEL))) return -ENOMEM; - length = inode->u.proc_i.op.proc_read(task, (char*)page); + length = PROC_I(inode)->op.proc_read(task, (char*)page); if (length < 0) { free_page(page); @@ -342,7 +348,7 @@ static int mem_open(struct inode* inode, struct file* file) static ssize_t mem_read(struct file * file, char * buf, size_t count, loff_t *ppos) { - struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + struct task_struct *task = proc_task(file->f_dentry->d_inode); char *page; unsigned long src = *ppos; int copied = 0; @@ -404,7 +410,7 @@ static ssize_t mem_write(struct file * file, const char * buf, { int copied = 0; char *page; - struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task; + struct task_struct *task = proc_task(file->f_dentry->d_inode); unsigned long dst = *ppos; if (!MAY_PTRACE(task)) @@ -463,7 +469,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) if (error) goto out; - error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); nd->last_type = LAST_BIND; out: return error; @@ -503,7 +509,7 @@ static int proc_pid_readlink(struct dentry * dentry, char * buffer, int buflen) if (error) goto out; - error = inode->u.proc_i.op.proc_get_link(inode, &de, &mnt); + error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); if (error) goto out; @@ -570,7 +576,7 @@ static struct pid_entry base_stuff[] = { static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct task_struct *p = inode->u.proc_i.task; + struct task_struct *p = proc_task(inode); unsigned int fd, pid, ino; int retval; char buf[NUMBUF]; @@ -598,6 +604,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) task_unlock(p); if (!files) goto out; + read_lock(&files->file_lock); for (fd = filp->f_pos-2; fd < files->max_fds; fd++, filp->f_pos++) { @@ -605,6 +612,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) if (!fcheck_files(files, fd)) continue; + read_unlock(&files->file_lock); j = NUMBUF; i = fd; @@ -617,7 +625,9 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) ino = fake_ino(pid, PROC_PID_FD_DIR + fd); if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) break; + read_lock(&files->file_lock); } + read_unlock(&files->file_lock); put_files_struct(files); } out: @@ -632,7 +642,7 @@ static int proc_base_readdir(struct file * filp, struct inode *inode = filp->f_dentry->d_inode; struct pid_entry *p; - pid = inode->u.proc_i.task->pid; + pid = proc_task(inode)->pid; if (!pid) return -ENOENT; i = filp->f_pos; @@ -684,6 +694,7 @@ static int task_dumpable(struct task_struct *task) static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino) { struct inode * inode; + struct proc_inode *ei; /* We need a new inode */ @@ -692,7 +703,9 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st goto out; /* Common stuff */ - + ei = PROC_I(inode); + ei->task = NULL; + ei->file = NULL; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); @@ -703,7 +716,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st * grab the reference to task. */ get_task_struct(task); - inode->u.proc_i.task = task; + ei->task = task; inode->i_uid = 0; inode->i_gid = 0; if (ino == PROC_PID_INO || task_dumpable(task)) { @@ -733,7 +746,7 @@ static int pid_fd_revalidate(struct dentry * dentry, int flags) */ static int pid_base_revalidate(struct dentry * dentry, int flags) { - if (dentry->d_inode->u.proc_i.task->pid) + if (proc_task(dentry->d_inode)->pid) return 1; d_drop(dentry); return 0; @@ -767,10 +780,11 @@ static struct dentry_operations pid_base_dentry_operations = static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) { unsigned int fd, c; - struct task_struct *task = dir->u.proc_i.task; + struct task_struct *task = proc_task(dir); struct file * file; struct files_struct * files; struct inode *inode; + struct proc_inode *ei; const char *name; int len; @@ -792,6 +806,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) inode = proc_pid_make_inode(dir->i_sb, task, PROC_PID_FD_DIR+fd); if (!inode) goto out; + ei = PROC_I(inode); task_lock(task); files = task->files; if (files) @@ -800,7 +815,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) if (!files) goto out_unlock; read_lock(&files->file_lock); - file = inode->u.proc_i.file = fcheck_files(files, fd); + file = ei->file = fcheck_files(files, fd); if (!file) goto out_unlock2; get_file(file); @@ -809,7 +824,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry) inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; inode->i_mode = S_IFLNK; - inode->u.proc_i.op.proc_get_link = proc_fd_link; + ei->op.proc_get_link = proc_fd_link; if (file->f_mode & 1) inode->i_mode |= S_IRUSR | S_IXUSR; if (file->f_mode & 2) @@ -844,8 +859,9 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) { struct inode *inode; int error; - struct task_struct *task = dir->u.proc_i.task; + struct task_struct *task = proc_task(dir); struct pid_entry *p; + struct proc_inode *ei; error = -ENOENT; inode = NULL; @@ -864,6 +880,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) if (!inode) goto out; + ei = PROC_I(inode); inode->i_mode = p->mode; /* * Yes, it does not scale. And it should not. Don't add @@ -877,35 +894,35 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) break; case PROC_PID_EXE: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_exe_link; + ei->op.proc_get_link = proc_exe_link; break; case PROC_PID_CWD: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_cwd_link; + ei->op.proc_get_link = proc_cwd_link; break; case PROC_PID_ROOT: inode->i_op = &proc_pid_link_inode_operations; - inode->u.proc_i.op.proc_get_link = proc_root_link; + ei->op.proc_get_link = proc_root_link; break; case PROC_PID_ENVIRON: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_environ; + ei->op.proc_read = proc_pid_environ; break; case PROC_PID_STATUS: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_status; + ei->op.proc_read = proc_pid_status; break; case PROC_PID_STAT: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_stat; + ei->op.proc_read = proc_pid_stat; break; case PROC_PID_CMDLINE: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_cmdline; + ei->op.proc_read = proc_pid_cmdline; break; case PROC_PID_STATM: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_statm; + ei->op.proc_read = proc_pid_statm; break; case PROC_PID_MAPS: inode->i_fop = &proc_maps_operations; @@ -913,7 +930,7 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry) #ifdef CONFIG_SMP case PROC_PID_CPU: inode->i_fop = &proc_info_file_operations; - inode->u.proc_i.op.proc_read = proc_pid_cpu; + ei->op.proc_read = proc_pid_cpu; break; #endif case PROC_PID_MEM: @@ -973,6 +990,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) struct task_struct *task; const char *name; struct inode *inode; + struct proc_inode *ei; int len; pid = 0; @@ -982,10 +1000,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry) inode = new_inode(dir->i_sb); if (!inode) return ERR_PTR(-ENOMEM); + ei = PROC_I(inode); inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(0, PROC_PID_INO); - inode->u.proc_i.file = NULL; - inode->u.proc_i.task = NULL; + ei->file = NULL; + ei->task = NULL; inode->i_mode = S_IFLNK|S_IRWXUGO; inode->i_uid = inode->i_gid = 0; inode->i_size = 64; @@ -1035,10 +1054,10 @@ out: void proc_pid_delete_inode(struct inode *inode) { - if (inode->u.proc_i.file) - fput(inode->u.proc_i.file); - if (inode->u.proc_i.task) - free_task_struct(inode->u.proc_i.task); + if (PROC_I(inode)->file) + fput(PROC_I(inode)->file); + if (proc_task(inode)) + free_task_struct(proc_task(inode)); } #define PROC_NUMBUF 10 diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 3e31f65e266b..f50b13026f27 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -58,7 +58,7 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) char *start; struct proc_dir_entry * dp; - dp = (struct proc_dir_entry *) inode->u.generic_ip; + dp = PDE(inode); if (!(page = (char*) __get_free_page(GFP_KERNEL))) return -ENOMEM; @@ -128,7 +128,7 @@ proc_file_write(struct file * file, const char * buffer, struct inode *inode = file->f_dentry->d_inode; struct proc_dir_entry * dp; - dp = (struct proc_dir_entry *) inode->u.generic_ip; + dp = PDE(inode); if (!dp->write_proc) return -EIO; @@ -221,13 +221,13 @@ out: static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) { - char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; + char *s=PDE(dentry->d_inode)->data; return vfs_readlink(dentry, buffer, buflen, s); } static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data; + char *s=PDE(dentry->d_inode)->data; return vfs_follow_link(nd, s); } @@ -264,7 +264,7 @@ struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry) error = -ENOENT; inode = NULL; - de = (struct proc_dir_entry *) dir->u.generic_ip; + de = PDE(dir); if (de) { for (de = de->subdir; de ; de = de->next) { if (!de || !de->low_ino) @@ -306,7 +306,7 @@ int proc_readdir(struct file * filp, struct inode *inode = filp->f_dentry->d_inode; ino = inode->i_ino; - de = (struct proc_dir_entry *) inode->u.generic_ip; + de = PDE(inode); if (!de) return -EINVAL; i = filp->f_pos; @@ -413,7 +413,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) if (dentry->d_op != &proc_dentry_operations) continue; inode = dentry->d_inode; - if (inode->u.generic_ip != de) + if (PDE(inode) != de) continue; fops = filp->f_op; filp->f_op = NULL; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 8af8a6868e92..b670f91ca023 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -58,7 +58,7 @@ void de_put(struct proc_dir_entry *de) */ static void proc_delete_inode(struct inode *inode) { - struct proc_dir_entry *de = inode->u.generic_ip; + struct proc_dir_entry *de = PDE(inode); inode->i_state = I_CLEAR; @@ -91,14 +91,51 @@ static int proc_statfs(struct super_block *sb, struct statfs *buf) return 0; } +static kmem_cache_t * proc_inode_cachep; + +static struct inode *proc_alloc_inode(struct super_block *sb) +{ + struct proc_inode *ei; + ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL); + if (!ei) + return NULL; + return &ei->vfs_inode; +} + +static void proc_destroy_inode(struct inode *inode) +{ + kmem_cache_free(proc_inode_cachep, PROC_I(inode)); +} + +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) +{ + struct proc_inode *ei = (struct proc_inode *) foo; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) + inode_init_once(&ei->vfs_inode); +} + +int __init proc_init_inodecache(void) +{ + proc_inode_cachep = kmem_cache_create("proc_inode_cache", + sizeof(struct proc_inode), + 0, SLAB_HWCACHE_ALIGN, + init_once, NULL); + if (proc_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + static struct super_operations proc_sops = { + alloc_inode: proc_alloc_inode, + destroy_inode: proc_destroy_inode, read_inode: proc_read_inode, put_inode: force_delete, delete_inode: proc_delete_inode, statfs: proc_statfs, }; - static int parse_options(char *options,uid_t *uid,gid_t *gid) { char *this_char,*value; @@ -147,7 +184,7 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, atomic_read(&d if (!inode) goto out_fail; - inode->u.generic_ip = (void *) de; + PROC_I(inode)->pde = de; if (de) { if (de->mode) { inode->i_mode = de->mode; diff --git a/fs/proc/root.c b/fs/proc/root.c index 3db40a53bc0f..447bb7cc84bb 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -25,9 +25,13 @@ struct proc_dir_entry *proc_sys_root; static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE); +extern int __init proc_init_inodecache(void); void __init proc_root_init(void) { - int err = register_filesystem(&proc_fs_type); + int err = proc_init_inodecache(); + if (err) + return; + err = register_filesystem(&proc_fs_type); if (err) return; proc_mnt = kern_mount(&proc_fs_type); diff --git a/include/linux/fs.h b/include/linux/fs.h index b150576116ce..5fa0e8f61911 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -289,7 +289,6 @@ extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long #include /* #include */ #include -#include #include /* @@ -455,7 +454,6 @@ struct inode { union { /* struct umsdos_inode_info umsdos_i; */ struct romfs_inode_info romfs_i; - struct proc_inode_info proc_i; void *generic_ip; } u; }; diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 4688c8c90ede..3f9e4c2c60e1 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -205,4 +205,26 @@ extern struct proc_dir_entry proc_root; #endif /* CONFIG_PROC_FS */ +struct proc_inode { + struct task_struct *task; + int type; + union { + int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **); + int (*proc_read)(struct task_struct *task, char *page); + } op; + struct file *file; + struct proc_dir_entry *pde; + struct inode vfs_inode; +}; + +static inline struct proc_inode *PROC_I(struct inode *inode) +{ + return list_entry(inode, struct proc_inode, vfs_inode); +} + +static inline struct proc_dir_entry *PDE(struct inode *inode) +{ + return PROC_I(inode)->pde; +} + #endif /* _LINUX_PROC_FS_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9035ae798d0e..21a5c8fe6543 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -677,7 +677,7 @@ static ssize_t do_rw_proc(int write, struct file * file, char * buf, size_t res; ssize_t error; - de = (struct proc_dir_entry*) file->f_dentry->d_inode->u.generic_ip; + de = PDE(file->f_dentry->d_inode); if (!de || !de->data) return -ENOTDIR; table = (struct ctl_table *) de->data; diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 5c994e1a1257..c8482f9ab40f 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c @@ -236,7 +236,7 @@ static ssize_t vlan_proc_read(struct file *file, char *buf, if (count <= 0) return 0; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->get_info == NULL)) return 0; diff --git a/net/atm/proc.c b/net/atm/proc.c index 3fdd52372ea0..e19a6a69a0a4 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -498,8 +498,7 @@ static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count, if (count == 0) return 0; page = get_free_page(GFP_KERNEL); if (!page) return -ENOMEM; - dev = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip) - ->data; + dev = PDE(file->f_dentry->d_inode)->data; if (!dev->ops->proc_read) length = -EINVAL; else { @@ -521,8 +520,7 @@ static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count, unsigned long page; int length; int (*info)(loff_t,char *); - info = ((struct proc_dir_entry *) file->f_dentry->d_inode->u.generic_ip) - ->data; + info = PDE(file->f_dentry->d_inode)->data; if (count == 0) return 0; page = get_free_page(GFP_KERNEL); diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index b58338f52f06..38838887c22d 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -500,7 +500,7 @@ int wanrouter_ioctl(struct inode *inode, struct file *file, if ((cmd >> 8) != ROUTER_IOCTL) return -EINVAL; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->data == NULL)) return -EINVAL; diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 14cf0257f28c..51b0f8b18c9b 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -248,7 +248,7 @@ typedef struct wan_stat_entry if (count <= 0) return 0; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->get_info == NULL)) return 0; @@ -794,7 +794,7 @@ typedef struct wan_stat_entry if (count <= 0) return 0; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->get_info == NULL)) return 0; @@ -828,7 +828,7 @@ typedef struct wan_stat_entry if (count <= 0) return 0; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->get_info == NULL)) return -ENODATA; err = verify_area(VERIFY_WRITE, buf, count); @@ -1068,7 +1068,7 @@ static int device_write( if (err) return err; - dent = inode->u.generic_ip; + dent = PDE(inode); if ((dent == NULL) || (dent->data == NULL)) return -ENODATA; -- cgit v1.2.3 From 70902864c2030297d0a13917bd68c9714e87da16 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Tue, 5 Feb 2002 18:46:29 -0800 Subject: [PATCH] (1/5) beginning of getattr series. added new helpers - vfs_stat(), vfs_lstat() and vfs_fstat(). fs/stat.c switched to use them. Following patches will stat(2) variants in arch/* that used to copy inode fields manually switched to vfs_*stat() and partially cleaned up irix_...() switched from sys_new*stat() to vfs_*stat() and cleaned up. Missing LFS check added. similar for solaris ones ditto for x86 compatibility ones on ia64. We are almost ready to switch to ->getattr() - let filesystem decide what values should go into ->st_... (e.g. for CODA life would become much easier if it could just use ->i_size of caching file, for supermount we want ->i_ino inherited from underlying fs, etc.) Another thing that needs to be done is fixing the rest of LFS/uid size fsckups in architecture-specific variants of stat() - I've fixed several, but quite a few are still there. --- fs/stat.c | 383 +++++++++++++++++++++++---------------------------- include/linux/fs.h | 4 + include/linux/stat.h | 19 +++ 3 files changed, 193 insertions(+), 213 deletions(-) (limited to 'include/linux') diff --git a/fs/stat.c b/fs/stat.c index d7ed42c77f59..20bd373580c5 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -25,68 +25,28 @@ do_revalidate(struct dentry *dentry) return 0; } - -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) - -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ -static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf) +static int do_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { - static int warncount = 5; - struct __old_kernel_stat tmp; - - if (warncount > 0) { - warncount--; - printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", - current->comm); - } else if (warncount < 0) { - /* it's laughable, but... */ - warncount = 0; - } - - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - SET_OLDSTAT_UID(tmp, inode->i_uid); - SET_OLDSTAT_GID(tmp, inode->i_gid); - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); -#if BITS_PER_LONG == 32 - if (inode->i_size > MAX_NON_LFS) - return -EOVERFLOW; -#endif - tmp.st_size = inode->i_size; - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; -} - -#endif - -static int cp_new_stat(struct inode * inode, struct stat * statbuf) -{ - struct stat tmp; + int res = 0; unsigned int blocks, indirect; - - memset(&tmp, 0, sizeof(tmp)); - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - SET_STAT_UID(tmp, inode->i_uid); - SET_STAT_GID(tmp, inode->i_gid); - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); -#if BITS_PER_LONG == 32 - if (inode->i_size > MAX_NON_LFS) - return -EOVERFLOW; -#endif - tmp.st_size = inode->i_size; - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; + struct inode *inode = dentry->d_inode; + + res = do_revalidate(dentry); + if (res) + return res; + + stat->dev = kdev_t_to_nr(inode->i_dev); + stat->ino = inode->i_ino; + stat->mode = inode->i_mode; + stat->nlink = inode->i_nlink; + stat->uid = inode->i_uid; + stat->gid = inode->i_gid; + stat->rdev = kdev_t_to_nr(inode->i_rdev); + stat->atime = inode->i_atime; + stat->mtime = inode->i_mtime; + stat->ctime = inode->i_ctime; + stat->ctime = inode->i_ctime; + stat->size = inode->i_size; /* * st_blocks and st_blksize are approximated with a simple algorithm if * they aren't supported directly by the filesystem. The minix and msdos @@ -106,7 +66,7 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf) #define I_B (BLOCK_SIZE / sizeof(unsigned short)) if (!inode->i_blksize) { - blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + blocks = (stat->size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; if (blocks > D_B) { indirect = (blocks - D_B + I_B - 1) / I_B; blocks += indirect; @@ -117,130 +77,178 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf) blocks++; } } - tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; - tmp.st_blksize = BLOCK_SIZE; + stat->blocks = (BLOCK_SIZE / 512) * blocks; + stat->blksize = BLOCK_SIZE; } else { - tmp.st_blocks = inode->i_blocks; - tmp.st_blksize = inode->i_blksize; + stat->blocks = inode->i_blocks; + stat->blksize = inode->i_blksize; } - return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; + return 0; } - -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ -asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) +int vfs_stat(char *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk(filename, &nd); + error = user_path_walk(name, &nd); if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); + error = do_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); } return error; } -#endif -asmlinkage long sys_newstat(char * filename, struct stat * statbuf) +int vfs_lstat(char *name, struct kstat *stat) { struct nameidata nd; int error; - error = user_path_walk(filename, &nd); + error = user_path_walk_link(name, &nd); if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); + error = do_getattr(nd.mnt, nd.dentry, stat); path_release(&nd); } return error; } +int vfs_fstat(unsigned int fd, struct kstat *stat) +{ + struct file *f = fget(fd); + int error = -EBADF; + + if (f) { + error = do_getattr(f->f_vfsmnt, f->f_dentry, stat); + fput(f); + } + return error; +} + #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) /* * For backward compatibility? Maybe this should be moved * into arch/i386 instead? */ -asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) +static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat * statbuf) { - struct nameidata nd; - int error; + static int warncount = 5; + struct __old_kernel_stat tmp; - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_old_stat(nd.dentry->d_inode, statbuf); - path_release(&nd); + if (warncount > 0) { + warncount--; + printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n", + current->comm); + } else if (warncount < 0) { + /* it's laughable, but... */ + warncount = 0; } - return error; -} -#endif + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + SET_OLDSTAT_UID(tmp, stat->uid); + SET_OLDSTAT_GID(tmp, stat->gid); + tmp.st_rdev = stat->rdev; +#if BITS_PER_LONG == 32 + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; +#endif + tmp.st_size = stat->size; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} -asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) +asmlinkage long sys_stat(char * filename, struct __old_kernel_stat * statbuf) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_old_stat(&stat, statbuf); - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } +asmlinkage long sys_lstat(char * filename, struct __old_kernel_stat * statbuf) +{ + struct kstat stat; + int error = vfs_lstat(filename, &stat); -#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) + if (!error) + error = cp_old_stat(&stat, statbuf); -/* - * For backward compatibility? Maybe this should be moved - * into arch/i386 instead? - */ + return error; +} asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat * statbuf) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_old_stat(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_old_stat(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } #endif +static int cp_new_stat(struct kstat *stat, struct stat *statbuf) +{ + struct stat tmp; + + memset(&tmp, 0, sizeof(tmp)); + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + SET_STAT_UID(tmp, stat->uid); + SET_STAT_GID(tmp, stat->gid); + tmp.st_rdev = stat->rdev; +#if BITS_PER_LONG == 32 + if (stat->size > MAX_NON_LFS) + return -EOVERFLOW; +#endif + tmp.st_size = stat->size; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + tmp.st_blocks = stat->blocks; + tmp.st_blksize = stat->blksize; + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +asmlinkage long sys_newstat(char * filename, struct stat * statbuf) +{ + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} +asmlinkage long sys_newlstat(char * filename, struct stat * statbuf) +{ + struct kstat stat; + int error = vfs_lstat(filename, &stat); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_new_stat(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_new_stat(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz) @@ -270,110 +278,59 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz) /* ---------- LFS-64 ----------- */ #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X) -static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf) +static long cp_new_stat64(struct kstat *stat, struct stat64 *statbuf) { struct stat64 tmp; - unsigned int blocks, indirect; memset(&tmp, 0, sizeof(tmp)); - tmp.st_dev = kdev_t_to_nr(inode->i_dev); - tmp.st_ino = inode->i_ino; + tmp.st_dev = stat->dev; + tmp.st_ino = stat->ino; #ifdef STAT64_HAS_BROKEN_ST_INO - tmp.__st_ino = inode->i_ino; + tmp.__st_ino = stat->ino; #endif - tmp.st_mode = inode->i_mode; - tmp.st_nlink = inode->i_nlink; - tmp.st_uid = inode->i_uid; - tmp.st_gid = inode->i_gid; - tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); - tmp.st_atime = inode->i_atime; - tmp.st_mtime = inode->i_mtime; - tmp.st_ctime = inode->i_ctime; - tmp.st_size = inode->i_size; -/* - * st_blocks and st_blksize are approximated with a simple algorithm if - * they aren't supported directly by the filesystem. The minix and msdos - * filesystems don't keep track of blocks, so they would either have to - * be counted explicitly (by delving into the file itself), or by using - * this simple algorithm to get a reasonable (although not 100% accurate) - * value. - */ - -/* - * Use minix fs values for the number of direct and indirect blocks. The - * count is now exact for the minix fs except that it counts zero blocks. - * Everything is in units of BLOCK_SIZE until the assignment to - * tmp.st_blksize. - */ -#define D_B 7 -#define I_B (BLOCK_SIZE / sizeof(unsigned short)) - - if (!inode->i_blksize) { - blocks = (tmp.st_size + BLOCK_SIZE - 1) >> BLOCK_SIZE_BITS; - if (blocks > D_B) { - indirect = (blocks - D_B + I_B - 1) / I_B; - blocks += indirect; - if (indirect > 1) { - indirect = (indirect - 1 + I_B - 1) / I_B; - blocks += indirect; - if (indirect > 1) - blocks++; - } - } - tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; - tmp.st_blksize = BLOCK_SIZE; - } else { - tmp.st_blocks = inode->i_blocks; - tmp.st_blksize = inode->i_blksize; - } + tmp.st_mode = stat->mode; + tmp.st_nlink = stat->nlink; + tmp.st_uid = stat->uid; + tmp.st_gid = stat->gid; + tmp.st_rdev = stat->rdev; + tmp.st_atime = stat->atime; + tmp.st_mtime = stat->mtime; + tmp.st_ctime = stat->ctime; + tmp.st_size = stat->size; + tmp.st_blocks = stat->blocks; + tmp.st_blksize = stat->blksize; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } asmlinkage long sys_stat64(char * filename, struct stat64 * statbuf, long flags) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_stat(filename, &stat); + + if (!error) + error = cp_new_stat64(&stat, statbuf); - error = user_path_walk(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } - asmlinkage long sys_lstat64(char * filename, struct stat64 * statbuf, long flags) { - struct nameidata nd; - int error; + struct kstat stat; + int error = vfs_lstat(filename, &stat); + + if (!error) + error = cp_new_stat64(&stat, statbuf); - error = user_path_walk_link(filename, &nd); - if (!error) { - error = do_revalidate(nd.dentry); - if (!error) - error = cp_new_stat64(nd.dentry->d_inode, statbuf); - path_release(&nd); - } return error; } - asmlinkage long sys_fstat64(unsigned long fd, struct stat64 * statbuf, long flags) { - struct file * f; - int err = -EBADF; + struct kstat stat; + int error = vfs_fstat(fd, &stat); - f = fget(fd); - if (f) { - struct dentry * dentry = f->f_dentry; + if (!error) + error = cp_new_stat64(&stat, statbuf); - err = do_revalidate(dentry); - if (!err) - err = cp_new_stat64(dentry->d_inode, statbuf); - fput(f); - } - return err; + return error; } #endif /* LFS-64 */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 5fa0e8f61911..461566f52c16 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1475,6 +1475,10 @@ extern struct inode_operations page_symlink_inode_operations; extern int vfs_readdir(struct file *, filldir_t, void *); extern int dcache_readdir(struct file *, void *, filldir_t); +extern int vfs_stat(char *, struct kstat *); +extern int vfs_lstat(char *, struct kstat *); +extern int vfs_fstat(unsigned int, struct kstat *); + extern struct file_system_type *get_fs_type(const char *name); extern struct super_block *get_super(kdev_t); extern void drop_super(struct super_block *sb); diff --git a/include/linux/stat.h b/include/linux/stat.h index e43e241f31cb..d78a416a3a39 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -52,6 +52,25 @@ #define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH) #define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH) #define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH) + +#include + +struct kstat { + unsigned long ino; + dev_t dev; + umode_t mode; + nlink_t nlink; + uid_t uid; + gid_t gid; + dev_t rdev; + loff_t size; + time_t atime; + time_t mtime; + time_t ctime; + unsigned long blksize; + unsigned long blocks; +}; + #endif #endif -- cgit v1.2.3 From 5284a260fde96ff04bb6e004756fb7c7d5e317d3 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Tue, 5 Feb 2002 18:46:40 -0800 Subject: [PATCH] 2.5.4-pre1: further llseek cleanup (1/3) This is the first of three patches implementing further llseek cleanup, against 2.5.4-pre1. The 'push locking into llseek methods' patch was integrated into 2.5.3. The networking filesystems, however, do not protect i_size and can not rely on the inode semaphore used in generic_file_llseek. This patch implements a remote_llseek method, which is basically the pre-2.5.3 version of generic_file_llseek. Locking is done via the BKL. When we have a saner locking system in place, we can push it into this function in lieu. Ncpfs, nfs, and smbfs have been converted to use this new llseek. Note this is updated over the previous posted patch. Robert Love --- fs/ncpfs/file.c | 2 +- fs/nfs/file.c | 2 +- fs/read_write.c | 25 +++++++++++++++++++++++++ fs/smbfs/file.c | 2 +- include/linux/fs.h | 1 + kernel/ksyms.c | 1 + 6 files changed, 30 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index 1f70ec451ce7..fbd2c3137dd4 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c @@ -281,7 +281,7 @@ static int ncp_release(struct inode *inode, struct file *file) { struct file_operations ncp_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: ncp_file_read, write: ncp_file_write, ioctl: ncp_ioctl, diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 1d5e7dbde28a..d25cb4968931 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -41,7 +41,7 @@ static int nfs_file_flush(struct file *); static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); struct file_operations nfs_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: nfs_file_read, write: nfs_file_write, mmap: nfs_file_mmap, diff --git a/fs/read_write.c b/fs/read_write.c index 31cee2a6aa4e..ce5230669579 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -51,6 +51,31 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin) return retval; } +loff_t remote_llseek(struct file *file, loff_t offset, int origin) +{ + long long retval; + + lock_kernel(); + switch (origin) { + case 2: + offset += file->f_dentry->d_inode->i_size; + break; + case 1: + offset += file->f_pos; + } + retval = -EINVAL; + if (offset>=0 && offset<=file->f_dentry->d_inode->i_sb->s_maxbytes) { + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_reada = 0; + file->f_version = ++event; + } + retval = offset; + } + unlock_kernel(); + return retval; +} + loff_t no_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index b3feaa56924a..39badd71692f 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c @@ -381,7 +381,7 @@ smb_file_permission(struct inode *inode, int mask) struct file_operations smb_file_operations = { - llseek: generic_file_llseek, + llseek: remote_llseek, read: smb_file_read, write: smb_file_write, ioctl: smb_ioctl, diff --git a/include/linux/fs.h b/include/linux/fs.h index 461566f52c16..f4699a15157d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1461,6 +1461,7 @@ extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *) extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); extern loff_t no_llseek(struct file *file, loff_t offset, int origin); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); +extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); extern ssize_t generic_read_dir(struct file *, char *, size_t, loff_t *); extern int generic_file_open(struct inode * inode, struct file * filp); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index c271a8e6f6fc..73db2a0b2678 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -251,6 +251,7 @@ EXPORT_SYMBOL(vfs_rename); EXPORT_SYMBOL(vfs_statfs); EXPORT_SYMBOL(generic_read_dir); EXPORT_SYMBOL(generic_file_llseek); +EXPORT_SYMBOL(remote_llseek); EXPORT_SYMBOL(no_llseek); EXPORT_SYMBOL(__pollwait); EXPORT_SYMBOL(poll_freewait); -- cgit v1.2.3 From 6ccadfbb780542e41608e3d6353091f4e8890fea Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Tue, 5 Feb 2002 18:46:47 -0800 Subject: [PATCH] hpfs cleanup (switch from sleep_on() to semaphore) Pair (flag, wait_queue) in hpfs replaced with semaphore. --- fs/hpfs/buffer.c | 6 ++---- fs/hpfs/super.c | 4 ++-- include/linux/hpfs_fs_sb.h | 5 +---- 3 files changed, 5 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c index 0049e5ee48fa..94b663656ac4 100644 --- a/fs/hpfs/buffer.c +++ b/fs/hpfs/buffer.c @@ -14,8 +14,7 @@ void hpfs_lock_creation(struct super_block *s) #ifdef DEBUG_LOCKS printk("lock creation\n"); #endif - while (s->s_hpfs_creation_de_lock) sleep_on(&s->s_hpfs_creation_de); - s->s_hpfs_creation_de_lock = 1; + down(&s->u.hpfs_sb.hpfs_creation_de); } void hpfs_unlock_creation(struct super_block *s) @@ -23,8 +22,7 @@ void hpfs_unlock_creation(struct super_block *s) #ifdef DEBUG_LOCKS printk("unlock creation\n"); #endif - s->s_hpfs_creation_de_lock = 0; - wake_up(&s->s_hpfs_creation_de); + up(&s->u.hpfs_sb.hpfs_creation_de); } void hpfs_lock_iget(struct super_block *s, int mode) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 2483e920b597..3d59f27c82b8 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -427,8 +427,8 @@ struct super_block *hpfs_read_super(struct super_block *s, void *options, s->s_hpfs_bmp_dir = NULL; s->s_hpfs_cp_table = NULL; - s->s_hpfs_creation_de_lock = s->s_hpfs_rd_inode = 0; - init_waitqueue_head(&s->s_hpfs_creation_de); + s->s_hpfs_rd_inode = 0; + init_MUTEX(&s->u.hpfs_sb.hpfs_creation_de); init_waitqueue_head(&s->s_hpfs_iget_q); uid = current->uid; diff --git a/include/linux/hpfs_fs_sb.h b/include/linux/hpfs_fs_sb.h index 9059054cf82d..068035e9a4bd 100644 --- a/include/linux/hpfs_fs_sb.h +++ b/include/linux/hpfs_fs_sb.h @@ -30,9 +30,8 @@ struct hpfs_sb_info { /* 128 bytes lowercasing table */ unsigned *sb_bmp_dir; /* main bitmap directory */ unsigned sb_c_bitmap; /* current bitmap */ - wait_queue_head_t sb_creation_de;/* when creating dirents, nobody else + struct semaphore hpfs_creation_de; /* when creating dirents, nobody else can alloc blocks */ - unsigned sb_creation_de_lock : 1; /*unsigned sb_mounting : 1;*/ int sb_timeshift; }; @@ -60,8 +59,6 @@ struct hpfs_sb_info { #define s_hpfs_cp_table u.hpfs_sb.sb_cp_table #define s_hpfs_bmp_dir u.hpfs_sb.sb_bmp_dir #define s_hpfs_c_bitmap u.hpfs_sb.sb_c_bitmap -#define s_hpfs_creation_de u.hpfs_sb.sb_creation_de -#define s_hpfs_creation_de_lock u.hpfs_sb.sb_creation_de_lock #define s_hpfs_iget_q u.hpfs_sb.sb_iget_q /*#define s_hpfs_mounting u.hpfs_sb.sb_mounting*/ #define s_hpfs_timeshift u.hpfs_sb.sb_timeshift -- cgit v1.2.3 From a707e95372ce388eba723f3283324dd65f5d9c2d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 5 Feb 2002 23:43:18 -0800 Subject: usb core: - initial add of the "int mem_flags" call to the usb_submit_urb() call --- drivers/usb/usb.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- include/linux/usb.h | 4 ++-- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c index 06b8c6623c43..e94daf9e1e89 100644 --- a/drivers/usb/usb.c +++ b/drivers/usb/usb.c @@ -1148,6 +1148,7 @@ struct urb * usb_get_urb(struct urb *urb) /** * usb_submit_urb - asynchronously issue a transfer request for an endpoint * @urb: pointer to the urb describing the request + * @mem_flags: the type of memory to allocate, see kmalloc() for a list of valid options for this. * * This submits a transfer request, and transfers control of the URB * describing that request to the USB subsystem. Request completion will @@ -1197,12 +1198,49 @@ struct urb * usb_get_urb(struct urb *urb) * * If the USB subsystem can't reserve sufficient bandwidth to perform * the periodic request, and bandwidth reservation is being done for - * this controller, submitting such a periodic request will fail. + * this controller, submitting such a periodic request will fail. + * + * Memory Flags: + * + * General rules for how to decide which mem_flags to use: + * + * Basically the rules are the same as for kmalloc. There are four + * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and + * GFP_ATOMIC. + * + * GFP_NOFS is not ever used, as it has not been implemented yet. + * + * There are three situations you must use GFP_ATOMIC. + * a) you are inside a completion handler, an interrupt, bottom half, + * tasklet or timer. + * b) you are holding a spinlock or rwlock (does not apply to + * semaphores) + * c) current->state != TASK_RUNNING, this is the case only after + * you've changed it. + * + * GFP_NOIO is used in the block io path and error handling of storage + * devices. + * + * All other situations use GFP_KERNEL. + * + * Specfic rules for how to decide which mem_flags to use: + * + * - start_xmit, timeout, and receive methods of network drivers must + * use GFP_ATOMIC (spinlock) + * - queuecommand methods of scsi drivers must use GFP_ATOMIC (spinlock) + * - If you use a kernel thread with a network driver you must use + * GFP_NOIO, unless b) or c) apply + * - After you have done a down() you use GFP_KERNEL, unless b) or c) + * apply or your are in a storage driver's block io path + * - probe and disconnect use GFP_KERNEL unless b) or c) apply + * - Changing firmware on a running storage or net device uses + * GFP_NOIO, unless b) or c) apply + * */ -int usb_submit_urb(struct urb *urb) +int usb_submit_urb(struct urb *urb, int mem_flags) { if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op) - return urb->dev->bus->op->submit_urb(urb); + return urb->dev->bus->op->submit_urb(urb, mem_flags); else return -ENODEV; } @@ -1272,7 +1310,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) add_wait_queue(&awd.wqh, &wait); urb->context = &awd; - status = usb_submit_urb(urb); + status = usb_submit_urb(urb, GFP_KERNEL); if (status) { // something went wrong usb_free_urb(urb); diff --git a/include/linux/usb.h b/include/linux/usb.h index 4c5837e684cd..d598c720ad2d 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -857,7 +857,7 @@ extern struct urb *usb_alloc_urb(int iso_packets); extern void usb_free_urb(struct urb *urb); #define usb_put_urb usb_free_urb extern struct urb *usb_get_urb(struct urb *urb); -extern int usb_submit_urb(struct urb *urb); +extern int usb_submit_urb(struct urb *urb, int mem_flags); extern int usb_unlink_urb(struct urb *urb); /*-------------------------------------------------------------------* @@ -906,7 +906,7 @@ struct usb_operations { int (*allocate)(struct usb_device *); int (*deallocate)(struct usb_device *); int (*get_frame_number) (struct usb_device *usb_dev); - int (*submit_urb) (struct urb *urb); + int (*submit_urb) (struct urb *urb, int mem_flags); int (*unlink_urb) (struct urb *urb); }; -- cgit v1.2.3 From 143845d146b39e0cff995ba43d8cd83739cf61fd Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 6 Feb 2002 05:57:56 -0800 Subject: [PATCH] (1/8) ->get_sb() switchover OK, here comes the long-promised switchover to ->get_sb(). New method added - ->get_sb(type, flags, dev, data). At this point we still keep ->read_super(), but it will go away in the end of series. ->get_sb() is a generalization of get_sb_{bdev,nodev,single}() - as the matter of fact, these will become common helpers used by filesystems in their ->get_sb(). --- fs/super.c | 4 +++- include/linux/fs.h | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/super.c b/fs/super.c index fb70602790ae..c632db504c73 100644 --- a/fs/super.c +++ b/fs/super.c @@ -792,7 +792,9 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) mnt = alloc_vfsmnt(name); if (!mnt) goto out; - if (type->fs_flags & FS_REQUIRES_DEV) + if (type->get_sb) + sb = type->get_sb(type, flags, name, data); + else if (type->fs_flags & FS_REQUIRES_DEV) sb = get_sb_bdev(type, flags, name, data); else if (type->fs_flags & FS_SINGLE) sb = get_sb_single(type, flags, name, data); diff --git a/include/linux/fs.h b/include/linux/fs.h index f4699a15157d..fd96319ad140 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -926,9 +926,20 @@ struct dquot_operations { int (*transfer) (struct inode *, struct iattr *); }; +/* + * NOTE NOTE NOTE + * + * ->read_super() is going to die. New method (->get_sb) should replace + * it. The only reason why ->read_super() is left for _SHORT_ transition + * period is to avoid a single patch touching every fs. They will be + * converted one-by-one and ONCE THAT IS DONE OR TWO WEEKS HAD PASSED + * (whatever sooner) ->read_super() WILL DISAPPEAR. + */ + struct file_system_type { const char *name; int fs_flags; + struct super_block *(*get_sb) (struct file_system_type *, int, char *, void *); struct super_block *(*read_super) (struct super_block *, void *, int); struct module *owner; struct file_system_type * next; -- cgit v1.2.3 From 702ff7f973cdf8783dbf47239a27a8176b05aa51 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 6 Feb 2002 05:57:58 -0800 Subject: [PATCH] (2/8) ->get_sb() switchover get_sb_bdev() et.al. get a new argument (fill_super) and become exported. --- fs/super.c | 61 ++++++++++++++++++++++++++++++++++++++++-------------- include/linux/fs.h | 10 +++++++++ kernel/ksyms.c | 3 +++ 3 files changed, 58 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/fs/super.c b/fs/super.c index c632db504c73..b5cb41c7cf12 100644 --- a/fs/super.c +++ b/fs/super.c @@ -641,8 +641,9 @@ retry: return s; } -static struct super_block *get_sb_bdev(struct file_system_type *fs_type, - int flags, char *dev_name, void * data) +struct super_block *get_sb_bdev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data, + int (*fill_super)(struct super_block *, void *, int)) { struct inode *inode; struct block_device *bdev; @@ -698,7 +699,7 @@ restart: list_for_each(p, &super_blocks) { struct super_block *old = sb_entry(p); - if (!kdev_same(old->s_dev, dev)) + if (old->s_bdev != bdev) continue; if (old->s_type != fs_type || ((flags ^ old->s_flags) & MS_RDONLY)) { @@ -718,8 +719,8 @@ restart: s->s_flags = flags; insert_super(s, fs_type); strncpy(s->s_id, bdevname(dev), sizeof(s->s_id)); - error = -EINVAL; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) goto failed; s->s_flags |= MS_ACTIVE; path_release(&nd); @@ -736,19 +737,23 @@ out: return ERR_PTR(error); } -static struct super_block *get_sb_nodev(struct file_system_type *fs_type, - int flags, char *dev_name, void *data) +struct super_block *get_sb_nodev(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)) { + int error; struct super_block *s = get_anon_super(fs_type, NULL, NULL); if (IS_ERR(s)) return s; s->s_flags = flags; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) { deactivate_super(s); remove_super(s); - return ERR_PTR(-EINVAL); + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; return s; @@ -759,19 +764,22 @@ static int compare_single(struct super_block *s, void *p) return 1; } -static struct super_block *get_sb_single(struct file_system_type *fs_type, - int flags, char *dev_name, void *data) +struct super_block *get_sb_single(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)) { + int error; struct super_block *s = get_anon_super(fs_type, compare_single, NULL); if (IS_ERR(s)) return s; if (!s->s_root) { s->s_flags = flags; - if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0)) { + error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); + if (error) { deactivate_super(s); remove_super(s); - return ERR_PTR(-EINVAL); + return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; } @@ -779,6 +787,27 @@ static struct super_block *get_sb_single(struct file_system_type *fs_type, return s; } +/* Will go away */ +static int fill_super(struct super_block *sb, void *data, int verbose) +{ + return sb->s_type->read_super(sb, data, verbose) ? 0 : -EINVAL; +} +static struct super_block *__get_sb_bdev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, fill_super); +} +static struct super_block *__get_sb_nodev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data) +{ + return get_sb_nodev(fs_type, flags, data, fill_super); +} +static struct super_block *__get_sb_single(struct file_system_type *fs_type, + int flags, char *dev_name, void * data) +{ + return get_sb_nodev(fs_type, flags, data, fill_super); +} + struct vfsmount * do_kern_mount(const char *fstype, int flags, char *name, void *data) { @@ -795,11 +824,11 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) if (type->get_sb) sb = type->get_sb(type, flags, name, data); else if (type->fs_flags & FS_REQUIRES_DEV) - sb = get_sb_bdev(type, flags, name, data); + sb = __get_sb_bdev(type, flags, name, data); else if (type->fs_flags & FS_SINGLE) - sb = get_sb_single(type, flags, name, data); + sb = __get_sb_single(type, flags, name, data); else - sb = get_sb_nodev(type, flags, name, data); + sb = __get_sb_nodev(type, flags, name, data); if (IS_ERR(sb)) goto out_mnt; if (type->fs_flags & FS_NOMOUNT) diff --git a/include/linux/fs.h b/include/linux/fs.h index fd96319ad140..b2a0019e9e8b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -946,6 +946,16 @@ struct file_system_type { struct list_head fs_supers; }; +struct super_block *get_sb_bdev(struct file_system_type *fs_type, + int flags, char *dev_name, void * data, + int (*fill_super)(struct super_block *, void *, int)); +struct super_block *get_sb_single(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)); +struct super_block *get_sb_nodev(struct file_system_type *fs_type, + int flags, void *data, + int (*fill_super)(struct super_block *, void *, int)); + #define DECLARE_FSTYPE(var,type,read,flags) \ struct file_system_type var = { \ name: type, \ diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 73db2a0b2678..42ebfe7f746c 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -275,6 +275,9 @@ EXPORT_SYMBOL(lock_may_write); EXPORT_SYMBOL(dcache_readdir); EXPORT_SYMBOL(fd_install); EXPORT_SYMBOL(put_unused_fd); +EXPORT_SYMBOL(get_sb_bdev); +EXPORT_SYMBOL(get_sb_nodev); +EXPORT_SYMBOL(get_sb_single); /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */ EXPORT_SYMBOL(default_llseek); -- cgit v1.2.3 From 739492612d1c4db7f5f8b2154d1ee9aa5fa28b96 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 6 Feb 2002 05:58:02 -0800 Subject: [PATCH] (4/8) ->get_sb() switchover convert procfs to ->get_sb(). Similar to ext2, except that we use get_sb_single() instead of get_sb_bdev(). Notice the we _don't_ keep FS_SINGLE in flags - as the matter of fact, with ->get_sb() FS_SINGLE is useless. --- fs/proc/inode.c | 7 +++---- fs/proc/root.c | 11 ++++++++++- include/linux/proc_fs.h | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b670f91ca023..c96bde47f090 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -213,8 +213,7 @@ out_fail: goto out; } -struct super_block *proc_read_super(struct super_block *s,void *data, - int silent) +int proc_fill_super(struct super_block *s, void *data, int silent) { struct inode * root_inode; struct task_struct *p; @@ -237,11 +236,11 @@ struct super_block *proc_read_super(struct super_block *s,void *data, if (!s->s_root) goto out_no_root; parse_options(data, &root_inode->i_uid, &root_inode->i_gid); - return s; + return 0; out_no_root: printk("proc_read_super: get root inode failed\n"); iput(root_inode); - return NULL; + return -ENOMEM; } MODULE_LICENSE("GPL"); diff --git a/fs/proc/root.c b/fs/proc/root.c index 447bb7cc84bb..666166bfcf57 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -23,7 +23,16 @@ struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver; struct proc_dir_entry *proc_sys_root; #endif -static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, FS_SINGLE); +static struct super_block *proc_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_single(fs_type, flags, data, proc_fill_super); +} + +static struct file_system_type proc_fs_type = { + name: "proc", + get_sb: proc_get_sb, +}; extern int __init proc_init_inodecache(void); void __init proc_root_init(void) diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 3f9e4c2c60e1..5c0a4642fd69 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -97,7 +97,7 @@ extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent); extern struct vfsmount *proc_mnt; -extern struct super_block *proc_read_super(struct super_block *,void *,int); +extern int proc_fill_super(struct super_block *,void *,int); extern struct inode * proc_get_inode(struct super_block *, int, struct proc_dir_entry *); extern int proc_match(int, const char *,struct proc_dir_entry *); -- cgit v1.2.3 From 8e018235150d59daa128f4cf0f2b48caaae6a089 Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 6 Feb 2002 06:08:26 -0800 Subject: [PATCH] (6/6) more ->get_sb() stuff Now that all FS_SINGLE filesystems are using ->get_sb(), FS_SINGLE can die. --- fs/super.c | 7 ------- include/linux/fs.h | 1 - 2 files changed, 8 deletions(-) (limited to 'include/linux') diff --git a/fs/super.c b/fs/super.c index 91df8dd2bb22..f9f6a9802ad4 100644 --- a/fs/super.c +++ b/fs/super.c @@ -802,11 +802,6 @@ static struct super_block *__get_sb_nodev(struct file_system_type *fs_type, { return get_sb_nodev(fs_type, flags, data, fill_super); } -static struct super_block *__get_sb_single(struct file_system_type *fs_type, - int flags, char *dev_name, void * data) -{ - return get_sb_single(fs_type, flags, data, fill_super); -} struct vfsmount * do_kern_mount(const char *fstype, int flags, char *name, void *data) @@ -825,8 +820,6 @@ do_kern_mount(const char *fstype, int flags, char *name, void *data) sb = type->get_sb(type, flags, name, data); else if (type->fs_flags & FS_REQUIRES_DEV) sb = __get_sb_bdev(type, flags, name, data); - else if (type->fs_flags & FS_SINGLE) - sb = __get_sb_single(type, flags, name, data); else sb = __get_sb_nodev(type, flags, name, data); if (IS_ERR(sb)) diff --git a/include/linux/fs.h b/include/linux/fs.h index b2a0019e9e8b..fdcc041f300a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -91,7 +91,6 @@ extern int leases_enable, dir_notify_enable, lease_break_time; #define FS_NO_PRELIM 4 /* prevent preloading of dentries, even if * FS_NO_DCACHE is not set. */ -#define FS_SINGLE 8 /* Filesystem that can have only one superblock */ #define FS_NOMOUNT 16 /* Never mount from userland */ #define FS_LITTER 32 /* Keeps the tree in dcache */ #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon -- cgit v1.2.3 From d8fbaf736c183a121f7edb1041ca0f0530a762a7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 6 Feb 2002 06:13:41 -0800 Subject: [PATCH] Automatic file-max sizing The default for NR_FILES of 8192 is far too low for many workloads. This patch does dynamic sizing for it instead. It assumes file+inode+dentry are roughly 1K and will use upto 10% of the memory for it. Also removes two obsolete prototypes. --- fs/dcache.c | 1 + fs/file_table.c | 14 ++++++++++++++ include/linux/fs.h | 3 +-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/dcache.c b/fs/dcache.c index 7246506fff37..a421788191fb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1283,6 +1283,7 @@ void __init vfs_caches_init(unsigned long mempages) dcache_init(mempages); inode_init(mempages); + files_init(mempages); mnt_init(mempages); bdev_cache_init(); cdev_cache_init(); diff --git a/fs/file_table.c b/fs/file_table.c index 27713eb016fc..e7248739e3d4 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -186,3 +186,17 @@ too_bad: file_list_unlock(); return 0; } + +void __init files_init(unsigned long mempages) +{ + int n; + /* One file with associated inode and dcache is very roughly 1K. + * Per default don't use more than 10% of our memory for files. + */ + + n = (mempages * (PAGE_SIZE / 1024)) / 10; + files_stat.max_files = n; + if (files_stat.max_files < NR_FILE) + files_stat.max_files = NR_FILE; +} + diff --git a/include/linux/fs.h b/include/linux/fs.h index f4699a15157d..95b6286bbe58 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -208,6 +208,7 @@ extern void update_atime (struct inode *); extern void buffer_init(unsigned long); extern void inode_init(unsigned long); extern void mnt_init(unsigned long); +extern void files_init(unsigned long); /* bh state bits */ enum bh_state_bits { @@ -1492,8 +1493,6 @@ static inline int is_mounted(kdev_t dev) } return 0; } -unsigned long generate_cluster(kdev_t, int b[], int); -unsigned long generate_cluster_swab32(kdev_t, int b[], int); extern kdev_t ROOT_DEV; extern char root_device_name[]; -- cgit v1.2.3 From 2ad3072dab4041d63866e7712d7d3600bf838d90 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 6 Feb 2002 06:13:48 -0800 Subject: [PATCH] Fix page cache limit wrapping in filesystems Several file systems in tree that nominally support files >2GB set their s_maxbytes value to ~0ULL. This has the nasty side effect on 32bit machines that when a file write reaches the page cache limit (e.g. 2^43) it'll silently wrap and destroy data at the beginning of the file. This patch changes the file systems in question to fill in a proper limit. I also have an alternate patch that adds a check for this generically in super.c, but preliminary comments from Al suggested that he prefered to do it in the file systems, so it is done this way way. --- fs/nfs/inode.c | 2 ++ fs/ntfs/fs.c | 2 +- fs/udf/super.c | 2 +- include/linux/fs.h | 8 ++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 261cadb58635..b72b6e662e77 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -455,6 +455,8 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) server->namelen = maxlen; sb->s_maxbytes = fsinfo.maxfilesize; + if (sb->s_maxbytes > MAX_LFS_FILESIZE) + sb->s_maxbytes = MAX_LFS_FILESIZE; /* Fire up the writeback cache */ if (nfs_reqlist_alloc(server) < 0) { diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index 4fa8e2f018e4..d28ea94084a9 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -1130,7 +1130,7 @@ struct super_block *ntfs_read_super(struct super_block *sb, void *options, /* Inform the kernel about which super operations are available. */ sb->s_op = &ntfs_super_operations; sb->s_magic = NTFS_SUPER_MAGIC; - sb->s_maxbytes = ~0ULL >> 1; + sb->s_maxbytes = MAX_LFS_FILESIZE; ntfs_debug(DEBUG_OTHER, "Reading special files\n"); if (ntfs_load_special_files(vol)) { ntfs_error("Error loading special files\n"); diff --git a/fs/udf/super.c b/fs/udf/super.c index a4984734a384..cf78cf53cc76 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1544,7 +1544,7 @@ udf_read_super(struct super_block *sb, void *options, int silent) iput(inode); goto error_out; } - sb->s_maxbytes = ~0ULL; + sb->s_maxbytes = MAX_LFS_FILESIZE; return sb; error_out: diff --git a/include/linux/fs.h b/include/linux/fs.h index 95b6286bbe58..87b160730060 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -520,6 +520,14 @@ extern int init_private_file(struct file *, struct dentry *, int); #define MAX_NON_LFS ((1UL<<31) - 1) +/* Page cache limit. The filesystems should put that into their s_maxbytes + limits, otherwise bad things can happen in VM. */ +#if BITS_PER_LONG==32 +#define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) +#elif BITS_PER_LONG==64 +#define MAX_LFS_FILESIZE 0x7fffffffffffffff +#endif + #define FL_POSIX 1 #define FL_FLOCK 2 #define FL_BROKEN 4 /* broken flock() emulation */ -- cgit v1.2.3 From 0fcf90eb6eae2288605e8fd28a974efec465a05c Mon Sep 17 00:00:00 2001 From: Alexander Viro Date: Wed, 6 Feb 2002 06:34:55 -0800 Subject: [PATCH] (9/9) more ->get_sb() stuff More ->get_sb() patches: nfs. It still acts as nodev - what we want to (and can) do now is to give it enough smarts to recognize that same tree might be already mounted. We are almost done with nodev filesystems by now. --- fs/nfs/inode.c | 27 ++++++++++++++++++++++----- include/linux/nfs_fs.h | 1 - 2 files changed, 22 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index b72b6e662e77..28d57bf19bad 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -245,8 +245,7 @@ nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh) * and the root file handle obtained from the server's mount * daemon. We stash these away in the private superblock fields. */ -struct super_block * -nfs_read_super(struct super_block *sb, void *raw_data, int silent) +int nfs_fill_super(struct super_block *sb, void *raw_data, int silent) { struct nfs_mount_data *data = (struct nfs_mount_data *) raw_data; struct nfs_server *server; @@ -469,7 +468,7 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent) /* Check whether to start the lockd process */ if (!(server->flags & NFS_MOUNT_NONLM)) lockd_up(); - return sb; + return 0; /* Yargs. It didn't work out. */ failure_kill_reqlist: @@ -508,7 +507,7 @@ out_miss_args: printk("nfs_read_super: missing data argument\n"); out_fail: - return NULL; + return -EINVAL; } static int @@ -1139,7 +1138,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) /* * File system information */ -static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, FS_ODD_RENAME); + +/* + * Right now we are using get_sb_nodev, but we ought to switch to + * get_anon_super() with appropriate comparison function. The only + * question being, when two NFS mounts are the same? Identical IP + * of server + identical root fhandle? Trond? + */ +static struct super_block *nfs_get_sb(struct file_system_type *fs_type, + int flags, char *dev_name, void *data) +{ + return get_sb_nodev(fs_type, flags, data, nfs_fill_super); +} + +static struct file_system_type nfs_fs_type = { + owner: THIS_MODULE, + name: "nfs", + get_sb: nfs_get_sb, + fs_flags: FS_ODD_RENAME, +}; extern int nfs_init_nfspagecache(void); extern void nfs_destroy_nfspagecache(void); diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index eda80eca898e..e95a085a2fdd 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -226,7 +226,6 @@ unsigned long page_index(struct page *page) /* * linux/fs/nfs/inode.c */ -extern struct super_block *nfs_read_super(struct super_block *, void *, int); extern void nfs_zap_caches(struct inode *); extern int nfs_inode_is_stale(struct inode *, struct nfs_fh *, struct nfs_fattr *); -- cgit v1.2.3 From 0ec120046dee44027a28b66a3c28d1031982a9eb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 6 Feb 2002 07:17:34 -0800 Subject: Fix up tree oddities that Al pointed out. --- include/linux/proc_fs_i.h | 9 ---- include/linux/zconf.h | 90 +++++++++++++++++++++++++++++++++ include/linux/zutil.h | 126 ++++++++++++++++++++++++++++++++++++++++++++++ linux/zconf.h | 90 --------------------------------- linux/zutil.h | 126 ---------------------------------------------- 5 files changed, 216 insertions(+), 225 deletions(-) delete mode 100644 include/linux/proc_fs_i.h create mode 100644 include/linux/zconf.h create mode 100644 include/linux/zutil.h delete mode 100644 linux/zconf.h delete mode 100644 linux/zutil.h (limited to 'include/linux') diff --git a/include/linux/proc_fs_i.h b/include/linux/proc_fs_i.h deleted file mode 100644 index d4bde0989084..000000000000 --- a/include/linux/proc_fs_i.h +++ /dev/null @@ -1,9 +0,0 @@ -struct proc_inode_info { - struct task_struct *task; - int type; - union { - int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **); - int (*proc_read)(struct task_struct *task, char *page); - } op; - struct file *file; -}; diff --git a/include/linux/zconf.h b/include/linux/zconf.h new file mode 100644 index 000000000000..0b5ec883812b --- /dev/null +++ b/include/linux/zconf.h @@ -0,0 +1,90 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +#if defined(__GNUC__) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif + +#if defined(__STDC__) || defined(__cplusplus) +# ifndef STDC +# define STDC +# endif +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# define MAX_MEM_LEVEL 9 +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef FAR +# define FAR +#endif + +typedef unsigned char Byte; /* 8 bits */ +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +typedef Byte FAR Bytef; +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +typedef void FAR *voidpf; +typedef void *voidp; + +#include /* for off_t */ +#include /* for SEEK_* and off_t */ +#define z_off_t off_t + +#endif /* _ZCONF_H */ diff --git a/include/linux/zutil.h b/include/linux/zutil.h new file mode 100644 index 000000000000..a4a4d8d75f1e --- /dev/null +++ b/include/linux/zutil.h @@ -0,0 +1,126 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include +#include +#include +#include + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + + /* functions */ + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); + + + /* checksum functions */ + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ +static inline uLong zlib_adler32(uLong adler, + const Bytef *buf, + uInt len) +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} + +#endif /* _Z_UTIL_H */ diff --git a/linux/zconf.h b/linux/zconf.h deleted file mode 100644 index 0b5ec883812b..000000000000 --- a/linux/zconf.h +++ /dev/null @@ -1,90 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-1998 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef _ZCONF_H -#define _ZCONF_H - -#if defined(__GNUC__) || defined(__386__) || defined(i386) -# ifndef __32BIT__ -# define __32BIT__ -# endif -#endif - -#if defined(__STDC__) || defined(__cplusplus) -# ifndef STDC -# define STDC -# endif -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# define MAX_MEM_LEVEL 9 -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef FAR -# define FAR -#endif - -typedef unsigned char Byte; /* 8 bits */ -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -typedef Byte FAR Bytef; -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -typedef void FAR *voidpf; -typedef void *voidp; - -#include /* for off_t */ -#include /* for SEEK_* and off_t */ -#define z_off_t off_t - -#endif /* _ZCONF_H */ diff --git a/linux/zutil.h b/linux/zutil.h deleted file mode 100644 index a4a4d8d75f1e..000000000000 --- a/linux/zutil.h +++ /dev/null @@ -1,126 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-1998 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: zutil.h,v 1.1 2000/01/01 03:32:23 davem Exp $ */ - -#ifndef _Z_UTIL_H -#define _Z_UTIL_H - -#include -#include -#include -#include - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - - /* Common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - - /* functions */ - -typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, - uInt len)); - - - /* checksum functions */ - -#define BASE 65521L /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* ========================================================================= */ -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ -static inline uLong zlib_adler32(uLong adler, - const Bytef *buf, - uInt len) -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int k; - - if (buf == Z_NULL) return 1L; - - while (len > 0) { - k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) { - DO16(buf); - buf += 16; - k -= 16; - } - if (k != 0) do { - s1 += *buf++; - s2 += s1; - } while (--k); - s1 %= BASE; - s2 %= BASE; - } - return (s2 << 16) | s1; -} - -#endif /* _Z_UTIL_H */ -- cgit v1.2.3