diff options
Diffstat (limited to 'fs')
40 files changed, 750 insertions, 417 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index fa8ea33ab0b..08e4414b837 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1499,6 +1499,9 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) #endif int thread_status_size = 0; elf_addr_t *auxv; +#ifdef ELF_CORE_WRITE_EXTRA_NOTES + int extra_notes_size; +#endif /* * We no longer stop all VM operations. @@ -1628,7 +1631,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) sz += thread_status_size; #ifdef ELF_CORE_WRITE_EXTRA_NOTES - sz += ELF_CORE_EXTRA_NOTES_SIZE; + extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE; + sz += extra_notes_size; #endif fill_elf_note_phdr(&phdr, sz, offset); @@ -1674,6 +1678,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) #ifdef ELF_CORE_WRITE_EXTRA_NOTES ELF_CORE_WRITE_EXTRA_NOTES; + foffset += extra_notes_size; #endif /* write out the thread status notes section */ diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 7b0265d7f3a..861141b4f6d 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -558,7 +558,7 @@ static int load_flat_file(struct linux_binprm * bprm, if (!realdatastart) realdatastart = (unsigned long) -ENOMEM; printk("Unable to allocate RAM for process data, errno %d\n", - (int)-datapos); + (int)-realdatastart); do_munmap(current->mm, textpos, text_len); ret = realdatastart; goto err; diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 6017c465440..07838b2ac1c 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -7,16 +7,16 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/fs.h> @@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length) char *charptr = data; char buf[10], line[80]; - printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", + printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", label, length, data); for (i = 0; i < length; i += 16) { line[0] = 0; @@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length) #ifdef CONFIG_CIFS_DEBUG2 void cifs_dump_detail(struct smb_hdr * smb) { - cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", + cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", smb->Command, smb->Status.CifsError, smb->Flags, smb->Flags2, smb->Mid, smb->Pid)); - cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb))); + cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb))); } @@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server) struct list_head *tmp; struct mid_q_entry * mid_entry; - if(server == NULL) + if (server == NULL) return; - cERROR(1,("Dump pending requests:")); + cERROR(1, ("Dump pending requests:")); spin_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - if(mid_entry) { - cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", + if (mid_entry) { + cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", mid_entry->midState, (int)mid_entry->command, mid_entry->pid, mid_entry->tsk, mid_entry->mid)); #ifdef CONFIG_CIFS_STATS2 - cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld", + cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", mid_entry->largeBuf, mid_entry->resp_buf, mid_entry->when_received, jiffies)); #endif /* STATS2 */ - cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp, + cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, mid_entry->multiEnd)); - if(mid_entry->resp_buf) { + if (mid_entry->resp_buf) { cifs_dump_detail(mid_entry->resp_buf); cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62 /* fixme */); } - } } spin_unlock(&GlobalMid_Lock); @@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, "Display Internal CIFS Data Structures for Debugging\n" "---------------------------------------------------\n"); buf += length; - length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION); + length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION); buf += length; - length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid); + length = sprintf(buf, + "Active VFS Requests: %d\n", GlobalTotalActiveXid); buf += length; length = sprintf(buf, "Servers:"); buf += length; @@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, list_for_each(tmp, &GlobalSMBSessionList) { i++; ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); - if((ses->serverDomain == NULL) || (ses->serverOS == NULL) || + if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) || (ses->serverNOS == NULL)) { buf += sprintf(buf, "\nentry for %s not fully " "displayed\n\t", ses->serverName); @@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, } else { length = sprintf(buf, - "\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t", + "\n%d) Name: %s Domain: %s Mounts: %d OS:" + " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB" + " session status: %d\t", i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), ses->serverOS, ses->serverNOS, - ses->capabilities,ses->status); + ses->capabilities, ses->status); buf += length; } - if(ses->server) { - buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d", + if (ses->server) { + buf += sprintf(buf, "TCP status: %d\n\tLocal Users To " + "Server: %d SecMode: 0x%x Req On Wire: %d", ses->server->tcpStatus, atomic_read(&ses->server->socketUseCount), ses->server->secMode, @@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, #ifdef CONFIG_CIFS_STATS2 buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d", - atomic_read(&ses->server->inSend), + atomic_read(&ses->server->inSend), atomic_read(&ses->server->num_waiters)); #endif @@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, mid_entry = list_entry(tmp1, struct mid_q_entry, qhead); - if(mid_entry) { - length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n", - mid_entry->midState, - (int)mid_entry->command, - mid_entry->pid, - mid_entry->tsk, - mid_entry->mid); + if (mid_entry) { + length = sprintf(buf, + "State: %d com: %d pid:" + " %d tsk: %p mid %d\n", + mid_entry->midState, + (int)mid_entry->command, + mid_entry->pid, + mid_entry->tsk, + mid_entry->mid); buf += length; } } - spin_unlock(&GlobalMid_Lock); + spin_unlock(&GlobalMid_Lock); } } @@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); length = sprintf(buf, - "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d", + "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x " + "Attributes: 0x%x\nPathComponentMax: %d Status: %d", i, tcon->treeName, atomic_read(&tcon->useCount), tcon->nativeFileSystem, @@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, le32_to_cpu(tcon->fsAttrInfo.Attributes), le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), tcon->tidStatus); - buf += length; + buf += length; if (dev_type == FILE_DEVICE_DISK) length = sprintf(buf, " type: DISK "); else if (dev_type == FILE_DEVICE_CD_ROM) @@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, length = sprintf(buf, " type: %d ", dev_type); buf += length; - if(tcon->tidStatus == CifsNeedReconnect) { + if (tcon->tidStatus == CifsNeedReconnect) { buf += sprintf(buf, "\tDISCONNECTED "); length += 14; } @@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, /* Now calculate total size of returned data */ length = buf - original_buf; - if(offset + count >= length) + if (offset + count >= length) *eof = 1; - if(length < offset) { + if (length < offset) { *eof = 1; return 0; } else { @@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, static int cifs_stats_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { - char c; - int rc; + char c; + int rc; struct list_head *tmp; struct cifsTconInfo *tcon; - rc = get_user(c, buffer); - if (rc) - return rc; + rc = get_user(c, buffer); + if (rc) + return rc; - if (c == '1' || c == 'y' || c == 'Y' || c == '0') { + if (c == '1' || c == 'y' || c == 'Y' || c == '0') { read_lock(&GlobalSMBSeslock); #ifdef CONFIG_CIFS_STATS2 atomic_set(&totBufAllocCount, 0); @@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer, read_unlock(&GlobalSMBSeslock); } - return count; + return count; } static int cifs_stats_read(char *buf, char **beginBuffer, off_t offset, int count, int *eof, void *data) { - int item_length,i,length; + int item_length, i, length; struct list_head *tmp; struct cifsTconInfo *tcon; @@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, "Resources in use\nCIFS Session: %d\n", sesInfoAllocCount.counter); buf += length; - item_length = - sprintf(buf,"Share (unique mount targets): %d\n", + item_length = + sprintf(buf, "Share (unique mount targets): %d\n", tconInfoAllocCount.counter); length += item_length; - buf += item_length; - item_length = - sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n", + buf += item_length; + item_length = + sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n", bufAllocCount.counter, cifs_min_rcv + tcpSesAllocCount.counter); length += item_length; buf += item_length; - item_length = - sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n", - smBufAllocCount.counter,cifs_min_small); + item_length = + sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n", + smBufAllocCount.counter, cifs_min_small); length += item_length; buf += item_length; #ifdef CONFIG_CIFS_STATS2 - item_length = sprintf(buf, "Total Large %d Small %d Allocations\n", + item_length = sprintf(buf, "Total Large %d Small %d Allocations\n", atomic_read(&totBufAllocCount), - atomic_read(&totSmBufAllocCount)); + atomic_read(&totSmBufAllocCount)); length += item_length; buf += item_length; #endif /* CONFIG_CIFS_STATS2 */ - item_length = - sprintf(buf,"Operations (MIDs): %d\n", + item_length = + sprintf(buf, "Operations (MIDs): %d\n", midCount.counter); length += item_length; buf += item_length; item_length = sprintf(buf, "\n%d session %d share reconnects\n", - tcpSesReconnectCount.counter,tconInfoReconnectCount.counter); + tcpSesReconnectCount.counter, tconInfoReconnectCount.counter); length += item_length; buf += item_length; item_length = sprintf(buf, "Total vfs operations: %d maximum at one time: %d\n", - GlobalCurrentXid,GlobalMaxActiveXid); + GlobalCurrentXid, GlobalMaxActiveXid); length += item_length; buf += item_length; @@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, list_for_each(tmp, &GlobalTreeConnectionList) { i++; tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); - item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName); + item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName); buf += item_length; length += item_length; - if(tcon->tidStatus == CifsNeedReconnect) { + if (tcon->tidStatus == CifsNeedReconnect) { buf += sprintf(buf, "\tDISCONNECTED "); length += 14; } @@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, item_length = sprintf(buf, "\nWrites: %d Bytes: %lld", atomic_read(&tcon->num_writes), (long long)(tcon->bytes_written)); - buf += item_length; - length += item_length; - item_length = sprintf(buf, + buf += item_length; + length += item_length; + item_length = sprintf(buf, "\nLocks: %d HardLinks: %d Symlinks: %d", - atomic_read(&tcon->num_locks), + atomic_read(&tcon->num_locks), atomic_read(&tcon->num_hardlinks), atomic_read(&tcon->num_symlinks)); - buf += item_length; - length += item_length; + buf += item_length; + length += item_length; item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d", atomic_read(&tcon->num_opens), @@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, } read_unlock(&GlobalSMBSeslock); - buf += sprintf(buf,"\n"); + buf += sprintf(buf, "\n"); length++; - if(offset + count >= length) + if (offset + count >= length) *eof = 1; - if(length < offset) { + if (length < offset) { *eof = 1; return 0; } else { @@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, } if (length > count) length = count; - + return length; } #endif @@ -547,11 +553,11 @@ cifs_proc_clean(void) remove_proc_entry("MultiuserMount", proc_fs_cifs); remove_proc_entry("OplockEnabled", proc_fs_cifs); /* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */ - remove_proc_entry("SecurityFlags",proc_fs_cifs); -/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */ - remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); - remove_proc_entry("Experimental",proc_fs_cifs); - remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); + remove_proc_entry("SecurityFlags", proc_fs_cifs); +/* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */ + remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); + remove_proc_entry("Experimental", proc_fs_cifs); + remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); remove_proc_entry("cifs", proc_root_fs); } @@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer, cifsFYI = 0; else if (c == '1' || c == 'y' || c == 'Y') cifsFYI = 1; - else if((c > '1') && (c <= '9')) + else if ((c > '1') && (c <= '9')) cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */ return count; @@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer, static int experimEnabled_read(char *page, char **start, off_t off, - int count, int *eof, void *data) + int count, int *eof, void *data) { - int len; + int len; - len = sprintf(page, "%d\n", experimEnabled); + len = sprintf(page, "%d\n", experimEnabled); - len -= off; - *start = page + off; + len -= off; + *start = page + off; - if (len > count) - len = count; - else - *eof = 1; + if (len > count) + len = count; + else + *eof = 1; - if (len < 0) - len = 0; + if (len < 0) + len = 0; - return len; + return len; } static int experimEnabled_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { char c; int rc; @@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer, static int linuxExtensionsEnabled_read(char *page, char **start, off_t off, - int count, int *eof, void *data) + int count, int *eof, void *data) { - int len; + int len; - len = sprintf(page, "%d\n", linuxExtEnabled); - len -= off; - *start = page + off; + len = sprintf(page, "%d\n", linuxExtEnabled); + len -= off; + *start = page + off; - if (len > count) - len = count; - else - *eof = 1; + if (len > count) + len = count; + else + *eof = 1; - if (len < 0) - len = 0; + if (len < 0) + len = 0; - return len; + return len; } static int linuxExtensionsEnabled_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { - char c; - int rc; - - rc = get_user(c, buffer); - if (rc) - return rc; - if (c == '0' || c == 'n' || c == 'N') - linuxExtEnabled = 0; - else if (c == '1' || c == 'y' || c == 'Y') - linuxExtEnabled = 1; - - return count; + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + linuxExtEnabled = 0; + else if (c == '1' || c == 'y' || c == 'Y') + linuxExtEnabled = 1; + + return count; } static int lookupFlag_read(char *page, char **start, off_t off, - int count, int *eof, void *data) + int count, int *eof, void *data) { int len; @@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer, char flags_string[12]; char c; - if((count < 1) || (count > 11)) + if ((count < 1) || (count > 11)) return -EINVAL; memset(flags_string, 0, 12); - if(copy_from_user(flags_string, buffer, count)) + if (copy_from_user(flags_string, buffer, count)) return -EFAULT; - if(count < 3) { + if (count < 3) { /* single char or single char followed by null */ c = flags_string[0]; if (c == '0' || c == 'n' || c == 'N') @@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer, flags = simple_strtoul(flags_string, NULL, 0); - cFYI(1,("sec flags 0x%x", flags)); + cFYI(1, ("sec flags 0x%x", flags)); - if(flags <= 0) { - cERROR(1,("invalid security flags %s",flags_string)); + if (flags <= 0) { + cERROR(1, ("invalid security flags %s", flags_string)); return -EINVAL; } - if(flags & ~CIFSSEC_MASK) { - cERROR(1,("attempt to set unsupported security flags 0x%x", + if (flags & ~CIFSSEC_MASK) { + cERROR(1, ("attempt to set unsupported security flags 0x%x", flags & ~CIFSSEC_MASK)); return -EINVAL; } diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index 793c4b95c16..701e9a9185f 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -6,16 +6,16 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software + * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/fs.h> @@ -32,7 +32,7 @@ * */ int -cifs_strfromUCS_le(char *to, const __le16 * from, +cifs_strfromUCS_le(char *to, const __le16 * from, int len, const struct nls_table *codepage) { int i; @@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len, { int charlen; int i; - wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */ + wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */ for (i = 0; len && *from; i++, from += charlen, len -= charlen) { @@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len, /* A question mark */ to[i] = cpu_to_le16(0x003f); charlen = 1; - } else + } else to[i] = cpu_to_le16(wchar_to[i]); } diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index d38c69b591c..7c04752b76c 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -825,8 +825,8 @@ cifs_init_mids(void) sizeof (struct oplock_q_entry), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if (cifs_oplock_cachep == NULL) { - kmem_cache_destroy(cifs_mid_cachep); mempool_destroy(cifs_mid_poolp); + kmem_cache_destroy(cifs_mid_cachep); return -ENOMEM; } diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 14de58fa143..57419a17668 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) cFYI(1,("secFlags 0x%x",secFlags)); pSMB->hdr.Mid = GetNextMid(server); - pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; - if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) + pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); + if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; count = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 216fb625843..f4e92661b22 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, srvTcp->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); if (srvTcp->tsk) { + struct task_struct *tsk; + /* If we could verify that kthread_stop would + always wake up processes blocked in + tcp in recv_mesg then we could remove the + send_sig call */ send_sig(SIGKILL,srvTcp->tsk,1); - kthread_stop(srvTcp->tsk); + tsk = srvTcp->tsk; + if(tsk) + kthread_stop(tsk); } } /* If find_unc succeeded then rc == 0 so we can not end */ @@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* if the socketUseCount is now zero */ if ((temp_rc == -ESHUTDOWN) && (pSesInfo->server) && (pSesInfo->server->tsk)) { + struct task_struct *tsk; send_sig(SIGKILL,pSesInfo->server->tsk,1); - kthread_stop(pSesInfo->server->tsk); + tsk = pSesInfo->server->tsk; + if (tsk) + kthread_stop(tsk); } } else cFYI(1, ("No session or bad tcon")); @@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) return 0; } else if (rc == -ESHUTDOWN) { cFYI(1,("Waking up socket by sending it signal")); - if(cifsd_task) { + if (cifsd_task) { send_sig(SIGKILL,cifsd_task,1); kthread_stop(cifsd_task); } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e5210519ac4..8e86aaceb68 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -2,7 +2,7 @@ * fs/cifs/dir.c * * vfs operations that deal with dentries - * + * * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * @@ -34,11 +34,12 @@ static void renew_parental_timestamps(struct dentry *direntry) { - /* BB check if there is a way to get the kernel to do this or if we really need this */ + /* BB check if there is a way to get the kernel to do this or if we + really need this */ do { direntry->d_time = jiffies; direntry = direntry->d_parent; - } while (!IS_ROOT(direntry)); + } while (!IS_ROOT(direntry)); } /* Note: caller must free return buffer */ @@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry) char *full_path; char dirsep; - if(direntry == NULL) + if (direntry == NULL) return NULL; /* not much we can do if dentry is freed and we need to reopen the file after it was closed implicitly when the server crashed */ @@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry) dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); pplen = CIFS_SB(direntry->d_sb)->prepathlen; cifs_bp_rename_retry: - namelen = pplen; + namelen = pplen; for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); + if (temp == NULL) { + cERROR(1, ("corrupt dentry")); return NULL; } } full_path = kmalloc(namelen+1, GFP_KERNEL); - if(full_path == NULL) + if (full_path == NULL) return full_path; full_path[namelen] = 0; /* trailing null */ for (temp = direntry; !IS_ROOT(temp);) { @@ -84,8 +85,8 @@ cifs_bp_rename_retry: cFYI(0, ("name: %s", full_path + namelen)); } temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); + if (temp == NULL) { + cERROR(1, ("corrupt dentry")); kfree(full_path); return NULL; } @@ -94,7 +95,7 @@ cifs_bp_rename_retry: cERROR(1, ("did not end path lookup where expected namelen is %d", namelen)); - /* presumably this is only possible if racing with a rename + /* presumably this is only possible if racing with a rename of one of the parent directories (we can not lock the dentries above us to prevent this, but retrying should be harmless) */ kfree(full_path); @@ -106,7 +107,7 @@ cifs_bp_rename_retry: since the '\' is a valid posix character so we can not switch those safely to '/' if any are found in the middle of the prepath */ /* BB test paths to Windows with '/' in the midst of prepath */ - strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); + strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen); return full_path; } @@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - if(full_path == NULL) { + if (full_path == NULL) { FreeXid(xid); return -ENOMEM; } - if(nd && (nd->flags & LOOKUP_OPEN)) { + if (nd && (nd->flags & LOOKUP_OPEN)) { int oflags = nd->intent.open.flags; desiredAccess = 0; @@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, write_only = TRUE; } - if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) + if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) disposition = FILE_CREATE; - else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) + else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) disposition = FILE_OVERWRITE_IF; - else if((oflags & O_CREAT) == O_CREAT) + else if ((oflags & O_CREAT) == O_CREAT) disposition = FILE_OPEN_IF; else { - cFYI(1,("Create flag not set in create function")); + cFYI(1, ("Create flag not set in create function")); } } - /* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ + /* BB add processing to set equivalent of mode - e.g. via CreateX with + ACLs */ if (oplockEnabled) oplock = REQ_OPLOCK; - buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); - if(buf == NULL) { + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (buf == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; } - if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) + if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls, @@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else rc = -EIO; /* no NT SMB support fall into legacy open below */ - if(rc == -EIO) { + if (rc == -EIO) { /* old server, retry the open legacy style */ rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } + } if (rc) { cFYI(1, ("cifs_create returned 0x%x", rc)); } else { /* If Open reported that we actually created a file then we now have to set the mode if possible */ if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && - (oplock & CIFS_CREATE_ACTION)) - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { + (oplock & CIFS_CREATE_ACTION)) { + mode &= ~current->fs->umask; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)current->fsuid, (__u64)current->fsgid, 0 /* dev */, - cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, @@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (__u64)-1, 0 /* dev */, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } - else { - /* BB implement mode setting via Windows security descriptors */ - /* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ - /* could set r/o dos attribute if mode & 0222 == 0 */ + } else { + /* BB implement mode setting via Windows security + descriptors e.g. */ + /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/ + + /* Could set r/o dos attribute if mode & 0222 == 0 */ } /* BB server might mask mode so we have to query for Unix case*/ if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb,xid); + inode->i_sb, xid); else { rc = cifs_get_inode_info(&newinode, full_path, - buf, inode->i_sb,xid); - if(newinode) { + buf, inode->i_sb, xid); + if (newinode) { newinode->i_mode = mode; - if((oplock & CIFS_CREATE_ACTION) && - (cifs_sb->mnt_cifs_flags & + if ((oplock & CIFS_CREATE_ACTION) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) { newinode->i_uid = current->fsuid; newinode->i_gid = current->fsgid; @@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, direntry->d_op = &cifs_dentry_ops; d_instantiate(direntry, newinode); } - if((nd->flags & LOOKUP_OPEN) == FALSE) { + if ((nd->flags & LOOKUP_OPEN) == FALSE) { /* mknod case - do not leave file open */ CIFSSMBClose(xid, pTcon, fileHandle); - } else if(newinode) { + } else if (newinode) { pCifsFile = kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); - - if(pCifsFile == NULL) + + if (pCifsFile == NULL) goto cifs_create_out; pCifsFile->netfid = fileHandle; pCifsFile->pid = current->tgid; @@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, init_MUTEX(&pCifsFile->fh_sem); mutex_init(&pCifsFile->lock_mutex); INIT_LIST_HEAD(&pCifsFile->llist); - atomic_set(&pCifsFile->wrtPending,0); + atomic_set(&pCifsFile->wrtPending, 0); - /* set the following in open now + /* set the following in open now pCifsFile->pfile = file; */ write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist,&pTcon->openFileList); + list_add(&pCifsFile->tlist, &pTcon->openFileList); pCifsInode = CIFS_I(newinode); - if(pCifsInode) { + if (pCifsInode) { /* if readable file instance put first in list*/ if (write_only == TRUE) { - list_add_tail(&pCifsFile->flist, + list_add_tail(&pCifsFile->flist, &pCifsInode->openFileList); } else { list_add(&pCifsFile->flist, &pCifsInode->openFileList); } - if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { + if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheRead = TRUE; - cFYI(1,("Exclusive Oplock for inode %p", + cFYI(1, ("Exclusive Oplock inode %p", newinode)); - } else if((oplock & 0xF) == OPLOCK_READ) + } else if ((oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = TRUE; } write_unlock(&GlobalSMBSeslock); } - } + } cifs_create_out: kfree(buf); kfree(full_path); @@ -310,8 +315,8 @@ cifs_create_out: return rc; } -int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, - dev_t device_number) +int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, + dev_t device_number) { int rc = -EPERM; int xid; @@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, pTcon = cifs_sb->tcon; full_path = build_path_from_dentry(direntry); - if(full_path == NULL) + if (full_path == NULL) rc = -ENOMEM; else if (pTcon->ses->capabilities & CAP_UNIX) { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { + mode &= ~current->fs->umask; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, - mode,(__u64)current->fsuid,(__u64)current->fsgid, + mode, (__u64)current->fsuid, + (__u64)current->fsgid, device_number, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)-1, (__u64)-1, device_number, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } - if(!rc) { + if (!rc) { rc = cifs_get_inode_info_unix(&newinode, full_path, - inode->i_sb,xid); + inode->i_sb, xid); if (pTcon->nocase) direntry->d_op = &cifs_ci_dentry_ops; else direntry->d_op = &cifs_dentry_ops; - if(rc == 0) + if (rc == 0) d_instantiate(direntry, newinode); } } else { - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { int oplock = 0; u16 fileHandle; FILE_ALL_INFO * buf; - cFYI(1,("sfu compat create special file")); + cFYI(1, ("sfu compat create special file")); - buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); - if(buf == NULL) { + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (buf == NULL) { kfree(full_path); FreeXid(xid); return -ENOMEM; @@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, /* fail if exists */ - GENERIC_WRITE /* BB would + GENERIC_WRITE /* BB would WRITE_OWNER | WRITE_DAC be better? */, /* Create a file and set the file attribute to SYSTEM */ CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, &fileHandle, &oplock, buf, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB FIXME - add handling for backlevel servers which need legacy open and check for all - calls to SMBOpen for fallback to - SMBLeagcyOpen */ - if(!rc) { + calls to SMBOpen for fallback to SMBLeagcyOpen */ + if (!rc) { /* BB Do not bother to decode buf since no local inode yet to put timestamps in, but we can reuse it safely */ int bytes_written; struct win_dev *pdev; pdev = (struct win_dev *)buf; - if(S_ISCHR(mode)) { + if (S_ISCHR(mode)) { memcpy(pdev->type, "IntxCHR", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); - pdev->minor = + pdev->minor = cpu_to_le64(MINOR(device_number)); rc = CIFSSMBWrite(xid, pTcon, fileHandle, sizeof(struct win_dev), 0, &bytes_written, (char *)pdev, NULL, 0); - } else if(S_ISBLK(mode)) { + } else if (S_ISBLK(mode)) { memcpy(pdev->type, "IntxBLK", 8); pdev->major = cpu_to_le64(MAJOR(device_number)); @@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, struct dentry * -cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) +cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, + struct nameidata *nd) { int xid; int rc = 0; /* to get around spurious gcc warning, set to zero here */ @@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name (" parent inode = 0x%p name is: %s and dentry = 0x%p", parent_dir_inode, direntry->d_name.name, direntry)); - /* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */ - /* check whether path exists */ cifs_sb = CIFS_SB(parent_dir_inode->i_sb); @@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name deadlock in the cases (beginning of sys_rename itself) in which we already have the sb rename sem */ full_path = build_path_from_dentry(direntry); - if(full_path == NULL) { + if (full_path == NULL) { FreeXid(xid); return ERR_PTR(-ENOMEM); } @@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name if (pTcon->ses->capabilities & CAP_UNIX) rc = cifs_get_inode_info_unix(&newInode, full_path, - parent_dir_inode->i_sb,xid); + parent_dir_inode->i_sb, xid); else rc = cifs_get_inode_info(&newInode, full_path, NULL, - parent_dir_inode->i_sb,xid); + parent_dir_inode->i_sb, xid); if ((rc == 0) && (newInode != NULL)) { if (pTcon->nocase) @@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name direntry->d_op = &cifs_dentry_ops; d_add(direntry, newInode); - /* since paths are not looked up by component - the parent + /* since paths are not looked up by component - the parent directories are presumed to be good here */ renew_parental_timestamps(direntry); @@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name else direntry->d_op = &cifs_dentry_ops; d_add(direntry, NULL); - /* if it was once a directory (but how can we tell?) we could do - shrink_dcache_parent(direntry); */ + /* if it was once a directory (but how can we tell?) we could do + shrink_dcache_parent(direntry); */ } else { - cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", - rc,full_path)); - /* BB special case check for Access Denied - watch security - exposure of returning dir info implicitly via different rc + cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s", + rc, full_path)); + /* BB special case check for Access Denied - watch security + exposure of returning dir info implicitly via different rc if file exists or not but no access BB */ } @@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) } else { cFYI(1, ("neg dentry 0x%p name = %s", direntry, direntry->d_name.name)); - if(time_after(jiffies, direntry->d_time + HZ) || + if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) { d_drop(direntry); isValid = 0; - } + } } return isValid; @@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) struct dentry_operations cifs_dentry_ops = { .d_revalidate = cifs_d_revalidate, -/* d_delete: cifs_d_delete, *//* not needed except for debugging */ - /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ +/* d_delete: cifs_d_delete, */ /* not needed except for debugging */ }; static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index da12b482ebe..8e375bb4b37 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -2,7 +2,7 @@ * fs/cifs/fcntl.c * * vfs operations that deal with the file control API - * + * * Copyright (C) International Business Machines Corp., 2003,2004 * Author(s): Steve French (sfrench@us.ibm.com) * @@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) /* No way on Linux VFS to ask to monitor xattr changes (and no stream support either */ - if(fcntl_notify_flags & DN_ACCESS) { + if (fcntl_notify_flags & DN_ACCESS) { cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; } - if(fcntl_notify_flags & DN_MODIFY) { + if (fcntl_notify_flags & DN_MODIFY) { /* What does this mean on directories? */ cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE; } - if(fcntl_notify_flags & DN_CREATE) { - cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | + if (fcntl_notify_flags & DN_CREATE) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_LAST_WRITE; } - if(fcntl_notify_flags & DN_DELETE) { + if (fcntl_notify_flags & DN_DELETE) { cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; } - if(fcntl_notify_flags & DN_RENAME) { + if (fcntl_notify_flags & DN_RENAME) { /* BB review this - checking various server behaviors */ - cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME; } - if(fcntl_notify_flags & DN_ATTRIB) { - cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | + if (fcntl_notify_flags & DN_ATTRIB) { + cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | FILE_NOTIFY_CHANGE_ATTRIBUTES; } -/* if(fcntl_notify_flags & DN_MULTISHOT) { +/* if (fcntl_notify_flags & DN_MULTISHOT) { cifs_ntfy_flags |= ; } */ /* BB fixme - not sure how to handle this with CIFS yet */ - return cifs_ntfy_flags; } @@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg) __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; __u16 netfid; - - if(experimEnabled == 0) + if (experimEnabled == 0) return 0; xid = GetXid(); @@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg) full_path = build_path_from_dentry(file->f_path.dentry); - if(full_path == NULL) { + if (full_path == NULL) { rc = -ENOMEM; } else { - cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg)); - rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, + cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg)); + rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ | SYNCHRONIZE, 0 /* create options */, - &netfid, &oplock,NULL, cifs_sb->local_nls, + &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB fixme - add this handle to a notify handle list */ - if(rc) { - cFYI(1,("Could not open directory for notify")); + if (rc) { + cFYI(1, ("Could not open directory for notify")); } else { filter = convert_to_cifs_notify_flags(arg); - if(filter != 0) { - rc = CIFSSMBNotify(xid, pTcon, + if (filter != 0) { + rc = CIFSSMBNotify(xid, pTcon, 0 /* no subdirs */, netfid, filter, file, arg & DN_MULTISHOT, cifs_sb->local_nls); @@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg) it would close automatically but may be a way to do it easily when inode freed or when notify info is cleared/changed */ - cFYI(1,("notify rc %d",rc)); + cFYI(1, ("notify rc %d", rc)); } } - + FreeXid(xid); return rc; } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 3e87dad3367..f0ff12b3f39 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -986,7 +986,8 @@ mkdir_get_info: * failed to get it from the server or was set bogus */ if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) direntry->d_inode->i_nlink = 2; - if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) + if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) { + mode &= ~current->fs->umask; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, @@ -1004,7 +1005,7 @@ mkdir_get_info: cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } - else { + } else { /* BB to be implemented via Windows secrty descriptors eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, -1, -1, local_nls); */ diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index e34c7db00f6..a414f1775ae 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -30,7 +30,7 @@ #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) -int cifs_ioctl (struct inode * inode, struct file * filep, +int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) { int rc = -ENOTTY; /* strange error - but the precedent */ @@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep, xid = GetXid(); - cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); + cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg)); cifs_sb = CIFS_SB(inode->i_sb); #ifdef CONFIG_CIFS_POSIX tcon = cifs_sb->tcon; - if(tcon) + if (tcon) caps = le64_to_cpu(tcon->fsUnixInfo.Capability); else { rc = -EIO; @@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep, } #endif /* CONFIG_CIFS_POSIX */ - switch(command) { + switch (command) { case CIFS_IOC_CHECKUMOUNT: - cFYI(1,("User unmount attempted")); - if(cifs_sb->mnt_uid == current->uid) + cFYI(1, ("User unmount attempted")); + if (cifs_sb->mnt_uid == current->uid) rc = 0; else { rc = -EACCES; - cFYI(1,("uids do not match")); + cFYI(1, ("uids do not match")); } break; #ifdef CONFIG_CIFS_POSIX case FS_IOC_GETFLAGS: - if(CIFS_UNIX_EXTATTR_CAP & caps) { + if (CIFS_UNIX_EXTATTR_CAP & caps) { if (pSMBFile == NULL) break; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); - if(rc == 0) + if (rc == 0) rc = put_user(ExtAttrBits & FS_FL_USER_VISIBLE, (int __user *)arg); @@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep, break; case FS_IOC_SETFLAGS: - if(CIFS_UNIX_EXTATTR_CAP & caps) { - if(get_user(ExtAttrBits,(int __user *)arg)) { + if (CIFS_UNIX_EXTATTR_CAP & caps) { + if (get_user(ExtAttrBits, (int __user *)arg)) { rc = -EFAULT; break; } @@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep, break; /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ - } - cFYI(1,("set flags not implemented yet")); + cFYI(1, ("set flags not implemented yet")); break; #endif /* CONFIG_CIFS_POSIX */ default: - cFYI(1,("unsupported ioctl")); + cFYI(1, ("unsupported ioctl")); break; } FreeXid(xid); return rc; -} +} diff --git a/fs/cifs/rfc1002pdu.h b/fs/cifs/rfc1002pdu.h index aede606132a..8b69fcceb59 100644 --- a/fs/cifs/rfc1002pdu.h +++ b/fs/cifs/rfc1002pdu.h @@ -18,7 +18,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ diff --git a/fs/direct-io.c b/fs/direct-io.c index 8593f3dfd29..52bb2638f7a 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1106,7 +1106,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, spin_lock_irqsave(&dio->bio_lock, flags); ret2 = --dio->refcount; spin_unlock_irqrestore(&dio->bio_lock, flags); - BUG_ON(!dio->is_async && ret2 != 0); + if (ret2 == 0) { ret = dio_complete(dio, offset, ret); kfree(dio); diff --git a/fs/dlm/Kconfig b/fs/dlm/Kconfig index 69a94690e49..54bcc00ec8d 100644 --- a/fs/dlm/Kconfig +++ b/fs/dlm/Kconfig @@ -3,7 +3,7 @@ menu "Distributed Lock Manager" config DLM tristate "Distributed Lock Manager (DLM)" - depends on IPV6 || IPV6=n + depends on SYSFS && (IPV6 || IPV6=n) select CONFIGFS_FS select IP_SCTP help diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index 403e3bad145..1b9dd9a96f1 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h @@ -580,5 +580,7 @@ void ecryptfs_write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat, size_t *written); +int ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, + int num_zeros); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 1548be26b5e..83e94fedd4e 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -800,6 +800,25 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) goto out_fput; } } else { /* new_length < i_size_read(inode) */ + pgoff_t index = 0; + int end_pos_in_page = -1; + + if (new_length != 0) { + index = ((new_length - 1) >> PAGE_CACHE_SHIFT); + end_pos_in_page = ((new_length - 1) & ~PAGE_CACHE_MASK); + } + if (end_pos_in_page != (PAGE_CACHE_SIZE - 1)) { + if ((rc = ecryptfs_write_zeros(&fake_ecryptfs_file, + index, + (end_pos_in_page + 1), + ((PAGE_CACHE_SIZE - 1) + - end_pos_in_page)))) { + printk(KERN_ERR "Error attempting to zero out " + "the remainder of the end page on " + "reducing truncate; rc = [%d]\n", rc); + goto out_fput; + } + } vmtruncate(inode, new_length); rc = ecryptfs_write_inode_size_to_metadata( lower_file, lower_dentry->d_inode, inode, dentry, @@ -875,9 +894,54 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia) struct ecryptfs_crypt_stat *crypt_stat; crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; - lower_dentry = ecryptfs_dentry_to_lower(dentry); + if (!(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED)) + ecryptfs_init_crypt_stat(crypt_stat); inode = dentry->d_inode; lower_inode = ecryptfs_inode_to_lower(inode); + lower_dentry = ecryptfs_dentry_to_lower(dentry); + mutex_lock(&crypt_stat->cs_mutex); + if (S_ISDIR(dentry->d_inode->i_mode)) + crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + else if (!(crypt_stat->flags & ECRYPTFS_POLICY_APPLIED) + || !(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { + struct vfsmount *lower_mnt; + struct file *lower_file = NULL; + struct ecryptfs_mount_crypt_stat *mount_crypt_stat; + int lower_flags; + + lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); + lower_flags = O_RDONLY; + if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, + lower_mnt, lower_flags))) { + printk(KERN_ERR + "Error opening lower file; rc = [%d]\n", rc); + mutex_unlock(&crypt_stat->cs_mutex); + goto out; + } + mount_crypt_stat = &ecryptfs_superblock_to_private( + dentry->d_sb)->mount_crypt_stat; + if ((rc = ecryptfs_read_metadata(dentry, lower_file))) { + if (!(mount_crypt_stat->flags + & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) { + rc = -EIO; + printk(KERN_WARNING "Attempt to read file that " + "is not in a valid eCryptfs format, " + "and plaintext passthrough mode is not " + "enabled; returning -EIO\n"); + + mutex_unlock(&crypt_stat->cs_mutex); + fput(lower_file); + goto out; + } + rc = 0; + crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); + mutex_unlock(&crypt_stat->cs_mutex); + fput(lower_file); + goto out; + } + fput(lower_file); + } + mutex_unlock(&crypt_stat->cs_mutex); if (ia->ia_valid & ATTR_SIZE) { ecryptfs_printk(KERN_DEBUG, "ia->ia_valid = [0x%x] ATTR_SIZE" " = [0x%x]\n", diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 55cec98a84e..7d5a43cb0d5 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -56,9 +56,6 @@ static struct page *ecryptfs_get1page(struct file *file, int index) return read_mapping_page(mapping, index, (void *)file); } -static -int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros); - /** * ecryptfs_fill_zeros * @file: The ecryptfs file @@ -101,10 +98,13 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length) if (old_end_page_index == new_end_page_index) { /* Start and end are in the same page; we just need to * set a portion of the existing page to zero's */ - rc = write_zeros(file, index, (old_end_pos_in_page + 1), - (new_end_pos_in_page - old_end_pos_in_page)); + rc = ecryptfs_write_zeros(file, index, + (old_end_pos_in_page + 1), + (new_end_pos_in_page + - old_end_pos_in_page)); if (rc) - ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], " + ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(" + "file=[%p], " "index=[0x%.16x], " "old_end_pos_in_page=[d], " "(PAGE_CACHE_SIZE - new_end_pos_in_page" @@ -117,10 +117,10 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length) goto out; } /* Fill the remainder of the previous last page with zeros */ - rc = write_zeros(file, index, (old_end_pos_in_page + 1), + rc = ecryptfs_write_zeros(file, index, (old_end_pos_in_page + 1), ((PAGE_CACHE_SIZE - 1) - old_end_pos_in_page)); if (rc) { - ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], " + ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file=[%p], " "index=[0x%.16x], old_end_pos_in_page=[d], " "(PAGE_CACHE_SIZE - old_end_pos_in_page)=[d]) " "returned [%d]\n", file, index, @@ -131,9 +131,10 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length) index++; while (index < new_end_page_index) { /* Fill all intermediate pages with zeros */ - rc = write_zeros(file, index, 0, PAGE_CACHE_SIZE); + rc = ecryptfs_write_zeros(file, index, 0, PAGE_CACHE_SIZE); if (rc) { - ecryptfs_printk(KERN_ERR, "write_zeros(file=[%p], " + ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(" + "file=[%p], " "index=[0x%.16x], " "old_end_pos_in_page=[d], " "(PAGE_CACHE_SIZE - new_end_pos_in_page" @@ -149,9 +150,9 @@ int ecryptfs_fill_zeros(struct file *file, loff_t new_length) } /* Fill the portion at the beginning of the last new page with * zero's */ - rc = write_zeros(file, index, 0, (new_end_pos_in_page + 1)); + rc = ecryptfs_write_zeros(file, index, 0, (new_end_pos_in_page + 1)); if (rc) { - ecryptfs_printk(KERN_ERR, "write_zeros(file=" + ecryptfs_printk(KERN_ERR, "ecryptfs_write_zeros(file=" "[%p], index=[0x%.16x], 0, " "new_end_pos_in_page=[%d]" "returned [%d]\n", file, index, @@ -400,7 +401,6 @@ out: static int ecryptfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to) { - loff_t pos; int rc = 0; if (from == 0 && to == PAGE_CACHE_SIZE) @@ -408,15 +408,22 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page, up to date. */ if (!PageUptodate(page)) rc = ecryptfs_do_readpage(file, page, page->index); - pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; - if (pos > i_size_read(page->mapping->host)) { - rc = ecryptfs_truncate(file->f_path.dentry, pos); - if (rc) { - printk(KERN_ERR "Error on attempt to " - "truncate to (higher) offset [%lld];" - " rc = [%d]\n", pos, rc); - goto out; + if (page->index != 0) { + loff_t end_of_prev_pg_pos = + (((loff_t)page->index << PAGE_CACHE_SHIFT) - 1); + + if (end_of_prev_pg_pos > i_size_read(page->mapping->host)) { + rc = ecryptfs_truncate(file->f_path.dentry, + end_of_prev_pg_pos); + if (rc) { + printk(KERN_ERR "Error on attempt to " + "truncate to (higher) offset [%lld];" + " rc = [%d]\n", end_of_prev_pg_pos, rc); + goto out; + } } + if (end_of_prev_pg_pos + 1 > i_size_read(page->mapping->host)) + zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0); } out: return rc; @@ -753,7 +760,7 @@ out: } /** - * write_zeros + * ecryptfs_write_zeros * @file: The ecryptfs file * @index: The index in which we are writing * @start: The position after the last block of data @@ -763,8 +770,8 @@ out: * * (start + num_zeros) must be less than or equal to PAGE_CACHE_SIZE */ -static -int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) +int +ecryptfs_write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) { int rc = 0; struct page *tmp_page; diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 16337bff027..5de5061eb33 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -1038,6 +1038,15 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); + ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset + EXT2_MOUNT_XIP if not */ + + if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) { + printk("XIP: Unsupported blocksize\n"); + err = -EINVAL; + goto restore_opts; + } + es = sbi->s_es; if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) != (old_mount_opt & EXT2_MOUNT_XIP)) && diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index a6cb6171c3a..2a85ddee474 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -2677,8 +2677,10 @@ void ext3_read_inode(struct inode * inode) */ ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT3_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > - EXT3_INODE_SIZE(inode->i_sb)) + EXT3_INODE_SIZE(inode->i_sb)) { + brelse (bh); goto bad_inode; + } if (ei->i_extra_isize == 0) { /* The extra space is currently unused. Use it. */ ei->i_extra_isize = sizeof(struct ext3_inode) - diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0bcf62a750f..8416fa28c42 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2673,8 +2673,10 @@ void ext4_read_inode(struct inode * inode) */ ei->i_extra_isize = le16_to_cpu(raw_inode->i_extra_isize); if (EXT4_GOOD_OLD_INODE_SIZE + ei->i_extra_isize > - EXT4_INODE_SIZE(inode->i_sb)) + EXT4_INODE_SIZE(inode->i_sb)) { + brelse (bh); goto bad_inode; + } if (ei->i_extra_isize == 0) { /* The extra space is currently unused. Use it. */ ei->i_extra_isize = sizeof(struct ext4_inode) - diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9804c0cdcb4..cc5efc13496 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -655,10 +655,9 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type, static struct file_system_type fuseblk_fs_type = { .owner = THIS_MODULE, .name = "fuseblk", - .fs_flags = FS_HAS_SUBTYPE, .get_sb = fuse_get_sb_blk, .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, }; static inline int register_fuseblk(void) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index aa083dd34e9..e6b46b3ac2f 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -736,15 +736,13 @@ static int can_do_hugetlb_shm(void) can_do_mlock()); } -struct file *hugetlb_zero_setup(size_t size) +struct file *hugetlb_file_setup(const char *name, size_t size) { int error = -ENOMEM; struct file *file; struct inode *inode; struct dentry *dentry, *root; struct qstr quick_string; - char buf[16]; - static atomic_t counter; if (!hugetlbfs_vfsmount) return ERR_PTR(-ENOENT); @@ -756,8 +754,7 @@ struct file *hugetlb_zero_setup(size_t size) return ERR_PTR(-ENOMEM); root = hugetlbfs_vfsmount->mnt_root; - snprintf(buf, 16, "%u", atomic_inc_return(&counter)); - quick_string.name = buf; + quick_string.name = name; quick_string.len = strlen(quick_string.name); quick_string.hash = 0; dentry = d_alloc(root, &quick_string); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 12e83f67eee..7b363786c2d 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -210,8 +210,7 @@ static void jffs2_kill_tn(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info * * offset, and the one with the smallest length will come first in the * ordering. * - * Returns 0 if the node was inserted - * 1 if the node is obsolete (because we can't mark it so yet) + * Returns 0 if the node was handled (including marking it obsolete) * < 0 an if error occurred */ static int jffs2_add_tn_to_tree(struct jffs2_sb_info *c, @@ -572,8 +571,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r * Helper function for jffs2_get_inode_nodes(). * It is called every time an directory entry node is found. * - * Returns: 0 on succes; - * 1 if the node should be marked obsolete; + * Returns: 0 on success; * negative error code on failure. */ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, @@ -680,8 +678,7 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r * Helper function for jffs2_get_inode_nodes(). * It is called every time an inode node is found. * - * Returns: 0 on success; - * 1 if the node should be marked obsolete; + * Returns: 0 on success (possibly after marking a bad node obsolete); * negative error code on failure. */ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, @@ -690,7 +687,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref { struct jffs2_tmp_dnode_info *tn; uint32_t len, csize; - int ret = 1; + int ret = 0; uint32_t crc; /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ @@ -719,8 +716,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* Sanity checks */ if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { - JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); - jffs2_dbg_dump_node(c, ref_offset(ref)); + JFFS2_WARNING("inode node header CRC is corrupted at %#08x\n", ref_offset(ref)); + jffs2_dbg_dump_node(c, ref_offset(ref)); + jffs2_mark_node_obsolete(c, ref); goto free_out; } @@ -775,6 +773,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (len >= csize && unlikely(tn->partial_crc != je32_to_cpu(rd->data_crc))) { JFFS2_NOTICE("wrong data CRC in data node at 0x%08x: read %#08x, calculated %#08x.\n", ref_offset(ref), tn->partial_crc, je32_to_cpu(rd->data_crc)); + jffs2_mark_node_obsolete(c, ref); goto free_out; } @@ -854,7 +853,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref * It is called every time an unknown node is found. * * Returns: 0 on success; - * 1 if the node should be marked obsolete; * negative error code on failure. */ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, struct jffs2_unknown_node *un) @@ -1088,10 +1086,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf } err = read_unknown(c, ref, &node->u); - if (err == 1) { - jffs2_mark_node_obsolete(c, ref); - break; - } else if (unlikely(err)) + if (unlikely(err)) goto free_out; } diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 0023b31e48a..a480b09c79b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -798,6 +798,11 @@ int ocfs2_map_and_write_splice_data(struct inode *inode, } to = from + bytes; + BUG_ON(from > PAGE_CACHE_SIZE); + BUG_ON(to > PAGE_CACHE_SIZE); + BUG_ON(from < cluster_start); + BUG_ON(to > cluster_end); + if (wc->w_this_page_new) ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, cluster_start, cluster_end, 1); @@ -809,11 +814,6 @@ int ocfs2_map_and_write_splice_data(struct inode *inode, goto out; } - BUG_ON(from > PAGE_CACHE_SIZE); - BUG_ON(to > PAGE_CACHE_SIZE); - BUG_ON(from > osb->s_clustersize); - BUG_ON(to > osb->s_clustersize); - src = buf->ops->map(sp->s_pipe, buf, 1); dst = kmap_atomic(wc->w_this_page, KM_USER1); memcpy(dst + from, src + src_from, bytes); @@ -890,6 +890,11 @@ int ocfs2_map_and_write_user_data(struct inode *inode, to = from + bytes; + BUG_ON(from > PAGE_CACHE_SIZE); + BUG_ON(to > PAGE_CACHE_SIZE); + BUG_ON(from < cluster_start); + BUG_ON(to > cluster_end); + if (wc->w_this_page_new) ret = ocfs2_map_page_blocks(wc->w_this_page, p_blkno, inode, cluster_start, cluster_end, 1); @@ -901,11 +906,6 @@ int ocfs2_map_and_write_user_data(struct inode *inode, goto out; } - BUG_ON(from > PAGE_CACHE_SIZE); - BUG_ON(to > PAGE_CACHE_SIZE); - BUG_ON(from > osb->s_clustersize); - BUG_ON(to > osb->s_clustersize); - dst = kmap(wc->w_this_page); memcpy(dst + from, bp->b_src_buf + src_from, bytes); kunmap(wc->w_this_page); diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c index a93620ce4ac..2b205f5d579 100644 --- a/fs/ocfs2/cluster/masklog.c +++ b/fs/ocfs2/cluster/masklog.c @@ -144,8 +144,7 @@ static struct kobj_type mlog_ktype = { }; static struct kset mlog_kset = { - .kobj = {.name = "logmask"}, - .ktype = &mlog_ktype + .kobj = {.name = "logmask", .ktype = &mlog_ktype}, }; int mlog_sys_init(struct kset *o2cb_subsys) diff --git a/fs/proc/array.c b/fs/proc/array.c index 74f30e0c038..98e78e2f18d 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -165,7 +165,6 @@ static inline char * task_state(struct task_struct *p, char *buffer) rcu_read_lock(); buffer += sprintf(buffer, "State:\t%s\n" - "SleepAVG:\t%lu%%\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" @@ -173,7 +172,6 @@ static inline char * task_state(struct task_struct *p, char *buffer) "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", get_task_state(p), - (p->sleep_avg/1024)*100/(1020000000/1024), p->tgid, p->pid, pid_alive(p) ? rcu_dereference(p->real_parent)->tgid : 0, pid_alive(p) && p->ptrace ? rcu_dereference(p->parent)->pid : 0, @@ -312,6 +310,41 @@ int proc_pid_status(struct task_struct *task, char * buffer) return buffer - orig; } +static clock_t task_utime(struct task_struct *p) +{ + clock_t utime = cputime_to_clock_t(p->utime), + total = utime + cputime_to_clock_t(p->stime); + u64 temp; + + /* + * Use CFS's precise accounting: + */ + temp = (u64)nsec_to_clock_t(p->se.sum_exec_runtime); + + if (total) { + temp *= utime; + do_div(temp, total); + } + utime = (clock_t)temp; + + return utime; +} + +static clock_t task_stime(struct task_struct *p) +{ + clock_t stime = cputime_to_clock_t(p->stime); + + /* + * Use CFS's precise accounting. (we subtract utime from + * the total, to make sure the total observed by userspace + * grows monotonically - apps rely on that): + */ + stime = nsec_to_clock_t(p->se.sum_exec_runtime) - task_utime(p); + + return stime; +} + + static int do_task_stat(struct task_struct *task, char * buffer, int whole) { unsigned long vsize, eip, esp, wchan = ~0UL; @@ -326,7 +359,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) unsigned long long start_time; unsigned long cmin_flt = 0, cmaj_flt = 0; unsigned long min_flt = 0, maj_flt = 0; - cputime_t cutime, cstime, utime, stime; + cputime_t cutime, cstime; + clock_t utime, stime; unsigned long rsslim = 0; char tcomm[sizeof(task->comm)]; unsigned long flags; @@ -344,7 +378,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) sigemptyset(&sigign); sigemptyset(&sigcatch); - cutime = cstime = utime = stime = cputime_zero; + cutime = cstime = cputime_zero; + utime = stime = 0; rcu_read_lock(); if (lock_task_sighand(task, &flags)) { @@ -370,15 +405,15 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) do { min_flt += t->min_flt; maj_flt += t->maj_flt; - utime = cputime_add(utime, t->utime); - stime = cputime_add(stime, t->stime); + utime += task_utime(t); + stime += task_stime(t); t = next_thread(t); } while (t != task); min_flt += sig->min_flt; maj_flt += sig->maj_flt; - utime = cputime_add(utime, sig->utime); - stime = cputime_add(stime, sig->stime); + utime += cputime_to_clock_t(sig->utime); + stime += cputime_to_clock_t(sig->stime); } sid = signal_session(sig); @@ -394,8 +429,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) if (!whole) { min_flt = task->min_flt; maj_flt = task->maj_flt; - utime = task->utime; - stime = task->stime; + utime = task_utime(task); + stime = task_stime(task); } /* scale priority and nice values from timeslices to -20..20 */ @@ -426,8 +461,8 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) cmin_flt, maj_flt, cmaj_flt, - cputime_to_clock_t(utime), - cputime_to_clock_t(stime), + utime, + stime, cputime_to_clock_t(cutime), cputime_to_clock_t(cstime), priority, diff --git a/fs/proc/base.c b/fs/proc/base.c index a5fa1fdafc4..46ea5d56e1b 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -296,7 +296,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer) */ static int proc_pid_schedstat(struct task_struct *task, char *buffer) { - return sprintf(buffer, "%lu %lu %lu\n", + return sprintf(buffer, "%llu %llu %lu\n", task->sched_info.cpu_time, task->sched_info.run_delay, task->sched_info.pcnt); @@ -929,6 +929,69 @@ static const struct file_operations proc_fault_inject_operations = { }; #endif +#ifdef CONFIG_SCHED_DEBUG +/* + * Print out various scheduling related per-task fields: + */ +static int sched_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + + WARN_ON(!inode); + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + proc_sched_show_task(p, m); + + put_task_struct(p); + + return 0; +} + +static ssize_t +sched_write(struct file *file, const char __user *buf, + size_t count, loff_t *offset) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct task_struct *p; + + WARN_ON(!inode); + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + proc_sched_set_task(p); + + put_task_struct(p); + + return count; +} + +static int sched_open(struct inode *inode, struct file *filp) +{ + int ret; + + ret = single_open(filp, sched_show, NULL); + if (!ret) { + struct seq_file *m = filp->private_data; + + m->private = inode; + } + return ret; +} + +static const struct file_operations proc_pid_sched_operations = { + .open = sched_open, + .read = seq_read, + .write = sched_write, + .llseek = seq_lseek, + .release = seq_release, +}; + +#endif + static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; @@ -1963,6 +2026,9 @@ static const struct pid_entry tgid_base_stuff[] = { INF("environ", S_IRUSR, pid_environ), INF("auxv", S_IRUSR, pid_auxv), INF("status", S_IRUGO, pid_status), +#ifdef CONFIG_SCHED_DEBUG + REG("sched", S_IRUGO|S_IWUSR, pid_sched), +#endif INF("cmdline", S_IRUGO, pid_cmdline), INF("stat", S_IRUGO, tgid_stat), INF("statm", S_IRUGO, pid_statm), @@ -2247,6 +2313,9 @@ static const struct pid_entry tid_base_stuff[] = { INF("environ", S_IRUSR, pid_environ), INF("auxv", S_IRUSR, pid_auxv), INF("status", S_IRUGO, pid_status), +#ifdef CONFIG_SCHED_DEBUG + REG("sched", S_IRUGO|S_IWUSR, pid_sched), +#endif INF("cmdline", S_IRUGO, pid_cmdline), INF("stat", S_IRUGO, tid_stat), INF("statm", S_IRUGO, pid_statm), diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 9345a46ffb3..5d258c40a2f 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -195,6 +195,11 @@ static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) unsigned int old_ia_valid = ia->ia_valid; int ret = 0; + /* POSIX UID/GID verification for setting inode attributes */ + ret = inode_change_ok(inode, ia); + if (ret) + return ret; + /* by providing our own setattr() method, we skip this quotaism */ if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) diff --git a/fs/signalfd.c b/fs/signalfd.c index f1da89203a9..3b07f26d984 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -133,7 +133,8 @@ static unsigned int signalfd_poll(struct file *file, poll_table *wait) * the peer disconnects. */ if (signalfd_lock(ctx, &lk)) { - if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 || + if ((lk.tsk == current && + next_signal(&lk.tsk->pending, &ctx->sigmask) > 0) || next_signal(&lk.tsk->signal->shared_pending, &ctx->sigmask) > 0) events |= POLLIN; diff --git a/fs/splice.c b/fs/splice.c index 12f28281d2b..e7d7080de2f 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -176,6 +176,7 @@ static const struct pipe_buf_operations user_page_pipe_buf_ops = { static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) { + unsigned int spd_pages = spd->nr_pages; int ret, do_wakeup, page_nr; ret = 0; @@ -244,17 +245,18 @@ static ssize_t splice_to_pipe(struct pipe_inode_info *pipe, pipe->waiting_writers--; } - if (pipe->inode) + if (pipe->inode) { mutex_unlock(&pipe->inode->i_mutex); - if (do_wakeup) { - smp_mb(); - if (waitqueue_active(&pipe->wait)) - wake_up_interruptible(&pipe->wait); - kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + if (do_wakeup) { + smp_mb(); + if (waitqueue_active(&pipe->wait)) + wake_up_interruptible(&pipe->wait); + kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); + } } - while (page_nr < spd->nr_pages) + while (page_nr < spd_pages) page_cache_release(spd->pages[page_nr++]); return ret; @@ -272,7 +274,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, struct page *page; pgoff_t index, end_index; loff_t isize; - size_t total_len; int error, page_nr; struct splice_pipe_desc spd = { .pages = pages, @@ -298,7 +299,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, * Now fill in the holes: */ error = 0; - total_len = 0; /* * Lookup the (hopefully) full range of pages we need. @@ -415,43 +415,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, break; } + } +fill_it: + /* + * i_size must be checked after PageUptodate. + */ + isize = i_size_read(mapping->host); + end_index = (isize - 1) >> PAGE_CACHE_SHIFT; + if (unlikely(!isize || index > end_index)) + break; + + /* + * if this is the last page, see if we need to shrink + * the length and stop + */ + if (end_index == index) { + unsigned int plen; /* - * i_size must be checked after ->readpage(). + * max good bytes in this page */ - isize = i_size_read(mapping->host); - end_index = (isize - 1) >> PAGE_CACHE_SHIFT; - if (unlikely(!isize || index > end_index)) + plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; + if (plen <= loff) break; /* - * if this is the last page, see if we need to shrink - * the length and stop + * force quit after adding this page */ - if (end_index == index) { - loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK); - if (total_len + loff > isize) - break; - /* - * force quit after adding this page - */ - len = this_len; - this_len = min(this_len, loff); - loff = 0; - } + this_len = min(this_len, plen - loff); + len = this_len; } -fill_it: + partial[page_nr].offset = loff; partial[page_nr].len = this_len; len -= this_len; - total_len += this_len; loff = 0; spd.nr_pages++; index++; } /* - * Release any pages at the end, if we quit early. 'i' is how far + * Release any pages at the end, if we quit early. 'page_nr' is how far * we got, 'nr_pages' is how many pages are in the map. */ while (page_nr < nr_pages) @@ -478,10 +482,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, { ssize_t spliced; int ret; + loff_t isize, left; + + isize = i_size_read(in->f_mapping->host); + if (unlikely(*ppos >= isize)) + return 0; + + left = isize - *ppos; + if (unlikely(left < len)) + len = left; ret = 0; spliced = 0; - while (len) { ret = __generic_file_splice_read(in, ppos, pipe, len, flags); @@ -644,7 +656,6 @@ find_page: * accessed, we are now done! */ mark_page_accessed(page); - balance_dirty_pages_ratelimited(mapping); out: page_cache_release(page); unlock_page(page); @@ -802,7 +813,10 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, ret = __splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { + unsigned long nr_pages; + *ppos += ret; + nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * If file or inode is SYNC and we actually wrote some data, @@ -815,6 +829,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, if (err) ret = err; } + balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } return ret; @@ -853,7 +868,10 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ret = splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_file); if (ret > 0) { + unsigned long nr_pages; + *ppos += ret; + nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; /* * If file or inode is SYNC and we actually wrote some data, @@ -868,6 +886,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, if (err) ret = err; } + balance_dirty_pages_ratelimited_nr(mapping, nr_pages); } return ret; @@ -922,7 +941,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) { - loff_t isize, left; int ret; if (unlikely(!in->f_op || !in->f_op->splice_read)) @@ -935,14 +953,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, if (unlikely(ret < 0)) return ret; - isize = i_size_read(in->f_mapping->host); - if (unlikely(*ppos >= isize)) - return 0; - - left = isize - *ppos; - if (unlikely(left < len)) - len = left; - return in->f_op->splice_read(in, ppos, pipe, len, flags); } @@ -1058,8 +1068,6 @@ out_release: return ret; } -EXPORT_SYMBOL(do_splice_direct); - /* * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same * location, so checking ->i_pipe is not enough to verify that this is a diff --git a/fs/sync.c b/fs/sync.c index 2f97576355b..7cd005ea763 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -236,6 +236,14 @@ out: return ret; } +/* It would be nice if people remember that not all the world's an i386 + when they introduce new system calls */ +asmlinkage long sys_sync_file_range2(int fd, unsigned int flags, + loff_t offset, loff_t nbytes) +{ + return sys_sync_file_range(fd, offset, nbytes, flags); +} + /* * `endbyte' is inclusive */ diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 85a668680f8..c4342a01997 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -13,14 +13,26 @@ #include "sysfs.h" DECLARE_RWSEM(sysfs_rename_sem); +spinlock_t sysfs_lock = SPIN_LOCK_UNLOCKED; static void sysfs_d_iput(struct dentry * dentry, struct inode * inode) { struct sysfs_dirent * sd = dentry->d_fsdata; if (sd) { - BUG_ON(sd->s_dentry != dentry); - sd->s_dentry = NULL; + /* sd->s_dentry is protected with sysfs_lock. This + * allows sysfs_drop_dentry() to dereference it. + */ + spin_lock(&sysfs_lock); + + /* The dentry might have been deleted or another + * lookup could have happened updating sd->s_dentry to + * point the new dentry. Ignore if it isn't pointing + * to this dentry. + */ + if (sd->s_dentry == dentry) + sd->s_dentry = NULL; + spin_unlock(&sysfs_lock); sysfs_put(sd); } iput(inode); @@ -30,6 +42,14 @@ static struct dentry_operations sysfs_dentry_ops = { .d_iput = sysfs_d_iput, }; +static unsigned int sysfs_inode_counter; +ino_t sysfs_get_inum(void) +{ + if (unlikely(sysfs_inode_counter < 3)) + sysfs_inode_counter = 3; + return sysfs_inode_counter++; +} + /* * Allocates a new sysfs_dirent and links it to the parent sysfs_dirent */ @@ -41,6 +61,7 @@ static struct sysfs_dirent * __sysfs_new_dirent(void * element) if (!sd) return NULL; + sd->s_ino = sysfs_get_inum(); atomic_set(&sd->s_count, 1); atomic_set(&sd->s_event, 1); INIT_LIST_HEAD(&sd->s_children); @@ -238,7 +259,10 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry) } dentry->d_fsdata = sysfs_get(sd); + /* protect sd->s_dentry against sysfs_d_iput */ + spin_lock(&sysfs_lock); sd->s_dentry = dentry; + spin_unlock(&sysfs_lock); error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init); if (error) { sysfs_put(sd); @@ -260,7 +284,10 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry) int err = 0; dentry->d_fsdata = sysfs_get(sd); + /* protect sd->s_dentry against sysfs_d_iput */ + spin_lock(&sysfs_lock); sd->s_dentry = dentry; + spin_unlock(&sysfs_lock); err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink); if (!err) { dentry->d_op = &sysfs_dentry_ops; @@ -509,7 +536,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) switch (i) { case 0: - ino = dentry->d_inode->i_ino; + ino = parent_sd->s_ino; if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) break; filp->f_pos++; @@ -538,10 +565,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) name = sysfs_get_name(next); len = strlen(name); - if (next->s_dentry) - ino = next->s_dentry->d_inode->i_ino; - else - ino = iunique(sysfs_sb, 2); + ino = next->s_ino; if (filldir(dirent, name, len, filp->f_pos, ino, dt_type(next)) < 0) diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index bdd30e74de6..5266eec15f6 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -141,6 +141,7 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd) inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info; inode->i_op = &sysfs_inode_operations; + inode->i_ino = sd->s_ino; lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key); if (sd->s_iattr) { @@ -245,13 +246,27 @@ static inline void orphan_all_buffers(struct inode *node) */ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) { - struct dentry * dentry = sd->s_dentry; + struct dentry *dentry = NULL; struct inode *inode; + /* We're not holding a reference to ->s_dentry dentry but the + * field will stay valid as long as sysfs_lock is held. + */ + spin_lock(&sysfs_lock); + spin_lock(&dcache_lock); + + /* dget dentry if it's still alive */ + if (sd->s_dentry && sd->s_dentry->d_inode) + dentry = dget_locked(sd->s_dentry); + + spin_unlock(&dcache_lock); + spin_unlock(&sysfs_lock); + + /* drop dentry */ if (dentry) { spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); - if (!(d_unhashed(dentry) && dentry->d_inode)) { + if (!d_unhashed(dentry) && dentry->d_inode) { inode = dentry->d_inode; spin_lock(&inode->i_lock); __iget(inode); @@ -267,6 +282,8 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent) spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); } + + dput(dentry); } } diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 23a48a38e6a..00ab9125d39 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c @@ -33,6 +33,7 @@ static struct sysfs_dirent sysfs_root = { .s_element = NULL, .s_type = SYSFS_ROOT, .s_iattr = NULL, + .s_ino = 1, }; static void sysfs_clear_inode(struct inode *inode) diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index a77c57e5a6d..502c949c402 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -5,6 +5,7 @@ struct sysfs_dirent { void * s_element; int s_type; umode_t s_mode; + ino_t s_ino; struct dentry * s_dentry; struct iattr * s_iattr; atomic_t s_event; @@ -32,6 +33,7 @@ extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd); extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent); extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); +extern spinlock_t sysfs_lock; extern struct rw_semaphore sysfs_rename_sem; extern struct super_block * sysfs_sb; extern const struct file_operations sysfs_dir_operations; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 1f0129405cf..bf7de0bdbab 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -100,14 +100,23 @@ no_delete: clear_inode(inode); } +/* + * If we are going to release inode from memory, we discard preallocation and + * truncate last inode extent to proper length. We could use drop_inode() but + * it's called under inode_lock and thus we cannot mark inode dirty there. We + * use clear_inode() but we have to make sure to write inode as it's not written + * automatically. + */ void udf_clear_inode(struct inode *inode) { if (!(inode->i_sb->s_flags & MS_RDONLY)) { lock_kernel(); + /* Discard preallocation for directories, symlinks, etc. */ udf_discard_prealloc(inode); + udf_truncate_tail_extent(inode); unlock_kernel(); + write_inode_now(inode, 1); } - kfree(UDF_I_DATA(inode)); UDF_I_DATA(inode) = NULL; } diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 77975ae291a..60d27764424 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -61,7 +61,11 @@ static void extent_trunc(struct inode * inode, struct extent_position *epos, } } -void udf_discard_prealloc(struct inode * inode) +/* + * Truncate the last extent to match i_size. This function assumes + * that preallocation extent is already truncated. + */ +void udf_truncate_tail_extent(struct inode *inode) { struct extent_position epos = { NULL, 0, {0, 0}}; kernel_lb_addr eloc; @@ -71,7 +75,10 @@ void udf_discard_prealloc(struct inode * inode) int adsize; if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB || - inode->i_size == UDF_I_LENEXTENTS(inode)) + inode->i_size == UDF_I_LENEXTENTS(inode)) + return; + /* Are we going to delete the file anyway? */ + if (inode->i_nlink == 0) return; if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) @@ -79,36 +86,76 @@ void udf_discard_prealloc(struct inode * inode) else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) adsize = sizeof(long_ad); else - adsize = 0; - - epos.block = UDF_I_LOCATION(inode); + BUG(); /* Find the last extent in the file */ while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { etype = netype; lbcount += elen; - if (lbcount > inode->i_size && lbcount - elen < inode->i_size) - { - WARN_ON(lbcount - inode->i_size >= inode->i_sb->s_blocksize); + if (lbcount > inode->i_size) { + if (lbcount - inode->i_size >= inode->i_sb->s_blocksize) + printk(KERN_WARNING + "udf_truncate_tail_extent(): Too long " + "extent after EOF in inode %u: i_size: " + "%Ld lbcount: %Ld extent %u+%u\n", + (unsigned)inode->i_ino, + (long long)inode->i_size, + (long long)lbcount, + (unsigned)eloc.logicalBlockNum, + (unsigned)elen); nelen = elen - (lbcount - inode->i_size); epos.offset -= adsize; extent_trunc(inode, &epos, eloc, etype, elen, nelen); epos.offset += adsize; - lbcount = inode->i_size; + if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) + printk(KERN_ERR "udf_truncate_tail_extent(): " + "Extent after EOF in inode %u.\n", + (unsigned)inode->i_ino); + break; } } + /* This inode entry is in-memory only and thus we don't have to mark + * the inode dirty */ + UDF_I_LENEXTENTS(inode) = inode->i_size; + brelse(epos.bh); +} + +void udf_discard_prealloc(struct inode *inode) +{ + struct extent_position epos = { NULL, 0, {0, 0}}; + kernel_lb_addr eloc; + uint32_t elen; + uint64_t lbcount = 0; + int8_t etype = -1, netype; + int adsize; + + if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB || + inode->i_size == UDF_I_LENEXTENTS(inode)) + return; + + if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) + adsize = sizeof(short_ad); + else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG) + adsize = sizeof(long_ad); + else + adsize = 0; + + epos.block = UDF_I_LOCATION(inode); + + /* Find the last extent in the file */ + while ((netype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { + etype = netype; + lbcount += elen; + } if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { epos.offset -= adsize; lbcount -= elen; extent_trunc(inode, &epos, eloc, etype, elen, 0); - if (!epos.bh) - { + if (!epos.bh) { UDF_I_LENALLOC(inode) = epos.offset - udf_file_entry_alloc_offset(inode); mark_inode_dirty(inode); - } - else - { + } else { struct allocExtDesc *aed = (struct allocExtDesc *)(epos.bh->b_data); aed->lengthAllocDescs = cpu_to_le32(epos.offset - sizeof(struct allocExtDesc)); if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) @@ -118,9 +165,9 @@ void udf_discard_prealloc(struct inode * inode) mark_buffer_dirty_inode(epos.bh, inode); } } + /* This inode entry is in-memory only and thus we don't have to mark + * the inode dirty */ UDF_I_LENEXTENTS(inode) = lbcount; - - WARN_ON(lbcount != inode->i_size); brelse(epos.bh); } diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 67ded289497..f581f2f69c0 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -146,6 +146,7 @@ extern void udf_free_inode(struct inode *); extern struct inode * udf_new_inode (struct inode *, int, int *); /* truncate.c */ +extern void udf_truncate_tail_extent(struct inode *); extern void udf_discard_prealloc(struct inode *); extern void udf_truncate_extents(struct inode *); diff --git a/fs/utimes.c b/fs/utimes.c index 480f7c8c29d..b3c88952465 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -106,9 +106,16 @@ long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags if (IS_IMMUTABLE(inode)) goto dput_and_out; - if (current->fsuid != inode->i_uid && - (error = vfs_permission(&nd, MAY_WRITE)) != 0) - goto dput_and_out; + if (current->fsuid != inode->i_uid) { + if (f) { + if (!(f->f_mode & FMODE_WRITE)) + goto dput_and_out; + } else { + error = vfs_permission(&nd, MAY_WRITE); + if (error) + goto dput_and_out; + } + } } mutex_lock(&inode->i_mutex); error = notify_change(dentry, &newattrs); diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 86fb671a8bc..ed90403f0ee 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -159,7 +159,7 @@ xfs_iozero( if (status) goto unlock; - memclear_highpage_flush(page, offset, bytes); + zero_user_page(page, offset, bytes, KM_USER0); status = mapping->a_ops->commit_write(NULL, page, offset, offset + bytes); |